LLVMのLLVM言語の識別子、型、定数(リテラル)の仕様についてのメモ。
※LLVMのバージョンは10.0.0
目次
識別子
関数、レジスタ、型につける名前を「識別子」と呼ぶ。
識別子にはvalue
(値)を割り当てることができる。
要するに、識別子は一般的なプログラミング言語における変数のようなものと理解すればよい。
ただし、LLVM言語においては識別子と変数は区別すべきと思われる。 ここでいう変数とは、スタック領域に配置されるローカル変数や、静的領域に配置されるグローバル変数などのこと。 LLVM言語では、これらの変数には名前を付けることができず、ポインタ型の識別子経由でアクセスする必要がある。
識別子の先頭には、@
か%
をつける。
- 先頭が
@
の場合はグローバル識別子になる。 - 先頭が
%
の場合はローカル識別子になる。
識別子には名前付きの値と無名の値がある。
- 名前付きの値
- 識別子につけられる名前の書式は、正規表現であらわすと
[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*
。
- 識別子につけられる名前の書式は、正規表現であらわすと
- 名前なしの値
- 明示的に名前を付けなかった場合、名前として
@
か%
と数値が割り当てられる。数値は、関数内に登場した順番に0から割り当てられる。 - 関数の引数と先頭ブロックに名前を付けていない場合、それらも無名の値として番号が割り当てられる。
例:
define i32 @main(i32, i8**) { add i32 %0, 10 ret i32 %3 }
main
関数の2つの引数それぞれに%0
、%1
が割り当てられる。- 関数の先頭のブロックにラベル
%2
が割り当てられる。 add
命令の戻り値に%3
が割り当てられる。
- 明示的に名前を付けなかった場合、名前として
型
型は大きく分けて以下の3つ。
- Void型
- 関数型
- ファーストクラス型
ファーストクラス型とは、主に以下のような性質を持つ型のことである(参考)。
- 引数として渡せる
- 関数から返せる
- 変更できる
- 変数に割り当てられる
LLVM言語におけるファーストクラス型は、整数型、浮動小数点型、ポインタ型、配列型、構造体型など。
以降で示す各型の構文は、他の何らかの構文の中の<type>
や<ty>
等の部分に記述できるものを表す。
Void型
値とサイズを持たない型。
構文
void
例えば、call <ty> <fnptrval>()
という引数なしの関数呼び出しの構文に対して、戻り値の型がVoid型である関数foo
を呼び出す場合、以下のように書く。
call void @foo()
関数型
返却値の型と引数の型のリストからなる関数を表す型。 いわゆる関数シグネチャのこと。
構文
<returntype> (<parameter list>)
<returntype>
はラベルとメタデータ以外の任意の型。
<parameter list>
は、カンマ区切り型のリスト。
例
i32 (i32) |
i32型を引数にとりi32型を返す関数 |
float (i16, i32 *) * |
i16型とi32のポインタ型を引数にとり、floatを返す関数へのポインタ |
{i32, i32} (i32) |
i32型を引数にとり、2つのi32型を持つ構造体を返す関数 |
ファーストクラス型
整数型
1
から2の32乗-1
までの任意のビット幅を持つ整数。
構文
iN
N
はビット幅を表す整数。
例
i1 |
1ビット幅整数 |
i32 |
32ビット幅整数 |
i8388607 |
800万以上のビット幅の整数 |
LLVM言語ではC言語などと違って、型は符号付きか符号なしかの情報を持たない。 演算の際に、符号付きか符号なしかを指定する。
浮動小数点数型
型 | 説明 |
---|---|
half | 16ビット浮動小数点数 |
float | 32ビット浮動小数点数 |
double | 64ビット浮動小数点数 |
fp128 | 128ビット浮動小数点数 (112ビットが仮数部) |
x86_fp80 | 80ビット浮動小数点数(X87) |
ppc_fp128 | 128ビット浮動小数点数(2つの64ビット) |
half、float、double、fp128のバイナリ形式はそれぞれ、IEEE-754-2008のbinary16、binary32、binary64、binary128に対応する。
ポインタ型
メモリ位置を指す型。
構文
<type>*
例
[4 x i32]* |
i32配列のポインタ |
i32 (i32*) * |
i32*型を引数にとりi32型を返す関数のポインタ |
LLVM言語ではvoid*
とlabel*
は使えない。代わりにi8*
を使う。
ラベル型
ラベルを表す型。
構文
label
配列型
同じ型の要素を複数もつデータ構造を表す型。
構文
[<# elements> x <elementtype>]
<# elements>
は要素数。
<elementtype>
は要素の型。
例
[40 x i32] |
32ビット整数の配列 |
[3 x [4 x i32]] |
二次元配列 |
[2 x [3 x [4 x i16]]] |
三次元配列 |
構造体型
複数の任意の型の組み合わせを表す型。
構文
type { <type list> }
例
{i32, i32, i32} |
3つの整数の組 |
定数
公式ドキュメントではconstants(定数)と記述されているが、いわゆるリテラルのこと。
単純な定数
複雑な定数
- 構造体定数
{
、}
で囲んだカンマ区切りの値のリスト(例:{ i32 4, float 17.0, i32* @G }
)
- 配列定数
[
、]
で囲んだカンマ区切りの値のリスト(例:[ i32 42, i32 11, i32 74 ]
)- 文字列定数は
c"
、"
で囲む(例:c"Hello World\0A\00"
)
- ゼロ初期化
zeroinitializer
で任意の型の値をゼロ値に初期化できる。