//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ExecutionEngine/GenericValue.h"
-#include "llvm/ExecutionEngine/JITMemoryManager.h"
-#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/JITEventListener.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/ValueHandle.h"
STATISTIC(NumInitBytes, "Number of bytes of global vars initialized");
STATISTIC(NumGlobals , "Number of global vars initialized");
-// Pin the vtable to this file.
-void ObjectCache::anchor() {}
-void ObjectBuffer::anchor() {}
-void ObjectBufferStream::anchor() {}
-
-ExecutionEngine *(*ExecutionEngine::JITCtor)(
- Module *M,
- std::string *ErrorStr,
- JITMemoryManager *JMM,
- bool GVsWithCode,
- TargetMachine *TM) = nullptr;
ExecutionEngine *(*ExecutionEngine::MCJITCtor)(
- Module *M,
- std::string *ErrorStr,
- RTDyldMemoryManager *MCJMM,
- TargetMachine *TM) = nullptr;
-ExecutionEngine *(*ExecutionEngine::InterpCtor)(Module *M,
+ std::unique_ptr<Module> M, std::string *ErrorStr,
+ std::shared_ptr<MCJITMemoryManager> MemMgr,
+ std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver,
+ std::unique_ptr<TargetMachine> TM) = nullptr;
+
+ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)(
+ std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr,
+ std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver,
+ std::unique_ptr<TargetMachine> TM) = nullptr;
+
+ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr) =nullptr;
-ExecutionEngine::ExecutionEngine(Module *M)
- : EEState(*this),
- LazyFunctionCreator(nullptr) {
+void JITEventListener::anchor() {}
+
+ExecutionEngine::ExecutionEngine(std::unique_ptr<Module> M)
+ : LazyFunctionCreator(nullptr) {
CompilingLazily = false;
GVCompilationDisabled = false;
SymbolSearchingDisabled = false;
VerifyModules = false;
#endif
- Modules.push_back(M);
assert(M && "Module is null?");
+ Modules.push_back(std::move(M));
}
ExecutionEngine::~ExecutionEngine() {
clearAllGlobalMappings();
- for (unsigned i = 0, e = Modules.size(); i != e; ++i)
- delete Modules[i];
}
namespace {
Type *ElTy = GV->getType()->getElementType();
size_t GVSize = (size_t)TD.getTypeAllocSize(ElTy);
void *RawMemory = ::operator new(
- DataLayout::RoundUpAlignment(sizeof(GVMemoryBlock),
- TD.getPreferredAlignment(GV))
+ RoundUpToAlignment(sizeof(GVMemoryBlock),
+ TD.getPreferredAlignment(GV))
+ GVSize);
new(RawMemory) GVMemoryBlock(GV);
return static_cast<char*>(RawMemory) + sizeof(GVMemoryBlock);
llvm_unreachable("ExecutionEngine subclass doesn't implement addObjectFile.");
}
-void ExecutionEngine::addArchive(std::unique_ptr<object::Archive> A) {
+void
+ExecutionEngine::addObjectFile(object::OwningBinary<object::ObjectFile> O) {
+ llvm_unreachable("ExecutionEngine subclass doesn't implement addObjectFile.");
+}
+
+void ExecutionEngine::addArchive(object::OwningBinary<object::Archive> A) {
llvm_unreachable("ExecutionEngine subclass doesn't implement addArchive.");
}
bool ExecutionEngine::removeModule(Module *M) {
- for(SmallVectorImpl<Module *>::iterator I = Modules.begin(),
- E = Modules.end(); I != E; ++I) {
- Module *Found = *I;
+ for (auto I = Modules.begin(), E = Modules.end(); I != E; ++I) {
+ Module *Found = I->get();
if (Found == M) {
+ I->release();
Modules.erase(I);
clearGlobalMappingsFromModule(M);
return true;
Function *ExecutionEngine::FindFunctionNamed(const char *FnName) {
for (unsigned i = 0, e = Modules.size(); i != e; ++i) {
- if (Function *F = Modules[i]->getFunction(FnName))
+ Function *F = Modules[i]->getFunction(FnName);
+ if (F && !F->isDeclaration())
return F;
}
return nullptr;
}
-void *ExecutionEngineState::RemoveMapping(const GlobalValue *ToUnmap) {
- GlobalAddressMapTy::iterator I = GlobalAddressMap.find(ToUnmap);
- void *OldVal;
+uint64_t ExecutionEngineState::RemoveMapping(StringRef Name) {
+ GlobalAddressMapTy::iterator I = GlobalAddressMap.find(Name);
+ uint64_t OldVal;
// FIXME: This is silly, we shouldn't end up with a mapping -> 0 in the
// GlobalAddressMap.
if (I == GlobalAddressMap.end())
- OldVal = nullptr;
+ OldVal = 0;
else {
+ GlobalAddressReverseMap.erase(I->second);
OldVal = I->second;
GlobalAddressMap.erase(I);
}
- GlobalAddressReverseMap.erase(OldVal);
return OldVal;
}
+std::string ExecutionEngine::getMangledName(const GlobalValue *GV) {
+ MutexGuard locked(lock);
+ Mangler Mang(DL);
+ SmallString<128> FullName;
+ Mang.getNameWithPrefix(FullName, GV->getName());
+ return FullName.str();
+}
+
void ExecutionEngine::addGlobalMapping(const GlobalValue *GV, void *Addr) {
MutexGuard locked(lock);
+ addGlobalMapping(getMangledName(GV), (uint64_t) Addr);
+}
- DEBUG(dbgs() << "JIT: Map \'" << GV->getName()
- << "\' to [" << Addr << "]\n";);
- void *&CurVal = EEState.getGlobalAddressMap()[GV];
+void ExecutionEngine::addGlobalMapping(StringRef Name, uint64_t Addr) {
+ MutexGuard locked(lock);
+
+ assert(!Name.empty() && "Empty GlobalMapping symbol name!");
+
+ DEBUG(dbgs() << "JIT: Map \'" << Name << "\' to [" << Addr << "]\n";);
+ uint64_t &CurVal = EEState.getGlobalAddressMap()[Name];
assert((!CurVal || !Addr) && "GlobalMapping already established!");
CurVal = Addr;
// If we are using the reverse mapping, add it too.
if (!EEState.getGlobalAddressReverseMap().empty()) {
- AssertingVH<const GlobalValue> &V =
- EEState.getGlobalAddressReverseMap()[Addr];
- assert((!V || !GV) && "GlobalMapping already established!");
- V = GV;
+ std::string &V = EEState.getGlobalAddressReverseMap()[CurVal];
+ assert((!V.empty() || !Name.empty()) &&
+ "GlobalMapping already established!");
+ V = Name;
}
}
MutexGuard locked(lock);
for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI)
- EEState.RemoveMapping(FI);
+ EEState.RemoveMapping(getMangledName(FI));
for (Module::global_iterator GI = M->global_begin(), GE = M->global_end();
GI != GE; ++GI)
- EEState.RemoveMapping(GI);
+ EEState.RemoveMapping(getMangledName(GI));
}
-void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) {
+uint64_t ExecutionEngine::updateGlobalMapping(const GlobalValue *GV,
+ void *Addr) {
+ MutexGuard locked(lock);
+ return updateGlobalMapping(getMangledName(GV), (uint64_t) Addr);
+}
+
+uint64_t ExecutionEngine::updateGlobalMapping(StringRef Name, uint64_t Addr) {
MutexGuard locked(lock);
ExecutionEngineState::GlobalAddressMapTy &Map =
// Deleting from the mapping?
if (!Addr)
- return EEState.RemoveMapping(GV);
+ return EEState.RemoveMapping(Name);
- void *&CurVal = Map[GV];
- void *OldVal = CurVal;
+ uint64_t &CurVal = Map[Name];
+ uint64_t OldVal = CurVal;
if (CurVal && !EEState.getGlobalAddressReverseMap().empty())
EEState.getGlobalAddressReverseMap().erase(CurVal);
// If we are using the reverse mapping, add it too.
if (!EEState.getGlobalAddressReverseMap().empty()) {
- AssertingVH<const GlobalValue> &V =
- EEState.getGlobalAddressReverseMap()[Addr];
- assert((!V || !GV) && "GlobalMapping already established!");
- V = GV;
+ std::string &V = EEState.getGlobalAddressReverseMap()[CurVal];
+ assert((!V.empty() || !Name.empty()) &&
+ "GlobalMapping already established!");
+ V = Name;
}
return OldVal;
}
-void *ExecutionEngine::getPointerToGlobalIfAvailable(const GlobalValue *GV) {
+uint64_t ExecutionEngine::getAddressToGlobalIfAvailable(StringRef S) {
MutexGuard locked(lock);
-
+ uint64_t Address = 0;
ExecutionEngineState::GlobalAddressMapTy::iterator I =
- EEState.getGlobalAddressMap().find(GV);
- return I != EEState.getGlobalAddressMap().end() ? I->second : nullptr;
+ EEState.getGlobalAddressMap().find(S);
+ if (I != EEState.getGlobalAddressMap().end())
+ Address = I->second;
+ return Address;
+}
+
+
+void *ExecutionEngine::getPointerToGlobalIfAvailable(StringRef S) {
+ MutexGuard locked(lock);
+ if (void* Address = (void *) getAddressToGlobalIfAvailable(S))
+ return Address;
+ return nullptr;
+}
+
+void *ExecutionEngine::getPointerToGlobalIfAvailable(const GlobalValue *GV) {
+ MutexGuard locked(lock);
+ return getPointerToGlobalIfAvailable(getMangledName(GV));
}
const GlobalValue *ExecutionEngine::getGlobalValueAtAddress(void *Addr) {
// If we haven't computed the reverse mapping yet, do so first.
if (EEState.getGlobalAddressReverseMap().empty()) {
for (ExecutionEngineState::GlobalAddressMapTy::iterator
- I = EEState.getGlobalAddressMap().begin(),
- E = EEState.getGlobalAddressMap().end(); I != E; ++I)
+ I = EEState.getGlobalAddressMap().begin(),
+ E = EEState.getGlobalAddressMap().end(); I != E; ++I) {
+ StringRef Name = I->first();
+ uint64_t Addr = I->second;
EEState.getGlobalAddressReverseMap().insert(std::make_pair(
- I->second, I->first));
+ Addr, Name));
+ }
}
- std::map<void *, AssertingVH<const GlobalValue> >::iterator I =
- EEState.getGlobalAddressReverseMap().find(Addr);
- return I != EEState.getGlobalAddressReverseMap().end() ? I->second : nullptr;
+ std::map<uint64_t, std::string>::iterator I =
+ EEState.getGlobalAddressReverseMap().find((uint64_t) Addr);
+
+ if (I != EEState.getGlobalAddressReverseMap().end()) {
+ StringRef Name = I->second;
+ for (unsigned i = 0, e = Modules.size(); i != e; ++i)
+ if (GlobalValue *GV = Modules[i]->getNamedValue(Name))
+ return GV;
+ }
+ return nullptr;
}
namespace {
class ArgvArray {
- char *Array;
- std::vector<char*> Values;
+ std::unique_ptr<char[]> Array;
+ std::vector<std::unique_ptr<char[]>> Values;
public:
- ArgvArray() : Array(nullptr) {}
- ~ArgvArray() { clear(); }
- void clear() {
- delete[] Array;
- Array = nullptr;
- for (size_t I = 0, E = Values.size(); I != E; ++I) {
- delete[] Values[I];
- }
- Values.clear();
- }
/// Turn a vector of strings into a nice argv style array of pointers to null
/// terminated strings.
void *reset(LLVMContext &C, ExecutionEngine *EE,
} // anonymous namespace
void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE,
const std::vector<std::string> &InputArgv) {
- clear(); // Free the old contents.
+ Values.clear(); // Free the old contents.
+ Values.reserve(InputArgv.size());
unsigned PtrSize = EE->getDataLayout()->getPointerSize();
- Array = new char[(InputArgv.size()+1)*PtrSize];
+ Array = make_unique<char[]>((InputArgv.size()+1)*PtrSize);
- DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array << "\n");
+ DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array.get() << "\n");
Type *SBytePtr = Type::getInt8PtrTy(C);
for (unsigned i = 0; i != InputArgv.size(); ++i) {
unsigned Size = InputArgv[i].size()+1;
- char *Dest = new char[Size];
- Values.push_back(Dest);
- DEBUG(dbgs() << "JIT: ARGV[" << i << "] = " << (void*)Dest << "\n");
+ auto Dest = make_unique<char[]>(Size);
+ DEBUG(dbgs() << "JIT: ARGV[" << i << "] = " << (void*)Dest.get() << "\n");
- std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
+ std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest.get());
Dest[Size-1] = 0;
// Endian safe: Array[i] = (PointerTy)Dest;
- EE->StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Array+i*PtrSize),
- SBytePtr);
+ EE->StoreValueToMemory(PTOGV(Dest.get()),
+ (GenericValue*)(&Array[i*PtrSize]), SBytePtr);
+ Values.push_back(std::move(Dest));
}
// Null terminate it
EE->StoreValueToMemory(PTOGV(nullptr),
- (GenericValue*)(Array+InputArgv.size()*PtrSize),
+ (GenericValue*)(&Array[InputArgv.size()*PtrSize]),
SBytePtr);
- return Array;
+ return Array.get();
}
-void ExecutionEngine::runStaticConstructorsDestructors(Module *module,
+void ExecutionEngine::runStaticConstructorsDestructors(Module &module,
bool isDtors) {
const char *Name = isDtors ? "llvm.global_dtors" : "llvm.global_ctors";
- GlobalVariable *GV = module->getNamedGlobal(Name);
+ GlobalVariable *GV = module.getNamedGlobal(Name);
// If this global has internal linkage, or if it has a use, then it must be
// an old-style (llvmgcc3) static ctor with __main linked in and in use. If
void ExecutionEngine::runStaticConstructorsDestructors(bool isDtors) {
// Execute global ctors/dtors for each module in the program.
- for (unsigned i = 0, e = Modules.size(); i != e; ++i)
- runStaticConstructorsDestructors(Modules[i], isDtors);
+ for (std::unique_ptr<Module> &M : Modules)
+ runStaticConstructorsDestructors(*M, isDtors);
}
#ifndef NDEBUG
return runFunction(Fn, GVArgs).IntVal.getZExtValue();
}
-void EngineBuilder::InitEngine() {
- WhichEngine = EngineKind::Either;
- ErrorStr = nullptr;
- OptLevel = CodeGenOpt::Default;
- MCJMM = nullptr;
- JMM = nullptr;
- Options = TargetOptions();
- AllocateGVsWithCode = false;
- RelocModel = Reloc::Default;
- CMModel = CodeModel::JITDefault;
- UseMCJIT = false;
+EngineBuilder::EngineBuilder() : EngineBuilder(nullptr) {}
+EngineBuilder::EngineBuilder(std::unique_ptr<Module> M)
+ : M(std::move(M)), WhichEngine(EngineKind::Either), ErrorStr(nullptr),
+ OptLevel(CodeGenOpt::Default), MemMgr(nullptr), Resolver(nullptr),
+ RelocModel(Reloc::Default), CMModel(CodeModel::JITDefault),
+ UseOrcMCJITReplacement(false) {
// IR module verification is enabled by default in debug builds, and disabled
// by default in release builds.
#ifndef NDEBUG
#endif
}
+EngineBuilder::~EngineBuilder() = default;
+
+EngineBuilder &EngineBuilder::setMCJITMemoryManager(
+ std::unique_ptr<RTDyldMemoryManager> mcjmm) {
+ auto SharedMM = std::shared_ptr<RTDyldMemoryManager>(std::move(mcjmm));
+ MemMgr = SharedMM;
+ Resolver = SharedMM;
+ return *this;
+}
+
+EngineBuilder&
+EngineBuilder::setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM) {
+ MemMgr = std::shared_ptr<MCJITMemoryManager>(std::move(MM));
+ return *this;
+}
+
+EngineBuilder&
+EngineBuilder::setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR) {
+ Resolver = std::shared_ptr<RuntimeDyld::SymbolResolver>(std::move(SR));
+ return *this;
+}
+
ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
std::unique_ptr<TargetMachine> TheTM(TM); // Take ownership.
// to the function tells DynamicLibrary to load the program, not a library.
if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, ErrorStr))
return nullptr;
-
- assert(!(JMM && MCJMM));
// If the user specified a memory manager but didn't specify which engine to
// create, we assume they only want the JIT, and we fail if they only want
// the interpreter.
- if (JMM || MCJMM) {
+ if (MemMgr) {
if (WhichEngine & EngineKind::JIT)
WhichEngine = EngineKind::JIT;
else {
return nullptr;
}
}
-
- if (MCJMM && ! UseMCJIT) {
- if (ErrorStr)
- *ErrorStr =
- "Cannot create a legacy JIT with a runtime dyld memory "
- "manager.";
- return nullptr;
- }
// Unless the interpreter was explicitly selected or the JIT is not linked,
// try making a JIT.
}
ExecutionEngine *EE = nullptr;
- if (UseMCJIT && ExecutionEngine::MCJITCtor)
- EE = ExecutionEngine::MCJITCtor(M, ErrorStr, MCJMM ? MCJMM : JMM,
- TheTM.release());
- else if (ExecutionEngine::JITCtor)
- EE = ExecutionEngine::JITCtor(M, ErrorStr, JMM,
- AllocateGVsWithCode, TheTM.release());
+ if (ExecutionEngine::OrcMCJITReplacementCtor && UseOrcMCJITReplacement) {
+ EE = ExecutionEngine::OrcMCJITReplacementCtor(ErrorStr, std::move(MemMgr),
+ std::move(Resolver),
+ std::move(TheTM));
+ EE->addModule(std::move(M));
+ } else if (ExecutionEngine::MCJITCtor)
+ EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MemMgr),
+ std::move(Resolver), std::move(TheTM));
if (EE) {
EE->setVerifyModules(VerifyModules);
// an interpreter instead.
if (WhichEngine & EngineKind::Interpreter) {
if (ExecutionEngine::InterpCtor)
- return ExecutionEngine::InterpCtor(M, ErrorStr);
+ return ExecutionEngine::InterpCtor(std::move(M), ErrorStr);
if (ErrorStr)
*ErrorStr = "Interpreter has not been linked in.";
return nullptr;
}
- if ((WhichEngine & EngineKind::JIT) && !ExecutionEngine::JITCtor &&
- !ExecutionEngine::MCJITCtor) {
+ if ((WhichEngine & EngineKind::JIT) && !ExecutionEngine::MCJITCtor) {
if (ErrorStr)
*ErrorStr = "JIT has not been linked in.";
}
return getPointerToFunction(F);
MutexGuard locked(lock);
- if (void *P = EEState.getGlobalAddressMap()[GV])
+ if (void* P = getPointerToGlobalIfAvailable(GV))
return P;
// Global variable might have been added since interpreter started.
else
llvm_unreachable("Global hasn't had an address allocated yet!");
- return EEState.getGlobalAddressMap()[GV];
+ return getPointerToGlobalIfAvailable(GV);
}
/// \brief Converts a Constant* into a GenericValue, including handling of
Result = PTOGV(getPointerToFunctionOrStub(const_cast<Function*>(F)));
else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
Result = PTOGV(getOrEmitGlobalVariable(const_cast<GlobalVariable*>(GV)));
- else if (const BlockAddress *BA = dyn_cast<BlockAddress>(C))
- Result = PTOGV(getPointerToBasicBlock(const_cast<BasicBlock*>(
- BA->getBasicBlock())));
else
llvm_unreachable("Unknown constant pointer type!");
break;
NumInitBytes += (unsigned)GVSize;
++NumGlobals;
}
-
-ExecutionEngineState::ExecutionEngineState(ExecutionEngine &EE)
- : EE(EE), GlobalAddressMap(this) {
-}
-
-sys::Mutex *
-ExecutionEngineState::AddressMapConfig::getMutex(ExecutionEngineState *EES) {
- return &EES->EE.lock;
-}
-
-void ExecutionEngineState::AddressMapConfig::onDelete(ExecutionEngineState *EES,
- const GlobalValue *Old) {
- void *OldVal = EES->GlobalAddressMap.lookup(Old);
- EES->GlobalAddressReverseMap.erase(OldVal);
-}
-
-void ExecutionEngineState::AddressMapConfig::onRAUW(ExecutionEngineState *,
- const GlobalValue *,
- const GlobalValue *) {
- llvm_unreachable("The ExecutionEngine doesn't know how to handle a"
- " RAUW on a value it has a global mapping for.");
-}