26

Type*手に持っています。そのサイズ (このタイプのオブジェクトがメモリ内で占有するサイズ) をビット/バイト単位で調べるにはどうすればよいですか? 「プリミティブ」または「スカラー」サイズを取得できるあらゆる種類のメソッドを目にしますが、それは集約型には役立ちません...

4

2 に答える 2

33

サイズを IR に挿入するためだけにサイズが必要な場合(たとえば、 への呼び出しに送信できるようにするためmalloc())、命令を使用して、ここで説明されgetelementptrているように (少しキャストして) ダーティな作業を行うことができます(最新の LLVM の更新):

sizeofLLVMには特別な目的/offsetof命令 は含まれていませんが、getelementptr命令を使用してこれらの値を評価できます。基本的な考え方はgetelementptrnullポインターから使用して、必要に応じて値を計算することです。は値をポインターとして生成するため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 オプティマイザーは、値を定数にも変換します。

于 2015-06-14T14:18:57.270 に答える
33

サイズはターゲットによって異なります (いくつかの理由から、配置もその 1 つです)。

LLVM バージョン 3.2 以降では、 DataLayout、特にそのgetTypeAllocSizeメソッドを使用する必要があります。これはサイズをバイト単位で返します。 という名前のビット バージョンもありますgetTypeAllocSizeInBitsDataLayoutインスタンスは、現在のモジュールから作成することで取得できます: DataLayout* TD = new DataLayout(M).

バージョン 3.1 (を含む) までの LLVMでは、TargetData代わりに を使用しDataLayoutます。getTypeAllocSizeただし、同じメソッドを公開します。

于 2013-01-30T15:59:16.883 に答える