2010年04月06日
LLVM の JIT を使ってみる (4)
今回はローカル変数を作ってみました。
また、JIT 実行ではなく、bitcode をファイルに書き出してみました。
WriteBitcodeToFile() API の使い方などは、ModuleMaker.cpp というサンプルを参考にしました。そのままそのサンプルの main() 関数を、後述するものに置き換えて、関連しそうなプロジェクト全てに依存関係を設定すれば、ビルド & 実行できるはずです。
(なぜか HowToUseJIT サンプルでは、関連しそうなプロジェクト全てに依存関係を設定しても、BitcodeWriter.cpp の関数がリンクできませんでした。)
/* 以下のような main 関数を作る。 int32_t main() { int32_t x; x = 123; return x; } 実際は以下のようになる。 int32_t main() { int32_t *x = alloca(sizeof(int32_t)); *x = 123; return *x; } */ int main() { LLVMContext ctx; Module *m = new Module("test", ctx); Function *f = cast<Function>(m->getOrInsertFunction("main", Type::getInt32Ty(ctx), NULL)); BasicBlock *block = BasicBlock::Create(ctx, "", f); IRBuilder<> builder(block); // 定数 123 Value *c = ConstantInt::get(Type::getInt32Ty(ctx), 123); // 32 bit 自動変数へのポインタ Value *xp = builder.CreateAlloca(Type::getInt32Ty(ctx), 0, "x"); builder.CreateStore(c, xp); Value *x = builder.CreateLoad(xp); builder.CreateRet(x); WriteBitcodeToFile(m, outs()); delete m; return 0; }
実行すると、以下のようになります。
C:\llvm\work> ModuleMaker > ModuleMaker.bc
C:\llvm\work>llvm-dis ModuleMaker.bc
C:\llvm\work>ls modulemaker.bc modulemaker.ll
C:\llvm\work>cat ModuleMaker.ll ; ModuleID = 'ModuleMaker.bc' define i32 @main() { %x = alloca i32 ; <i32*> [#uses=2] store i32 123, i32* %x %1 = load i32* %x ; <i32> [#uses=1] ret i32 %1 }
:\llvm\work>llc ModuleMaker.ll
C:\llvm\work>cat ModuleMaker.s .def _main; .scl 2; .type 32; .endef .text .globl _main .align 16, 0x90 _main: # @main # BB#0: subl $4, %esp Llabel1: movl $123, (%esp) movl $123, %eax addl $4, %esp ret
C:\llvm\work>path %path%;c:\MinGW\bin
C:\llvm\work>gcc ModuleMaker.s