LLVMでJITアドレス空間にあるメモリにアクセスする

久々にLLVMをいじっている。LLVMにロマンを感じるのは自分がそういう人間だからなのだろうと思う。

LLVMを使って作りたいと思っているものがあって、そのための下調べをしている。まずはJITアドレス空間にあるメモリにアクセスする方法。ネットを探したところ、こんな記事が見つかった。

Old Nabble - LLVM - Dev - Creating Pointer Constants http://old.nabble.com/Creating-Pointer-Constants-td22401381.html

この記事を参考に試してみたところ、メモリにアクセスすることができた。ソースコードは以下のとおり。HowToJITを改造している。

int value = 0;

int main() {
	InitializeNativeTarget();

	LLVMContext Context;

	Module *M = new Module("test", Context);

	Function *testFunction = cast<Function>(M->getOrInsertFunction("testFunction", Type::getVoidTy(Context), (Type *)0));
	BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", testFunction);
	IRBuilder<> builder(BB);

	Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1);
	llvm::Constant* constInt = llvm::ConstantInt::get(llvm::Type::getInt64Ty(Context), (unsigned long long)&value); 
	llvm::Value* constPtr = llvm::ConstantExpr::getIntToPtr(constInt, llvm::PointerType::getUnqual(llvm::Type::getInt32Ty(Context)));
	builder.CreateStore(One, constPtr);

	builder.CreateRetVoid();

	ExecutionEngine* EE = EngineBuilder(M).create();

	std::vector<GenericValue> noargs;
	EE->runFunction(testFunction, noargs);

	outs() << "value: " << value << "\n";

	EE->freeMachineCodeForFunction(testFunction);
	delete EE;
	llvm_shutdown();
	return 0;
}

ただ、一度キャストしているところがなんとなく気持ち悪く感じられる。もう少しスマートに出来ないだろうか・・・。

LLVMでJITアドレス空間にある関数を使用する

前の記事に引き続いてLLVMJITアドレス空間にある関数にアクセスする方法。

LLVMチュートリアルのCh.4にやり方が載っているのだが、そのままでは動かなかった。理由はLLVMが関数のシンボルを見つけられないかららしい。VisualStudioではシンボルのエクスポートをするおまじない(?)を書く必要がある。Linuxでは"-rdynamic"コンパイルオプション付きでコンパイルすればよいらしいが、試していないのでよく分からない。ソースコードは以下の通り。

extern "C"
__declspec(dllexport) void printHelloWorld() {
	printf("Hello, World!\n");
}

int main() {
	InitializeNativeTarget();

	LLVMContext Context;

	Module *M = new Module("test", Context);

	Function *testFunction = cast<Function>(M->getOrInsertFunction("testFunction", Type::getVoidTy(Context), (Type *)0));
	BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", testFunction);
	IRBuilder<> builder(BB);

	FunctionType *FT = FunctionType::get(Type::getVoidTy(Context), false);
	Function *F = Function::Create(FT, Function::ExternalLinkage, "printHelloWorld", M);
	builder.CreateCall(M->getFunction("printHelloWorld"));

	builder.CreateRetVoid();

	ExecutionEngine* EE = EngineBuilder(M).create();

	std::vector<GenericValue> noargs;
	EE->runFunction(testFunction, noargs);

	EE->freeMachineCodeForFunction(testFunction);
	delete EE;
	llvm_shutdown();
	return 0;
}