Geoff Levner via llvm-dev
2018-Jun-04 12:51 UTC
[llvm-dev] reusing an ExecutionEngine instance
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>
Geoff Levner via llvm-dev
2018-Jun-05 15:56 UTC
[llvm-dev] reusing an ExecutionEngine instance
Well, if anybody out there comes across a similar problem, I found the solution: create your own LLVMContext object and pass it to the EmitLLVMOnlyAction constructor. If you don't, CodeGenAction creates a temporary context and deletes it when the CodeGenAction is deleted. And the LLVMContext destructor deletes the module that was created, even though you may have a std::unique_ptr to it... Geoff On 4 June 2018 at 14:51, Geoff Levner <glevner at gmail.com> wrote:> 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 > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180605/84c52f5d/attachment-0001.html>