我想使用 clang/llvm API 编译一个在字符串中定义的 c 函数并立即执行它。像这样:
void main() {
std::string codestr = "int foo(int bar) { return bar * 2; }"
clang::??? *code = clang::???.compile(codestr);
int result = code->call("foo", 5);
}
我正在寻找教程,但到目前为止我发现的内容与我的目标不太相符或不起作用,因为它指的是 LLVM 的过时版本。目前,我正在使用LLVM 3.5。
有人手头有好的教程吗?
我关注了这篇博文,取得了很好的效果。clang API 已更改,因此您可能需要进行调整。使用 LLVM 3.6.1,我使用以下代码获得了良好的结果:
llvm::Module* compile(const char* filename) {
clang::CompilerInstance compiler;
clang::CompilerInvocation* invocation = new clang::CompilerInvocation();
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
auto diagOptions = new clang::DiagnosticOptions();
clang::DiagnosticsEngine Diags(DiagID, diagOptions,
new clang::TextDiagnosticPrinter(llvm::errs(), diagOptions));
std::vector<const char *> arguments = {filename};
clang::CompilerInvocation::CreateFromArgs(*invocation,
&*arguments.begin(), &*arguments.end(),
Diags);
compiler.setInvocation(invocation);
compiler.setDiagnostics(new clang::DiagnosticsEngine(DiagID, diagOptions,
new clang::TextDiagnosticPrinter(llvm::errs(), diagOptions)));
std::unique_ptr<clang::CodeGenAction> action(new clang::EmitLLVMOnlyAction());
compiler.ExecuteAction(*action);
std::unique_ptr<llvm::Module> result = action->takeModule();
llvm::errs() << *result;
return result.release();
}
我对指针非常粗心,所以很可能存在内存泄漏或双重释放(尽管它没有崩溃)。
我不知道如何从内存缓冲区中获取源代码,所以我使用 mkstemp
将其转储到临时文件中。
我没有开始执行结果,但我认为您可以遵循@michael-haidi的响应,或者查看LLVM万花筒教程(这是JIT章节)。
我建议使用 MCJIT,因为旧的 JIT 基础结构将在进一步的版本中删除。我不能向您指出完整的教程,也不能保证自博客文章以来API没有更改,但在这里您将找到如何将MCJIT与LLVM的万花筒示例一起使用的指南,仅此而已。LLVM/Clang 很难找到示例和教程。但是,我建议尝试一下,也许你可以用一个简短的例子来记录你的旅程。
Julia 项目还使用 MCJIT 对 Julia lang 内部的C++代码进行 jit 编译。也许你可以偷看代码,找出如何使用MCJIT的。
祝你好运;)