【问题标题】:Compile and run C code using clang API使用 clang API 编译和运行 C 代码
【发布时间】:2015-01-29 08:56:42
【问题描述】:

我想使用 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。

有人手头有很好的教程吗?

【问题讨论】:

    标签: api clang llvm jit


    【解决方案1】:

    我关注this blog post 取得了不错的成绩。 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 Kaleidoscope 教程 (This is the JIT chapter)。

    【讨论】:

    • 我无法重新创建您的代码,您有更新版本吗?或者可能是整个代码本身,以便我可以跟进它?
    • 我无权访问该代码。但是,完整的代码并不相关,它只是移动输入并将其转储到文件中,或者读取输出并将其转储。我只写了这个版本,正如我在帖子中所说,我从来没有开始执行它(我需要这个来进行一些优化测试,但不得不转移到另一个项目)。对不起。
    【解决方案2】:

    我建议使用 MCJIT,因为旧的 JIT 基础架构将在后续版本中删除。 我不能给你指一个完整的教程,也不能保证自博客文章以来 API 没有改变,但here 你会找到一个指南,如何将 MCJIT 与来自 LLVM 的 Kaleidoscope 示例一起使用,仅此而已。很难找到 LLVM/Clang 的示例和教程。不过,我建议您尝试一下,也许您可​​以通过一个简短的示例来记录您的旅程。

    Julia 项目还使用 MCJIT 对 Julia lang 内的 C++ 代码进行 jit 编译。或许你可以看一下代码,了解如何使用 MCJIT。

    祝你好运;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-01
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多