近&況

Recent Posts
Edit

llvmのsub expressionっぽいやつの書き方

2017-02-06

メモ。

LLVM IRは基本的に以下のような構造をしている。

; (レジスタ名) = (命令名) (引数 ...)
%2 = mul i64 %0, %1

ところがコンパイラが生成した.llファイルを見ていると、引数の部分に別の命令が入っていたりする。

%4 = mul i32 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i32), %3

ここではmul命令の引数に、ptrtoint命令とgetelementptr命令の呼び出しが入っている…ように見える。しかしそれにしては括弧の位置が微妙におかしい。例えば「to i32」はどの命令にかかるのだろうか?

実はこれらはConstant Expressionsと呼ばれるもので、特定の命令だけ、このような書き方が許されている。上記の例では以下の2つのConstant Expressionが使われている。

ptrtoint (CST to TYPE)
getelementptr (TY, CSTPTR, IDX0, IDX1, ...)

ということで、上記の「to i32」はptrtointと対応しているのであった。

以下のような構造体Aについて、これのサイズを計算したいとする。

%A = type { i32 }

これは以下のように書ける。

; nullを%A*と見なして、1だけ進めた位置のアドレスを得る
%addr = getelementptr %A, %A* null, i32 1
; アドレス値を整数に変換する
%A_size = ptrtoint %A* %addr to i64

この2行を1行にまとめるにはどうすれば良いか。まず1行目のgetelementptrをConstant Expressionとして書き直すと以下のようになる。

getelementptr (%A, %A* null, i32 1)

これを2行目の%addrと差し替えれば出来上がり。

%A_size = ptrtoint %A* getelementptr (%A, %A* null, i32 1) to i64

(LLVM構造体のサイズ計算についてはこのエントリを参考にした)