Search code examples
c++llvmjitglobalmcjit

LLVM - How to properly use globals with MCJIT


So I'm building a compiler which can invoke code at compile-time. After everything has successfully compiled, I create an llvm::ExecutionEngine and add each llvm::Module the program requires.

Lastly I call llvm::ExecutionEngine::finalizeObject and execute a function within the modules.

llvm::ExecutionEngine* execution_engine = llvm::EngineBuilder(std::move(module)).setErrorStr(&error_str).create();

// Ensure execution engine was created successfully
if(!execution_engine){
    std::cerr << "Failed to construct ExecutionEngine: " << error_str << std::endl;
    return 1;
}

// Add all of the dependencies to the execution engine
for(size_t i = 0; i != dependencies.size(); i++){
    ModuleDependency* dependency = &dependencies[i];

    if(!dependency->is_nothing){
        llvm::SMDiagnostic sm_diagnostic;
        std::unique_ptr<llvm::Module> required_module = llvm::parseIRFile(dependency->bytecode_filename, sm_diagnostic, llvm_context);

        if (!required_module) {
            sm_diagnostic.print("Failed to parse IR File: ", llvm::errs());
            return false;
        }

        required_module->setModuleIdentifier(dependency->bytecode_filename.c_str());
        execution_engine->addModule(std::move(required_module));
    }
}

execution_engine->finalizeObject();
llvm::GenericValue returned_value = execution_engine->runFunction(entry_point, args);

Everything works fine except one thing:

llvm::ExecutionEngine::finalizeObject crashes with Integer division by zero error whenever a module contains global variables.

So my question: How to properly use global variables with MCJIT?

Notes:
- Global variables work fine when in native executables
- The execution engine works fine when not using global variables
- I think the problem might have something to do with the linkage of the global variables or the data layout of the execution engine

Thanks for any feedback!


Solution

  • I found my problem.

    My globals had CommonLinkage which makes no sense for JIT code. Changing the linkage of global variables to InernalLinkage made my code work just fine.