をType*手に持っています。そのサイズ (このタイプのオブジェクトがメモリ内で占有するサイズ) をビット/バイト単位で調べるにはどうすればよいですか? 「プリミティブ」または「スカラー」サイズを取得できるあらゆる種類のメソッドを目にしますが、それは集約型には役立ちません...
2 に答える
サイズを IR に挿入するためだけにサイズが必要な場合(たとえば、 への呼び出しに送信できるようにするためmalloc())、命令を使用して、ここで説明されgetelementptrているように (少しキャストして) ダーティな作業を行うことができます(最新の LLVM の更新):
sizeofLLVMには特別な目的/offsetof命令 は含まれていませんが、getelementptr命令を使用してこれらの値を評価できます。基本的な考え方はgetelementptr、nullポインターから使用して、必要に応じて値を計算することです。は値をポインターとして生成するためgetelementptr、結果は使用前に整数にキャストされます。たとえば、あるタイプのサイズを取得するには、
%T次のようなものを使用します。%Size = getelementptr %T* null, i32 1 %SizeI = ptrtoint %T* %Size to i32このコードは事実上、ポインター
Tから始まる要素の配列があるように装っています。nullこれは、配列の 2 番目の要素 (要素 #1) へのポインターを取得しT、整数として扱います。Tこれは、1 つの要素のサイズを計算します。
これを行うことの良い点は、値が何であるかをまったく気にしない場合に役立つことです。IRから何かに正しい値を渡す必要があるだけです。sizeof()これは、IR 生成で -alike 操作を必要とする最も一般的なケースです。
offsetof()このページでは、同等の方法についても説明しています。
構造体の一部のフィールドのオフセットを取得するには、同様のトリックが使用されます。たとえば、 の 2 番目の要素 (要素 #1) のアドレスを取得するには
{ i8, i32* }(ポインターのターゲット アラインメント要件によって異なります)、次のようなものを使用する必要があります。%Offset = getelementptr {i8,i32*}* null, i32 0, i32 1 %OffsetI = ptrtoint i32** %Offset to i32
sizeofこれはトリックと同じように機能します:nullポインタに型のインスタンスがあるふりをして、関心のあるフィールドのアドレスを取得します。このアドレスはフィールドのオフセットです。どちらの場合も、式はコード生成時に定数として評価されるため、この手法を使用しても実行時のオーバーヘッドは発生しないことに注意してください。
IR オプティマイザーは、値を定数にも変換します。
サイズはターゲットによって異なります (いくつかの理由から、配置もその 1 つです)。
LLVM バージョン 3.2 以降では、 DataLayout、特にそのgetTypeAllocSizeメソッドを使用する必要があります。これはサイズをバイト単位で返します。 という名前のビット バージョンもありますgetTypeAllocSizeInBits。DataLayoutインスタンスは、現在のモジュールから作成することで取得できます: DataLayout* TD = new DataLayout(M).
バージョン 3.1 (を含む) までの LLVMでは、TargetData代わりに を使用しDataLayoutます。getTypeAllocSizeただし、同じメソッドを公開します。