Create a new llvm::Module per codegen'ed transaction.
MCJIT needs to finalize modules. To simplify the interface with MCJIT, each transaction now has its own module. It gets created when the previous module gets passed to the execution engine; the first one is created by clang::CreateLLVMCodeGen(). CodeGen now releases the module such that it can be added to the execution engine. This enables simple use cases of cling with MCJIT; most notably cross-module linking is still missing.
This commit is contained in:
parent
39c7e56770
commit
baf51f6b04
@ -624,6 +624,9 @@ namespace cling {
|
||||
///
|
||||
void AddAtExitFunc(void (*Func) (void*), void* Arg);
|
||||
|
||||
///\brief Forwards to cling::IncrementalExecutor::addModule.
|
||||
///
|
||||
void addModule(llvm::Module* module);
|
||||
|
||||
void GenerateAutoloadingMap(llvm::StringRef inFile, llvm::StringRef outFile,
|
||||
bool enableMacros = false, bool enableLogs = true);
|
||||
|
@ -262,7 +262,7 @@ IncrementalExecutor::executeFunction(llvm::StringRef funcname,
|
||||
PromptWrapper_t wrapperFunction;
|
||||
void* address;
|
||||
} p2f;
|
||||
p2f.address = m_engine->getPointerToFunction(f);
|
||||
p2f.address = (void*)m_engine->getFunctionAddress(funcname);
|
||||
|
||||
// check if there is any unresolved symbol in the list
|
||||
if (diagnoseUnresolvedSymbols(funcname, "function"))
|
||||
@ -279,6 +279,8 @@ IncrementalExecutor::runStaticInitializersOnce(llvm::Module* m) {
|
||||
assert(m && "Module must not be null");
|
||||
assert(m_engine && "Code generation did not create an engine!");
|
||||
|
||||
m_engine->finalizeObject();
|
||||
|
||||
llvm::GlobalVariable* GV
|
||||
= m->getGlobalVariable("llvm.global_ctors", true);
|
||||
// Nothing to do is good, too.
|
||||
@ -402,6 +404,11 @@ IncrementalExecutor::addSymbol(const char* symbolName, void* symbolAddress) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void IncrementalExecutor::addModule(llvm::Module* module) {
|
||||
m_engine->addModule(module);
|
||||
}
|
||||
|
||||
|
||||
void* IncrementalExecutor::getAddressOfGlobal(llvm::Module* m,
|
||||
llvm::StringRef symbolName,
|
||||
bool* fromJIT /*=0*/) {
|
||||
|
@ -148,6 +148,12 @@ namespace cling {
|
||||
///
|
||||
bool addSymbol(const char* symbolName, void* symbolAddress);
|
||||
|
||||
///\brief Add a llvm::Module to the ExecutionEngine, see
|
||||
/// ExecutionEngine::addModule()
|
||||
///
|
||||
/// @param[in] module - The module to pass to the execution engine.
|
||||
void addModule(llvm::Module* module);
|
||||
|
||||
///\brief Tells the execution context that we are shutting down the system.
|
||||
///
|
||||
/// This that notification is needed because the execution context needs to
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "DeclCollector.h"
|
||||
#include "DeclExtractor.h"
|
||||
#include "DynamicLookup.h"
|
||||
#include "IncrementalExecutor.h"
|
||||
#include "NullDerefProtectionTransformer.h"
|
||||
#include "ValueExtractionSynthesizer.h"
|
||||
#include "TransactionPool.h"
|
||||
@ -155,7 +156,7 @@ namespace cling {
|
||||
IncrementalParser::IncrementalParser(Interpreter* interp,
|
||||
int argc, const char* const *argv,
|
||||
const char* llvmdir):
|
||||
m_Interpreter(interp), m_Consumer(0) {
|
||||
m_Interpreter(interp), m_Consumer(0), m_ModuleNo(0) {
|
||||
|
||||
CompilerInstance* CI = CIFactory::createCI("", argc, argv, llvmdir);
|
||||
assert(CI && "CompilerInstance is (null)!");
|
||||
@ -166,7 +167,7 @@ namespace cling {
|
||||
m_CI.reset(CI);
|
||||
|
||||
if (CI->getFrontendOpts().ProgramAction != clang::frontend::ParseSyntaxOnly){
|
||||
m_CodeGen.reset(CreateLLVMCodeGen(CI->getDiagnostics(), "cling input",
|
||||
m_CodeGen.reset(CreateLLVMCodeGen(CI->getDiagnostics(), "cling-module-0",
|
||||
CI->getCodeGenOpts(),
|
||||
CI->getTargetOpts(),
|
||||
*m_Interpreter->getLLVMContext()
|
||||
@ -271,9 +272,6 @@ namespace cling {
|
||||
}
|
||||
|
||||
IncrementalParser::~IncrementalParser() {
|
||||
if (hasCodeGenerator()) {
|
||||
getCodeGenerator()->ReleaseModule();
|
||||
}
|
||||
const Transaction* T = getFirstTransaction();
|
||||
const Transaction* nextT = 0;
|
||||
while (T) {
|
||||
@ -579,6 +577,25 @@ namespace cling {
|
||||
} // for deserialized DGRs
|
||||
|
||||
getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext());
|
||||
|
||||
// This llvm::Module is done; finalize it and pass it to the execution
|
||||
// engine.
|
||||
if (!T->isNestedTransaction() && hasCodeGenerator()) {
|
||||
if (llvm::Module* M = getCodeGenerator()->ReleaseModule()) {
|
||||
assert(M == T->getModule() && "Transaction has inconsistent module");
|
||||
m_Interpreter->addModule(M);
|
||||
}
|
||||
|
||||
// Create a new module.
|
||||
std::string ModuleName;
|
||||
{
|
||||
llvm::raw_string_ostream strm(ModuleName);
|
||||
strm << "cling-module-" << ++m_ModuleNo;
|
||||
}
|
||||
getCodeGenerator()->StartModule(ModuleName,
|
||||
*m_Interpreter->getLLVMContext());
|
||||
}
|
||||
|
||||
if ((deserT = endTransaction(deserT)))
|
||||
commitTransaction(deserT);
|
||||
}
|
||||
|
@ -77,6 +77,9 @@ namespace cling {
|
||||
///
|
||||
std::deque<Transaction*> m_Transactions;
|
||||
|
||||
///\brief Number of created modules.
|
||||
unsigned m_ModuleNo;
|
||||
|
||||
///\brief Code generator
|
||||
///
|
||||
std::unique_ptr<clang::CodeGenerator> m_CodeGen;
|
||||
|
@ -1136,7 +1136,7 @@ namespace cling {
|
||||
assert(T.getState() == Transaction::kCommitted && "Must be committed");
|
||||
// Forward to IncrementalExecutor; should not be called by
|
||||
// anyone except for IncrementalParser.
|
||||
llvm::Module* module = m_IncrParser->getCodeGenerator()->GetModule();
|
||||
llvm::Module* module = T.getModule();
|
||||
IncrementalExecutor::ExecutionResult ExeRes
|
||||
= m_Executor->runStaticInitializersOnce(module);
|
||||
|
||||
@ -1161,6 +1161,11 @@ namespace cling {
|
||||
return m_Executor->addSymbol(symbolName, symbolAddress);
|
||||
}
|
||||
|
||||
void Interpreter::addModule(llvm::Module* module) {
|
||||
m_Executor->addModule(module);
|
||||
}
|
||||
|
||||
|
||||
void* Interpreter::getAddressOfGlobal(const GlobalDecl& GD,
|
||||
bool* fromJIT /*=0*/) const {
|
||||
// Return a symbol's address, and whether it was jitted.
|
||||
|
Loading…
Reference in New Issue
Block a user