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:
Axel Naumann 2015-01-07 10:22:52 +01:00 committed by sftnight
parent 39c7e56770
commit baf51f6b04
6 changed files with 48 additions and 7 deletions

View File

@ -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);

View File

@ -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*/) {

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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.