をType*
手に持っています。そのサイズ (このタイプのオブジェクトがメモリ内で占有するサイズ) をビット/バイト単位で調べるにはどうすればよいですか? 「プリミティブ」または「スカラー」サイズを取得できるあらゆる種類のメソッドを目にしますが、それは集約型には役立ちません...
2 に答える
サイズを IR に挿入するためだけにサイズが必要な場合(たとえば、 への呼び出しに送信できるようにするためmalloc()
)、命令を使用して、ここで説明されgetelementptr
ているように (少しキャストして) ダーティな作業を行うことができます(最新の LLVM の更新):
sizeof
LLVMには特別な目的/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
ただし、同じメソッドを公開します。