schalli
schalli

Reputation: 61

Compile and run C code using clang API

I would like to use the clang/llvm APIs to compile a c-function, defined in a string and immediately execute it. Something like:

void main() {
  std::string codestr = "int foo(int bar) { return bar * 2; }"

  clang::??? *code = clang::???.compile(codestr);

  int result = code->call("foo", 5);
}

I am looking for tutorials, but what I found so far does not quite match my goal or does not work, because it refers to an outdated version of LLVM. Currently, I am using LLVM 3.5.

Does anyone have a good tutorial at hand?

Upvotes: 5

Views: 3261

Answers (2)

Omer Anson
Omer Anson

Reputation: 329

I followed this blog post with good results. The clang API has changed, so you may have to make adjustments. With LLVM 3.6.1, I got good results with the following code:

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();                                                              
}                                                                                             

I was very careless with the pointers, so its very possible there's a memory leak or a double free (although it didn't crash).

I couldn't figure out how to take the source from a memory buffer, so I dumped it in a temporary file using mkstemp.

I didn't get around to executing the result, but I think you can follow @michael-haidi's response, or check out the LLVM Kaleidoscope tutorial (This is the JIT chapter).

Upvotes: 4

Michael Haidl
Michael Haidl

Reputation: 5492

I recommend using MCJIT because the old JIT infrastructure will be removed in a further release. I can't point you to a full tutorial and cannot promise that the API hasn't changed since the blog post but here you'll find a guide how to use MCJIT with the Kaleidoscope example from LLVM and thats it. Examples and tutorials are hard to find for LLVM/Clang. However, I suggest trying it and maybe you can document your journey with a short example.

The Julia project also uses MCJIT for jit compilation of C++ code inside of the Julia lang. Maybe you can peek at the code and find out how the use MCJIT.

Good luck ;)

Upvotes: 1

Related Questions