[llvm-dev] reusing an ExecutionEngine instance

Geoff Levner via llvm-dev llvm-dev at lists.llvm.org
Mon Jun 4 05:51:08 PDT 2018


Greetings, LLVM wizards,

I am trying to use Clang to compile a function in memory once, then to
execute it several times with different parameters. That is, I want to keep
the resulting ExecutionEngine instance around and reuse it. (Or, if there
is a better way to do this, I am open to suggestions.) (And if this is not
the right mailing list for this kind of question, I am open to suggestions,
too.)

In the code below, the ExecutionEngine works fine if I use it immediately.
But if I return from the function and use it afterward, I get memory
corruption and crashes, presumably because it contains references to
something that has been deleted. And in fact, if I change the code so that
the CodeGenAction is not deleted, it seems to work.

My question is: why should deleting the CodeGenAction corrupt the
ExecutionEngine? Are there other things I should avoid deleting as well?
(The following code was adapted from the clang-interpreter example in the
v4.0.1 source code.)

Geoff


ExecutionEngine* compile(const std::string& filename)
{
    const char *resource_dir = getenv("CLANG_RESOURCE_DIR");
    if (resource_dir == NULL) {
        std::cerr << "Clang resource directory has not been defined.\n";
        return NULL;
    }

    IntrusiveRefCntPtr<DiagnosticOptions> diag_opts(new DiagnosticOptions);
    TextDiagnosticPrinter *diag_client =
        new TextDiagnosticPrinter(llvm::errs(), diag_opts.get());
    IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs);
    DiagnosticsEngine diags(diag_ids, diag_opts.get(), diag_client);
    std::string executable = "dg2";
    Driver driver(executable, llvm::sys::getDefaultTargetTriple(), diags);

    SmallVector<const char*, 16> args;
    args.push_back(executable.c_str());
    args.push_back(filename.c_str());
    args.push_back("-fsyntax-only");
    args.push_back("-fno-use-cxa-atexit");
    args.push_back("-resource-dir");
    args.push_back(resource_dir);
    args.push_back("-std=c++11");
    args.push_back("-O3");

    std::unique_ptr<Compilation> compilation(driver.BuildCompilation(args));
    const JobList& jobs = compilation->getJobs();
    if (jobs.size() != 1 || !llvm::isa<Command>(*jobs.begin())) {
        std::cerr << "Expected a single Command job from Compilation...\n";
        return NULL;
    }

    const Command& cmd = llvm::cast<Command>(*jobs.begin());
    if (StringRef(cmd.getCreator().getName()) != "clang") {
        std::cerr << "Expected a single clang Command from
Compilation...\n";
        return NULL;
    }

    const ArgStringList& ccargs = cmd.getArguments();
    std::unique_ptr<CompilerInvocation> invocation(new CompilerInvocation);
    CompilerInvocation::CreateFromArgs(
        *invocation,
        const_cast<const char**>(ccargs.data()),
        const_cast<const char**>(ccargs.data()) + ccargs.size(),
        diags);

    CompilerInstance clang;
    clang.setInvocation(std::move(invocation));
    clang.createDiagnostics();

    std::unique_ptr<CodeGenAction> action(new EmitLLVMOnlyAction);
    if (!clang.ExecuteAction(*action)) {
        return NULL;
    }
    std::unique_ptr<Module> module(action->takeModule());

    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();

    std::string error;

    ExecutionEngine *exec_engine =
        EngineBuilder(std::move(module))
        .setEngineKind(llvm::EngineKind::Either)
        .setErrorStr(&error)
        .create();

    if (!exec_engine) {
        std::cerr << "Could not create execution engine: " << error <<
std::endl;
        return NULL;
    }

    exec_engine->finalizeObject();
    return exec_engine;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180604/fddfde71/attachment.html>


More information about the llvm-dev mailing list