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