LLVMの中間コードアセンブラを試してみた (Mac OS X編)

以前に.NETの中間コード(MSIL)用のTinyBasicコンパイラとか、Javaの中間コード(bytecode)用のTinyBasicコンパイラとか作っており、次はLLVM用をやってみたいと考えている。
Javaバイトコードを生成するTiny BASICコンパイラを作ってみた
CIL(MSIL)中間コードを生成するTiny BASICコンパイラを作ってみた

きつねさんでもわかるLLVMという本を参考にして、LLVMの中間コードアセンブラを試してみた。
 きつねさんでもわかるLLVM ~コンパイラを自作するためのガイドブック~(Amazon)

この本では、Ubuntu上でLLVMをソースからビルドしてインストールしていたのだけど、Mac上で作業するためにMac OS XでLLVMをインストールした。
Mac OS X MavericksにHomebrewでLLVMをインストール

LLVMが動かせたので、まず最初に、参考書などに載っているHello worldというサンプルコードを試してみた。

@HW = internal constant [14 x i8] c"Hello world!\0A\00"

declare i32 @puts(i8*)

define i32 @main() {
  %cast_hw = getelementptr [14 x i8]* @HW, i32 0, i32 0
  call i32 @puts(i8* %cast_hw)
  ret i32 0
}

上記を、hello.llという名前で保存し、
% llvm-as hello.ll
というコマンドでビルドすると、LLVMの中間コードのbitcode出力が得られる。
lliを使って実行して、動作を確認することができた。

で、その次は、a=2; b=3; printf(“%d”,a); printf(“%d”,b); a=a+b; printf(“%d”,a);というような処理を書いてみた。

define i32 @main() {
  %a= alloca i32
  %b= alloca i32
  store i32 2 , i32* %a
  store i32 3 , i32* %b
  %cast_msg = getelementptr [4 x i8]* @MSG, i32 0, i32 0
  %tmp1=load i32* %a
  %tmp2=load i32* %b
  call i32 (i8*, ...)* @printf(i8* %cast_msg, i32 %tmp1)
  call i32 (i8*, ...)* @printf(i8* %cast_msg, i32 %tmp2)
  %tmp3= add i32 %tmp1,%tmp2
  store i32 %tmp3, i32* %a
  %tmp4=load i32* %a
  call i32 (i8*, ...)* @printf(i8* %cast_msg, i32 %tmp4)
  ret i32 0
}
declare i32 @printf(i8*, ...)
@MSG = internal constant [4 x i8] c"%d\0A\00"

静的単一代入のため、普通に%aや%bという変数を整数型にして計算することができないため、ポインタ変数を使ってメモリ確保をして一時変数に取り出しながら処理をしている。
そのためtmp1,tmp2,tmp3,..とかSSA風の変数をたくさん使い捨てで使っている。
こういうやりかたで良いのかちょっと自信がないが、なんとなくTinyBasicくらいならいけそうな気がしてきた。


追記
時間が空いてしまったが、ようやくLLVM用のTinyBasicを作った。
LLVM中間コードを生成するTiny BASICコンパイラを作ってみた




コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Time limit is exhausted. Please reload CAPTCHA.

10 + = 15