[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