summaryrefslogtreecommitdiff
path: root/llvm/lib/ExecutionEngine
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
commitb60736ec1405bb0a8dd40989f67ef4c93da068ab (patch)
tree5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /llvm/lib/ExecutionEngine
parentcfca06d7963fa0909f90483b42a6d7d194d01e08 (diff)
Diffstat (limited to 'llvm/lib/ExecutionEngine')
-rw-r--r--llvm/lib/ExecutionEngine/ExecutionEngine.cpp15
-rw-r--r--llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp370
-rw-r--r--llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h45
-rw-r--r--llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp334
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h24
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF.cpp66
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp538
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/JITLink.cpp58
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp62
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h16
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp3
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachO.cpp60
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp10
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h4
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp111
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp65
-rw-r--r--llvm/lib/ExecutionEngine/MCJIT/MCJIT.h10
-rw-r--r--llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp76
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Core.cpp2494
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp40
-rw-r--r--llvm/lib/ExecutionEngine/Orc/IRCompileLayer.cpp6
-rw-r--r--llvm/lib/ExecutionEngine/Orc/IRTransformLayer.cpp6
-rw-r--r--llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp21
-rw-r--r--llvm/lib/ExecutionEngine/Orc/LLJIT.cpp182
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Layer.cpp67
-rw-r--r--llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp70
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Legacy.cpp68
-rw-r--r--llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp57
-rw-r--r--llvm/lib/ExecutionEngine/Orc/NullResolver.cpp37
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp335
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ObjectTransformLayer.cpp7
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp158
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h534
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp138
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h502
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp303
-rw-r--r--llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp149
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp (renamed from llvm/lib/ExecutionEngine/OrcError/OrcError.cpp)13
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Shared/RPCError.cpp (renamed from llvm/lib/ExecutionEngine/OrcError/RPCError.cpp)17
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.cpp44
-rw-r--r--llvm/lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp9
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Speculation.cpp7
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.cpp70
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TPCEHFrameRegistrar.cpp80
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp423
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp208
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp43
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TargetProcessControl.cpp153
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ThreadSafeModule.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp12
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp56
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp4
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp39
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h7
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h9
-rw-r--r--llvm/lib/ExecutionEngine/SectionMemoryManager.cpp20
57 files changed, 4705 insertions, 3554 deletions
diff --git a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
index d8bd671c6661..c8bbf0bcdfda 100644
--- a/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -53,11 +53,6 @@ ExecutionEngine *(*ExecutionEngine::MCJITCtor)(
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) = nullptr;
-ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)(
- std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr,
- std::shared_ptr<LegacyJITSymbolResolver> Resolver,
- std::unique_ptr<TargetMachine> TM) = nullptr;
-
ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr) =nullptr;
@@ -476,8 +471,7 @@ 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),
- UseOrcMCJITReplacement(false) {
+ OptLevel(CodeGenOpt::Default), MemMgr(nullptr), Resolver(nullptr) {
// IR module verification is enabled by default in debug builds, and disabled
// by default in release builds.
#ifndef NDEBUG
@@ -540,12 +534,7 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
}
ExecutionEngine *EE = nullptr;
- 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)
+ if (ExecutionEngine::MCJITCtor)
EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MemMgr),
std::move(Resolver), std::move(TheTM));
diff --git a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
index 1ebc820a8b49..3f75012f5cf9 100644
--- a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
+++ b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "IntelJITEventsWrapper.h"
+#include "ittnotify.h"
#include "llvm-c/ExecutionEngine.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -36,6 +37,86 @@ using namespace llvm::object;
namespace {
+class IntelIttnotifyInfo {
+ std::string ModuleName;
+ std::vector<std::string> SectionNamesVector;
+ std::vector<__itt_section_info> SectionInfoVector;
+ __itt_module_object *ModuleObject;
+ IntelJITEventsWrapper &WrapperRef;
+
+public:
+ IntelIttnotifyInfo(IntelJITEventsWrapper &Wrapper)
+ : ModuleObject(NULL), WrapperRef(Wrapper){};
+ ~IntelIttnotifyInfo() { delete ModuleObject; };
+
+ void setModuleName(const char *Name) { ModuleName = std::string(Name); }
+
+ const char *getModuleName() { return ModuleName.c_str(); }
+
+ void setModuleObject(__itt_module_object *ModuleObj) {
+ ModuleObject = ModuleObj;
+ }
+
+ __itt_module_object *getModuleObject() { return ModuleObject; }
+
+ __itt_section_info *getSectionInfoVectorBegin() {
+ if (SectionInfoVector.size())
+ return &SectionInfoVector[0];
+ return NULL;
+ }
+
+ void reportSection(llvm::IttEventType EventType, const char *SectionName,
+ unsigned int SectionSize) {
+ WrapperRef.iJitIttNotifyInfo(EventType, SectionName, SectionSize);
+ }
+
+ int fillSectionInformation(const ObjectFile &Obj,
+ const RuntimeDyld::LoadedObjectInfo &L) {
+
+ int SectionCounter = 0;
+
+ for (auto &Section : Obj.sections()) {
+ uint64_t SectionLoadAddr = L.getSectionLoadAddress(Section);
+ if (SectionLoadAddr) {
+ object::ELFSectionRef ElfSection(Section);
+
+ __itt_section_info SectionInfo;
+ memset(&SectionInfo, 0, sizeof(SectionInfo));
+ SectionInfo.start_addr = reinterpret_cast<void *>(SectionLoadAddr);
+ SectionInfo.file_offset = ElfSection.getOffset();
+ SectionInfo.flags = ElfSection.getFlags();
+
+ StringRef SectionName("");
+ auto SectionNameOrError = ElfSection.getName();
+ if (SectionNameOrError)
+ SectionName = *SectionNameOrError;
+
+ SectionNamesVector.push_back(SectionName.str());
+ SectionInfo.size = ElfSection.getSize();
+ reportSection(llvm::LoadBinarySection, SectionName.str().c_str(),
+ SectionInfo.size);
+
+ if (ElfSection.isBSS()) {
+ SectionInfo.type = itt_section_type_bss;
+ } else if (ElfSection.isData()) {
+ SectionInfo.type = itt_section_type_data;
+ } else if (ElfSection.isText()) {
+ SectionInfo.type = itt_section_type_text;
+ }
+ SectionInfoVector.push_back(SectionInfo);
+ ++SectionCounter;
+ }
+ }
+ // Hereinafter: don't change SectionNamesVector content to avoid vector
+ // reallocation - reallocation invalidates all the references, pointers, and
+ // iterators referring to the elements in the sequence.
+ for (int I = 0; I < SectionCounter; ++I) {
+ SectionInfoVector[I].name = SectionNamesVector[I].c_str();
+ }
+ return SectionCounter;
+ }
+};
+
class IntelJITEventListener : public JITEventListener {
typedef DenseMap<void*, unsigned int> MethodIDMap;
@@ -48,6 +129,8 @@ class IntelJITEventListener : public JITEventListener {
ObjectMap LoadedObjectMap;
std::map<ObjectKey, OwningBinary<ObjectFile>> DebugObjects;
+ std::map<ObjectKey, std::unique_ptr<IntelIttnotifyInfo>> KeyToIttnotify;
+
public:
IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) {
Wrapper.reset(libraryWrapper);
@@ -95,146 +178,205 @@ static iJIT_Method_Load FunctionDescToIntelJITFormat(
return Result;
}
+int getBackwardCompatibilityMode() {
+
+ char *BackwardCompatibilityEnv = getenv("INTEL_JIT_BACKWARD_COMPATIBILITY");
+ int BackwardCompatibilityMode = 0;
+ if (BackwardCompatibilityEnv) {
+ StringRef(BackwardCompatibilityEnv)
+ .getAsInteger(10, BackwardCompatibilityMode);
+ }
+ return BackwardCompatibilityMode;
+}
+
void IntelJITEventListener::notifyObjectLoaded(
ObjectKey Key, const ObjectFile &Obj,
const RuntimeDyld::LoadedObjectInfo &L) {
- OwningBinary<ObjectFile> DebugObjOwner = L.getObjectForDebug(Obj);
- const ObjectFile *DebugObj = DebugObjOwner.getBinary();
- if (!DebugObj)
- return;
+ int BackwardCompatibilityMode = getBackwardCompatibilityMode();
+ if (BackwardCompatibilityMode == 0) {
+ if (Obj.isELF()) {
+ std::unique_ptr<IntelIttnotifyInfo> ModuleIttnotify =
+ std::make_unique<IntelIttnotifyInfo>(*Wrapper);
+ ModuleIttnotify->setModuleName(
+ StringRef(llvm::utohexstr(
+ MD5Hash(Obj.getMemoryBufferRef().getBuffer()), true))
+ .str()
+ .c_str());
- // Get the address of the object image for use as a unique identifier
- const void* ObjData = DebugObj->getData().data();
- std::unique_ptr<DIContext> Context = DWARFContext::create(*DebugObj);
- MethodAddressVector Functions;
+ __itt_module_object *ModuleObject = new __itt_module_object();
+ ModuleObject->module_name = ModuleIttnotify->getModuleName();
+ ModuleObject->module_size = Obj.getMemoryBufferRef().getBufferSize();
+ Wrapper->iJitIttNotifyInfo(llvm::LoadBinaryModule,
+ ModuleObject->module_name,
+ ModuleObject->module_size);
+ ModuleObject->module_type = __itt_module_type_elf;
+ ModuleObject->section_number =
+ ModuleIttnotify->fillSectionInformation(Obj, L);
+ ModuleObject->module_buffer =
+ (void *)const_cast<char *>(Obj.getMemoryBufferRef().getBufferStart());
+ ModuleObject->module_id =
+ __itt_id_make((void *)&(*ModuleObject), ModuleObject->module_size);
+ ModuleObject->section_array =
+ ModuleIttnotify->getSectionInfoVectorBegin();
+ ModuleIttnotify->setModuleObject(ModuleObject);
- // Use symbol info to iterate functions in the object.
- for (const std::pair<SymbolRef, uint64_t> &P : computeSymbolSizes(*DebugObj)) {
- SymbolRef Sym = P.first;
- std::vector<LineNumberInfo> LineInfo;
- std::string SourceFileName;
+ __itt_module_load_with_sections(ModuleObject);
- Expected<SymbolRef::Type> SymTypeOrErr = Sym.getType();
- if (!SymTypeOrErr) {
- // TODO: Actually report errors helpfully.
- consumeError(SymTypeOrErr.takeError());
- continue;
+ KeyToIttnotify[Key] = std::move(ModuleIttnotify);
}
- SymbolRef::Type SymType = *SymTypeOrErr;
- if (SymType != SymbolRef::ST_Function)
- continue;
+ } else if (BackwardCompatibilityMode == 1) {
- Expected<StringRef> Name = Sym.getName();
- if (!Name) {
- // TODO: Actually report errors helpfully.
- consumeError(Name.takeError());
- continue;
- }
+ OwningBinary<ObjectFile> DebugObjOwner = L.getObjectForDebug(Obj);
+ const ObjectFile *DebugObj = DebugObjOwner.getBinary();
+ if (!DebugObj)
+ return;
- Expected<uint64_t> AddrOrErr = Sym.getAddress();
- if (!AddrOrErr) {
- // TODO: Actually report errors helpfully.
- consumeError(AddrOrErr.takeError());
- continue;
- }
- uint64_t Addr = *AddrOrErr;
- uint64_t Size = P.second;
+ // Get the address of the object image for use as a unique identifier
+ const void *ObjData = DebugObj->getData().data();
+ std::unique_ptr<DIContext> Context = DWARFContext::create(*DebugObj);
+ MethodAddressVector Functions;
- auto SecOrErr = Sym.getSection();
- if (!SecOrErr) {
- // TODO: Actually report errors helpfully.
- consumeError(SecOrErr.takeError());
- continue;
- }
- object::section_iterator Sec = *SecOrErr;
- if (Sec == Obj.section_end())
- continue;
- uint64_t Index = Sec->getIndex();
+ // Use symbol info to iterate functions in the object.
+ for (const std::pair<SymbolRef, uint64_t> &P :
+ computeSymbolSizes(*DebugObj)) {
+ SymbolRef Sym = P.first;
+ std::vector<LineNumberInfo> LineInfo;
+ std::string SourceFileName;
- // Record this address in a local vector
- Functions.push_back((void*)Addr);
+ Expected<SymbolRef::Type> SymTypeOrErr = Sym.getType();
+ if (!SymTypeOrErr) {
+ // TODO: Actually report errors helpfully.
+ consumeError(SymTypeOrErr.takeError());
+ continue;
+ }
+ SymbolRef::Type SymType = *SymTypeOrErr;
+ if (SymType != SymbolRef::ST_Function)
+ continue;
- // Build the function loaded notification message
- iJIT_Method_Load FunctionMessage =
- FunctionDescToIntelJITFormat(*Wrapper, Name->data(), Addr, Size);
- DILineInfoTable Lines =
- Context->getLineInfoForAddressRange({Addr, Index}, Size);
- DILineInfoTable::iterator Begin = Lines.begin();
- DILineInfoTable::iterator End = Lines.end();
- for (DILineInfoTable::iterator It = Begin; It != End; ++It) {
- LineInfo.push_back(
- DILineInfoToIntelJITFormat((uintptr_t)Addr, It->first, It->second));
- }
- if (LineInfo.size() == 0) {
- FunctionMessage.source_file_name = 0;
- FunctionMessage.line_number_size = 0;
- FunctionMessage.line_number_table = 0;
- } else {
- // Source line information for the address range is provided as
- // a code offset for the start of the corresponding sub-range and
- // a source line. JIT API treats offsets in LineNumberInfo structures
- // as the end of the corresponding code region. The start of the code
- // is taken from the previous element. Need to shift the elements.
+ Expected<StringRef> Name = Sym.getName();
+ if (!Name) {
+ // TODO: Actually report errors helpfully.
+ consumeError(Name.takeError());
+ continue;
+ }
+
+ Expected<uint64_t> AddrOrErr = Sym.getAddress();
+ if (!AddrOrErr) {
+ // TODO: Actually report errors helpfully.
+ consumeError(AddrOrErr.takeError());
+ continue;
+ }
+ uint64_t Addr = *AddrOrErr;
+ uint64_t Size = P.second;
+
+ auto SecOrErr = Sym.getSection();
+ if (!SecOrErr) {
+ // TODO: Actually report errors helpfully.
+ consumeError(SecOrErr.takeError());
+ continue;
+ }
+ object::section_iterator Sec = *SecOrErr;
+ if (Sec == Obj.section_end())
+ continue;
+ uint64_t Index = Sec->getIndex();
+
+ // Record this address in a local vector
+ Functions.push_back((void *)Addr);
+
+ // Build the function loaded notification message
+ iJIT_Method_Load FunctionMessage =
+ FunctionDescToIntelJITFormat(*Wrapper, Name->data(), Addr, Size);
+ DILineInfoTable Lines =
+ Context->getLineInfoForAddressRange({Addr, Index}, Size);
+ DILineInfoTable::iterator Begin = Lines.begin();
+ DILineInfoTable::iterator End = Lines.end();
+ for (DILineInfoTable::iterator It = Begin; It != End; ++It) {
+ LineInfo.push_back(
+ DILineInfoToIntelJITFormat((uintptr_t)Addr, It->first, It->second));
+ }
+ if (LineInfo.size() == 0) {
+ FunctionMessage.source_file_name = 0;
+ FunctionMessage.line_number_size = 0;
+ FunctionMessage.line_number_table = 0;
+ } else {
+ // Source line information for the address range is provided as
+ // a code offset for the start of the corresponding sub-range and
+ // a source line. JIT API treats offsets in LineNumberInfo structures
+ // as the end of the corresponding code region. The start of the code
+ // is taken from the previous element. Need to shift the elements.
- LineNumberInfo last = LineInfo.back();
- last.Offset = FunctionMessage.method_size;
- LineInfo.push_back(last);
- for (size_t i = LineInfo.size() - 2; i > 0; --i)
- LineInfo[i].LineNumber = LineInfo[i - 1].LineNumber;
+ LineNumberInfo last = LineInfo.back();
+ last.Offset = FunctionMessage.method_size;
+ LineInfo.push_back(last);
+ for (size_t i = LineInfo.size() - 2; i > 0; --i)
+ LineInfo[i].LineNumber = LineInfo[i - 1].LineNumber;
- SourceFileName = Lines.front().second.FileName;
- FunctionMessage.source_file_name =
- const_cast<char *>(SourceFileName.c_str());
- FunctionMessage.line_number_size = LineInfo.size();
- FunctionMessage.line_number_table = &*LineInfo.begin();
+ SourceFileName = Lines.front().second.FileName;
+ FunctionMessage.source_file_name =
+ const_cast<char *>(SourceFileName.c_str());
+ FunctionMessage.line_number_size = LineInfo.size();
+ FunctionMessage.line_number_table = &*LineInfo.begin();
+ }
+
+ Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
+ &FunctionMessage);
+ MethodIDs[(void *)Addr] = FunctionMessage.method_id;
}
- Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
- &FunctionMessage);
- MethodIDs[(void*)Addr] = FunctionMessage.method_id;
+ // To support object unload notification, we need to keep a list of
+ // registered function addresses for each loaded object. We will
+ // use the MethodIDs map to get the registered ID for each function.
+ LoadedObjectMap[ObjData] = Functions;
+ DebugObjects[Key] = std::move(DebugObjOwner);
}
-
- // To support object unload notification, we need to keep a list of
- // registered function addresses for each loaded object. We will
- // use the MethodIDs map to get the registered ID for each function.
- LoadedObjectMap[ObjData] = Functions;
- DebugObjects[Key] = std::move(DebugObjOwner);
}
void IntelJITEventListener::notifyFreeingObject(ObjectKey Key) {
- // This object may not have been registered with the listener. If it wasn't,
- // bail out.
- if (DebugObjects.find(Key) == DebugObjects.end())
- return;
- // Get the address of the object image for use as a unique identifier
- const ObjectFile &DebugObj = *DebugObjects[Key].getBinary();
- const void* ObjData = DebugObj.getData().data();
+ int BackwardCompatibilityMode = getBackwardCompatibilityMode();
+ if (BackwardCompatibilityMode == 0) {
+ if (KeyToIttnotify.find(Key) == KeyToIttnotify.end())
+ return;
+ __itt_module_unload_with_sections(KeyToIttnotify[Key]->getModuleObject());
+ Wrapper->iJitIttNotifyInfo(
+ llvm::UnloadBinaryModule,
+ KeyToIttnotify[Key]->getModuleObject()->module_name,
+ KeyToIttnotify[Key]->getModuleObject()->module_size);
+ KeyToIttnotify.erase(Key);
+ } else if (BackwardCompatibilityMode == 1) {
+ // This object may not have been registered with the listener. If it wasn't,
+ // bail out.
+ if (DebugObjects.find(Key) == DebugObjects.end())
+ return;
+
+ // Get the address of the object image for use as a unique identifier
+ const ObjectFile &DebugObj = *DebugObjects[Key].getBinary();
+ const void *ObjData = DebugObj.getData().data();
- // Get the object's function list from LoadedObjectMap
- ObjectMap::iterator OI = LoadedObjectMap.find(ObjData);
- if (OI == LoadedObjectMap.end())
- return;
- MethodAddressVector& Functions = OI->second;
+ // Get the object's function list from LoadedObjectMap
+ ObjectMap::iterator OI = LoadedObjectMap.find(ObjData);
+ if (OI == LoadedObjectMap.end())
+ return;
+ MethodAddressVector &Functions = OI->second;
- // Walk the function list, unregistering each function
- for (MethodAddressVector::iterator FI = Functions.begin(),
- FE = Functions.end();
- FI != FE;
- ++FI) {
- void* FnStart = const_cast<void*>(*FI);
- MethodIDMap::iterator MI = MethodIDs.find(FnStart);
- if (MI != MethodIDs.end()) {
- Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
- &MI->second);
- MethodIDs.erase(MI);
+ // Walk the function list, unregistering each function
+ for (MethodAddressVector::iterator FI = Functions.begin(),
+ FE = Functions.end();
+ FI != FE; ++FI) {
+ void *FnStart = const_cast<void *>(*FI);
+ MethodIDMap::iterator MI = MethodIDs.find(FnStart);
+ if (MI != MethodIDs.end()) {
+ Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START,
+ &MI->second);
+ MethodIDs.erase(MI);
+ }
}
- }
- // Erase the object from LoadedObjectMap
- LoadedObjectMap.erase(OI);
- DebugObjects.erase(Key);
+ // Erase the object from LoadedObjectMap
+ LoadedObjectMap.erase(OI);
+ DebugObjects.erase(Key);
+ }
}
} // anonymous namespace.
diff --git a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h
index 68699c6a2200..088b33b798a3 100644
--- a/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h
+++ b/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h
@@ -21,10 +21,18 @@
namespace llvm {
+typedef enum {
+ LoadBinaryModule,
+ LoadBinarySection,
+ UnloadBinaryModule,
+ UnloadBinarySection
+} IttEventType;
+
class IntelJITEventsWrapper {
// Function pointer types for testing implementation of Intel jitprofiling
// library
typedef int (*NotifyEventPtr)(iJIT_JVM_EVENT, void*);
+ typedef int (*IttnotifyInfoPtr)(IttEventType, const char *, unsigned int);
typedef void (*RegisterCallbackExPtr)(void *, iJIT_ModeChangedEx );
typedef iJIT_IsProfilingActiveFlags (*IsProfilingActivePtr)(void);
typedef void (*FinalizeThreadPtr)(void);
@@ -32,6 +40,7 @@ class IntelJITEventsWrapper {
typedef unsigned int (*GetNewMethodIDPtr)(void);
NotifyEventPtr NotifyEventFunc;
+ IttnotifyInfoPtr IttnotifyInfoFunc;
RegisterCallbackExPtr RegisterCallbackExFunc;
IsProfilingActivePtr IsProfilingActiveFunc;
GetNewMethodIDPtr GetNewMethodIDFunc;
@@ -42,23 +51,22 @@ public:
}
IntelJITEventsWrapper()
- : NotifyEventFunc(::iJIT_NotifyEvent),
- RegisterCallbackExFunc(::iJIT_RegisterCallbackEx),
- IsProfilingActiveFunc(::iJIT_IsProfilingActive),
- GetNewMethodIDFunc(::iJIT_GetNewMethodID) {
- }
+ : NotifyEventFunc(::iJIT_NotifyEvent), IttnotifyInfoFunc(0),
+ RegisterCallbackExFunc(::iJIT_RegisterCallbackEx),
+ IsProfilingActiveFunc(::iJIT_IsProfilingActive),
+ GetNewMethodIDFunc(::iJIT_GetNewMethodID) {}
IntelJITEventsWrapper(NotifyEventPtr NotifyEventImpl,
- RegisterCallbackExPtr RegisterCallbackExImpl,
- IsProfilingActivePtr IsProfilingActiveImpl,
- FinalizeThreadPtr FinalizeThreadImpl,
- FinalizeProcessPtr FinalizeProcessImpl,
- GetNewMethodIDPtr GetNewMethodIDImpl)
- : NotifyEventFunc(NotifyEventImpl),
- RegisterCallbackExFunc(RegisterCallbackExImpl),
- IsProfilingActiveFunc(IsProfilingActiveImpl),
- GetNewMethodIDFunc(GetNewMethodIDImpl) {
- }
+ IttnotifyInfoPtr IttnotifyInfoImpl,
+ RegisterCallbackExPtr RegisterCallbackExImpl,
+ IsProfilingActivePtr IsProfilingActiveImpl,
+ FinalizeThreadPtr FinalizeThreadImpl,
+ FinalizeProcessPtr FinalizeProcessImpl,
+ GetNewMethodIDPtr GetNewMethodIDImpl)
+ : NotifyEventFunc(NotifyEventImpl), IttnotifyInfoFunc(IttnotifyInfoImpl),
+ RegisterCallbackExFunc(RegisterCallbackExImpl),
+ IsProfilingActiveFunc(IsProfilingActiveImpl),
+ GetNewMethodIDFunc(GetNewMethodIDImpl) {}
// Sends an event announcing that a function has been emitted
// return values are event-specific. See Intel documentation for details.
@@ -68,6 +76,13 @@ public:
return NotifyEventFunc(EventType, EventSpecificData);
}
+ int iJitIttNotifyInfo(IttEventType EventType, const char *Name,
+ unsigned int Size) {
+ if (!IttnotifyInfoFunc)
+ return -1;
+ return IttnotifyInfoFunc(EventType, Name, Size);
+ }
+
// Registers a callback function to receive notice of profiling state changes
void iJIT_RegisterCallbackEx(void *UserData,
iJIT_ModeChangedEx NewModeCallBackFuncEx) {
diff --git a/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
index cb1b35d62388..3aa77557862e 100644
--- a/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
+++ b/llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
@@ -419,7 +419,7 @@ static GenericValue lle_X_printf(FunctionType *FT,
char Buffer[10000];
std::vector<GenericValue> NewArgs;
NewArgs.push_back(PTOGV((void*)&Buffer[0]));
- NewArgs.insert(NewArgs.end(), Args.begin(), Args.end());
+ llvm::append_range(NewArgs, Args);
GenericValue GV = lle_X_sprintf(FT, NewArgs);
outs() << Buffer;
return GV;
diff --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
index f1114e92c360..3602601287f4 100644
--- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
@@ -10,6 +10,8 @@
#include "EHFrameSupportImpl.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Config/config.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
#include "llvm/Support/DynamicLibrary.h"
#define DEBUG_TYPE "jitlink"
@@ -117,10 +119,10 @@ Error EHFrameSplitter::processBlock(LinkGraph &G, Block &B,
}
EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName,
- Edge::Kind FDEToCIE, Edge::Kind FDEToPCBegin,
- Edge::Kind FDEToLSDA)
- : EHFrameSectionName(EHFrameSectionName), FDEToCIE(FDEToCIE),
- FDEToPCBegin(FDEToPCBegin), FDEToLSDA(FDEToLSDA) {}
+ unsigned PointerSize, Edge::Kind Delta64,
+ Edge::Kind Delta32, Edge::Kind NegDelta32)
+ : EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize),
+ Delta64(Delta64), Delta32(Delta32), NegDelta32(NegDelta32) {}
Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
auto *EHFrame = G.findSectionByName(EHFrameSectionName);
@@ -133,6 +135,11 @@ Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
return Error::success();
}
+ // Check that we support the graph's pointer size.
+ if (G.getPointerSize() != 4 && G.getPointerSize() != 8)
+ return make_error<JITLinkError>(
+ "EHFrameEdgeFixer only supports 32 and 64 bit targets");
+
LLVM_DEBUG({
dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << "...\n";
});
@@ -257,7 +264,6 @@ Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
size_t RecordOffset, size_t RecordLength,
size_t CIEDeltaFieldOffset) {
- using namespace dwarf;
LLVM_DEBUG(dbgs() << " Record is CIE\n");
@@ -328,11 +334,12 @@ Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
uint8_t LSDAPointerEncoding;
if (auto Err = RecordReader.readInteger(LSDAPointerEncoding))
return Err;
- if (LSDAPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr))
+ if (!isSupportedPointerEncoding(LSDAPointerEncoding))
return make_error<JITLinkError>(
"Unsupported LSDA pointer encoding " +
formatv("{0:x2}", LSDAPointerEncoding) + " in CIE at " +
formatv("{0:x16}", CIESymbol.getAddress()));
+ CIEInfo.LSDAPointerEncoding = LSDAPointerEncoding;
break;
}
case 'P': {
@@ -340,7 +347,8 @@ Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
if (auto Err = RecordReader.readInteger(PersonalityPointerEncoding))
return Err;
if (PersonalityPointerEncoding !=
- (DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4))
+ (dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+ dwarf::DW_EH_PE_sdata4))
return make_error<JITLinkError>(
"Unspported personality pointer "
"encoding " +
@@ -355,12 +363,12 @@ Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
uint8_t FDEPointerEncoding;
if (auto Err = RecordReader.readInteger(FDEPointerEncoding))
return Err;
- if (FDEPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr))
+ if (!isSupportedPointerEncoding(FDEPointerEncoding))
return make_error<JITLinkError>(
- "Unsupported FDE address pointer "
- "encoding " +
+ "Unsupported FDE pointer encoding " +
formatv("{0:x2}", FDEPointerEncoding) + " in CIE at " +
formatv("{0:x16}", CIESymbol.getAddress()));
+ CIEInfo.FDEPointerEncoding = FDEPointerEncoding;
break;
}
default:
@@ -417,7 +425,7 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
else
return CIEInfoOrErr.takeError();
assert(CIEInfo->CIESymbol && "CIEInfo has no CIE symbol set");
- B.addEdge(FDEToCIE, RecordOffset + CIEDeltaFieldOffset,
+ B.addEdge(NegDelta32, RecordOffset + CIEDeltaFieldOffset,
*CIEInfo->CIESymbol, 0);
} else {
LLVM_DEBUG({
@@ -444,11 +452,13 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
JITTargetAddress PCBeginFieldOffset = RecordReader.getOffset();
auto PCEdgeItr = BlockEdges.find(RecordOffset + PCBeginFieldOffset);
if (PCEdgeItr == BlockEdges.end()) {
- auto PCBeginDelta = readAbsolutePointer(PC.G, RecordReader);
- if (!PCBeginDelta)
- return PCBeginDelta.takeError();
- JITTargetAddress PCBegin =
- RecordAddress + PCBeginFieldOffset + *PCBeginDelta;
+ auto PCBeginPtrInfo =
+ readEncodedPointer(CIEInfo->FDEPointerEncoding,
+ RecordAddress + PCBeginFieldOffset, RecordReader);
+ if (!PCBeginPtrInfo)
+ return PCBeginPtrInfo.takeError();
+ JITTargetAddress PCBegin = PCBeginPtrInfo->first;
+ Edge::Kind PCBeginEdgeKind = PCBeginPtrInfo->second;
LLVM_DEBUG({
dbgs() << " Adding edge at "
<< formatv("{0:x16}", RecordAddress + PCBeginFieldOffset)
@@ -457,7 +467,7 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
auto PCBeginSym = getOrCreateSymbol(PC, PCBegin);
if (!PCBeginSym)
return PCBeginSym.takeError();
- B.addEdge(FDEToPCBegin, RecordOffset + PCBeginFieldOffset, *PCBeginSym,
+ B.addEdge(PCBeginEdgeKind, RecordOffset + PCBeginFieldOffset, *PCBeginSym,
0);
PCBeginBlock = &PCBeginSym->getBlock();
} else {
@@ -479,38 +489,42 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
" points at external block");
}
PCBeginBlock = &EI.Target->getBlock();
- if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
+ if (auto Err = RecordReader.skip(
+ getPointerEncodingDataSize(CIEInfo->FDEPointerEncoding)))
return Err;
}
// Add a keep-alive edge from the FDE target to the FDE to ensure that the
// FDE is kept alive if its target is.
assert(PCBeginBlock && "PC-begin block not recorded");
+ LLVM_DEBUG({
+ dbgs() << " Adding keep-alive edge from target at "
+ << formatv("{0:x16}", PCBeginBlock->getAddress()) << " to FDE at "
+ << formatv("{0:x16}", RecordAddress) << "\n";
+ });
PCBeginBlock->addEdge(Edge::KeepAlive, 0, FDESymbol, 0);
}
// Skip over the PC range size field.
- if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
+ if (auto Err = RecordReader.skip(
+ getPointerEncodingDataSize(CIEInfo->FDEPointerEncoding)))
return Err;
if (CIEInfo->FDEsHaveLSDAField) {
uint64_t AugmentationDataSize;
if (auto Err = RecordReader.readULEB128(AugmentationDataSize))
return Err;
- if (AugmentationDataSize != PC.G.getPointerSize())
- return make_error<JITLinkError>(
- "Unexpected FDE augmentation data size (expected " +
- Twine(PC.G.getPointerSize()) + ", got " +
- Twine(AugmentationDataSize) + ") for FDE at " +
- formatv("{0:x16}", RecordAddress));
JITTargetAddress LSDAFieldOffset = RecordReader.getOffset();
auto LSDAEdgeItr = BlockEdges.find(RecordOffset + LSDAFieldOffset);
if (LSDAEdgeItr == BlockEdges.end()) {
- auto LSDADelta = readAbsolutePointer(PC.G, RecordReader);
- if (!LSDADelta)
- return LSDADelta.takeError();
- JITTargetAddress LSDA = RecordAddress + LSDAFieldOffset + *LSDADelta;
+ auto LSDAPointerInfo =
+ readEncodedPointer(CIEInfo->LSDAPointerEncoding,
+ RecordAddress + LSDAFieldOffset, RecordReader);
+ if (!LSDAPointerInfo)
+ return LSDAPointerInfo.takeError();
+ JITTargetAddress LSDA = LSDAPointerInfo->first;
+ Edge::Kind LSDAEdgeKind = LSDAPointerInfo->second;
auto LSDASym = getOrCreateSymbol(PC, LSDA);
if (!LSDASym)
return LSDASym.takeError();
@@ -519,7 +533,7 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
<< formatv("{0:x16}", RecordAddress + LSDAFieldOffset)
<< " to LSDA at " << formatv("{0:x16}", LSDA) << "\n";
});
- B.addEdge(FDEToLSDA, RecordOffset + LSDAFieldOffset, *LSDASym, 0);
+ B.addEdge(LSDAEdgeKind, RecordOffset + LSDAFieldOffset, *LSDASym, 0);
} else {
LLVM_DEBUG({
auto &EI = LSDAEdgeItr->second;
@@ -530,7 +544,7 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
dbgs() << " + " << formatv("{0:x16}", EI.Addend);
dbgs() << "\n";
});
- if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
+ if (auto Err = RecordReader.skip(AugmentationDataSize))
return Err;
}
} else {
@@ -581,23 +595,110 @@ EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
return std::move(AugInfo);
}
-Expected<JITTargetAddress>
-EHFrameEdgeFixer::readAbsolutePointer(LinkGraph &G,
- BinaryStreamReader &RecordReader) {
+bool EHFrameEdgeFixer::isSupportedPointerEncoding(uint8_t PointerEncoding) {
+ using namespace dwarf;
+
+ // We only support PC-rel for now.
+ if ((PointerEncoding & 0x70) != DW_EH_PE_pcrel)
+ return false;
+
+ // readEncodedPointer does not handle indirect.
+ if (PointerEncoding & DW_EH_PE_indirect)
+ return false;
+
+ // Supported datatypes.
+ switch (PointerEncoding & 0xf) {
+ case DW_EH_PE_absptr:
+ case DW_EH_PE_udata4:
+ case DW_EH_PE_udata8:
+ case DW_EH_PE_sdata4:
+ case DW_EH_PE_sdata8:
+ return true;
+ }
+
+ return false;
+}
+
+unsigned EHFrameEdgeFixer::getPointerEncodingDataSize(uint8_t PointerEncoding) {
+ using namespace dwarf;
+
+ assert(isSupportedPointerEncoding(PointerEncoding) &&
+ "Unsupported pointer encoding");
+ switch (PointerEncoding & 0xf) {
+ case DW_EH_PE_absptr:
+ return PointerSize;
+ case DW_EH_PE_udata4:
+ case DW_EH_PE_sdata4:
+ return 4;
+ case DW_EH_PE_udata8:
+ case DW_EH_PE_sdata8:
+ return 8;
+ default:
+ llvm_unreachable("Unsupported encoding");
+ }
+}
+
+Expected<std::pair<JITTargetAddress, Edge::Kind>>
+EHFrameEdgeFixer::readEncodedPointer(uint8_t PointerEncoding,
+ JITTargetAddress PointerFieldAddress,
+ BinaryStreamReader &RecordReader) {
static_assert(sizeof(JITTargetAddress) == sizeof(uint64_t),
"Result must be able to hold a uint64_t");
+ assert(isSupportedPointerEncoding(PointerEncoding) &&
+ "Unsupported pointer encoding");
+
+ using namespace dwarf;
+
+ // Isolate data type, remap absptr to udata4 or udata8. This relies on us
+ // having verified that the graph uses 32-bit or 64-bit pointers only at the
+ // start of this pass.
+ uint8_t EffectiveType = PointerEncoding & 0xf;
+ if (EffectiveType == DW_EH_PE_absptr)
+ EffectiveType = (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
+
JITTargetAddress Addr;
- if (G.getPointerSize() == 8) {
- if (auto Err = RecordReader.readInteger(Addr))
+ Edge::Kind PointerEdgeKind;
+ switch (EffectiveType) {
+ case DW_EH_PE_udata4: {
+ uint32_t Val;
+ if (auto Err = RecordReader.readInteger(Val))
+ return std::move(Err);
+ Addr = PointerFieldAddress + Val;
+ PointerEdgeKind = Delta32;
+ break;
+ }
+ case DW_EH_PE_udata8: {
+ uint64_t Val;
+ if (auto Err = RecordReader.readInteger(Val))
return std::move(Err);
- } else if (G.getPointerSize() == 4) {
- uint32_t Addr32;
- if (auto Err = RecordReader.readInteger(Addr32))
+ Addr = PointerFieldAddress + Val;
+ PointerEdgeKind = Delta64;
+ break;
+ }
+ case DW_EH_PE_sdata4: {
+ int32_t Val;
+ if (auto Err = RecordReader.readInteger(Val))
return std::move(Err);
- Addr = Addr32;
- } else
- llvm_unreachable("Pointer size is not 32-bit or 64-bit");
- return Addr;
+ Addr = PointerFieldAddress + Val;
+ PointerEdgeKind = Delta32;
+ break;
+ }
+ case DW_EH_PE_sdata8: {
+ int64_t Val;
+ if (auto Err = RecordReader.readInteger(Val))
+ return std::move(Err);
+ Addr = PointerFieldAddress + Val;
+ PointerEdgeKind = Delta64;
+ break;
+ }
+ }
+
+ if (PointerEdgeKind == Edge::Invalid)
+ return make_error<JITLinkError>(
+ "Unspported edge kind for encoded pointer at " +
+ formatv("{0:x}", PointerFieldAddress));
+
+ return std::make_pair(Addr, Delta64);
}
Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
@@ -629,146 +730,21 @@ Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
return PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);
}
-// Determine whether we can register EH tables.
-#if (defined(__GNUC__) && !defined(__ARM_EABI__) && !defined(__ia64__) && \
- !(defined(_AIX) && defined(__ibmxl__)) && !defined(__SEH__) && \
- !defined(__USING_SJLJ_EXCEPTIONS__))
-#define HAVE_EHTABLE_SUPPORT 1
-#else
-#define HAVE_EHTABLE_SUPPORT 0
-#endif
-
-#if HAVE_EHTABLE_SUPPORT
-extern "C" void __register_frame(const void *);
-extern "C" void __deregister_frame(const void *);
-
-Error registerFrameWrapper(const void *P) {
- __register_frame(P);
- return Error::success();
-}
-
-Error deregisterFrameWrapper(const void *P) {
- __deregister_frame(P);
- return Error::success();
-}
-
-#else
-
-// The building compiler does not have __(de)register_frame but
-// it may be found at runtime in a dynamically-loaded library.
-// For example, this happens when building LLVM with Visual C++
-// but using the MingW runtime.
-static Error registerFrameWrapper(const void *P) {
- static void((*RegisterFrame)(const void *)) = 0;
-
- if (!RegisterFrame)
- *(void **)&RegisterFrame =
- llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
-
- if (RegisterFrame) {
- RegisterFrame(P);
- return Error::success();
- }
-
- return make_error<JITLinkError>("could not register eh-frame: "
- "__register_frame function not found");
-}
-
-static Error deregisterFrameWrapper(const void *P) {
- static void((*DeregisterFrame)(const void *)) = 0;
-
- if (!DeregisterFrame)
- *(void **)&DeregisterFrame =
- llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
- "__deregister_frame");
-
- if (DeregisterFrame) {
- DeregisterFrame(P);
- return Error::success();
- }
-
- return make_error<JITLinkError>("could not deregister eh-frame: "
- "__deregister_frame function not found");
-}
-#endif
-
-#ifdef __APPLE__
-
-template <typename HandleFDEFn>
-Error walkAppleEHFrameSection(const char *const SectionStart,
- size_t SectionSize,
- HandleFDEFn HandleFDE) {
- const char *CurCFIRecord = SectionStart;
- const char *End = SectionStart + SectionSize;
- uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
-
- while (CurCFIRecord != End && Size != 0) {
- const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
- if (Size == 0xffffffff)
- Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
- else
- Size += 4;
- uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
-
- LLVM_DEBUG({
- dbgs() << "Registering eh-frame section:\n";
- dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
- << (void *)CurCFIRecord << ": [";
- for (unsigned I = 0; I < Size; ++I)
- dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
- dbgs() << " ]\n";
- });
-
- if (Offset != 0)
- if (auto Err = HandleFDE(CurCFIRecord))
- return Err;
-
- CurCFIRecord += Size;
-
- Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
- }
-
- return Error::success();
-}
-
-#endif // __APPLE__
-
-Error registerEHFrameSection(const void *EHFrameSectionAddr,
- size_t EHFrameSectionSize) {
-#ifdef __APPLE__
- // On Darwin __register_frame has to be called for each FDE entry.
- return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
- EHFrameSectionSize,
- registerFrameWrapper);
-#else
- // On Linux __register_frame takes a single argument:
- // a pointer to the start of the .eh_frame section.
-
- // How can it find the end? Because crtendS.o is linked
- // in and it has an .eh_frame section with four zero chars.
- return registerFrameWrapper(EHFrameSectionAddr);
-#endif
-}
-
-Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
- size_t EHFrameSectionSize) {
-#ifdef __APPLE__
- return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
- EHFrameSectionSize,
- deregisterFrameWrapper);
-#else
- return deregisterFrameWrapper(EHFrameSectionAddr);
-#endif
-}
-
EHFrameRegistrar::~EHFrameRegistrar() {}
-InProcessEHFrameRegistrar &InProcessEHFrameRegistrar::getInstance() {
- static InProcessEHFrameRegistrar Instance;
- return Instance;
+Error InProcessEHFrameRegistrar::registerEHFrames(
+ JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
+ return orc::registerEHFrameSection(
+ jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
+ EHFrameSectionSize);
}
-InProcessEHFrameRegistrar::InProcessEHFrameRegistrar() {}
+Error InProcessEHFrameRegistrar::deregisterEHFrames(
+ JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
+ return orc::deregisterEHFrameSection(
+ jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
+ EHFrameSectionSize);
+}
LinkGraphPassFunction
createEHFrameRecorderPass(const Triple &TT,
diff --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
index a8cd32c664dc..5e68e72ba18d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
+++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
@@ -40,8 +40,9 @@ private:
/// edges.
class EHFrameEdgeFixer {
public:
- EHFrameEdgeFixer(StringRef EHFrameSectionName, Edge::Kind FDEToCIE,
- Edge::Kind FDEToPCBegin, Edge::Kind FDEToLSDA);
+ EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize,
+ Edge::Kind Delta64, Edge::Kind Delta32,
+ Edge::Kind NegDelta32);
Error operator()(LinkGraph &G);
private:
@@ -57,6 +58,8 @@ private:
CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {}
Symbol *CIESymbol = nullptr;
bool FDEsHaveLSDAField = false;
+ uint8_t FDEPointerEncoding = 0;
+ uint8_t LSDAPointerEncoding = 0;
};
struct EdgeTarget {
@@ -96,14 +99,21 @@ private:
Expected<AugmentationInfo>
parseAugmentationString(BinaryStreamReader &RecordReader);
- Expected<JITTargetAddress>
- readAbsolutePointer(LinkGraph &G, BinaryStreamReader &RecordReader);
+
+ static bool isSupportedPointerEncoding(uint8_t PointerEncoding);
+ unsigned getPointerEncodingDataSize(uint8_t PointerEncoding);
+ Expected<std::pair<JITTargetAddress, Edge::Kind>>
+ readEncodedPointer(uint8_t PointerEncoding,
+ JITTargetAddress PointerFieldAddress,
+ BinaryStreamReader &RecordReader);
+
Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, JITTargetAddress Addr);
StringRef EHFrameSectionName;
- Edge::Kind FDEToCIE;
- Edge::Kind FDEToPCBegin;
- Edge::Kind FDEToLSDA;
+ unsigned PointerSize;
+ Edge::Kind Delta64;
+ Edge::Kind Delta32;
+ Edge::Kind NegDelta32;
};
} // end namespace jitlink
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
index 6160583b13fe..27eb7d576e2d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
@@ -15,6 +15,7 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
+#include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -27,24 +28,63 @@ using namespace llvm;
namespace llvm {
namespace jitlink {
-void jitLink_ELF(std::unique_ptr<JITLinkContext> Ctx) {
+Expected<uint16_t> readTargetMachineArch(StringRef Buffer) {
+ const char *Data = Buffer.data();
- // We don't want to do full ELF validation here. We just verify it is elf'ish.
- // Probably should parse into an elf header when we support more than x86 :)
-
- StringRef Data = Ctx->getObjectBuffer().getBuffer();
- if (Data.size() < llvm::ELF::EI_MAG3 + 1) {
- Ctx->notifyFailed(make_error<JITLinkError>("Truncated ELF buffer"));
- return;
+ if (Data[ELF::EI_DATA] == ELF::ELFDATA2LSB) {
+ if (Data[ELF::EI_CLASS] == ELF::ELFCLASS64) {
+ if (auto File = llvm::object::ELF64LEFile::create(Buffer)) {
+ return File->getHeader().e_machine;
+ } else {
+ return File.takeError();
+ }
+ } else if (Data[ELF::EI_CLASS] == ELF::ELFCLASS32) {
+ if (auto File = llvm::object::ELF32LEFile::create(Buffer)) {
+ return File->getHeader().e_machine;
+ } else {
+ return File.takeError();
+ }
+ }
}
- if (!memcmp(Data.data(), llvm::ELF::ElfMagic, strlen(llvm::ELF::ElfMagic))) {
- if (Data.data()[llvm::ELF::EI_CLASS] == ELF::ELFCLASS64) {
- return jitLink_ELF_x86_64(std::move(Ctx));
- }
+ return ELF::EM_NONE;
+}
+
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
+ StringRef Buffer = ObjectBuffer.getBuffer();
+ if (Buffer.size() < ELF::EI_MAG3 + 1)
+ return make_error<JITLinkError>("Truncated ELF buffer");
+
+ if (memcmp(Buffer.data(), ELF::ElfMagic, strlen(ELF::ElfMagic)) != 0)
+ return make_error<JITLinkError>("ELF magic not valid");
+
+ Expected<uint16_t> TargetMachineArch = readTargetMachineArch(Buffer);
+ if (!TargetMachineArch)
+ return TargetMachineArch.takeError();
+
+ switch (*TargetMachineArch) {
+ case ELF::EM_X86_64:
+ return createLinkGraphFromELFObject_x86_64(std::move(ObjectBuffer));
+ default:
+ return make_error<JITLinkError>(
+ "Unsupported target machine architecture in ELF object " +
+ ObjectBuffer.getBufferIdentifier());
}
+}
- Ctx->notifyFailed(make_error<JITLinkError>("ELF magic not valid"));
+void link_ELF(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+ switch (G->getTargetTriple().getArch()) {
+ case Triple::x86_64:
+ link_ELF_x86_64(std::move(G), std::move(Ctx));
+ return;
+ default:
+ Ctx->notifyFailed(make_error<JITLinkError>(
+ "Unsupported target machine architecture in ELF link graph " +
+ G->getName()));
+ return;
+ }
}
} // end namespace jitlink
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
index 505f03590b6b..2a6b3eb19ded 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
@@ -11,16 +11,204 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
-#include "JITLinkGeneric.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/Endian.h"
+
+#include "BasicGOTAndStubsBuilder.h"
+#include "EHFrameSupportImpl.h"
+#include "JITLinkGeneric.h"
#define DEBUG_TYPE "jitlink"
using namespace llvm;
using namespace llvm::jitlink;
+using namespace llvm::jitlink::ELF_x86_64_Edges;
+
+namespace {
+
+class ELF_x86_64_GOTAndStubsBuilder
+ : public BasicGOTAndStubsBuilder<ELF_x86_64_GOTAndStubsBuilder> {
+public:
+ static const uint8_t NullGOTEntryContent[8];
+ static const uint8_t StubContent[6];
+
+ ELF_x86_64_GOTAndStubsBuilder(LinkGraph &G)
+ : BasicGOTAndStubsBuilder<ELF_x86_64_GOTAndStubsBuilder>(G) {}
+
+ bool isGOTEdge(Edge &E) const {
+ return E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad;
+ }
+
+ Symbol &createGOTEntry(Symbol &Target) {
+ auto &GOTEntryBlock = G.createContentBlock(
+ getGOTSection(), getGOTEntryBlockContent(), 0, 8, 0);
+ GOTEntryBlock.addEdge(Pointer64, 0, Target, 0);
+ return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false);
+ }
+
+ void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
+ assert((E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad) &&
+ "Not a GOT edge?");
+ // If this is a PCRel32GOT then change it to an ordinary PCRel32. If it is
+ // a PCRel32GOTLoad then leave it as-is for now. We will use the kind to
+ // check for GOT optimization opportunities in the
+ // optimizeMachO_x86_64_GOTAndStubs pass below.
+ if (E.getKind() == PCRel32GOT)
+ E.setKind(PCRel32);
+
+ E.setTarget(GOTEntry);
+ // Leave the edge addend as-is.
+ }
+
+ bool isExternalBranchEdge(Edge &E) {
+ return E.getKind() == Branch32 && !E.getTarget().isDefined();
+ }
+
+ Symbol &createStub(Symbol &Target) {
+ auto &StubContentBlock =
+ G.createContentBlock(getStubsSection(), getStubBlockContent(), 0, 1, 0);
+ // Re-use GOT entries for stub targets.
+ auto &GOTEntrySymbol = getGOTEntrySymbol(Target);
+ StubContentBlock.addEdge(PCRel32, 2, GOTEntrySymbol, -4);
+ return G.addAnonymousSymbol(StubContentBlock, 0, 6, true, false);
+ }
+
+ void fixExternalBranchEdge(Edge &E, Symbol &Stub) {
+ assert(E.getKind() == Branch32 && "Not a Branch32 edge?");
+
+ // Set the edge kind to Branch32ToStub. We will use this to check for stub
+ // optimization opportunities in the optimize ELF_x86_64_GOTAndStubs pass
+ // below.
+ E.setKind(Branch32ToStub);
+ E.setTarget(Stub);
+ }
+
+private:
+ Section &getGOTSection() {
+ if (!GOTSection)
+ GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ);
+ return *GOTSection;
+ }
+
+ Section &getStubsSection() {
+ if (!StubsSection) {
+ auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
+ sys::Memory::MF_READ | sys::Memory::MF_EXEC);
+ StubsSection = &G.createSection("$__STUBS", StubsProt);
+ }
+ return *StubsSection;
+ }
+
+ StringRef getGOTEntryBlockContent() {
+ return StringRef(reinterpret_cast<const char *>(NullGOTEntryContent),
+ sizeof(NullGOTEntryContent));
+ }
+
+ StringRef getStubBlockContent() {
+ return StringRef(reinterpret_cast<const char *>(StubContent),
+ sizeof(StubContent));
+ }
+
+ Section *GOTSection = nullptr;
+ Section *StubsSection = nullptr;
+};
+
+const char *const DwarfSectionNames[] = {
+#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
+ ELF_NAME,
+#include "llvm/BinaryFormat/Dwarf.def"
+#undef HANDLE_DWARF_SECTION
+};
+
+} // namespace
+
+const uint8_t ELF_x86_64_GOTAndStubsBuilder::NullGOTEntryContent[8] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+const uint8_t ELF_x86_64_GOTAndStubsBuilder::StubContent[6] = {
+ 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
static const char *CommonSectionName = "__common";
+static Error optimizeELF_x86_64_GOTAndStubs(LinkGraph &G) {
+ LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n");
+
+ for (auto *B : G.blocks())
+ for (auto &E : B->edges())
+ if (E.getKind() == PCRel32GOTLoad) {
+ // Replace GOT load with LEA only for MOVQ instructions.
+ constexpr uint8_t MOVQRIPRel[] = {0x48, 0x8b};
+ if (E.getOffset() < 3 ||
+ strncmp(B->getContent().data() + E.getOffset() - 3,
+ reinterpret_cast<const char *>(MOVQRIPRel), 2) != 0)
+ continue;
+
+ auto &GOTBlock = E.getTarget().getBlock();
+ assert(GOTBlock.getSize() == G.getPointerSize() &&
+ "GOT entry block should be pointer sized");
+ assert(GOTBlock.edges_size() == 1 &&
+ "GOT entry should only have one outgoing edge");
+
+ auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
+ JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset();
+ JITTargetAddress TargetAddr = GOTTarget.getAddress();
+
+ int64_t Displacement = TargetAddr - EdgeAddr + 4;
+ if (Displacement >= std::numeric_limits<int32_t>::min() &&
+ Displacement <= std::numeric_limits<int32_t>::max()) {
+ // Change the edge kind as we don't go through GOT anymore. This is
+ // for formal correctness only. Technically, the two relocation kinds
+ // are resolved the same way.
+ E.setKind(PCRel32);
+ E.setTarget(GOTTarget);
+ auto *BlockData = reinterpret_cast<uint8_t *>(
+ const_cast<char *>(B->getContent().data()));
+ BlockData[E.getOffset() - 2] = 0x8d;
+ LLVM_DEBUG({
+ dbgs() << " Replaced GOT load wih LEA:\n ";
+ printEdge(dbgs(), *B, E, getELFX86RelocationKindName(E.getKind()));
+ dbgs() << "\n";
+ });
+ }
+ } else if (E.getKind() == Branch32ToStub) {
+ auto &StubBlock = E.getTarget().getBlock();
+ assert(StubBlock.getSize() ==
+ sizeof(ELF_x86_64_GOTAndStubsBuilder::StubContent) &&
+ "Stub block should be stub sized");
+ assert(StubBlock.edges_size() == 1 &&
+ "Stub block should only have one outgoing edge");
+
+ auto &GOTBlock = StubBlock.edges().begin()->getTarget().getBlock();
+ assert(GOTBlock.getSize() == G.getPointerSize() &&
+ "GOT block should be pointer sized");
+ assert(GOTBlock.edges_size() == 1 &&
+ "GOT block should only have one outgoing edge");
+
+ auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
+ JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset();
+ JITTargetAddress TargetAddr = GOTTarget.getAddress();
+
+ int64_t Displacement = TargetAddr - EdgeAddr + 4;
+ if (Displacement >= std::numeric_limits<int32_t>::min() &&
+ Displacement <= std::numeric_limits<int32_t>::max()) {
+ E.setKind(Branch32);
+ E.setTarget(GOTTarget);
+ LLVM_DEBUG({
+ dbgs() << " Replaced stub branch with direct branch:\n ";
+ printEdge(dbgs(), *B, E, getELFX86RelocationKindName(E.getKind()));
+ dbgs() << "\n";
+ });
+ }
+ }
+
+ return Error::success();
+}
+
+static bool isDwarfSection(StringRef SectionName) {
+ for (auto &DwarfSectionName : DwarfSectionNames)
+ if (SectionName == DwarfSectionName)
+ return true;
+ return false;
+}
namespace llvm {
namespace jitlink {
@@ -35,7 +223,8 @@ private:
// Find a better way
using SymbolTable = object::ELFFile<object::ELF64LE>::Elf_Shdr;
// For now we just assume
- std::map<int32_t, Symbol *> JITSymbolTable;
+ using SymbolMap = std::map<int32_t, Symbol *>;
+ SymbolMap JITSymbolTable;
Section &getCommonSection() {
if (!CommonSection) {
@@ -51,6 +240,16 @@ private:
switch (Type) {
case ELF::R_X86_64_PC32:
return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32;
+ case ELF::R_X86_64_PC64:
+ return ELF_x86_64_Edges::ELFX86RelocationKind::Delta64;
+ case ELF::R_X86_64_64:
+ return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer64;
+ case ELF::R_X86_64_GOTPCREL:
+ case ELF::R_X86_64_GOTPCRELX:
+ case ELF::R_X86_64_REX_GOTPCRELX:
+ return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32GOTLoad;
+ case ELF::R_X86_64_PLT32:
+ return ELF_x86_64_Edges::ELFX86RelocationKind::Branch32;
}
return make_error<JITLinkError>("Unsupported x86-64 relocation:" +
formatv("{0:d}", Type));
@@ -62,7 +261,7 @@ private:
object::ELFFile<object::ELF64LE>::Elf_Shdr_Range sections;
SymbolTable SymTab;
- bool isRelocatable() { return Obj.getHeader()->e_type == llvm::ELF::ET_REL; }
+ bool isRelocatable() { return Obj.getHeader().e_type == llvm::ELF::ET_REL; }
support::endianness
getEndianness(const object::ELFFile<object::ELF64LE> &Obj) {
@@ -71,7 +270,7 @@ private:
// This could also just become part of a template
unsigned getPointerSize(const object::ELFFile<object::ELF64LE> &Obj) {
- return Obj.getHeader()->getFileClass() == ELF::ELFCLASS64 ? 8 : 4;
+ return Obj.getHeader().getFileClass() == ELF::ELFCLASS64 ? 8 : 4;
}
// We don't technically need this right now
@@ -95,16 +294,12 @@ private:
auto StrTabSec = Obj.getSection(SecRef.sh_link);
if (!StrTabSec)
return StrTabSec.takeError();
- auto StringTable = Obj.getStringTable(*StrTabSec);
+ auto StringTable = Obj.getStringTable(**StrTabSec);
if (!StringTable)
return StringTable.takeError();
for (auto SymRef : *Symbols) {
Optional<StringRef> Name;
- uint64_t Size = 0;
-
- // FIXME: Read size.
- (void)Size;
if (auto NameOrErr = SymRef.getName(*StringTable))
Name = *NameOrErr;
@@ -112,16 +307,13 @@ private:
return NameOrErr.takeError();
LLVM_DEBUG({
- dbgs() << " ";
- if (!Name)
- dbgs() << "<anonymous symbol>";
- else
- dbgs() << *Name;
- dbgs() << ": value = " << formatv("{0:x16}", SymRef.getValue())
+ dbgs() << " value = " << formatv("{0:x16}", SymRef.getValue())
<< ", type = " << formatv("{0:x2}", SymRef.getType())
- << ", binding = " << SymRef.getBinding()
- << ", size =" << Size;
- dbgs() << "\n";
+ << ", binding = " << formatv("{0:x2}", SymRef.getBinding())
+ << ", size = "
+ << formatv("{0:x16}", static_cast<uint64_t>(SymRef.st_size))
+ << ", info = " << formatv("{0:x2}", SymRef.st_info)
+ << " :" << (Name ? *Name : "<anonymous symbol>") << "\n";
});
}
}
@@ -131,9 +323,19 @@ private:
Error createNormalizedSections() {
LLVM_DEBUG(dbgs() << "Creating normalized sections...\n");
for (auto &SecRef : sections) {
- auto Name = Obj.getSectionName(&SecRef);
+ auto Name = Obj.getSectionName(SecRef);
if (!Name)
return Name.takeError();
+
+ // Skip Dwarf sections.
+ if (isDwarfSection(*Name)) {
+ LLVM_DEBUG({
+ dbgs() << *Name
+ << " is a debug section: No graph section will be created.\n";
+ });
+ continue;
+ }
+
sys::Memory::ProtectionFlags Prot;
if (SecRef.sh_flags & ELF::SHF_EXECINSTR) {
Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
@@ -147,8 +349,8 @@ private:
uint64_t Flags = SecRef.sh_flags;
uint64_t Alignment = SecRef.sh_addralign;
const char *Data = nullptr;
- // TODO: figure out what it is that has 0 size no name and address
- // 0000-0000
+ // for now we just use this to skip the "undefined" section, probably need
+ // to revist
if (Size == 0)
continue;
@@ -158,13 +360,13 @@ private:
LLVM_DEBUG({
dbgs() << " " << *Name << ": " << formatv("{0:x16}", Address) << " -- "
<< formatv("{0:x16}", Address + Size) << ", align: " << Alignment
- << " Flags:" << Flags << "\n";
+ << " Flags: " << formatv("{0:x}", Flags) << "\n";
});
if (SecRef.sh_type != ELF::SHT_NOBITS) {
// .sections() already checks that the data is not beyond the end of
// file
- auto contents = Obj.getSectionContentsAsArray<char>(&SecRef);
+ auto contents = Obj.getSectionContentsAsArray<char>(SecRef);
if (!contents)
return contents.takeError();
@@ -178,6 +380,9 @@ private:
if (SecRef.sh_type == ELF::SHT_SYMTAB)
// TODO: Dynamic?
SymTab = SecRef;
+ } else {
+ auto &Section = G->createSection(*Name, Prot);
+ G->createZeroFillBlock(Section, Size, Address, Alignment, 0);
}
}
@@ -196,21 +401,34 @@ private:
return make_error<llvm::StringError>("Shouldn't have REL in x64",
llvm::inconvertibleErrorCode());
- auto RelSectName = Obj.getSectionName(&SecRef);
+ auto RelSectName = Obj.getSectionName(SecRef);
if (!RelSectName)
return RelSectName.takeError();
- // Deal with .eh_frame later
- if (*RelSectName == StringRef(".rela.eh_frame"))
- continue;
+
+ LLVM_DEBUG({
+ dbgs() << "Adding relocations from section " << *RelSectName << "\n";
+ });
auto UpdateSection = Obj.getSection(SecRef.sh_info);
if (!UpdateSection)
return UpdateSection.takeError();
- auto UpdateSectionName = Obj.getSectionName(*UpdateSection);
+ auto UpdateSectionName = Obj.getSectionName(**UpdateSection);
if (!UpdateSectionName)
return UpdateSectionName.takeError();
+ // Don't process relocations for debug sections.
+ if (isDwarfSection(*UpdateSectionName)) {
+ LLVM_DEBUG({
+ dbgs() << " Target is dwarf section " << *UpdateSectionName
+ << ". Skipping.\n";
+ });
+ continue;
+ } else
+ LLVM_DEBUG({
+ dbgs() << " For target section " << *UpdateSectionName << "\n";
+ });
+
auto JITSection = G->findSectionByName(*UpdateSectionName);
if (!JITSection)
return make_error<llvm::StringError>(
@@ -218,7 +436,7 @@ private:
*UpdateSectionName,
llvm::inconvertibleErrorCode());
- auto Relocations = Obj.relas(&SecRef);
+ auto Relocations = Obj.relas(SecRef);
if (!Relocations)
return Relocations.takeError();
@@ -229,13 +447,22 @@ private:
dbgs() << "Relocation Type: " << Type << "\n"
<< "Name: " << Obj.getRelocationTypeName(Type) << "\n";
});
-
- auto Symbol = Obj.getRelocationSymbol(&Rela, &SymTab);
+ auto SymbolIndex = Rela.getSymbol(false);
+ auto Symbol = Obj.getRelocationSymbol(Rela, &SymTab);
if (!Symbol)
return Symbol.takeError();
auto BlockToFix = *(JITSection->blocks().begin());
- auto TargetSymbol = JITSymbolTable[(*Symbol)->st_shndx];
+ auto *TargetSymbol = JITSymbolTable[SymbolIndex];
+
+ if (!TargetSymbol) {
+ return make_error<llvm::StringError>(
+ "Could not find symbol at given index, did you add it to "
+ "JITSymbolTable? index: " + std::to_string(SymbolIndex)
+ + ", shndx: " + std::to_string((*Symbol)->st_shndx) +
+ " Size of table: " + std::to_string(JITSymbolTable.size()),
+ llvm::inconvertibleErrorCode());
+ }
uint64_t Addend = Rela.r_addend;
JITTargetAddress FixupAddress =
(*UpdateSection)->sh_addr + Rela.r_offset;
@@ -251,8 +478,8 @@ private:
LLVM_DEBUG({
Edge GE(*Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,
Addend);
- // TODO a mapping of KIND => type then call getRelocationTypeName4
- printEdge(dbgs(), *BlockToFix, GE, StringRef(""));
+ printEdge(dbgs(), *BlockToFix, GE,
+ getELFX86RelocationKindName(*Kind));
dbgs() << "\n";
});
BlockToFix->addEdge(*Kind, FixupAddress - BlockToFix->getAddress(),
@@ -284,25 +511,31 @@ private:
auto StrTabSec = Obj.getSection(SecRef.sh_link);
if (!StrTabSec)
return StrTabSec.takeError();
- auto StringTable = Obj.getStringTable(*StrTabSec);
+ auto StringTable = Obj.getStringTable(**StrTabSec);
if (!StringTable)
return StringTable.takeError();
- auto Name = Obj.getSectionName(&SecRef);
+ auto Name = Obj.getSectionName(SecRef);
if (!Name)
return Name.takeError();
+
+ LLVM_DEBUG(dbgs() << "Processing symbol section " << *Name << ":\n");
+
auto Section = G->findSectionByName(*Name);
if (!Section)
- return make_error<llvm::StringError>("Could not find a section",
+ return make_error<llvm::StringError>("Could not find a section " +
+ *Name,
llvm::inconvertibleErrorCode());
// we only have one for now
auto blocks = Section->blocks();
if (blocks.empty())
return make_error<llvm::StringError>("Section has no block",
llvm::inconvertibleErrorCode());
-
+ int SymbolIndex = -1;
for (auto SymRef : *Symbols) {
+ ++SymbolIndex;
auto Type = SymRef.getType();
- if (Type == ELF::STT_NOTYPE || Type == ELF::STT_FILE)
+
+ if (Type == ELF::STT_FILE || SymbolIndex == 0)
continue;
// these should do it for now
// if(Type != ELF::STT_NOTYPE &&
@@ -312,68 +545,119 @@ private:
// Type != ELF::STT_COMMON) {
// continue;
// }
- std::pair<Linkage, Scope> bindings;
auto Name = SymRef.getName(*StringTable);
// I am not sure on If this is going to hold as an invariant. Revisit.
if (!Name)
return Name.takeError();
- // TODO: weak and hidden
- if (SymRef.isExternal())
- bindings = {Linkage::Strong, Scope::Default};
- else
- bindings = {Linkage::Strong, Scope::Local};
+
+ if (SymRef.isCommon()) {
+ // Symbols in SHN_COMMON refer to uninitialized data. The st_value
+ // field holds alignment constraints.
+ Symbol &S =
+ G->addCommonSymbol(*Name, Scope::Default, getCommonSection(), 0,
+ SymRef.st_size, SymRef.getValue(), false);
+ JITSymbolTable[SymbolIndex] = &S;
+ continue;
+ }
+
+ // Map Visibility and Binding to Scope and Linkage:
+ Linkage L = Linkage::Strong;
+ Scope S = Scope::Default;
+
+ switch (SymRef.getBinding()) {
+ case ELF::STB_LOCAL:
+ S = Scope::Local;
+ break;
+ case ELF::STB_GLOBAL:
+ // Nothing to do here.
+ break;
+ case ELF::STB_WEAK:
+ L = Linkage::Weak;
+ break;
+ default:
+ return make_error<StringError>("Unrecognized symbol binding for " +
+ *Name,
+ inconvertibleErrorCode());
+ }
+
+ switch (SymRef.getVisibility()) {
+ case ELF::STV_DEFAULT:
+ case ELF::STV_PROTECTED:
+ // FIXME: Make STV_DEFAULT symbols pre-emptible? This probably needs
+ // Orc support.
+ // Otherwise nothing to do here.
+ break;
+ case ELF::STV_HIDDEN:
+ // Default scope -> Hidden scope. No effect on local scope.
+ if (S == Scope::Default)
+ S = Scope::Hidden;
+ break;
+ case ELF::STV_INTERNAL:
+ return make_error<StringError>("Unrecognized symbol visibility for " +
+ *Name,
+ inconvertibleErrorCode());
+ }
if (SymRef.isDefined() &&
- (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT)) {
+ (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT ||
+ Type == ELF::STT_SECTION)) {
auto DefinedSection = Obj.getSection(SymRef.st_shndx);
if (!DefinedSection)
return DefinedSection.takeError();
- auto sectName = Obj.getSectionName(*DefinedSection);
+ auto sectName = Obj.getSectionName(**DefinedSection);
if (!sectName)
return Name.takeError();
+ // Skip debug section symbols.
+ if (isDwarfSection(*sectName))
+ continue;
+
auto JitSection = G->findSectionByName(*sectName);
if (!JitSection)
return make_error<llvm::StringError>(
- "Could not find a section", llvm::inconvertibleErrorCode());
+ "Could not find the JitSection " + *sectName,
+ llvm::inconvertibleErrorCode());
auto bs = JitSection->blocks();
if (bs.empty())
return make_error<llvm::StringError>(
"Section has no block", llvm::inconvertibleErrorCode());
- auto B = *bs.begin();
- LLVM_DEBUG({ dbgs() << " " << *Name << ": "; });
+ auto *B = *bs.begin();
+ LLVM_DEBUG({ dbgs() << " " << *Name << " at index " << SymbolIndex << "\n"; });
+ if (SymRef.getType() == ELF::STT_SECTION)
+ *Name = *sectName;
+ auto &Sym = G->addDefinedSymbol(
+ *B, SymRef.getValue(), *Name, SymRef.st_size, L, S,
+ SymRef.getType() == ELF::STT_FUNC, false);
+ JITSymbolTable[SymbolIndex] = &Sym;
+ } else if (SymRef.isUndefined() && SymRef.isExternal()) {
+ auto &Sym = G->addExternalSymbol(*Name, SymRef.st_size, L);
+ JITSymbolTable[SymbolIndex] = &Sym;
+ } else
+ LLVM_DEBUG({
+ dbgs()
+ << "Not creating graph symbol for normalized symbol at index "
+ << SymbolIndex << ", \"" << *Name << "\"\n";
+ });
- auto &S = G->addDefinedSymbol(
- *B, SymRef.getValue(), *Name, SymRef.st_size, bindings.first,
- bindings.second, SymRef.getType() == ELF::STT_FUNC, false);
- JITSymbolTable[SymRef.st_shndx] = &S;
- }
- //TODO: The following has to be implmented.
+ // TODO: The following has to be implmented.
// leaving commented out to save time for future patchs
/*
G->addAbsoluteSymbol(*Name, SymRef.getValue(), SymRef.st_size,
Linkage::Strong, Scope::Default, false);
-
- if(SymRef.isCommon()) {
- G->addCommonSymbol(*Name, Scope::Default, getCommonSection(), 0, 0,
- SymRef.getValue(), false);
- }
-
-
- //G->addExternalSymbol(*Name, SymRef.st_size, Linkage::Strong);
- */
+ */
}
}
return Error::success();
}
public:
- ELFLinkGraphBuilder_x86_64(std::string filename,
+ ELFLinkGraphBuilder_x86_64(StringRef FileName,
const object::ELFFile<object::ELF64LE> &Obj)
- : G(std::make_unique<LinkGraph>(filename, getPointerSize(Obj),
- getEndianness(Obj))),
+ : G(std::make_unique<LinkGraph>(FileName.str(),
+ Triple("x86_64-unknown-linux"),
+ getPointerSize(Obj), getEndianness(Obj))),
Obj(Obj) {}
Expected<std::unique_ptr<LinkGraph>> buildGraph() {
@@ -409,55 +693,121 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
public:
ELFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
- : JITLinker(std::move(Ctx), std::move(PassConfig)) {}
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
private:
- StringRef getEdgeKindName(Edge::Kind R) const override { return StringRef(); }
-
- Expected<std::unique_ptr<LinkGraph>>
- buildGraph(MemoryBufferRef ObjBuffer) override {
- auto ELFObj = object::ObjectFile::createELFObjectFile(ObjBuffer);
- if (!ELFObj)
- return ELFObj.takeError();
+ StringRef getEdgeKindName(Edge::Kind R) const override {
+ return getELFX86RelocationKindName(R);
+ }
- auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
- std::string fileName(ELFObj->get()->getFileName());
- return ELFLinkGraphBuilder_x86_64(std::move(fileName),
- *ELFObjFile.getELFFile())
- .buildGraph();
+ static Error targetOutOfRangeError(const Block &B, const Edge &E) {
+ std::string ErrMsg;
+ {
+ raw_string_ostream ErrStream(ErrMsg);
+ ErrStream << "Relocation target out of range: ";
+ printEdge(ErrStream, B, E, getELFX86RelocationKindName(E.getKind()));
+ ErrStream << "\n";
+ }
+ return make_error<JITLinkError>(std::move(ErrMsg));
}
Error applyFixup(Block &B, const Edge &E, char *BlockWorkingMem) const {
using namespace ELF_x86_64_Edges;
+ using namespace llvm::support;
char *FixupPtr = BlockWorkingMem + E.getOffset();
JITTargetAddress FixupAddress = B.getAddress() + E.getOffset();
switch (E.getKind()) {
-
+ case ELFX86RelocationKind::Branch32:
+ case ELFX86RelocationKind::Branch32ToStub:
case ELFX86RelocationKind::PCRel32:
+ case ELFX86RelocationKind::PCRel32GOTLoad: {
+ int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
+ if (Value < std::numeric_limits<int32_t>::min() ||
+ Value > std::numeric_limits<int32_t>::max())
+ return targetOutOfRangeError(B, E);
+ *(little32_t *)FixupPtr = Value;
+ break;
+ }
+ case ELFX86RelocationKind::Pointer64: {
+ int64_t Value = E.getTarget().getAddress() + E.getAddend();
+ *(ulittle64_t *)FixupPtr = Value;
+ break;
+ }
+ case ELFX86RelocationKind::Delta64: {
int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
- // verify
- *(support::little32_t *)FixupPtr = Value;
+ *(little64_t *)FixupPtr = Value;
break;
}
+ }
return Error::success();
}
};
-void jitLink_ELF_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer) {
+ LLVM_DEBUG({
+ dbgs() << "Building jitlink graph for new input "
+ << ObjectBuffer.getBufferIdentifier() << "...\n";
+ });
+
+ auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
+ if (!ELFObj)
+ return ELFObj.takeError();
+
+ auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
+ return ELFLinkGraphBuilder_x86_64((*ELFObj)->getFileName(),
+ ELFObjFile.getELFFile())
+ .buildGraph();
+}
+
+void link_ELF_x86_64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
PassConfiguration Config;
- Triple TT("x86_64-linux");
- // Construct a JITLinker and run the link function.
- // Add a mark-live pass.
- if (auto MarkLive = Ctx->getMarkLivePass(TT))
- Config.PrePrunePasses.push_back(std::move(MarkLive));
- else
- Config.PrePrunePasses.push_back(markAllSymbolsLive);
- if (auto Err = Ctx->modifyPassConfig(TT, Config))
+ if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
+
+ Config.PrePrunePasses.push_back(EHFrameSplitter(".eh_frame"));
+ Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
+ ".eh_frame", G->getPointerSize(), Delta64, Delta32, NegDelta32));
+
+ // Construct a JITLinker and run the link function.
+ // Add a mark-live pass.
+ if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
+ Config.PrePrunePasses.push_back(std::move(MarkLive));
+ else
+ Config.PrePrunePasses.push_back(markAllSymbolsLive);
+
+ // Add an in-place GOT/Stubs pass.
+ Config.PostPrunePasses.push_back([](LinkGraph &G) -> Error {
+ ELF_x86_64_GOTAndStubsBuilder(G).run();
+ return Error::success();
+ });
+
+ // Add GOT/Stubs optimizer pass.
+ Config.PreFixupPasses.push_back(optimizeELF_x86_64_GOTAndStubs);
+ }
+
+ if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
return Ctx->notifyFailed(std::move(Err));
- ELFJITLinker_x86_64::link(std::move(Ctx), std::move(Config));
+ ELFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
+}
+StringRef getELFX86RelocationKindName(Edge::Kind R) {
+ switch (R) {
+ case PCRel32:
+ return "PCRel32";
+ case Pointer64:
+ return "Pointer64";
+ case PCRel32GOTLoad:
+ return "PCRel32GOTLoad";
+ case Branch32:
+ return "Branch32";
+ case Branch32ToStub:
+ return "Branch32ToStub";
+ }
+ return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
}
} // end namespace jitlink
} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index 5105ec495148..93dfba9c759b 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -64,7 +64,7 @@ const char *getGenericEdgeKindName(Edge::Kind K) {
case Edge::KeepAlive:
return "Keep-Alive";
default:
- llvm_unreachable("Unrecognized relocation kind");
+ return "<Unrecognized edge kind>";
}
}
@@ -93,6 +93,7 @@ const char *getScopeName(Scope S) {
raw_ostream &operator<<(raw_ostream &OS, const Block &B) {
return OS << formatv("{0:x16}", B.getAddress()) << " -- "
<< formatv("{0:x16}", B.getAddress() + B.getSize()) << ": "
+ << "size = " << formatv("{0:x}", B.getSize()) << ", "
<< (B.isZeroFill() ? "zero-fill" : "content")
<< ", align = " << B.getAlignment()
<< ", align-ofs = " << B.getAlignmentOffset()
@@ -126,10 +127,10 @@ raw_ostream &operator<<(raw_ostream &OS, const Symbol &Sym) {
break;
}
OS << (Sym.isLive() ? '+' : '-')
- << ", size = " << formatv("{0:x8}", Sym.getSize())
+ << ", size = " << formatv("{0:x}", Sym.getSize())
<< ", addr = " << formatv("{0:x16}", Sym.getAddress()) << " ("
<< formatv("{0:x16}", Sym.getAddressable().getAddress()) << " + "
- << formatv("{0:x8}", Sym.getOffset());
+ << formatv("{0:x}", Sym.getOffset());
if (Sym.isDefined())
OS << " " << Sym.getBlock().getSection().getName();
OS << ")>";
@@ -139,8 +140,33 @@ raw_ostream &operator<<(raw_ostream &OS, const Symbol &Sym) {
void printEdge(raw_ostream &OS, const Block &B, const Edge &E,
StringRef EdgeKindName) {
OS << "edge@" << formatv("{0:x16}", B.getAddress() + E.getOffset()) << ": "
- << formatv("{0:x16}", B.getAddress()) << " + " << E.getOffset() << " -- "
- << EdgeKindName << " -> " << E.getTarget() << " + " << E.getAddend();
+ << formatv("{0:x16}", B.getAddress()) << " + "
+ << formatv("{0:x}", E.getOffset()) << " -- " << EdgeKindName << " -> ";
+
+ auto &TargetSym = E.getTarget();
+ if (TargetSym.hasName())
+ OS << TargetSym.getName();
+ else {
+ auto &TargetBlock = TargetSym.getBlock();
+ auto &TargetSec = TargetBlock.getSection();
+ JITTargetAddress SecAddress = ~JITTargetAddress(0);
+ for (auto *B : TargetSec.blocks())
+ if (B->getAddress() < SecAddress)
+ SecAddress = B->getAddress();
+
+ JITTargetAddress SecDelta = TargetSym.getAddress() - SecAddress;
+ OS << formatv("{0:x16}", TargetSym.getAddress()) << " (section "
+ << TargetSec.getName();
+ if (SecDelta)
+ OS << " + " << formatv("{0:x}", SecDelta);
+ OS << " / block " << formatv("{0:x16}", TargetBlock.getAddress());
+ if (TargetSym.getOffset())
+ OS << " + " << formatv("{0:x}", TargetSym.getOffset());
+ OS << ")";
+ }
+
+ if (E.getAddend() != 0)
+ OS << " + " << E.getAddend();
}
Section::~Section() {
@@ -296,15 +322,27 @@ Error markAllSymbolsLive(LinkGraph &G) {
return Error::success();
}
-void jitLink(std::unique_ptr<JITLinkContext> Ctx) {
- auto Magic = identify_magic(Ctx->getObjectBuffer().getBuffer());
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromObject(MemoryBufferRef ObjectBuffer) {
+ auto Magic = identify_magic(ObjectBuffer.getBuffer());
switch (Magic) {
case file_magic::macho_object:
- return jitLink_MachO(std::move(Ctx));
+ return createLinkGraphFromMachOObject(std::move(ObjectBuffer));
case file_magic::elf_relocatable:
- return jitLink_ELF(std::move(Ctx));
+ return createLinkGraphFromELFObject(std::move(ObjectBuffer));
+ default:
+ return make_error<JITLinkError>("Unsupported file format");
+ };
+}
+
+void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) {
+ switch (G->getTargetTriple().getObjectFormat()) {
+ case Triple::MachO:
+ return link_MachO(std::move(G), std::move(Ctx));
+ case Triple::ELF:
+ return link_ELF(std::move(G), std::move(Ctx));
default:
- Ctx->notifyFailed(make_error<JITLinkError>("Unsupported file format"));
+ Ctx->notifyFailed(make_error<JITLinkError>("Unsupported object format"));
};
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
index 1d76a49939dc..7a5e014f223d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.cpp
@@ -24,15 +24,6 @@ JITLinkerBase::~JITLinkerBase() {}
void JITLinkerBase::linkPhase1(std::unique_ptr<JITLinkerBase> Self) {
- LLVM_DEBUG({ dbgs() << "Building jitlink graph for new input...\n"; });
-
- // Build the link graph.
- if (auto GraphOrErr = buildGraph(Ctx->getObjectBuffer()))
- G = std::move(*GraphOrErr);
- else
- return Ctx->notifyFailed(GraphOrErr.takeError());
- assert(G && "Graph should have been created by buildGraph above");
-
LLVM_DEBUG({
dbgs() << "Starting link phase 1 for graph " << G->getName() << "\n";
});
@@ -64,10 +55,22 @@ void JITLinkerBase::linkPhase1(std::unique_ptr<JITLinkerBase> Self) {
if (auto Err = allocateSegments(Layout))
return Ctx->notifyFailed(std::move(Err));
+ LLVM_DEBUG({
+ dbgs() << "Link graph \"" << G->getName()
+ << "\" before post-allocation passes:\n";
+ dumpGraph(dbgs());
+ });
+
+ // Run post-allocation passes.
+ if (auto Err = runPasses(Passes.PostAllocationPasses))
+ return Ctx->notifyFailed(std::move(Err));
+
// Notify client that the defined symbols have been assigned addresses.
LLVM_DEBUG(
{ dbgs() << "Resolving symbols defined in " << G->getName() << "\n"; });
- Ctx->notifyResolved(*G);
+
+ if (auto Err = Ctx->notifyResolved(*G))
+ return Ctx->notifyFailed(std::move(Err));
auto ExternalSymbols = getExternalSymbolNames();
@@ -117,11 +120,11 @@ void JITLinkerBase::linkPhase2(std::unique_ptr<JITLinkerBase> Self,
LLVM_DEBUG({
dbgs() << "Link graph \"" << G->getName()
- << "\" before post-allocation passes:\n";
+ << "\" before pre-fixup passes:\n";
dumpGraph(dbgs());
});
- if (auto Err = runPasses(Passes.PostAllocationPasses))
+ if (auto Err = runPasses(Passes.PreFixupPasses))
return deallocateAndBailOut(std::move(Err));
LLVM_DEBUG({
@@ -261,7 +264,8 @@ Error JITLinkerBase::allocateSegments(const SegmentLayoutMap &Layout) {
}
LLVM_DEBUG(dbgs() << " }\n");
- if (auto AllocOrErr = Ctx->getMemoryManager().allocate(Segments))
+ if (auto AllocOrErr =
+ Ctx->getMemoryManager().allocate(Ctx->getJITLinkDylib(), Segments))
Alloc = std::move(*AllocOrErr);
else
return AllocOrErr.takeError();
@@ -332,12 +336,6 @@ void JITLinkerBase::applyLookupResult(AsyncLookupResult Result) {
dbgs() << " " << Sym->getName() << ": "
<< formatv("{0:x16}", Sym->getAddress()) << "\n";
});
- assert(llvm::all_of(G->external_symbols(),
- [](Symbol *Sym) {
- return Sym->getAddress() != 0 ||
- Sym->getLinkage() == Linkage::Weak;
- }) &&
- "All strong external symbols should have been resolved by now");
}
void JITLinkerBase::copyBlockContentToWorkingMemory(
@@ -445,16 +443,19 @@ void prune(LinkGraph &G) {
VisitedBlocks.insert(&B);
for (auto &E : Sym->getBlock().edges()) {
- if (E.getTarget().isDefined() && !E.getTarget().isLive()) {
- E.getTarget().setLive(true);
+ // If the edge target is a defined symbol that is being newly marked live
+ // then add it to the worklist.
+ if (E.getTarget().isDefined() && !E.getTarget().isLive())
Worklist.push_back(&E.getTarget());
- }
+
+ // Mark the target live.
+ E.getTarget().setLive(true);
}
}
- // Collect all the symbols to remove, then remove them.
+ // Collect all defined symbols to remove, then remove them.
{
- LLVM_DEBUG(dbgs() << "Dead-stripping symbols:\n");
+ LLVM_DEBUG(dbgs() << "Dead-stripping defined symbols:\n");
std::vector<Symbol *> SymbolsToRemove;
for (auto *Sym : G.defined_symbols())
if (!Sym->isLive())
@@ -477,6 +478,19 @@ void prune(LinkGraph &G) {
G.removeBlock(*B);
}
}
+
+ // Collect all external symbols to remove, then remove them.
+ {
+ LLVM_DEBUG(dbgs() << "Removing unused external symbols:\n");
+ std::vector<Symbol *> SymbolsToRemove;
+ for (auto *Sym : G.external_symbols())
+ if (!Sym->isLive())
+ SymbolsToRemove.push_back(Sym);
+ for (auto *Sym : SymbolsToRemove) {
+ LLVM_DEBUG(dbgs() << " " << *Sym << "...\n");
+ G.removeExternalSymbol(*Sym);
+ }
+ }
}
} // end namespace jitlink
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
index 87e5e8bbc98d..1d28f5006b2b 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
@@ -32,9 +32,11 @@ namespace jitlink {
/// remaining linker work) to allow them to be performed asynchronously.
class JITLinkerBase {
public:
- JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx, PassConfiguration Passes)
- : Ctx(std::move(Ctx)), Passes(std::move(Passes)) {
+ JITLinkerBase(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G, PassConfiguration Passes)
+ : Ctx(std::move(Ctx)), G(std::move(G)), Passes(std::move(Passes)) {
assert(this->Ctx && "Ctx can not be null");
+ assert(this->G && "G can not be null");
}
virtual ~JITLinkerBase();
@@ -50,8 +52,7 @@ protected:
using SegmentLayoutMap = DenseMap<unsigned, SegmentLayout>;
// Phase 1:
- // 1.1: Build link graph
- // 1.2: Run pre-prune passes
+ // 1.1: Run pre-prune passes
// 1.2: Prune graph
// 1.3: Run post-prune passes
// 1.4: Sort blocks into segments
@@ -72,11 +73,6 @@ protected:
// 3.1: Call OnFinalized callback, handing off allocation.
void linkPhase3(std::unique_ptr<JITLinkerBase> Self, Error Err);
- // Build a graph from the given object buffer.
- // To be implemented by the client.
- virtual Expected<std::unique_ptr<LinkGraph>>
- buildGraph(MemoryBufferRef ObjBuffer) = 0;
-
// For debug dumping of the link graph.
virtual StringRef getEdgeKindName(Edge::Kind K) const = 0;
@@ -113,8 +109,8 @@ private:
void dumpGraph(raw_ostream &OS);
std::unique_ptr<JITLinkContext> Ctx;
- PassConfiguration Passes;
std::unique_ptr<LinkGraph> G;
+ PassConfiguration Passes;
std::unique_ptr<JITLinkMemoryManager::Allocation> Alloc;
};
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp
index 68ec9d79af9b..fbbb29e9164a 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkMemoryManager.cpp
@@ -17,7 +17,8 @@ JITLinkMemoryManager::~JITLinkMemoryManager() = default;
JITLinkMemoryManager::Allocation::~Allocation() = default;
Expected<std::unique_ptr<JITLinkMemoryManager::Allocation>>
-InProcessMemoryManager::allocate(const SegmentsRequestMap &Request) {
+InProcessMemoryManager::allocate(const JITLinkDylib *JD,
+ const SegmentsRequestMap &Request) {
using AllocationMap = DenseMap<unsigned, sys::MemoryBlock>;
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO.cpp
index b3e45868ab22..e9327df6da41 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO.cpp
@@ -27,39 +27,29 @@ using namespace llvm;
namespace llvm {
namespace jitlink {
-void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx) {
-
- // We don't want to do full MachO validation here. Just parse enough of the
- // header to find out what MachO linker to use.
-
- StringRef Data = Ctx->getObjectBuffer().getBuffer();
- if (Data.size() < 4) {
- StringRef BufferName = Ctx->getObjectBuffer().getBufferIdentifier();
- Ctx->notifyFailed(make_error<JITLinkError>("Truncated MachO buffer \"" +
- BufferName + "\""));
- return;
- }
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromMachOObject(MemoryBufferRef ObjectBuffer) {
+ StringRef Data = ObjectBuffer.getBuffer();
+ if (Data.size() < 4)
+ return make_error<JITLinkError>("Truncated MachO buffer \"" +
+ ObjectBuffer.getBufferIdentifier() + "\"");
uint32_t Magic;
memcpy(&Magic, Data.data(), sizeof(uint32_t));
LLVM_DEBUG({
dbgs() << "jitLink_MachO: magic = " << format("0x%08" PRIx32, Magic)
- << ", identifier = \""
- << Ctx->getObjectBuffer().getBufferIdentifier() << "\"\n";
+ << ", identifier = \"" << ObjectBuffer.getBufferIdentifier()
+ << "\"\n";
});
- if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM) {
- Ctx->notifyFailed(
- make_error<JITLinkError>("MachO 32-bit platforms not supported"));
- return;
- } else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) {
+ if (Magic == MachO::MH_MAGIC || Magic == MachO::MH_CIGAM)
+ return make_error<JITLinkError>("MachO 32-bit platforms not supported");
+ else if (Magic == MachO::MH_MAGIC_64 || Magic == MachO::MH_CIGAM_64) {
- if (Data.size() < sizeof(MachO::mach_header_64)) {
- StringRef BufferName = Ctx->getObjectBuffer().getBufferIdentifier();
- Ctx->notifyFailed(make_error<JITLinkError>("Truncated MachO buffer \"" +
- BufferName + "\""));
- return;
- }
+ if (Data.size() < sizeof(MachO::mach_header_64))
+ return make_error<JITLinkError>("Truncated MachO buffer \"" +
+ ObjectBuffer.getBufferIdentifier() +
+ "\"");
// Read the CPU type from the header.
uint32_t CPUType;
@@ -74,15 +64,27 @@ void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx) {
switch (CPUType) {
case MachO::CPU_TYPE_ARM64:
- return jitLink_MachO_arm64(std::move(Ctx));
+ return createLinkGraphFromMachOObject_arm64(std::move(ObjectBuffer));
case MachO::CPU_TYPE_X86_64:
- return jitLink_MachO_x86_64(std::move(Ctx));
+ return createLinkGraphFromMachOObject_x86_64(std::move(ObjectBuffer));
}
+ return make_error<JITLinkError>("MachO-64 CPU type not valid");
+ } else
+ return make_error<JITLinkError>("Unrecognized MachO magic value");
+}
+
+void link_MachO(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+
+ switch (G->getTargetTriple().getArch()) {
+ case Triple::aarch64:
+ return link_MachO_arm64(std::move(G), std::move(Ctx));
+ case Triple::x86_64:
+ return link_MachO_x86_64(std::move(G), std::move(Ctx));
+ default:
Ctx->notifyFailed(make_error<JITLinkError>("MachO-64 CPU type not valid"));
return;
}
-
- Ctx->notifyFailed(make_error<JITLinkError>("MachO magic not valid"));
}
} // end namespace jitlink
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
index fa3f403b717c..4602154eb579 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
@@ -45,10 +45,12 @@ Expected<std::unique_ptr<LinkGraph>> MachOLinkGraphBuilder::buildGraph() {
return std::move(G);
}
-MachOLinkGraphBuilder::MachOLinkGraphBuilder(const object::MachOObjectFile &Obj)
+MachOLinkGraphBuilder::MachOLinkGraphBuilder(const object::MachOObjectFile &Obj,
+ Triple TT)
: Obj(Obj),
G(std::make_unique<LinkGraph>(std::string(Obj.getFileName()),
- getPointerSize(Obj), getEndianness(Obj))) {}
+ std::move(TT), getPointerSize(Obj),
+ getEndianness(Obj))) {}
void MachOLinkGraphBuilder::addCustomSectionParser(
StringRef SectionName, SectionParserFunction Parser) {
@@ -64,10 +66,8 @@ Linkage MachOLinkGraphBuilder::getLinkage(uint16_t Desc) {
}
Scope MachOLinkGraphBuilder::getScope(StringRef Name, uint8_t Type) {
- if (Type & MachO::N_PEXT)
- return Scope::Hidden;
if (Type & MachO::N_EXT) {
- if (Name.startswith("l"))
+ if ((Type & MachO::N_PEXT) || Name.startswith("l"))
return Scope::Hidden;
else
return Scope::Default;
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
index dd3bcf27494c..26e6859de91d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
@@ -16,10 +16,10 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/Object/MachO.h"
#include "EHFrameSupportImpl.h"
#include "JITLinkGeneric.h"
-#include "llvm/Object/MachO.h"
#include <list>
@@ -81,7 +81,7 @@ protected:
using SectionParserFunction = std::function<Error(NormalizedSection &S)>;
- MachOLinkGraphBuilder(const object::MachOObjectFile &Obj);
+ MachOLinkGraphBuilder(const object::MachOObjectFile &Obj, Triple TT);
LinkGraph &getGraph() const { return *G; }
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
index 463845a5b8cb..8366e9658539 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
@@ -26,7 +26,7 @@ namespace {
class MachOLinkGraphBuilder_arm64 : public MachOLinkGraphBuilder {
public:
MachOLinkGraphBuilder_arm64(const object::MachOObjectFile &Obj)
- : MachOLinkGraphBuilder(Obj),
+ : MachOLinkGraphBuilder(Obj, Triple("arm64-apple-darwin")),
NumSymbols(Obj.getSymtabLoadCommand().nsyms) {}
private:
@@ -148,10 +148,11 @@ private:
else
return ToSymbolOrErr.takeError();
} else {
- if (auto ToSymbolOrErr = findSymbolByAddress(FixupValue))
- ToSymbol = &*ToSymbolOrErr;
- else
- return ToSymbolOrErr.takeError();
+ auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);
+ if (!ToSymbolSec)
+ return ToSymbolSec.takeError();
+ ToSymbol = getSymbolByAddress(ToSymbolSec->Address);
+ assert(ToSymbol && "No symbol for section");
FixupValue -= ToSymbol->getAddress();
}
@@ -181,6 +182,8 @@ private:
using namespace support;
auto &Obj = getObject();
+ LLVM_DEBUG(dbgs() << "Processing relocations:\n");
+
for (auto &S : Obj.sections()) {
JITTargetAddress SectionAddress = S.getAddress();
@@ -199,8 +202,8 @@ private:
getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
if (!NSec.GraphSection) {
LLVM_DEBUG({
- dbgs() << "Skipping relocations for MachO section " << NSec.SegName
- << "/" << NSec.SectName
+ dbgs() << " Skipping relocations for MachO section "
+ << NSec.SegName << "/" << NSec.SectName
<< " which has no associated graph section\n";
});
continue;
@@ -221,9 +224,10 @@ private:
JITTargetAddress FixupAddress = SectionAddress + (uint32_t)RI.r_address;
LLVM_DEBUG({
- dbgs() << "Processing " << getMachOARM64RelocationKindName(*Kind)
- << " relocation at " << format("0x%016" PRIx64, FixupAddress)
- << "\n";
+ auto &NSec =
+ getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
+ dbgs() << " " << NSec.SectName << " + "
+ << formatv("{0:x8}", RI.r_address) << ":\n";
});
// Find the block that the fixup points to.
@@ -252,7 +256,7 @@ private:
// If this is an Addend relocation then process it and move to the
// paired reloc.
- Addend = RI.r_symbolnum;
+ Addend = SignExtend64(RI.r_symbolnum, 24);
if (RelItr == RelEnd)
return make_error<JITLinkError>("Unpaired Addend reloc at " +
@@ -268,11 +272,12 @@ private:
return make_error<JITLinkError>(
"Invalid relocation pair: Addend + " +
getMachOARM64RelocationKindName(*Kind));
- else
- LLVM_DEBUG({
- dbgs() << " pair is " << getMachOARM64RelocationKindName(*Kind)
- << "`\n";
- });
+
+ LLVM_DEBUG({
+ dbgs() << " Addend: value = " << formatv("{0:x6}", Addend)
+ << ", pair is " << getMachOARM64RelocationKindName(*Kind)
+ << "\n";
+ });
// Find the address of the value to fix up.
JITTargetAddress PairedFixupAddress =
@@ -335,6 +340,11 @@ private:
TargetSymbol = TargetSymbolOrErr->GraphSymbol;
else
return TargetSymbolOrErr.takeError();
+ uint32_t Instr = *(const ulittle32_t *)FixupContent;
+ uint32_t EncodedAddend = (Instr & 0x003FFC00) >> 10;
+ if (EncodedAddend != 0)
+ return make_error<JITLinkError>("GOTPAGEOFF12 target has non-zero "
+ "encoded addend");
break;
}
case GOTPageOffset12: {
@@ -377,6 +387,7 @@ private:
}
LLVM_DEBUG({
+ dbgs() << " ";
Edge GE(*Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,
Addend);
printEdge(dbgs(), *BlockToFix, GE,
@@ -490,22 +501,15 @@ class MachOJITLinker_arm64 : public JITLinker<MachOJITLinker_arm64> {
public:
MachOJITLinker_arm64(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
- : JITLinker(std::move(Ctx), std::move(PassConfig)) {}
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
private:
StringRef getEdgeKindName(Edge::Kind R) const override {
return getMachOARM64RelocationKindName(R);
}
- Expected<std::unique_ptr<LinkGraph>>
- buildGraph(MemoryBufferRef ObjBuffer) override {
- auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjBuffer);
- if (!MachOObj)
- return MachOObj.takeError();
- return MachOLinkGraphBuilder_arm64(**MachOObj).buildGraph();
- }
-
static Error targetOutOfRangeError(const Block &B, const Edge &E) {
std::string ErrMsg;
{
@@ -518,23 +522,17 @@ private:
}
static unsigned getPageOffset12Shift(uint32_t Instr) {
- constexpr uint32_t LDRLiteralMask = 0x3ffffc00;
+ constexpr uint32_t LoadStoreImm12Mask = 0x3b000000;
+ constexpr uint32_t Vec128Mask = 0x04800000;
- // Check for a GPR LDR immediate with a zero embedded literal.
- // If found, the top two bits contain the shift.
- if ((Instr & LDRLiteralMask) == 0x39400000)
- return Instr >> 30;
+ if ((Instr & LoadStoreImm12Mask) == 0x39000000) {
+ uint32_t ImplicitShift = Instr >> 30;
+ if (ImplicitShift == 0)
+ if ((Instr & Vec128Mask) == Vec128Mask)
+ ImplicitShift = 4;
- // Check for a Neon LDR immediate of size 64-bit or less with a zero
- // embedded literal. If found, the top two bits contain the shift.
- if ((Instr & LDRLiteralMask) == 0x3d400000)
- return Instr >> 30;
-
- // Check for a Neon LDR immediate of size 128-bit with a zero embedded
- // literal.
- constexpr uint32_t SizeBitsMask = 0xc0000000;
- if ((Instr & (LDRLiteralMask | SizeBitsMask)) == 0x3dc00000)
- return 4;
+ return ImplicitShift;
+ }
return 0;
}
@@ -581,10 +579,12 @@ private:
}
case Page21:
case GOTPage21: {
- assert(E.getAddend() == 0 && "PAGE21/GOTPAGE21 with non-zero addend");
+ assert((E.getKind() != GOTPage21 || E.getAddend() == 0) &&
+ "GOTPAGE21 with non-zero addend");
uint64_t TargetPage =
- E.getTarget().getAddress() & ~static_cast<uint64_t>(4096 - 1);
- uint64_t PCPage = B.getAddress() & ~static_cast<uint64_t>(4096 - 1);
+ (E.getTarget().getAddress() + E.getAddend()) &
+ ~static_cast<uint64_t>(4096 - 1);
+ uint64_t PCPage = FixupAddress & ~static_cast<uint64_t>(4096 - 1);
int64_t PageDelta = TargetPage - PCPage;
if (PageDelta < -(1 << 30) || PageDelta > ((1 << 30) - 1))
@@ -600,8 +600,8 @@ private:
break;
}
case PageOffset12: {
- assert(E.getAddend() == 0 && "PAGEOFF12 with non-zero addend");
- uint64_t TargetOffset = E.getTarget().getAddress() & 0xfff;
+ uint64_t TargetOffset =
+ (E.getTarget().getAddress() + E.getAddend()) & 0xfff;
uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
unsigned ImmShift = getPageOffset12Shift(RawInstr);
@@ -674,13 +674,22 @@ private:
uint64_t NullValue = 0;
};
-void jitLink_MachO_arm64(std::unique_ptr<JITLinkContext> Ctx) {
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer) {
+ auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
+ if (!MachOObj)
+ return MachOObj.takeError();
+ return MachOLinkGraphBuilder_arm64(**MachOObj).buildGraph();
+}
+
+void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+
PassConfiguration Config;
- Triple TT("arm64-apple-ios");
- if (Ctx->shouldAddDefaultTargetPasses(TT)) {
+ if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
// Add a mark-live pass.
- if (auto MarkLive = Ctx->getMarkLivePass(TT))
+ if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
Config.PrePrunePasses.push_back(std::move(MarkLive));
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
@@ -692,11 +701,11 @@ void jitLink_MachO_arm64(std::unique_ptr<JITLinkContext> Ctx) {
});
}
- if (auto Err = Ctx->modifyPassConfig(TT, Config))
+ if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
return Ctx->notifyFailed(std::move(Err));
// Construct a JITLinker and run the link function.
- MachOJITLinker_arm64::link(std::move(Ctx), std::move(Config));
+ MachOJITLinker_arm64::link(std::move(Ctx), std::move(G), std::move(Config));
}
StringRef getMachOARM64RelocationKindName(Edge::Kind R) {
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
index a91bc3b6033c..bde4a19e71ba 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
@@ -26,7 +26,7 @@ namespace {
class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {
public:
MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj)
- : MachOLinkGraphBuilder(Obj) {}
+ : MachOLinkGraphBuilder(Obj, Triple("x86_64-apple-darwin")) {}
private:
static Expected<MachOX86RelocationKind>
@@ -150,10 +150,11 @@ private:
else
return ToSymbolOrErr.takeError();
} else {
- if (auto ToSymbolOrErr = findSymbolByAddress(FixupValue))
- ToSymbol = &*ToSymbolOrErr;
- else
- return ToSymbolOrErr.takeError();
+ auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);
+ if (!ToSymbolSec)
+ return ToSymbolSec.takeError();
+ ToSymbol = getSymbolByAddress(ToSymbolSec->Address);
+ assert(ToSymbol && "No symbol for section");
FixupValue -= ToSymbol->getAddress();
}
@@ -183,6 +184,8 @@ private:
using namespace support;
auto &Obj = getObject();
+ LLVM_DEBUG(dbgs() << "Processing relocations:\n");
+
for (auto &S : Obj.sections()) {
JITTargetAddress SectionAddress = S.getAddress();
@@ -201,8 +204,8 @@ private:
getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
if (!NSec.GraphSection) {
LLVM_DEBUG({
- dbgs() << "Skipping relocations for MachO section " << NSec.SegName
- << "/" << NSec.SectName
+ dbgs() << " Skipping relocations for MachO section "
+ << NSec.SegName << "/" << NSec.SectName
<< " which has no associated graph section\n";
});
continue;
@@ -224,8 +227,10 @@ private:
JITTargetAddress FixupAddress = SectionAddress + (uint32_t)RI.r_address;
LLVM_DEBUG({
- dbgs() << "Processing relocation at "
- << format("0x%016" PRIx64, FixupAddress) << "\n";
+ auto &NSec =
+ getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
+ dbgs() << " " << NSec.SectName << " + "
+ << formatv("{0:x8}", RI.r_address) << ":\n";
});
// Find the block that the fixup points to.
@@ -334,12 +339,16 @@ private:
assert(TargetSymbol && "No target symbol from parsePairRelocation?");
break;
}
+ case PCRel32TLV:
+ return make_error<JITLinkError>(
+ "MachO TLV relocations not yet supported");
default:
llvm_unreachable("Special relocation kind should not appear in "
"mach-o file");
}
LLVM_DEBUG({
+ dbgs() << " ";
Edge GE(*Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,
Addend);
printEdge(dbgs(), *BlockToFix, GE,
@@ -539,22 +548,15 @@ class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {
public:
MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G,
PassConfiguration PassConfig)
- : JITLinker(std::move(Ctx), std::move(PassConfig)) {}
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
private:
StringRef getEdgeKindName(Edge::Kind R) const override {
return getMachOX86RelocationKindName(R);
}
- Expected<std::unique_ptr<LinkGraph>>
- buildGraph(MemoryBufferRef ObjBuffer) override {
- auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjBuffer);
- if (!MachOObj)
- return MachOObj.takeError();
- return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
- }
-
static Error targetOutOfRangeError(const Block &B, const Edge &E) {
std::string ErrMsg;
{
@@ -651,18 +653,27 @@ private:
uint64_t NullValue = 0;
};
-void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer) {
+ auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
+ if (!MachOObj)
+ return MachOObj.takeError();
+ return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
+}
+
+void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+
PassConfiguration Config;
- Triple TT("x86_64-apple-macosx");
- if (Ctx->shouldAddDefaultTargetPasses(TT)) {
+ if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
// Add eh-frame passses.
Config.PrePrunePasses.push_back(EHFrameSplitter("__eh_frame"));
- Config.PrePrunePasses.push_back(
- EHFrameEdgeFixer("__eh_frame", NegDelta32, Delta64, Delta64));
+ Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
+ "__eh_frame", G->getPointerSize(), Delta64, Delta32, NegDelta32));
// Add a mark-live pass.
- if (auto MarkLive = Ctx->getMarkLivePass(TT))
+ if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
Config.PrePrunePasses.push_back(std::move(MarkLive));
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
@@ -674,14 +685,14 @@ void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx) {
});
// Add GOT/Stubs optimizer pass.
- Config.PostAllocationPasses.push_back(optimizeMachO_x86_64_GOTAndStubs);
+ Config.PreFixupPasses.push_back(optimizeMachO_x86_64_GOTAndStubs);
}
- if (auto Err = Ctx->modifyPassConfig(TT, Config))
+ if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
return Ctx->notifyFailed(std::move(Err));
// Construct a JITLinker and run the link function.
- MachOJITLinker_x86_64::link(std::move(Ctx), std::move(Config));
+ MachOJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
}
StringRef getMachOX86RelocationKindName(Edge::Kind R) {
diff --git a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h
index 83b64b5171c0..52e7eda90310 100644
--- a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h
+++ b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.h
@@ -102,22 +102,22 @@ class MCJIT : public ExecutionEngine {
}
bool hasModuleBeenAddedButNotLoaded(Module *M) {
- return AddedModules.count(M) != 0;
+ return AddedModules.contains(M);
}
bool hasModuleBeenLoaded(Module *M) {
// If the module is in either the "loaded" or "finalized" sections it
// has been loaded.
- return (LoadedModules.count(M) != 0 ) || (FinalizedModules.count(M) != 0);
+ return LoadedModules.contains(M) || FinalizedModules.contains(M);
}
bool hasModuleBeenFinalized(Module *M) {
- return FinalizedModules.count(M) != 0;
+ return FinalizedModules.contains(M);
}
bool ownsModule(Module* M) {
- return (AddedModules.count(M) != 0) || (LoadedModules.count(M) != 0) ||
- (FinalizedModules.count(M) != 0);
+ return AddedModules.contains(M) || LoadedModules.contains(M) ||
+ FinalizedModules.contains(M);
}
void markModuleAsLoaded(Module *M) {
diff --git a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
index 9e38dc36faae..68878f6729e9 100644
--- a/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
@@ -73,22 +73,21 @@ class PartitioningIRMaterializationUnit : public IRMaterializationUnit {
public:
PartitioningIRMaterializationUnit(ExecutionSession &ES,
const IRSymbolMapper::ManglingOptions &MO,
- ThreadSafeModule TSM, VModuleKey K,
+ ThreadSafeModule TSM,
CompileOnDemandLayer &Parent)
- : IRMaterializationUnit(ES, MO, std::move(TSM), std::move(K)),
- Parent(Parent) {}
+ : IRMaterializationUnit(ES, MO, std::move(TSM)), Parent(Parent) {}
PartitioningIRMaterializationUnit(
- ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags,
+ ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags,
SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition,
CompileOnDemandLayer &Parent)
- : IRMaterializationUnit(std::move(TSM), std::move(K),
- std::move(SymbolFlags), std::move(InitSymbol),
+ : IRMaterializationUnit(std::move(TSM), std::move(SymbolFlags),
+ std::move(InitSymbol),
std::move(SymbolToDefinition)),
Parent(Parent) {}
private:
- void materialize(MaterializationResponsibility R) override {
+ void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
Parent.emitPartition(std::move(R), std::move(TSM),
std::move(SymbolToDefinition));
}
@@ -128,15 +127,15 @@ void CompileOnDemandLayer::setPartitionFunction(PartitionFunction Partition) {
void CompileOnDemandLayer::setImplMap(ImplSymbolMap *Imp) {
this->AliaseeImpls = Imp;
}
-void CompileOnDemandLayer::emit(MaterializationResponsibility R,
- ThreadSafeModule TSM) {
+void CompileOnDemandLayer::emit(
+ std::unique_ptr<MaterializationResponsibility> R, ThreadSafeModule TSM) {
assert(TSM && "Null module");
auto &ES = getExecutionSession();
// Sort the callables and non-callables, build re-exports and lodge the
// actual module with the implementation dylib.
- auto &PDR = getPerDylibResources(R.getTargetJITDylib());
+ auto &PDR = getPerDylibResources(R->getTargetJITDylib());
SymbolAliasMap NonCallables;
SymbolAliasMap Callables;
@@ -145,7 +144,7 @@ void CompileOnDemandLayer::emit(MaterializationResponsibility R,
cleanUpModule(M);
});
- for (auto &KV : R.getSymbols()) {
+ for (auto &KV : R->getSymbols()) {
auto &Name = KV.first;
auto &Flags = KV.second;
if (Flags.isCallable())
@@ -158,19 +157,29 @@ void CompileOnDemandLayer::emit(MaterializationResponsibility R,
// implementation dylib.
if (auto Err = PDR.getImplDylib().define(
std::make_unique<PartitioningIRMaterializationUnit>(
- ES, *getManglingOptions(), std::move(TSM), R.getVModuleKey(),
- *this))) {
+ ES, *getManglingOptions(), std::move(TSM), *this))) {
ES.reportError(std::move(Err));
- R.failMaterialization();
+ R->failMaterialization();
return;
}
if (!NonCallables.empty())
- R.replace(reexports(PDR.getImplDylib(), std::move(NonCallables),
- JITDylibLookupFlags::MatchAllSymbols));
- if (!Callables.empty())
- R.replace(lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(),
- std::move(Callables), AliaseeImpls));
+ if (auto Err =
+ R->replace(reexports(PDR.getImplDylib(), std::move(NonCallables),
+ JITDylibLookupFlags::MatchAllSymbols))) {
+ getExecutionSession().reportError(std::move(Err));
+ R->failMaterialization();
+ return;
+ }
+ if (!Callables.empty()) {
+ if (auto Err = R->replace(
+ lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(),
+ std::move(Callables), AliaseeImpls))) {
+ getExecutionSession().reportError(std::move(Err));
+ R->failMaterialization();
+ return;
+ }
+ }
}
CompileOnDemandLayer::PerDylibResources &
@@ -247,7 +256,7 @@ void CompileOnDemandLayer::expandPartition(GlobalValueSet &Partition) {
}
void CompileOnDemandLayer::emitPartition(
- MaterializationResponsibility R, ThreadSafeModule TSM,
+ std::unique_ptr<MaterializationResponsibility> R, ThreadSafeModule TSM,
IRMaterializationUnit::SymbolNameToDefinitionMap Defs) {
// FIXME: Need a 'notify lazy-extracting/emitting' callback to tie the
@@ -257,8 +266,8 @@ void CompileOnDemandLayer::emitPartition(
auto &ES = getExecutionSession();
GlobalValueSet RequestedGVs;
- for (auto &Name : R.getRequestedSymbols()) {
- if (Name == R.getInitializerSymbol())
+ for (auto &Name : R->getRequestedSymbols()) {
+ if (Name == R->getInitializerSymbol())
TSM.withModuleDo([&](Module &M) {
for (auto &GV : getStaticInitGVs(M))
RequestedGVs.insert(&GV);
@@ -285,9 +294,14 @@ void CompileOnDemandLayer::emitPartition(
// If the partition is empty, return the whole module to the symbol table.
if (GVsToExtract->empty()) {
- R.replace(std::make_unique<PartitioningIRMaterializationUnit>(
- std::move(TSM), R.getVModuleKey(), R.getSymbols(),
- R.getInitializerSymbol(), std::move(Defs), *this));
+ if (auto Err =
+ R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
+ std::move(TSM), R->getSymbols(), R->getInitializerSymbol(),
+ std::move(Defs), *this))) {
+ getExecutionSession().reportError(std::move(Err));
+ R->failMaterialization();
+ return;
+ }
return;
}
@@ -308,7 +322,7 @@ void CompileOnDemandLayer::emitPartition(
IRSymbolMapper::add(ES, *getManglingOptions(),
PromotedGlobals, SymbolFlags);
- if (auto Err = R.defineMaterializing(SymbolFlags))
+ if (auto Err = R->defineMaterializing(SymbolFlags))
return std::move(Err);
}
@@ -348,12 +362,16 @@ void CompileOnDemandLayer::emitPartition(
if (!ExtractedTSM) {
ES.reportError(ExtractedTSM.takeError());
- R.failMaterialization();
+ R->failMaterialization();
return;
}
- R.replace(std::make_unique<PartitioningIRMaterializationUnit>(
- ES, *getManglingOptions(), std::move(TSM), R.getVModuleKey(), *this));
+ if (auto Err = R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
+ ES, *getManglingOptions(), std::move(TSM), *this))) {
+ ES.reportError(std::move(Err));
+ R->failMaterialization();
+ return;
+ }
BaseLayer.emit(std::move(R), std::move(*ExtractedTSM));
}
diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp
index bad13cfebbc6..dfb558808c32 100644
--- a/llvm/lib/ExecutionEngine/Orc/Core.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp
@@ -11,18 +11,19 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
-#include "llvm/ExecutionEngine/Orc/OrcError.h"
+#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MSVCErrorWorkarounds.h"
#include <condition_variable>
-#if LLVM_ENABLE_THREADS
#include <future>
-#endif
#define DEBUG_TYPE "orc"
namespace llvm {
namespace orc {
+char ResourceTrackerDefunct::ID = 0;
char FailedToMaterialize::ID = 0;
char SymbolsNotFound::ID = 0;
char SymbolsCouldNotBeRemoved::ID = 0;
@@ -34,6 +35,45 @@ RegisterDependenciesFunction NoDependenciesToRegister =
void MaterializationUnit::anchor() {}
+ResourceTracker::ResourceTracker(JITDylibSP JD) {
+ assert((reinterpret_cast<uintptr_t>(JD.get()) & 0x1) == 0 &&
+ "JITDylib must be two byte aligned");
+ JD->Retain();
+ JDAndFlag.store(reinterpret_cast<uintptr_t>(JD.get()));
+}
+
+ResourceTracker::~ResourceTracker() {
+ getJITDylib().getExecutionSession().destroyResourceTracker(*this);
+ getJITDylib().Release();
+}
+
+Error ResourceTracker::remove() {
+ return getJITDylib().getExecutionSession().removeResourceTracker(*this);
+}
+
+void ResourceTracker::transferTo(ResourceTracker &DstRT) {
+ getJITDylib().getExecutionSession().transferResourceTracker(DstRT, *this);
+}
+
+void ResourceTracker::makeDefunct() {
+ uintptr_t Val = JDAndFlag.load();
+ Val |= 0x1U;
+ JDAndFlag.store(Val);
+}
+
+ResourceManager::~ResourceManager() {}
+
+ResourceTrackerDefunct::ResourceTrackerDefunct(ResourceTrackerSP RT)
+ : RT(std::move(RT)) {}
+
+std::error_code ResourceTrackerDefunct::convertToErrorCode() const {
+ return orcError(OrcErrorCode::UnknownORCError);
+}
+
+void ResourceTrackerDefunct::log(raw_ostream &OS) const {
+ OS << "Resource tracker " << (void *)RT.get() << " became defunct";
+}
+
FailedToMaterialize::FailedToMaterialize(
std::shared_ptr<SymbolDependenceMap> Symbols)
: Symbols(std::move(Symbols)) {
@@ -137,8 +177,6 @@ void AsynchronousSymbolQuery::handleComplete() {
TmpNotifyComplete(std::move(ResolvedSymbols));
}
-bool AsynchronousSymbolQuery::canStillFail() { return !!NotifyComplete; }
-
void AsynchronousSymbolQuery::handleFailed(Error Err) {
assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
OutstandingSymbolsCount == 0 &&
@@ -181,156 +219,9 @@ void AsynchronousSymbolQuery::detach() {
QueryRegistrations.clear();
}
-MaterializationResponsibility::~MaterializationResponsibility() {
- assert(SymbolFlags.empty() &&
- "All symbols should have been explicitly materialized or failed");
-}
-
-SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const {
- return JD->getRequestedSymbols(SymbolFlags);
-}
-
-Error MaterializationResponsibility::notifyResolved(const SymbolMap &Symbols) {
- LLVM_DEBUG({
- dbgs() << "In " << JD->getName() << " resolving " << Symbols << "\n";
- });
-#ifndef NDEBUG
- for (auto &KV : Symbols) {
- auto WeakFlags = JITSymbolFlags::Weak | JITSymbolFlags::Common;
- auto I = SymbolFlags.find(KV.first);
- assert(I != SymbolFlags.end() &&
- "Resolving symbol outside this responsibility set");
- assert(!I->second.hasMaterializationSideEffectsOnly() &&
- "Can't resolve materialization-side-effects-only symbol");
- assert((KV.second.getFlags() & ~WeakFlags) == (I->second & ~WeakFlags) &&
- "Resolving symbol with incorrect flags");
- }
-#endif
-
- return JD->resolve(Symbols);
-}
-
-Error MaterializationResponsibility::notifyEmitted() {
-
- LLVM_DEBUG({
- dbgs() << "In " << JD->getName() << " emitting " << SymbolFlags << "\n";
- });
-
- if (auto Err = JD->emit(SymbolFlags))
- return Err;
-
- SymbolFlags.clear();
- return Error::success();
-}
-
-Error MaterializationResponsibility::defineMaterializing(
- SymbolFlagsMap NewSymbolFlags) {
-
- LLVM_DEBUG({
- dbgs() << "In " << JD->getName() << " defining materializing symbols "
- << NewSymbolFlags << "\n";
- });
- if (auto AcceptedDefs = JD->defineMaterializing(std::move(NewSymbolFlags))) {
- // Add all newly accepted symbols to this responsibility object.
- for (auto &KV : *AcceptedDefs)
- SymbolFlags.insert(KV);
- return Error::success();
- } else
- return AcceptedDefs.takeError();
-}
-
-void MaterializationResponsibility::failMaterialization() {
-
- LLVM_DEBUG({
- dbgs() << "In " << JD->getName() << " failing materialization for "
- << SymbolFlags << "\n";
- });
-
- JITDylib::FailedSymbolsWorklist Worklist;
-
- for (auto &KV : SymbolFlags)
- Worklist.push_back(std::make_pair(JD.get(), KV.first));
- SymbolFlags.clear();
-
- JD->notifyFailed(std::move(Worklist));
-}
-
-void MaterializationResponsibility::replace(
- std::unique_ptr<MaterializationUnit> MU) {
-
- // If the replacement MU is empty then return.
- if (MU->getSymbols().empty())
- return;
-
- for (auto &KV : MU->getSymbols()) {
- assert(SymbolFlags.count(KV.first) &&
- "Replacing definition outside this responsibility set");
- SymbolFlags.erase(KV.first);
- }
-
- if (MU->getInitializerSymbol() == InitSymbol)
- InitSymbol = nullptr;
-
- LLVM_DEBUG(JD->getExecutionSession().runSessionLocked([&]() {
- dbgs() << "In " << JD->getName() << " replacing symbols with " << *MU
- << "\n";
- }););
-
- JD->replace(std::move(MU));
-}
-
-MaterializationResponsibility
-MaterializationResponsibility::delegate(const SymbolNameSet &Symbols,
- VModuleKey NewKey) {
-
- if (NewKey == VModuleKey())
- NewKey = K;
-
- SymbolStringPtr DelegatedInitSymbol;
- SymbolFlagsMap DelegatedFlags;
-
- for (auto &Name : Symbols) {
- auto I = SymbolFlags.find(Name);
- assert(I != SymbolFlags.end() &&
- "Symbol is not tracked by this MaterializationResponsibility "
- "instance");
-
- DelegatedFlags[Name] = std::move(I->second);
- if (Name == InitSymbol)
- std::swap(InitSymbol, DelegatedInitSymbol);
-
- SymbolFlags.erase(I);
- }
-
- return MaterializationResponsibility(JD, std::move(DelegatedFlags),
- std::move(DelegatedInitSymbol),
- std::move(NewKey));
-}
-
-void MaterializationResponsibility::addDependencies(
- const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) {
- LLVM_DEBUG({
- dbgs() << "Adding dependencies for " << Name << ": " << Dependencies
- << "\n";
- });
- assert(SymbolFlags.count(Name) &&
- "Symbol not covered by this MaterializationResponsibility instance");
- JD->addDependencies(Name, Dependencies);
-}
-
-void MaterializationResponsibility::addDependenciesForAll(
- const SymbolDependenceMap &Dependencies) {
- LLVM_DEBUG({
- dbgs() << "Adding dependencies for all symbols in " << SymbolFlags << ": "
- << Dependencies << "\n";
- });
- for (auto &KV : SymbolFlags)
- JD->addDependencies(KV.first, Dependencies);
-}
-
AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit(
- SymbolMap Symbols, VModuleKey K)
- : MaterializationUnit(extractFlags(Symbols), nullptr, std::move(K)),
+ SymbolMap Symbols)
+ : MaterializationUnit(extractFlags(Symbols), nullptr),
Symbols(std::move(Symbols)) {}
StringRef AbsoluteSymbolsMaterializationUnit::getName() const {
@@ -338,10 +229,10 @@ StringRef AbsoluteSymbolsMaterializationUnit::getName() const {
}
void AbsoluteSymbolsMaterializationUnit::materialize(
- MaterializationResponsibility R) {
+ std::unique_ptr<MaterializationResponsibility> R) {
// No dependencies, so these calls can't fail.
- cantFail(R.notifyResolved(Symbols));
- cantFail(R.notifyEmitted());
+ cantFail(R->notifyResolved(Symbols));
+ cantFail(R->notifyEmitted());
}
void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
@@ -360,26 +251,25 @@ AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
ReExportsMaterializationUnit::ReExportsMaterializationUnit(
JITDylib *SourceJD, JITDylibLookupFlags SourceJDLookupFlags,
- SymbolAliasMap Aliases, VModuleKey K)
- : MaterializationUnit(extractFlags(Aliases), nullptr, std::move(K)),
- SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags),
- Aliases(std::move(Aliases)) {}
+ SymbolAliasMap Aliases)
+ : MaterializationUnit(extractFlags(Aliases), nullptr), SourceJD(SourceJD),
+ SourceJDLookupFlags(SourceJDLookupFlags), Aliases(std::move(Aliases)) {}
StringRef ReExportsMaterializationUnit::getName() const {
return "<Reexports>";
}
void ReExportsMaterializationUnit::materialize(
- MaterializationResponsibility R) {
+ std::unique_ptr<MaterializationResponsibility> R) {
- auto &ES = R.getTargetJITDylib().getExecutionSession();
- JITDylib &TgtJD = R.getTargetJITDylib();
+ auto &ES = R->getTargetJITDylib().getExecutionSession();
+ JITDylib &TgtJD = R->getTargetJITDylib();
JITDylib &SrcJD = SourceJD ? *SourceJD : TgtJD;
// Find the set of requested aliases and aliasees. Return any unrequested
// aliases back to the JITDylib so as to not prematurely materialize any
// aliasees.
- auto RequestedSymbols = R.getRequestedSymbols();
+ auto RequestedSymbols = R->getRequestedSymbols();
SymbolAliasMap RequestedAliases;
for (auto &Name : RequestedSymbols) {
@@ -398,19 +288,27 @@ void ReExportsMaterializationUnit::materialize(
});
if (!Aliases.empty()) {
- if (SourceJD)
- R.replace(reexports(*SourceJD, std::move(Aliases), SourceJDLookupFlags));
- else
- R.replace(symbolAliases(std::move(Aliases)));
+ auto Err = SourceJD ? R->replace(reexports(*SourceJD, std::move(Aliases),
+ SourceJDLookupFlags))
+ : R->replace(symbolAliases(std::move(Aliases)));
+
+ if (Err) {
+ // FIXME: Should this be reported / treated as failure to materialize?
+ // Or should this be treated as a sanctioned bailing-out?
+ ES.reportError(std::move(Err));
+ R->failMaterialization();
+ return;
+ }
}
// The OnResolveInfo struct will hold the aliases and responsibilty for each
// query in the list.
struct OnResolveInfo {
- OnResolveInfo(MaterializationResponsibility R, SymbolAliasMap Aliases)
+ OnResolveInfo(std::unique_ptr<MaterializationResponsibility> R,
+ SymbolAliasMap Aliases)
: R(std::move(R)), Aliases(std::move(Aliases)) {}
- MaterializationResponsibility R;
+ std::unique_ptr<MaterializationResponsibility> R;
SymbolAliasMap Aliases;
};
@@ -450,8 +348,15 @@ void ReExportsMaterializationUnit::materialize(
assert(!QuerySymbols.empty() && "Alias cycle detected!");
- auto QueryInfo = std::make_shared<OnResolveInfo>(
- R.delegate(ResponsibilitySymbols), std::move(QueryAliases));
+ auto NewR = R->delegate(ResponsibilitySymbols);
+ if (!NewR) {
+ ES.reportError(NewR.takeError());
+ R->failMaterialization();
+ return;
+ }
+
+ auto QueryInfo = std::make_shared<OnResolveInfo>(std::move(*NewR),
+ std::move(QueryAliases));
QueryInfos.push_back(
make_pair(std::move(QuerySymbols), std::move(QueryInfo)));
}
@@ -480,12 +385,12 @@ void ReExportsMaterializationUnit::materialize(
for (auto &KV : QueryInfo->Aliases)
if (SrcJDDeps.count(KV.second.Aliasee)) {
PerAliasDeps = {KV.second.Aliasee};
- QueryInfo->R.addDependencies(KV.first, PerAliasDepsMap);
+ QueryInfo->R->addDependencies(KV.first, PerAliasDepsMap);
}
};
auto OnComplete = [QueryInfo](Expected<SymbolMap> Result) {
- auto &ES = QueryInfo->R.getTargetJITDylib().getExecutionSession();
+ auto &ES = QueryInfo->R->getTargetJITDylib().getExecutionSession();
if (Result) {
SymbolMap ResolutionMap;
for (auto &KV : QueryInfo->Aliases) {
@@ -499,19 +404,19 @@ void ReExportsMaterializationUnit::materialize(
ResolutionMap[KV.first] = JITEvaluatedSymbol(
(*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
}
- if (auto Err = QueryInfo->R.notifyResolved(ResolutionMap)) {
+ if (auto Err = QueryInfo->R->notifyResolved(ResolutionMap)) {
ES.reportError(std::move(Err));
- QueryInfo->R.failMaterialization();
+ QueryInfo->R->failMaterialization();
return;
}
- if (auto Err = QueryInfo->R.notifyEmitted()) {
+ if (auto Err = QueryInfo->R->notifyEmitted()) {
ES.reportError(std::move(Err));
- QueryInfo->R.failMaterialization();
+ QueryInfo->R->failMaterialization();
return;
}
} else {
ES.reportError(Result.takeError());
- QueryInfo->R.failMaterialization();
+ QueryInfo->R->failMaterialization();
}
};
@@ -538,20 +443,16 @@ ReExportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
return SymbolFlags;
}
-Expected<SymbolAliasMap>
-buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols) {
+Expected<SymbolAliasMap> buildSimpleReexportsAliasMap(JITDylib &SourceJD,
+ SymbolNameSet Symbols) {
SymbolLookupSet LookupSet(Symbols);
- auto Flags = SourceJD.lookupFlags(
- LookupKind::Static, JITDylibLookupFlags::MatchAllSymbols, LookupSet);
+ auto Flags = SourceJD.getExecutionSession().lookupFlags(
+ LookupKind::Static, {{&SourceJD, JITDylibLookupFlags::MatchAllSymbols}},
+ SymbolLookupSet(std::move(Symbols)));
if (!Flags)
return Flags.takeError();
- if (!LookupSet.empty()) {
- LookupSet.sortByName();
- return make_error<SymbolsNotFound>(LookupSet.getSymbolNames());
- }
-
SymbolAliasMap Result;
for (auto &Name : Symbols) {
assert(Flags->count(Name) && "Missing entry in flags map");
@@ -561,19 +462,100 @@ buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols) {
return Result;
}
+class InProgressLookupState {
+public:
+ InProgressLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,
+ SymbolLookupSet LookupSet, SymbolState RequiredState)
+ : K(K), SearchOrder(std::move(SearchOrder)),
+ LookupSet(std::move(LookupSet)), RequiredState(RequiredState) {
+ DefGeneratorCandidates = this->LookupSet;
+ }
+ virtual ~InProgressLookupState() {}
+ virtual void complete(std::unique_ptr<InProgressLookupState> IPLS) = 0;
+ virtual void fail(Error Err) = 0;
+
+ LookupKind K;
+ JITDylibSearchOrder SearchOrder;
+ SymbolLookupSet LookupSet;
+ SymbolState RequiredState;
+
+ std::unique_lock<std::mutex> GeneratorLock;
+ size_t CurSearchOrderIndex = 0;
+ bool NewJITDylib = true;
+ SymbolLookupSet DefGeneratorCandidates;
+ SymbolLookupSet DefGeneratorNonCandidates;
+ std::vector<std::weak_ptr<DefinitionGenerator>> CurDefGeneratorStack;
+};
+
+class InProgressLookupFlagsState : public InProgressLookupState {
+public:
+ InProgressLookupFlagsState(
+ LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
+ unique_function<void(Expected<SymbolFlagsMap>)> OnComplete)
+ : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),
+ SymbolState::NeverSearched),
+ OnComplete(std::move(OnComplete)) {}
+
+ void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
+ GeneratorLock = {}; // Unlock and release.
+ auto &ES = SearchOrder.front().first->getExecutionSession();
+ ES.OL_completeLookupFlags(std::move(IPLS), std::move(OnComplete));
+ }
+
+ void fail(Error Err) override {
+ GeneratorLock = {}; // Unlock and release.
+ OnComplete(std::move(Err));
+ }
+
+private:
+ unique_function<void(Expected<SymbolFlagsMap>)> OnComplete;
+};
+
+class InProgressFullLookupState : public InProgressLookupState {
+public:
+ InProgressFullLookupState(LookupKind K, JITDylibSearchOrder SearchOrder,
+ SymbolLookupSet LookupSet,
+ SymbolState RequiredState,
+ std::shared_ptr<AsynchronousSymbolQuery> Q,
+ RegisterDependenciesFunction RegisterDependencies)
+ : InProgressLookupState(K, std::move(SearchOrder), std::move(LookupSet),
+ RequiredState),
+ Q(std::move(Q)), RegisterDependencies(std::move(RegisterDependencies)) {
+ }
+
+ void complete(std::unique_ptr<InProgressLookupState> IPLS) override {
+ GeneratorLock = {}; // Unlock and release.
+ auto &ES = SearchOrder.front().first->getExecutionSession();
+ ES.OL_completeLookup(std::move(IPLS), std::move(Q),
+ std::move(RegisterDependencies));
+ }
+
+ void fail(Error Err) override {
+ GeneratorLock = {};
+ Q->detach();
+ Q->handleFailed(std::move(Err));
+ }
+
+private:
+ std::shared_ptr<AsynchronousSymbolQuery> Q;
+ RegisterDependenciesFunction RegisterDependencies;
+};
+
ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD,
JITDylibLookupFlags SourceJDLookupFlags,
SymbolPredicate Allow)
: SourceJD(SourceJD), SourceJDLookupFlags(SourceJDLookupFlags),
Allow(std::move(Allow)) {}
-Error ReexportsGenerator::tryToGenerate(LookupKind K, JITDylib &JD,
+Error ReexportsGenerator::tryToGenerate(LookupState &LS, LookupKind K,
+ JITDylib &JD,
JITDylibLookupFlags JDLookupFlags,
const SymbolLookupSet &LookupSet) {
assert(&JD != &SourceJD && "Cannot re-export from the same dylib");
// Use lookupFlags to find the subset of symbols that match our lookup.
- auto Flags = SourceJD.lookupFlags(K, JDLookupFlags, LookupSet);
+ auto Flags = JD.getExecutionSession().lookupFlags(
+ K, {{&SourceJD, JDLookupFlags}}, LookupSet);
if (!Flags)
return Flags.takeError();
@@ -590,19 +572,63 @@ Error ReexportsGenerator::tryToGenerate(LookupKind K, JITDylib &JD,
return JD.define(reexports(SourceJD, AliasMap, SourceJDLookupFlags));
}
-JITDylib::DefinitionGenerator::~DefinitionGenerator() {}
+LookupState::LookupState(std::unique_ptr<InProgressLookupState> IPLS)
+ : IPLS(std::move(IPLS)) {}
-void JITDylib::removeGenerator(DefinitionGenerator &G) {
+void LookupState::reset(InProgressLookupState *IPLS) { this->IPLS.reset(IPLS); }
+
+LookupState::LookupState() = default;
+LookupState::LookupState(LookupState &&) = default;
+LookupState &LookupState::operator=(LookupState &&) = default;
+LookupState::~LookupState() = default;
+
+void LookupState::continueLookup(Error Err) {
+ assert(IPLS && "Cannot call continueLookup on empty LookupState");
+ auto &ES = IPLS->SearchOrder.begin()->first->getExecutionSession();
+ ES.OL_applyQueryPhase1(std::move(IPLS), std::move(Err));
+}
+
+DefinitionGenerator::~DefinitionGenerator() {}
+
+Error JITDylib::clear() {
+ std::vector<ResourceTrackerSP> TrackersToRemove;
ES.runSessionLocked([&]() {
- auto I = std::find_if(DefGenerators.begin(), DefGenerators.end(),
- [&](const std::unique_ptr<DefinitionGenerator> &H) {
- return H.get() == &G;
- });
- assert(I != DefGenerators.end() && "Generator not found");
- DefGenerators.erase(I);
+ for (auto &KV : TrackerSymbols)
+ TrackersToRemove.push_back(KV.first);
+ TrackersToRemove.push_back(getDefaultResourceTracker());
+ });
+
+ Error Err = Error::success();
+ for (auto &RT : TrackersToRemove)
+ Err = joinErrors(std::move(Err), RT->remove());
+ return Err;
+}
+
+ResourceTrackerSP JITDylib::getDefaultResourceTracker() {
+ return ES.runSessionLocked([this] {
+ if (!DefaultTracker)
+ DefaultTracker = new ResourceTracker(this);
+ return DefaultTracker;
+ });
+}
+
+ResourceTrackerSP JITDylib::createResourceTracker() {
+ return ES.runSessionLocked([this] {
+ ResourceTrackerSP RT = new ResourceTracker(this);
+ return RT;
});
}
+void JITDylib::removeGenerator(DefinitionGenerator &G) {
+ std::lock_guard<std::mutex> Lock(GeneratorsMutex);
+ auto I = llvm::find_if(DefGenerators,
+ [&](const std::shared_ptr<DefinitionGenerator> &H) {
+ return H.get() == &G;
+ });
+ assert(I != DefGenerators.end() && "Generator not found");
+ DefGenerators.erase(I);
+}
+
Expected<SymbolFlagsMap>
JITDylib::defineMaterializing(SymbolFlagsMap SymbolFlags) {
@@ -652,11 +678,18 @@ JITDylib::defineMaterializing(SymbolFlagsMap SymbolFlags) {
});
}
-void JITDylib::replace(std::unique_ptr<MaterializationUnit> MU) {
+Error JITDylib::replace(MaterializationResponsibility &FromMR,
+ std::unique_ptr<MaterializationUnit> MU) {
assert(MU != nullptr && "Can not replace with a null MaterializationUnit");
+ std::unique_ptr<MaterializationUnit> MustRunMU;
+ std::unique_ptr<MaterializationResponsibility> MustRunMR;
- auto MustRunMU =
- ES.runSessionLocked([&, this]() -> std::unique_ptr<MaterializationUnit> {
+ auto Err =
+ ES.runSessionLocked([&, this]() -> Error {
+ auto RT = getTracker(FromMR);
+
+ if (RT->isDefunct())
+ return make_error<ResourceTrackerDefunct>(std::move(RT));
#ifndef NDEBUG
for (auto &KV : MU->getSymbols()) {
@@ -671,18 +704,27 @@ void JITDylib::replace(std::unique_ptr<MaterializationUnit> MU) {
}
#endif // NDEBUG
+ // If the tracker is defunct we need to bail out immediately.
+
// If any symbol has pending queries against it then we need to
// materialize MU immediately.
for (auto &KV : MU->getSymbols()) {
auto MII = MaterializingInfos.find(KV.first);
if (MII != MaterializingInfos.end()) {
- if (MII->second.hasQueriesPending())
- return std::move(MU);
+ if (MII->second.hasQueriesPending()) {
+ MustRunMR = ES.createMaterializationResponsibility(
+ *RT, std::move(MU->SymbolFlags), std::move(MU->InitSymbol));
+ MustRunMU = std::move(MU);
+ return Error::success();
+ }
}
}
// Otherwise, make MU responsible for all the symbols.
- auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
+ auto RTI = MRTrackers.find(&FromMR);
+ assert(RTI != MRTrackers.end() && "No tracker for FromMR");
+ auto UMI =
+ std::make_shared<UnmaterializedInfo>(std::move(MU), RTI->second);
for (auto &KV : UMI->MU->getSymbols()) {
auto SymI = Symbols.find(KV.first);
assert(SymI->second.getState() == SymbolState::Materializing &&
@@ -700,14 +742,36 @@ void JITDylib::replace(std::unique_ptr<MaterializationUnit> MU) {
UMIEntry = UMI;
}
- return nullptr;
+ return Error::success();
});
+ if (Err)
+ return Err;
+
if (MustRunMU) {
- auto MR =
- MustRunMU->createMaterializationResponsibility(shared_from_this());
- ES.dispatchMaterialization(std::move(MustRunMU), std::move(MR));
+ assert(MustRunMR && "MustRunMU set implies MustRunMR set");
+ ES.dispatchMaterialization(std::move(MustRunMU), std::move(MustRunMR));
+ } else {
+ assert(!MustRunMR && "MustRunMU unset implies MustRunMR unset");
}
+
+ return Error::success();
+}
+
+Expected<std::unique_ptr<MaterializationResponsibility>>
+JITDylib::delegate(MaterializationResponsibility &FromMR,
+ SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol) {
+
+ return ES.runSessionLocked(
+ [&]() -> Expected<std::unique_ptr<MaterializationResponsibility>> {
+ auto RT = getTracker(FromMR);
+
+ if (RT->isDefunct())
+ return make_error<ResourceTrackerDefunct>(std::move(RT));
+
+ return ES.createMaterializationResponsibility(
+ *RT, std::move(SymbolFlags), std::move(InitSymbol));
+ });
}
SymbolNameSet
@@ -808,89 +872,93 @@ void JITDylib::addDependencies(const SymbolStringPtr &Name,
Symbols[Name].setFlags(Symbols[Name].getFlags() | JITSymbolFlags::HasError);
}
-Error JITDylib::resolve(const SymbolMap &Resolved) {
- SymbolNameSet SymbolsInErrorState;
+Error JITDylib::resolve(MaterializationResponsibility &MR,
+ const SymbolMap &Resolved) {
AsynchronousSymbolQuerySet CompletedQueries;
- ES.runSessionLocked([&, this]() {
- struct WorklistEntry {
- SymbolTable::iterator SymI;
- JITEvaluatedSymbol ResolvedSym;
- };
+ if (auto Err = ES.runSessionLocked([&, this]() -> Error {
+ auto RTI = MRTrackers.find(&MR);
+ assert(RTI != MRTrackers.end() && "No resource tracker for MR?");
+ if (RTI->second->isDefunct())
+ return make_error<ResourceTrackerDefunct>(RTI->second);
- std::vector<WorklistEntry> Worklist;
- Worklist.reserve(Resolved.size());
+ struct WorklistEntry {
+ SymbolTable::iterator SymI;
+ JITEvaluatedSymbol ResolvedSym;
+ };
- // Build worklist and check for any symbols in the error state.
- for (const auto &KV : Resolved) {
+ SymbolNameSet SymbolsInErrorState;
+ std::vector<WorklistEntry> Worklist;
+ Worklist.reserve(Resolved.size());
- assert(!KV.second.getFlags().hasError() &&
- "Resolution result can not have error flag set");
+ // Build worklist and check for any symbols in the error state.
+ for (const auto &KV : Resolved) {
- auto SymI = Symbols.find(KV.first);
+ assert(!KV.second.getFlags().hasError() &&
+ "Resolution result can not have error flag set");
- assert(SymI != Symbols.end() && "Symbol not found");
- assert(!SymI->second.hasMaterializerAttached() &&
- "Resolving symbol with materializer attached?");
- assert(SymI->second.getState() == SymbolState::Materializing &&
- "Symbol should be materializing");
- assert(SymI->second.getAddress() == 0 &&
- "Symbol has already been resolved");
+ auto SymI = Symbols.find(KV.first);
- if (SymI->second.getFlags().hasError())
- SymbolsInErrorState.insert(KV.first);
- else {
- auto Flags = KV.second.getFlags();
- Flags &= ~(JITSymbolFlags::Weak | JITSymbolFlags::Common);
- assert(Flags == (SymI->second.getFlags() &
- ~(JITSymbolFlags::Weak | JITSymbolFlags::Common)) &&
- "Resolved flags should match the declared flags");
+ assert(SymI != Symbols.end() && "Symbol not found");
+ assert(!SymI->second.hasMaterializerAttached() &&
+ "Resolving symbol with materializer attached?");
+ assert(SymI->second.getState() == SymbolState::Materializing &&
+ "Symbol should be materializing");
+ assert(SymI->second.getAddress() == 0 &&
+ "Symbol has already been resolved");
- Worklist.push_back(
- {SymI, JITEvaluatedSymbol(KV.second.getAddress(), Flags)});
- }
- }
+ if (SymI->second.getFlags().hasError())
+ SymbolsInErrorState.insert(KV.first);
+ else {
+ auto Flags = KV.second.getFlags();
+ Flags &= ~(JITSymbolFlags::Weak | JITSymbolFlags::Common);
+ assert(Flags ==
+ (SymI->second.getFlags() &
+ ~(JITSymbolFlags::Weak | JITSymbolFlags::Common)) &&
+ "Resolved flags should match the declared flags");
- // If any symbols were in the error state then bail out.
- if (!SymbolsInErrorState.empty())
- return;
+ Worklist.push_back(
+ {SymI, JITEvaluatedSymbol(KV.second.getAddress(), Flags)});
+ }
+ }
- while (!Worklist.empty()) {
- auto SymI = Worklist.back().SymI;
- auto ResolvedSym = Worklist.back().ResolvedSym;
- Worklist.pop_back();
+ // If any symbols were in the error state then bail out.
+ if (!SymbolsInErrorState.empty()) {
+ auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
+ (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
+ return make_error<FailedToMaterialize>(
+ std::move(FailedSymbolsDepMap));
+ }
- auto &Name = SymI->first;
+ while (!Worklist.empty()) {
+ auto SymI = Worklist.back().SymI;
+ auto ResolvedSym = Worklist.back().ResolvedSym;
+ Worklist.pop_back();
- // Resolved symbols can not be weak: discard the weak flag.
- JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags();
- SymI->second.setAddress(ResolvedSym.getAddress());
- SymI->second.setFlags(ResolvedFlags);
- SymI->second.setState(SymbolState::Resolved);
+ auto &Name = SymI->first;
- auto MII = MaterializingInfos.find(Name);
- if (MII == MaterializingInfos.end())
- continue;
+ // Resolved symbols can not be weak: discard the weak flag.
+ JITSymbolFlags ResolvedFlags = ResolvedSym.getFlags();
+ SymI->second.setAddress(ResolvedSym.getAddress());
+ SymI->second.setFlags(ResolvedFlags);
+ SymI->second.setState(SymbolState::Resolved);
- auto &MI = MII->second;
- for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {
- Q->notifySymbolMetRequiredState(Name, ResolvedSym);
- Q->removeQueryDependence(*this, Name);
- if (Q->isComplete())
- CompletedQueries.insert(std::move(Q));
- }
- }
- });
+ auto MII = MaterializingInfos.find(Name);
+ if (MII == MaterializingInfos.end())
+ continue;
- assert((SymbolsInErrorState.empty() || CompletedQueries.empty()) &&
- "Can't fail symbols and completed queries at the same time");
+ auto &MI = MII->second;
+ for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) {
+ Q->notifySymbolMetRequiredState(Name, ResolvedSym);
+ Q->removeQueryDependence(*this, Name);
+ if (Q->isComplete())
+ CompletedQueries.insert(std::move(Q));
+ }
+ }
- // If we failed any symbols then return an error.
- if (!SymbolsInErrorState.empty()) {
- auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
- (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
- return make_error<FailedToMaterialize>(std::move(FailedSymbolsDepMap));
- }
+ return Error::success();
+ }))
+ return Err;
// Otherwise notify all the completed queries.
for (auto &Q : CompletedQueries) {
@@ -901,139 +969,145 @@ Error JITDylib::resolve(const SymbolMap &Resolved) {
return Error::success();
}
-Error JITDylib::emit(const SymbolFlagsMap &Emitted) {
+Error JITDylib::emit(MaterializationResponsibility &MR,
+ const SymbolFlagsMap &Emitted) {
AsynchronousSymbolQuerySet CompletedQueries;
- SymbolNameSet SymbolsInErrorState;
DenseMap<JITDylib *, SymbolNameVector> ReadySymbols;
- ES.runSessionLocked([&, this]() {
- std::vector<SymbolTable::iterator> Worklist;
+ if (auto Err = ES.runSessionLocked([&, this]() -> Error {
+ auto RTI = MRTrackers.find(&MR);
+ assert(RTI != MRTrackers.end() && "No resource tracker for MR?");
+ if (RTI->second->isDefunct())
+ return make_error<ResourceTrackerDefunct>(RTI->second);
- // Scan to build worklist, record any symbols in the erorr state.
- for (const auto &KV : Emitted) {
- auto &Name = KV.first;
+ SymbolNameSet SymbolsInErrorState;
+ std::vector<SymbolTable::iterator> Worklist;
- auto SymI = Symbols.find(Name);
- assert(SymI != Symbols.end() && "No symbol table entry for Name");
+ // Scan to build worklist, record any symbols in the erorr state.
+ for (const auto &KV : Emitted) {
+ auto &Name = KV.first;
- if (SymI->second.getFlags().hasError())
- SymbolsInErrorState.insert(Name);
- else
- Worklist.push_back(SymI);
- }
+ auto SymI = Symbols.find(Name);
+ assert(SymI != Symbols.end() && "No symbol table entry for Name");
- // If any symbols were in the error state then bail out.
- if (!SymbolsInErrorState.empty())
- return;
+ if (SymI->second.getFlags().hasError())
+ SymbolsInErrorState.insert(Name);
+ else
+ Worklist.push_back(SymI);
+ }
- // Otherwise update dependencies and move to the emitted state.
- while (!Worklist.empty()) {
- auto SymI = Worklist.back();
- Worklist.pop_back();
+ // If any symbols were in the error state then bail out.
+ if (!SymbolsInErrorState.empty()) {
+ auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
+ (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
+ return make_error<FailedToMaterialize>(
+ std::move(FailedSymbolsDepMap));
+ }
- auto &Name = SymI->first;
- auto &SymEntry = SymI->second;
+ // Otherwise update dependencies and move to the emitted state.
+ while (!Worklist.empty()) {
+ auto SymI = Worklist.back();
+ Worklist.pop_back();
- // Move symbol to the emitted state.
- assert(((SymEntry.getFlags().hasMaterializationSideEffectsOnly() &&
- SymEntry.getState() == SymbolState::Materializing) ||
- SymEntry.getState() == SymbolState::Resolved) &&
- "Emitting from state other than Resolved");
- SymEntry.setState(SymbolState::Emitted);
+ auto &Name = SymI->first;
+ auto &SymEntry = SymI->second;
- auto MII = MaterializingInfos.find(Name);
+ // Move symbol to the emitted state.
+ assert(((SymEntry.getFlags().hasMaterializationSideEffectsOnly() &&
+ SymEntry.getState() == SymbolState::Materializing) ||
+ SymEntry.getState() == SymbolState::Resolved) &&
+ "Emitting from state other than Resolved");
+ SymEntry.setState(SymbolState::Emitted);
- // If this symbol has no MaterializingInfo then it's trivially ready.
- // Update its state and continue.
- if (MII == MaterializingInfos.end()) {
- SymEntry.setState(SymbolState::Ready);
- continue;
- }
+ auto MII = MaterializingInfos.find(Name);
- auto &MI = MII->second;
+ // If this symbol has no MaterializingInfo then it's trivially ready.
+ // Update its state and continue.
+ if (MII == MaterializingInfos.end()) {
+ SymEntry.setState(SymbolState::Ready);
+ continue;
+ }
- // For each dependant, transfer this node's emitted dependencies to
- // it. If the dependant node is ready (i.e. has no unemitted
- // dependencies) then notify any pending queries.
- for (auto &KV : MI.Dependants) {
- auto &DependantJD = *KV.first;
- auto &DependantJDReadySymbols = ReadySymbols[&DependantJD];
- for (auto &DependantName : KV.second) {
- auto DependantMII =
- DependantJD.MaterializingInfos.find(DependantName);
- assert(DependantMII != DependantJD.MaterializingInfos.end() &&
- "Dependant should have MaterializingInfo");
+ auto &MI = MII->second;
- auto &DependantMI = DependantMII->second;
+ // For each dependant, transfer this node's emitted dependencies to
+ // it. If the dependant node is ready (i.e. has no unemitted
+ // dependencies) then notify any pending queries.
+ for (auto &KV : MI.Dependants) {
+ auto &DependantJD = *KV.first;
+ auto &DependantJDReadySymbols = ReadySymbols[&DependantJD];
+ for (auto &DependantName : KV.second) {
+ auto DependantMII =
+ DependantJD.MaterializingInfos.find(DependantName);
+ assert(DependantMII != DependantJD.MaterializingInfos.end() &&
+ "Dependant should have MaterializingInfo");
- // Remove the dependant's dependency on this node.
- assert(DependantMI.UnemittedDependencies.count(this) &&
- "Dependant does not have an unemitted dependencies record for "
- "this JITDylib");
- assert(DependantMI.UnemittedDependencies[this].count(Name) &&
- "Dependant does not count this symbol as a dependency?");
+ auto &DependantMI = DependantMII->second;
- DependantMI.UnemittedDependencies[this].erase(Name);
- if (DependantMI.UnemittedDependencies[this].empty())
- DependantMI.UnemittedDependencies.erase(this);
+ // Remove the dependant's dependency on this node.
+ assert(DependantMI.UnemittedDependencies.count(this) &&
+ "Dependant does not have an unemitted dependencies record "
+ "for "
+ "this JITDylib");
+ assert(DependantMI.UnemittedDependencies[this].count(Name) &&
+ "Dependant does not count this symbol as a dependency?");
- // Transfer unemitted dependencies from this node to the dependant.
- DependantJD.transferEmittedNodeDependencies(DependantMI,
- DependantName, MI);
+ DependantMI.UnemittedDependencies[this].erase(Name);
+ if (DependantMI.UnemittedDependencies[this].empty())
+ DependantMI.UnemittedDependencies.erase(this);
- auto DependantSymI = DependantJD.Symbols.find(DependantName);
- assert(DependantSymI != DependantJD.Symbols.end() &&
- "Dependant has no entry in the Symbols table");
- auto &DependantSymEntry = DependantSymI->second;
+ // Transfer unemitted dependencies from this node to the
+ // dependant.
+ DependantJD.transferEmittedNodeDependencies(DependantMI,
+ DependantName, MI);
- // If the dependant is emitted and this node was the last of its
- // unemitted dependencies then the dependant node is now ready, so
- // notify any pending queries on the dependant node.
- if (DependantSymEntry.getState() == SymbolState::Emitted &&
- DependantMI.UnemittedDependencies.empty()) {
- assert(DependantMI.Dependants.empty() &&
- "Dependants should be empty by now");
+ auto DependantSymI = DependantJD.Symbols.find(DependantName);
+ assert(DependantSymI != DependantJD.Symbols.end() &&
+ "Dependant has no entry in the Symbols table");
+ auto &DependantSymEntry = DependantSymI->second;
- // Since this dependant is now ready, we erase its MaterializingInfo
- // and update its materializing state.
- DependantSymEntry.setState(SymbolState::Ready);
- DependantJDReadySymbols.push_back(DependantName);
+ // If the dependant is emitted and this node was the last of its
+ // unemitted dependencies then the dependant node is now ready, so
+ // notify any pending queries on the dependant node.
+ if (DependantSymEntry.getState() == SymbolState::Emitted &&
+ DependantMI.UnemittedDependencies.empty()) {
+ assert(DependantMI.Dependants.empty() &&
+ "Dependants should be empty by now");
- for (auto &Q : DependantMI.takeQueriesMeeting(SymbolState::Ready)) {
- Q->notifySymbolMetRequiredState(
- DependantName, DependantSymI->second.getSymbol());
+ // Since this dependant is now ready, we erase its
+ // MaterializingInfo and update its materializing state.
+ DependantSymEntry.setState(SymbolState::Ready);
+ DependantJDReadySymbols.push_back(DependantName);
+
+ for (auto &Q :
+ DependantMI.takeQueriesMeeting(SymbolState::Ready)) {
+ Q->notifySymbolMetRequiredState(
+ DependantName, DependantSymI->second.getSymbol());
+ if (Q->isComplete())
+ CompletedQueries.insert(Q);
+ Q->removeQueryDependence(DependantJD, DependantName);
+ }
+ }
+ }
+ }
+
+ auto &ThisJDReadySymbols = ReadySymbols[this];
+ MI.Dependants.clear();
+ if (MI.UnemittedDependencies.empty()) {
+ SymI->second.setState(SymbolState::Ready);
+ ThisJDReadySymbols.push_back(Name);
+ for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {
+ Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
if (Q->isComplete())
CompletedQueries.insert(Q);
- Q->removeQueryDependence(DependantJD, DependantName);
+ Q->removeQueryDependence(*this, Name);
}
}
}
- }
- auto &ThisJDReadySymbols = ReadySymbols[this];
- MI.Dependants.clear();
- if (MI.UnemittedDependencies.empty()) {
- SymI->second.setState(SymbolState::Ready);
- ThisJDReadySymbols.push_back(Name);
- for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) {
- Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
- if (Q->isComplete())
- CompletedQueries.insert(Q);
- Q->removeQueryDependence(*this, Name);
- }
- }
- }
- });
-
- assert((SymbolsInErrorState.empty() || CompletedQueries.empty()) &&
- "Can't fail symbols and completed queries at the same time");
-
- // If we failed any symbols then return an error.
- if (!SymbolsInErrorState.empty()) {
- auto FailedSymbolsDepMap = std::make_shared<SymbolDependenceMap>();
- (*FailedSymbolsDepMap)[this] = std::move(SymbolsInErrorState);
- return make_error<FailedToMaterialize>(std::move(FailedSymbolsDepMap));
- }
+ return Error::success();
+ }))
+ return Err;
// Otherwise notify all the completed queries.
for (auto &Q : CompletedQueries) {
@@ -1044,120 +1118,122 @@ Error JITDylib::emit(const SymbolFlagsMap &Emitted) {
return Error::success();
}
-void JITDylib::notifyFailed(FailedSymbolsWorklist Worklist) {
+void JITDylib::unlinkMaterializationResponsibility(
+ MaterializationResponsibility &MR) {
+ ES.runSessionLocked([&]() {
+ auto I = MRTrackers.find(&MR);
+ assert(I != MRTrackers.end() && "MaterializationResponsibility not linked");
+ MRTrackers.erase(I);
+ });
+}
+
+std::pair<JITDylib::AsynchronousSymbolQuerySet,
+ std::shared_ptr<SymbolDependenceMap>>
+JITDylib::failSymbols(FailedSymbolsWorklist Worklist) {
AsynchronousSymbolQuerySet FailedQueries;
auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
- // Failing no symbols is a no-op.
- if (Worklist.empty())
- return;
-
- auto &ES = Worklist.front().first->getExecutionSession();
-
- ES.runSessionLocked([&]() {
- while (!Worklist.empty()) {
- assert(Worklist.back().first && "Failed JITDylib can not be null");
- auto &JD = *Worklist.back().first;
- auto Name = std::move(Worklist.back().second);
- Worklist.pop_back();
+ while (!Worklist.empty()) {
+ assert(Worklist.back().first && "Failed JITDylib can not be null");
+ auto &JD = *Worklist.back().first;
+ auto Name = std::move(Worklist.back().second);
+ Worklist.pop_back();
- (*FailedSymbolsMap)[&JD].insert(Name);
+ (*FailedSymbolsMap)[&JD].insert(Name);
- assert(JD.Symbols.count(Name) && "No symbol table entry for Name");
- auto &Sym = JD.Symbols[Name];
+ assert(JD.Symbols.count(Name) && "No symbol table entry for Name");
+ auto &Sym = JD.Symbols[Name];
- // Move the symbol into the error state.
- // Note that this may be redundant: The symbol might already have been
- // moved to this state in response to the failure of a dependence.
- Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError);
+ // Move the symbol into the error state.
+ // Note that this may be redundant: The symbol might already have been
+ // moved to this state in response to the failure of a dependence.
+ Sym.setFlags(Sym.getFlags() | JITSymbolFlags::HasError);
- // FIXME: Come up with a sane mapping of state to
- // presence-of-MaterializingInfo so that we can assert presence / absence
- // here, rather than testing it.
- auto MII = JD.MaterializingInfos.find(Name);
+ // FIXME: Come up with a sane mapping of state to
+ // presence-of-MaterializingInfo so that we can assert presence / absence
+ // here, rather than testing it.
+ auto MII = JD.MaterializingInfos.find(Name);
- if (MII == JD.MaterializingInfos.end())
- continue;
+ if (MII == JD.MaterializingInfos.end())
+ continue;
- auto &MI = MII->second;
+ auto &MI = MII->second;
- // Move all dependants to the error state and disconnect from them.
- for (auto &KV : MI.Dependants) {
- auto &DependantJD = *KV.first;
- for (auto &DependantName : KV.second) {
- assert(DependantJD.Symbols.count(DependantName) &&
- "No symbol table entry for DependantName");
- auto &DependantSym = DependantJD.Symbols[DependantName];
- DependantSym.setFlags(DependantSym.getFlags() |
- JITSymbolFlags::HasError);
+ // Move all dependants to the error state and disconnect from them.
+ for (auto &KV : MI.Dependants) {
+ auto &DependantJD = *KV.first;
+ for (auto &DependantName : KV.second) {
+ assert(DependantJD.Symbols.count(DependantName) &&
+ "No symbol table entry for DependantName");
+ auto &DependantSym = DependantJD.Symbols[DependantName];
+ DependantSym.setFlags(DependantSym.getFlags() |
+ JITSymbolFlags::HasError);
- assert(DependantJD.MaterializingInfos.count(DependantName) &&
- "No MaterializingInfo for dependant");
- auto &DependantMI = DependantJD.MaterializingInfos[DependantName];
+ assert(DependantJD.MaterializingInfos.count(DependantName) &&
+ "No MaterializingInfo for dependant");
+ auto &DependantMI = DependantJD.MaterializingInfos[DependantName];
- auto UnemittedDepI = DependantMI.UnemittedDependencies.find(&JD);
- assert(UnemittedDepI != DependantMI.UnemittedDependencies.end() &&
- "No UnemittedDependencies entry for this JITDylib");
- assert(UnemittedDepI->second.count(Name) &&
- "No UnemittedDependencies entry for this symbol");
- UnemittedDepI->second.erase(Name);
- if (UnemittedDepI->second.empty())
- DependantMI.UnemittedDependencies.erase(UnemittedDepI);
+ auto UnemittedDepI = DependantMI.UnemittedDependencies.find(&JD);
+ assert(UnemittedDepI != DependantMI.UnemittedDependencies.end() &&
+ "No UnemittedDependencies entry for this JITDylib");
+ assert(UnemittedDepI->second.count(Name) &&
+ "No UnemittedDependencies entry for this symbol");
+ UnemittedDepI->second.erase(Name);
+ if (UnemittedDepI->second.empty())
+ DependantMI.UnemittedDependencies.erase(UnemittedDepI);
- // If this symbol is already in the emitted state then we need to
- // take responsibility for failing its queries, so add it to the
- // worklist.
- if (DependantSym.getState() == SymbolState::Emitted) {
- assert(DependantMI.Dependants.empty() &&
- "Emitted symbol should not have dependants");
- Worklist.push_back(std::make_pair(&DependantJD, DependantName));
- }
+ // If this symbol is already in the emitted state then we need to
+ // take responsibility for failing its queries, so add it to the
+ // worklist.
+ if (DependantSym.getState() == SymbolState::Emitted) {
+ assert(DependantMI.Dependants.empty() &&
+ "Emitted symbol should not have dependants");
+ Worklist.push_back(std::make_pair(&DependantJD, DependantName));
}
}
- MI.Dependants.clear();
-
- // Disconnect from all unemitted depenencies.
- for (auto &KV : MI.UnemittedDependencies) {
- auto &UnemittedDepJD = *KV.first;
- for (auto &UnemittedDepName : KV.second) {
- auto UnemittedDepMII =
- UnemittedDepJD.MaterializingInfos.find(UnemittedDepName);
- assert(UnemittedDepMII != UnemittedDepJD.MaterializingInfos.end() &&
- "Missing MII for unemitted dependency");
- assert(UnemittedDepMII->second.Dependants.count(&JD) &&
- "JD not listed as a dependant of unemitted dependency");
- assert(UnemittedDepMII->second.Dependants[&JD].count(Name) &&
- "Name is not listed as a dependant of unemitted dependency");
- UnemittedDepMII->second.Dependants[&JD].erase(Name);
- if (UnemittedDepMII->second.Dependants[&JD].empty())
- UnemittedDepMII->second.Dependants.erase(&JD);
- }
- }
- MI.UnemittedDependencies.clear();
+ }
+ MI.Dependants.clear();
- // Collect queries to be failed for this MII.
- AsynchronousSymbolQueryList ToDetach;
- for (auto &Q : MII->second.pendingQueries()) {
- // Add the query to the list to be failed and detach it.
- FailedQueries.insert(Q);
- ToDetach.push_back(Q);
+ // Disconnect from all unemitted depenencies.
+ for (auto &KV : MI.UnemittedDependencies) {
+ auto &UnemittedDepJD = *KV.first;
+ for (auto &UnemittedDepName : KV.second) {
+ auto UnemittedDepMII =
+ UnemittedDepJD.MaterializingInfos.find(UnemittedDepName);
+ assert(UnemittedDepMII != UnemittedDepJD.MaterializingInfos.end() &&
+ "Missing MII for unemitted dependency");
+ assert(UnemittedDepMII->second.Dependants.count(&JD) &&
+ "JD not listed as a dependant of unemitted dependency");
+ assert(UnemittedDepMII->second.Dependants[&JD].count(Name) &&
+ "Name is not listed as a dependant of unemitted dependency");
+ UnemittedDepMII->second.Dependants[&JD].erase(Name);
+ if (UnemittedDepMII->second.Dependants[&JD].empty())
+ UnemittedDepMII->second.Dependants.erase(&JD);
}
- for (auto &Q : ToDetach)
- Q->detach();
+ }
+ MI.UnemittedDependencies.clear();
- assert(MI.Dependants.empty() &&
- "Can not delete MaterializingInfo with dependants still attached");
- assert(MI.UnemittedDependencies.empty() &&
- "Can not delete MaterializingInfo with unemitted dependencies "
- "still attached");
- assert(!MI.hasQueriesPending() &&
- "Can not delete MaterializingInfo with queries pending");
- JD.MaterializingInfos.erase(MII);
+ // Collect queries to be failed for this MII.
+ AsynchronousSymbolQueryList ToDetach;
+ for (auto &Q : MII->second.pendingQueries()) {
+ // Add the query to the list to be failed and detach it.
+ FailedQueries.insert(Q);
+ ToDetach.push_back(Q);
}
- });
+ for (auto &Q : ToDetach)
+ Q->detach();
- for (auto &Q : FailedQueries)
- Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbolsMap));
+ assert(MI.Dependants.empty() &&
+ "Can not delete MaterializingInfo with dependants still attached");
+ assert(MI.UnemittedDependencies.empty() &&
+ "Can not delete MaterializingInfo with unemitted dependencies "
+ "still attached");
+ assert(!MI.hasQueriesPending() &&
+ "Can not delete MaterializingInfo with queries pending");
+ JD.MaterializingInfos.erase(MII);
+ }
+
+ return std::make_pair(std::move(FailedQueries), std::move(FailedSymbolsMap));
}
void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder,
@@ -1168,8 +1244,7 @@ void JITDylib::setLinkOrder(JITDylibSearchOrder NewLinkOrder,
if (NewLinkOrder.empty() || NewLinkOrder.front().first != this)
LinkOrder.push_back(
std::make_pair(this, JITDylibLookupFlags::MatchAllSymbols));
- LinkOrder.insert(LinkOrder.end(), NewLinkOrder.begin(),
- NewLinkOrder.end());
+ llvm::append_range(LinkOrder, NewLinkOrder);
} else
LinkOrder = std::move(NewLinkOrder);
});
@@ -1192,10 +1267,10 @@ void JITDylib::replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
void JITDylib::removeFromLinkOrder(JITDylib &JD) {
ES.runSessionLocked([&]() {
- auto I = std::find_if(LinkOrder.begin(), LinkOrder.end(),
- [&](const JITDylibSearchOrder::value_type &KV) {
- return KV.first == &JD;
- });
+ auto I = llvm::find_if(LinkOrder,
+ [&](const JITDylibSearchOrder::value_type &KV) {
+ return KV.first == &JD;
+ });
if (I != LinkOrder.end())
LinkOrder.erase(I);
});
@@ -1257,279 +1332,6 @@ Error JITDylib::remove(const SymbolNameSet &Names) {
});
}
-Expected<SymbolFlagsMap>
-JITDylib::lookupFlags(LookupKind K, JITDylibLookupFlags JDLookupFlags,
- SymbolLookupSet LookupSet) {
- return ES.runSessionLocked([&, this]() -> Expected<SymbolFlagsMap> {
- SymbolFlagsMap Result;
- lookupFlagsImpl(Result, K, JDLookupFlags, LookupSet);
-
- // Run any definition generators.
- for (auto &DG : DefGenerators) {
-
- // Bail out early if we found everything.
- if (LookupSet.empty())
- break;
-
- // Run this generator.
- if (auto Err = DG->tryToGenerate(K, *this, JDLookupFlags, LookupSet))
- return std::move(Err);
-
- // Re-try the search.
- lookupFlagsImpl(Result, K, JDLookupFlags, LookupSet);
- }
-
- return Result;
- });
-}
-
-void JITDylib::lookupFlagsImpl(SymbolFlagsMap &Result, LookupKind K,
- JITDylibLookupFlags JDLookupFlags,
- SymbolLookupSet &LookupSet) {
-
- LookupSet.forEachWithRemoval(
- [&](const SymbolStringPtr &Name, SymbolLookupFlags Flags) -> bool {
- auto I = Symbols.find(Name);
- if (I == Symbols.end())
- return false;
- assert(!Result.count(Name) && "Symbol already present in Flags map");
- Result[Name] = I->second.getFlags();
- return true;
- });
-}
-
-Error JITDylib::lodgeQuery(MaterializationUnitList &MUs,
- std::shared_ptr<AsynchronousSymbolQuery> &Q,
- LookupKind K, JITDylibLookupFlags JDLookupFlags,
- SymbolLookupSet &Unresolved) {
- assert(Q && "Query can not be null");
-
- if (auto Err = lodgeQueryImpl(MUs, Q, K, JDLookupFlags, Unresolved))
- return Err;
-
- // Run any definition generators.
- for (auto &DG : DefGenerators) {
-
- // Bail out early if we have resolved everything.
- if (Unresolved.empty())
- break;
-
- // Run the generator.
- if (auto Err = DG->tryToGenerate(K, *this, JDLookupFlags, Unresolved))
- return Err;
-
- // Lodge query. This can not fail as any new definitions were added
- // by the generator under the session locked. Since they can't have
- // started materializing yet they can not have failed.
- cantFail(lodgeQueryImpl(MUs, Q, K, JDLookupFlags, Unresolved));
- }
-
- return Error::success();
-}
-
-Error JITDylib::lodgeQueryImpl(MaterializationUnitList &MUs,
- std::shared_ptr<AsynchronousSymbolQuery> &Q,
- LookupKind K, JITDylibLookupFlags JDLookupFlags,
- SymbolLookupSet &Unresolved) {
-
- return Unresolved.forEachWithRemoval(
- [&](const SymbolStringPtr &Name,
- SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
- // Search for name in symbols. If not found then continue without
- // removal.
- auto SymI = Symbols.find(Name);
- if (SymI == Symbols.end())
- return false;
-
- // If we match against a materialization-side-effects only symbol then
- // make sure it is weakly-referenced. Otherwise bail out with an error.
- if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
- SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol)
- return make_error<SymbolsNotFound>(SymbolNameVector({Name}));
-
- // If this is a non exported symbol and we're matching exported symbols
- // only then skip this symbol without removal.
- if (!SymI->second.getFlags().isExported() &&
- JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly)
- return false;
-
- // If we matched against this symbol but it is in the error state then
- // bail out and treat it as a failure to materialize.
- if (SymI->second.getFlags().hasError()) {
- auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
- (*FailedSymbolsMap)[this] = {Name};
- return make_error<FailedToMaterialize>(std::move(FailedSymbolsMap));
- }
-
- // If this symbol already meets the required state for then notify the
- // query, then remove the symbol and continue.
- if (SymI->second.getState() >= Q->getRequiredState()) {
- Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
- return true;
- }
-
- // Otherwise this symbol does not yet meet the required state. Check
- // whether it has a materializer attached, and if so prepare to run it.
- if (SymI->second.hasMaterializerAttached()) {
- assert(SymI->second.getAddress() == 0 &&
- "Symbol not resolved but already has address?");
- auto UMII = UnmaterializedInfos.find(Name);
- assert(UMII != UnmaterializedInfos.end() &&
- "Lazy symbol should have UnmaterializedInfo");
- auto MU = std::move(UMII->second->MU);
- assert(MU != nullptr && "Materializer should not be null");
-
- // Move all symbols associated with this MaterializationUnit into
- // materializing state.
- for (auto &KV : MU->getSymbols()) {
- auto SymK = Symbols.find(KV.first);
- SymK->second.setMaterializerAttached(false);
- SymK->second.setState(SymbolState::Materializing);
- UnmaterializedInfos.erase(KV.first);
- }
-
- // Add MU to the list of MaterializationUnits to be materialized.
- MUs.push_back(std::move(MU));
- }
-
- // Add the query to the PendingQueries list and continue, deleting the
- // element.
- assert(SymI->second.getState() != SymbolState::NeverSearched &&
- SymI->second.getState() != SymbolState::Ready &&
- "By this line the symbol should be materializing");
- auto &MI = MaterializingInfos[Name];
- MI.addQuery(Q);
- Q->addQueryDependence(*this, Name);
- return true;
- });
-}
-
-Expected<SymbolNameSet>
-JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
- SymbolNameSet Names) {
- assert(Q && "Query can not be null");
-
- ES.runOutstandingMUs();
-
- bool QueryComplete = false;
- std::vector<std::unique_ptr<MaterializationUnit>> MUs;
-
- SymbolLookupSet Unresolved(Names);
- auto Err = ES.runSessionLocked([&, this]() -> Error {
- QueryComplete = lookupImpl(Q, MUs, Unresolved);
-
- // Run any definition generators.
- for (auto &DG : DefGenerators) {
-
- // Bail out early if we have resolved everything.
- if (Unresolved.empty())
- break;
-
- assert(!QueryComplete && "query complete but unresolved symbols remain?");
- if (auto Err = DG->tryToGenerate(LookupKind::Static, *this,
- JITDylibLookupFlags::MatchAllSymbols,
- Unresolved))
- return Err;
-
- if (!Unresolved.empty())
- QueryComplete = lookupImpl(Q, MUs, Unresolved);
- }
- return Error::success();
- });
-
- if (Err)
- return std::move(Err);
-
- assert((MUs.empty() || !QueryComplete) &&
- "If action flags are set, there should be no work to do (so no MUs)");
-
- if (QueryComplete)
- Q->handleComplete();
-
- // FIXME: Swap back to the old code below once RuntimeDyld works with
- // callbacks from asynchronous queries.
- // Add MUs to the OutstandingMUs list.
- {
- std::lock_guard<std::recursive_mutex> Lock(ES.OutstandingMUsMutex);
- auto ThisJD = shared_from_this();
- for (auto &MU : MUs) {
- auto MR = MU->createMaterializationResponsibility(ThisJD);
- ES.OutstandingMUs.push_back(make_pair(std::move(MU), std::move(MR)));
- }
- }
- ES.runOutstandingMUs();
-
- // Dispatch any required MaterializationUnits for materialization.
- // for (auto &MU : MUs)
- // ES.dispatchMaterialization(*this, std::move(MU));
-
- SymbolNameSet RemainingSymbols;
- for (auto &KV : Unresolved)
- RemainingSymbols.insert(KV.first);
-
- return RemainingSymbols;
-}
-
-bool JITDylib::lookupImpl(
- std::shared_ptr<AsynchronousSymbolQuery> &Q,
- std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
- SymbolLookupSet &Unresolved) {
- bool QueryComplete = false;
-
- std::vector<SymbolStringPtr> ToRemove;
- Unresolved.forEachWithRemoval(
- [&](const SymbolStringPtr &Name, SymbolLookupFlags Flags) -> bool {
- // Search for the name in Symbols. Skip without removing if not found.
- auto SymI = Symbols.find(Name);
- if (SymI == Symbols.end())
- return false;
-
- // If the symbol is already in the required state then notify the query
- // and remove.
- if (SymI->second.getState() >= Q->getRequiredState()) {
- Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
- if (Q->isComplete())
- QueryComplete = true;
- return true;
- }
-
- // If the symbol is lazy, get the MaterialiaztionUnit for it.
- if (SymI->second.hasMaterializerAttached()) {
- assert(SymI->second.getAddress() == 0 &&
- "Lazy symbol should not have a resolved address");
- auto UMII = UnmaterializedInfos.find(Name);
- assert(UMII != UnmaterializedInfos.end() &&
- "Lazy symbol should have UnmaterializedInfo");
- auto MU = std::move(UMII->second->MU);
- assert(MU != nullptr && "Materializer should not be null");
-
- // Kick all symbols associated with this MaterializationUnit into
- // materializing state.
- for (auto &KV : MU->getSymbols()) {
- auto SymK = Symbols.find(KV.first);
- assert(SymK != Symbols.end() && "Missing symbol table entry");
- SymK->second.setState(SymbolState::Materializing);
- SymK->second.setMaterializerAttached(false);
- UnmaterializedInfos.erase(KV.first);
- }
-
- // Add MU to the list of MaterializationUnits to be materialized.
- MUs.push_back(std::move(MU));
- }
-
- // Add the query to the PendingQueries list.
- assert(SymI->second.getState() != SymbolState::NeverSearched &&
- SymI->second.getState() != SymbolState::Ready &&
- "By this line the symbol should be materializing");
- auto &MI = MaterializingInfos[Name];
- MI.addQuery(Q);
- Q->addQueryDependence(*this, Name);
- return true;
- });
-
- return QueryComplete;
-}
-
void JITDylib::dump(raw_ostream &OS) {
ES.runSessionLocked([&, this]() {
OS << "JITDylib \"" << JITDylibName << "\" (ES: "
@@ -1589,11 +1391,10 @@ void JITDylib::MaterializingInfo::addQuery(
void JITDylib::MaterializingInfo::removeQuery(
const AsynchronousSymbolQuery &Q) {
// FIXME: Implement 'find_as' for shared_ptr<T>/T*.
- auto I =
- std::find_if(PendingQueries.begin(), PendingQueries.end(),
- [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) {
- return V.get() == &Q;
- });
+ auto I = llvm::find_if(
+ PendingQueries, [&Q](const std::shared_ptr<AsynchronousSymbolQuery> &V) {
+ return V.get() == &Q;
+ });
assert(I != PendingQueries.end() &&
"Query is not attached to this MaterializingInfo");
PendingQueries.erase(I);
@@ -1618,6 +1419,137 @@ JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
LinkOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols});
}
+ResourceTrackerSP JITDylib::getTracker(MaterializationResponsibility &MR) {
+ auto I = MRTrackers.find(&MR);
+ assert(I != MRTrackers.end() && "MR is not linked");
+ assert(I->second && "Linked tracker is null");
+ return I->second;
+}
+
+std::pair<JITDylib::AsynchronousSymbolQuerySet,
+ std::shared_ptr<SymbolDependenceMap>>
+JITDylib::removeTracker(ResourceTracker &RT) {
+ // Note: Should be called under the session lock.
+
+ SymbolNameVector SymbolsToRemove;
+ std::vector<std::pair<JITDylib *, SymbolStringPtr>> SymbolsToFail;
+
+ if (&RT == DefaultTracker.get()) {
+ SymbolNameSet TrackedSymbols;
+ for (auto &KV : TrackerSymbols)
+ for (auto &Sym : KV.second)
+ TrackedSymbols.insert(Sym);
+
+ for (auto &KV : Symbols) {
+ auto &Sym = KV.first;
+ if (!TrackedSymbols.count(Sym))
+ SymbolsToRemove.push_back(Sym);
+ }
+
+ DefaultTracker.reset();
+ } else {
+ /// Check for a non-default tracker.
+ auto I = TrackerSymbols.find(&RT);
+ if (I != TrackerSymbols.end()) {
+ SymbolsToRemove = std::move(I->second);
+ TrackerSymbols.erase(I);
+ }
+ // ... if not found this tracker was already defunct. Nothing to do.
+ }
+
+ for (auto &Sym : SymbolsToRemove) {
+ assert(Symbols.count(Sym) && "Symbol not in symbol table");
+
+ // If there is a MaterializingInfo then collect any queries to fail.
+ auto MII = MaterializingInfos.find(Sym);
+ if (MII != MaterializingInfos.end())
+ SymbolsToFail.push_back({this, Sym});
+ }
+
+ AsynchronousSymbolQuerySet QueriesToFail;
+ auto Result = failSymbols(std::move(SymbolsToFail));
+
+ // Removed symbols should be taken out of the table altogether.
+ for (auto &Sym : SymbolsToRemove) {
+ auto I = Symbols.find(Sym);
+ assert(I != Symbols.end() && "Symbol not present in table");
+
+ // Remove Materializer if present.
+ if (I->second.hasMaterializerAttached()) {
+ // FIXME: Should this discard the symbols?
+ UnmaterializedInfos.erase(Sym);
+ } else {
+ assert(!UnmaterializedInfos.count(Sym) &&
+ "Symbol has materializer attached");
+ }
+
+ Symbols.erase(I);
+ }
+
+ return Result;
+}
+
+void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) {
+ assert(&DstRT != &SrcRT && "No-op transfers shouldn't call transferTracker");
+ assert(&DstRT.getJITDylib() == this && "DstRT is not for this JITDylib");
+ assert(&SrcRT.getJITDylib() == this && "SrcRT is not for this JITDylib");
+
+ // Update trackers for any not-yet materialized units.
+ for (auto &KV : UnmaterializedInfos) {
+ if (KV.second->RT == &SrcRT)
+ KV.second->RT = &DstRT;
+ }
+
+ // Update trackers for any active materialization responsibilities.
+ for (auto &KV : MRTrackers) {
+ if (KV.second == &SrcRT)
+ KV.second = &DstRT;
+ }
+
+ // If we're transfering to the default tracker we just need to delete the
+ // tracked symbols for the source tracker.
+ if (&DstRT == DefaultTracker.get()) {
+ TrackerSymbols.erase(&SrcRT);
+ return;
+ }
+
+ // If we're transferring from the default tracker we need to find all
+ // currently untracked symbols.
+ if (&SrcRT == DefaultTracker.get()) {
+ assert(!TrackerSymbols.count(&SrcRT) &&
+ "Default tracker should not appear in TrackerSymbols");
+
+ SymbolNameVector SymbolsToTrack;
+
+ SymbolNameSet CurrentlyTrackedSymbols;
+ for (auto &KV : TrackerSymbols)
+ for (auto &Sym : KV.second)
+ CurrentlyTrackedSymbols.insert(Sym);
+
+ for (auto &KV : Symbols) {
+ auto &Sym = KV.first;
+ if (!CurrentlyTrackedSymbols.count(Sym))
+ SymbolsToTrack.push_back(Sym);
+ }
+
+ TrackerSymbols[&DstRT] = std::move(SymbolsToTrack);
+ return;
+ }
+
+ auto &DstTrackedSymbols = TrackerSymbols[&DstRT];
+
+ // Finally if neither SrtRT or DstRT are the default tracker then
+ // just append DstRT's tracked symbols to SrtRT's.
+ auto SI = TrackerSymbols.find(&SrcRT);
+ if (SI == TrackerSymbols.end())
+ return;
+
+ DstTrackedSymbols.reserve(DstTrackedSymbols.size() + SI->second.size());
+ for (auto &Sym : SI->second)
+ DstTrackedSymbols.push_back(std::move(Sym));
+ TrackerSymbols.erase(SI);
+}
+
Error JITDylib::defineImpl(MaterializationUnit &MU) {
LLVM_DEBUG({ dbgs() << " " << MU.getSymbols() << "\n"; });
@@ -1685,6 +1617,22 @@ Error JITDylib::defineImpl(MaterializationUnit &MU) {
return Error::success();
}
+void JITDylib::installMaterializationUnit(
+ std::unique_ptr<MaterializationUnit> MU, ResourceTracker &RT) {
+
+ /// defineImpl succeeded.
+ if (&RT != DefaultTracker.get()) {
+ auto &TS = TrackerSymbols[&RT];
+ TS.reserve(TS.size() + MU->getSymbols().size());
+ for (auto &KV : MU->getSymbols())
+ TS.push_back(KV.first);
+ }
+
+ auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU), &RT);
+ for (auto &KV : UMI->MU->getSymbols())
+ UnmaterializedInfos[KV.first] = UMI;
+}
+
void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
const SymbolNameSet &QuerySymbols) {
for (auto &QuerySymbol : QuerySymbols) {
@@ -1773,7 +1721,39 @@ Expected<DenseMap<JITDylib *, SymbolMap>> Platform::lookupInitSymbols(
}
ExecutionSession::ExecutionSession(std::shared_ptr<SymbolStringPool> SSP)
- : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {
+ : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {}
+
+Error ExecutionSession::endSession() {
+ LLVM_DEBUG(dbgs() << "Ending ExecutionSession " << this << "\n");
+
+ std::vector<JITDylibSP> JITDylibsToClose = runSessionLocked([&] {
+ SessionOpen = false;
+ return std::move(JDs);
+ });
+
+ // TODO: notifiy platform? run static deinits?
+
+ Error Err = Error::success();
+ for (auto &JD : JITDylibsToClose)
+ Err = joinErrors(std::move(Err), JD->clear());
+ return Err;
+}
+
+void ExecutionSession::registerResourceManager(ResourceManager &RM) {
+ runSessionLocked([&] { ResourceManagers.push_back(&RM); });
+}
+
+void ExecutionSession::deregisterResourceManager(ResourceManager &RM) {
+ runSessionLocked([&] {
+ assert(!ResourceManagers.empty() && "No managers registered");
+ if (ResourceManagers.back() == &RM)
+ ResourceManagers.pop_back();
+ else {
+ auto I = llvm::find(ResourceManagers, &RM);
+ assert(I != ResourceManagers.end() && "RM not registered");
+ ResourceManagers.erase(I);
+ }
+ });
}
JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) {
@@ -1788,8 +1768,7 @@ JITDylib *ExecutionSession::getJITDylibByName(StringRef Name) {
JITDylib &ExecutionSession::createBareJITDylib(std::string Name) {
assert(!getJITDylibByName(Name) && "JITDylib with that name already exists");
return runSessionLocked([&, this]() -> JITDylib & {
- JDs.push_back(
- std::shared_ptr<JITDylib>(new JITDylib(*this, std::move(Name))));
+ JDs.push_back(new JITDylib(*this, std::move(Name)));
return *JDs.back();
});
}
@@ -1802,86 +1781,80 @@ Expected<JITDylib &> ExecutionSession::createJITDylib(std::string Name) {
return JD;
}
-void ExecutionSession::legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err) {
- assert(!!Err && "Error should be in failure state");
+std::vector<JITDylibSP> JITDylib::getDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
+ if (JDs.empty())
+ return {};
- bool SendErrorToQuery;
- runSessionLocked([&]() {
- Q.detach();
- SendErrorToQuery = Q.canStillFail();
+ auto &ES = JDs.front()->getExecutionSession();
+ return ES.runSessionLocked([&]() {
+ DenseSet<JITDylib *> Visited;
+ std::vector<JITDylibSP> Result;
+
+ for (auto &JD : JDs) {
+
+ if (Visited.count(JD.get()))
+ continue;
+
+ SmallVector<JITDylibSP, 64> WorkStack;
+ WorkStack.push_back(JD);
+ Visited.insert(JD.get());
+
+ while (!WorkStack.empty()) {
+ Result.push_back(std::move(WorkStack.back()));
+ WorkStack.pop_back();
+
+ for (auto &KV : llvm::reverse(Result.back()->LinkOrder)) {
+ auto &JD = *KV.first;
+ if (Visited.count(&JD))
+ continue;
+ Visited.insert(&JD);
+ WorkStack.push_back(&JD);
+ }
+ }
+ }
+ return Result;
});
+}
- if (SendErrorToQuery)
- Q.handleFailed(std::move(Err));
- else
- reportError(std::move(Err));
+std::vector<JITDylibSP>
+JITDylib::getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs) {
+ auto Tmp = getDFSLinkOrder(JDs);
+ std::reverse(Tmp.begin(), Tmp.end());
+ return Tmp;
}
-Expected<SymbolMap> ExecutionSession::legacyLookup(
- LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
- SymbolState RequiredState,
- RegisterDependenciesFunction RegisterDependencies) {
-#if LLVM_ENABLE_THREADS
- // In the threaded case we use promises to return the results.
- std::promise<SymbolMap> PromisedResult;
- Error ResolutionError = Error::success();
- auto NotifyComplete = [&](Expected<SymbolMap> R) {
- if (R)
- PromisedResult.set_value(std::move(*R));
- else {
- ErrorAsOutParameter _(&ResolutionError);
- ResolutionError = R.takeError();
- PromisedResult.set_value(SymbolMap());
- }
- };
-#else
- SymbolMap Result;
- Error ResolutionError = Error::success();
+std::vector<JITDylibSP> JITDylib::getDFSLinkOrder() {
+ return getDFSLinkOrder({this});
+}
- auto NotifyComplete = [&](Expected<SymbolMap> R) {
- ErrorAsOutParameter _(&ResolutionError);
- if (R)
- Result = std::move(*R);
- else
- ResolutionError = R.takeError();
- };
-#endif
+std::vector<JITDylibSP> JITDylib::getReverseDFSLinkOrder() {
+ return getReverseDFSLinkOrder({this});
+}
- auto Query = std::make_shared<AsynchronousSymbolQuery>(
- SymbolLookupSet(Names), RequiredState, std::move(NotifyComplete));
- // FIXME: This should be run session locked along with the registration code
- // and error reporting below.
- SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
+void ExecutionSession::lookupFlags(
+ LookupKind K, JITDylibSearchOrder SearchOrder, SymbolLookupSet LookupSet,
+ unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {
- // If the query was lodged successfully then register the dependencies,
- // otherwise fail it with an error.
- if (UnresolvedSymbols.empty())
- RegisterDependencies(Query->QueryRegistrations);
- else {
- bool DeliverError = runSessionLocked([&]() {
- Query->detach();
- return Query->canStillFail();
- });
- auto Err = make_error<SymbolsNotFound>(std::move(UnresolvedSymbols));
- if (DeliverError)
- Query->handleFailed(std::move(Err));
- else
- reportError(std::move(Err));
- }
+ OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
+ K, std::move(SearchOrder), std::move(LookupSet),
+ std::move(OnComplete)),
+ Error::success());
+}
-#if LLVM_ENABLE_THREADS
- auto ResultFuture = PromisedResult.get_future();
- auto Result = ResultFuture.get();
- if (ResolutionError)
- return std::move(ResolutionError);
- return std::move(Result);
+Expected<SymbolFlagsMap>
+ExecutionSession::lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
+ SymbolLookupSet LookupSet) {
-#else
- if (ResolutionError)
- return std::move(ResolutionError);
+ std::promise<MSVCPExpected<SymbolFlagsMap>> ResultP;
+ OL_applyQueryPhase1(std::make_unique<InProgressLookupFlagsState>(
+ K, std::move(SearchOrder), std::move(LookupSet),
+ [&ResultP](Expected<SymbolFlagsMap> Result) {
+ ResultP.set_value(std::move(Result));
+ }),
+ Error::success());
- return Result;
-#endif
+ auto ResultF = ResultP.get_future();
+ return ResultF.get();
}
void ExecutionSession::lookup(
@@ -1900,94 +1873,17 @@ void ExecutionSession::lookup(
// lookup can be re-entered recursively if running on a single thread. Run any
// outstanding MUs in case this query depends on them, otherwise this lookup
// will starve waiting for a result from an MU that is stuck in the queue.
- runOutstandingMUs();
+ dispatchOutstandingMUs();
auto Unresolved = std::move(Symbols);
- std::map<JITDylib *, MaterializationUnitList> CollectedMUsMap;
auto Q = std::make_shared<AsynchronousSymbolQuery>(Unresolved, RequiredState,
std::move(NotifyComplete));
- bool QueryComplete = false;
-
- auto LodgingErr = runSessionLocked([&]() -> Error {
- auto LodgeQuery = [&]() -> Error {
- for (auto &KV : SearchOrder) {
- assert(KV.first && "JITDylibList entries must not be null");
- assert(!CollectedMUsMap.count(KV.first) &&
- "JITDylibList should not contain duplicate entries");
-
- auto &JD = *KV.first;
- auto JDLookupFlags = KV.second;
- if (auto Err = JD.lodgeQuery(CollectedMUsMap[&JD], Q, K, JDLookupFlags,
- Unresolved))
- return Err;
- }
- // Strip any weakly referenced symbols that were not found.
- Unresolved.forEachWithRemoval(
- [&](const SymbolStringPtr &Name, SymbolLookupFlags Flags) {
- if (Flags == SymbolLookupFlags::WeaklyReferencedSymbol) {
- Q->dropSymbol(Name);
- return true;
- }
- return false;
- });
-
- if (!Unresolved.empty())
- return make_error<SymbolsNotFound>(Unresolved.getSymbolNames());
-
- return Error::success();
- };
-
- if (auto Err = LodgeQuery()) {
- // Query failed.
-
- // Disconnect the query from its dependencies.
- Q->detach();
-
- // Replace the MUs.
- for (auto &KV : CollectedMUsMap)
- for (auto &MU : KV.second)
- KV.first->replace(std::move(MU));
-
- return Err;
- }
-
- // Query lodged successfully.
-
- // Record whether this query is fully ready / resolved. We will use
- // this to call handleFullyResolved/handleFullyReady outside the session
- // lock.
- QueryComplete = Q->isComplete();
-
- // Call the register dependencies function.
- if (RegisterDependencies && !Q->QueryRegistrations.empty())
- RegisterDependencies(Q->QueryRegistrations);
-
- return Error::success();
- });
-
- if (LodgingErr) {
- Q->handleFailed(std::move(LodgingErr));
- return;
- }
-
- if (QueryComplete)
- Q->handleComplete();
+ auto IPLS = std::make_unique<InProgressFullLookupState>(
+ K, SearchOrder, std::move(Unresolved), RequiredState, std::move(Q),
+ std::move(RegisterDependencies));
- // Move the MUs to the OutstandingMUs list, then materialize.
- {
- std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
-
- for (auto &KV : CollectedMUsMap) {
- auto JD = KV.first->shared_from_this();
- for (auto &MU : KV.second) {
- auto MR = MU->createMaterializationResponsibility(JD);
- OutstandingMUs.push_back(std::make_pair(std::move(MU), std::move(MR)));
- }
- }
- }
-
- runOutstandingMUs();
+ OL_applyQueryPhase1(std::move(IPLS), Error::success());
}
Expected<SymbolMap>
@@ -2077,10 +1973,11 @@ void ExecutionSession::dump(raw_ostream &OS) {
});
}
-void ExecutionSession::runOutstandingMUs() {
+void ExecutionSession::dispatchOutstandingMUs() {
+ LLVM_DEBUG(dbgs() << "Dispatching MaterializationUnits...\n");
while (1) {
Optional<std::pair<std::unique_ptr<MaterializationUnit>,
- MaterializationResponsibility>>
+ std::unique_ptr<MaterializationResponsibility>>>
JMU;
{
@@ -2095,8 +1992,777 @@ void ExecutionSession::runOutstandingMUs() {
break;
assert(JMU->first && "No MU?");
+ LLVM_DEBUG(dbgs() << " Dispatching \"" << JMU->first->getName() << "\"\n");
dispatchMaterialization(std::move(JMU->first), std::move(JMU->second));
}
+ LLVM_DEBUG(dbgs() << "Done dispatching MaterializationUnits.\n");
+}
+
+Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {
+ LLVM_DEBUG({
+ dbgs() << "In " << RT.getJITDylib().getName() << " removing tracker "
+ << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
+ });
+ std::vector<ResourceManager *> CurrentResourceManagers;
+
+ JITDylib::AsynchronousSymbolQuerySet QueriesToFail;
+ std::shared_ptr<SymbolDependenceMap> FailedSymbols;
+
+ runSessionLocked([&] {
+ CurrentResourceManagers = ResourceManagers;
+ RT.makeDefunct();
+ std::tie(QueriesToFail, FailedSymbols) = RT.getJITDylib().removeTracker(RT);
+ });
+
+ Error Err = Error::success();
+
+ for (auto *L : reverse(CurrentResourceManagers))
+ Err =
+ joinErrors(std::move(Err), L->handleRemoveResources(RT.getKeyUnsafe()));
+
+ for (auto &Q : QueriesToFail)
+ Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
+
+ return Err;
+}
+
+void ExecutionSession::transferResourceTracker(ResourceTracker &DstRT,
+ ResourceTracker &SrcRT) {
+ LLVM_DEBUG({
+ dbgs() << "In " << SrcRT.getJITDylib().getName()
+ << " transfering resources from tracker "
+ << formatv("{0:x}", SrcRT.getKeyUnsafe()) << " to tracker "
+ << formatv("{0:x}", DstRT.getKeyUnsafe()) << "\n";
+ });
+
+ // No-op transfers are allowed and do not invalidate the source.
+ if (&DstRT == &SrcRT)
+ return;
+
+ assert(&DstRT.getJITDylib() == &SrcRT.getJITDylib() &&
+ "Can't transfer resources between JITDylibs");
+ runSessionLocked([&]() {
+ SrcRT.makeDefunct();
+ auto &JD = DstRT.getJITDylib();
+ JD.transferTracker(DstRT, SrcRT);
+ for (auto *L : reverse(ResourceManagers))
+ L->handleTransferResources(DstRT.getKeyUnsafe(), SrcRT.getKeyUnsafe());
+ });
+}
+
+void ExecutionSession::destroyResourceTracker(ResourceTracker &RT) {
+ runSessionLocked([&]() {
+ LLVM_DEBUG({
+ dbgs() << "In " << RT.getJITDylib().getName() << " destroying tracker "
+ << formatv("{0:x}", RT.getKeyUnsafe()) << "\n";
+ });
+ if (!RT.isDefunct())
+ transferResourceTracker(*RT.getJITDylib().getDefaultResourceTracker(),
+ RT);
+ });
+}
+
+Error ExecutionSession::IL_updateCandidatesFor(
+ JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
+ SymbolLookupSet &Candidates, SymbolLookupSet *NonCandidates) {
+ return Candidates.forEachWithRemoval(
+ [&](const SymbolStringPtr &Name,
+ SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
+ /// Search for the symbol. If not found then continue without
+ /// removal.
+ auto SymI = JD.Symbols.find(Name);
+ if (SymI == JD.Symbols.end())
+ return false;
+
+ // If this is a non-exported symbol and we're matching exported
+ // symbols only then remove this symbol from the candidates list.
+ //
+ // If we're tracking non-candidates then add this to the non-candidate
+ // list.
+ if (!SymI->second.getFlags().isExported() &&
+ JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {
+ if (NonCandidates)
+ NonCandidates->add(Name, SymLookupFlags);
+ return true;
+ }
+
+ // If we match against a materialization-side-effects only symbol
+ // then make sure it is weakly-referenced. Otherwise bail out with
+ // an error.
+ // FIXME: Use a "materialization-side-effects-only symbols must be
+ // weakly referenced" specific error here to reduce confusion.
+ if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
+ SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol)
+ return make_error<SymbolsNotFound>(SymbolNameVector({Name}));
+
+ // If we matched against this symbol but it is in the error state
+ // then bail out and treat it as a failure to materialize.
+ if (SymI->second.getFlags().hasError()) {
+ auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
+ (*FailedSymbolsMap)[&JD] = {Name};
+ return make_error<FailedToMaterialize>(std::move(FailedSymbolsMap));
+ }
+
+ // Otherwise this is a match. Remove it from the candidate set.
+ return true;
+ });
+}
+
+void ExecutionSession::OL_applyQueryPhase1(
+ std::unique_ptr<InProgressLookupState> IPLS, Error Err) {
+
+ LLVM_DEBUG({
+ dbgs() << "Entering OL_applyQueryPhase1:\n"
+ << " Lookup kind: " << IPLS->K << "\n"
+ << " Search order: " << IPLS->SearchOrder
+ << ", Current index = " << IPLS->CurSearchOrderIndex
+ << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
+ << " Lookup set: " << IPLS->LookupSet << "\n"
+ << " Definition generator candidates: "
+ << IPLS->DefGeneratorCandidates << "\n"
+ << " Definition generator non-candidates: "
+ << IPLS->DefGeneratorNonCandidates << "\n";
+ });
+
+ // FIXME: We should attach the query as we go: This provides a result in a
+ // single pass in the common case where all symbols have already reached the
+ // required state. The query could be detached again in the 'fail' method on
+ // IPLS. Phase 2 would be reduced to collecting and dispatching the MUs.
+
+ while (IPLS->CurSearchOrderIndex != IPLS->SearchOrder.size()) {
+
+ // If we've been handed an error or received one back from a generator then
+ // fail the query. We don't need to unlink: At this stage the query hasn't
+ // actually been lodged.
+ if (Err)
+ return IPLS->fail(std::move(Err));
+
+ // Get the next JITDylib and lookup flags.
+ auto &KV = IPLS->SearchOrder[IPLS->CurSearchOrderIndex];
+ auto &JD = *KV.first;
+ auto JDLookupFlags = KV.second;
+
+ LLVM_DEBUG({
+ dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
+ << ") with lookup set " << IPLS->LookupSet << ":\n";
+ });
+
+ // If we've just reached a new JITDylib then perform some setup.
+ if (IPLS->NewJITDylib) {
+
+ // Acquire the generator lock for this JITDylib.
+ IPLS->GeneratorLock = std::unique_lock<std::mutex>(JD.GeneratorsMutex);
+
+ // Add any non-candidates from the last JITDylib (if any) back on to the
+ // list of definition candidates for this JITDylib, reset definition
+ // non-candiates to the empty set.
+ SymbolLookupSet Tmp;
+ std::swap(IPLS->DefGeneratorNonCandidates, Tmp);
+ IPLS->DefGeneratorCandidates.append(std::move(Tmp));
+
+ LLVM_DEBUG({
+ dbgs() << " First time visiting " << JD.getName()
+ << ", resetting candidate sets and building generator stack\n";
+ });
+
+ // Build the definition generator stack for this JITDylib.
+ for (auto &DG : reverse(JD.DefGenerators))
+ IPLS->CurDefGeneratorStack.push_back(DG);
+
+ // Flag that we've done our initialization.
+ IPLS->NewJITDylib = false;
+ }
+
+ // Remove any generation candidates that are already defined (and match) in
+ // this JITDylib.
+ runSessionLocked([&] {
+ // Update the list of candidates (and non-candidates) for definition
+ // generation.
+ LLVM_DEBUG(dbgs() << " Updating candidate set...\n");
+ Err = IL_updateCandidatesFor(
+ JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
+ JD.DefGenerators.empty() ? nullptr
+ : &IPLS->DefGeneratorNonCandidates);
+ LLVM_DEBUG({
+ dbgs() << " Remaining candidates = " << IPLS->DefGeneratorCandidates
+ << "\n";
+ });
+ });
+
+ // If we encountered an error while filtering generation candidates then
+ // bail out.
+ if (Err)
+ return IPLS->fail(std::move(Err));
+
+ /// Apply any definition generators on the stack.
+ LLVM_DEBUG({
+ if (IPLS->CurDefGeneratorStack.empty())
+ LLVM_DEBUG(dbgs() << " No generators to run for this JITDylib.\n");
+ else if (IPLS->DefGeneratorCandidates.empty())
+ LLVM_DEBUG(dbgs() << " No candidates to generate.\n");
+ else
+ dbgs() << " Running " << IPLS->CurDefGeneratorStack.size()
+ << " remaining generators for "
+ << IPLS->DefGeneratorCandidates.size() << " candidates\n";
+ });
+ while (!IPLS->CurDefGeneratorStack.empty() &&
+ !IPLS->DefGeneratorCandidates.empty()) {
+ auto DG = IPLS->CurDefGeneratorStack.back().lock();
+ IPLS->CurDefGeneratorStack.pop_back();
+
+ if (!DG)
+ return IPLS->fail(make_error<StringError>(
+ "DefinitionGenerator removed while lookup in progress",
+ inconvertibleErrorCode()));
+
+ auto K = IPLS->K;
+ auto &LookupSet = IPLS->DefGeneratorCandidates;
+
+ // Run the generator. If the generator takes ownership of QA then this
+ // will break the loop.
+ {
+ LLVM_DEBUG(dbgs() << " Attempting to generate " << LookupSet << "\n");
+ LookupState LS(std::move(IPLS));
+ Err = DG->tryToGenerate(LS, K, JD, JDLookupFlags, LookupSet);
+ IPLS = std::move(LS.IPLS);
+ }
+
+ // If there was an error then fail the query.
+ if (Err) {
+ LLVM_DEBUG({
+ dbgs() << " Error attempting to generate " << LookupSet << "\n";
+ });
+ assert(IPLS && "LS cannot be retained if error is returned");
+ return IPLS->fail(std::move(Err));
+ }
+
+ // Otherwise if QA was captured then break the loop.
+ if (!IPLS) {
+ LLVM_DEBUG(
+ { dbgs() << " LookupState captured. Exiting phase1 for now.\n"; });
+ return;
+ }
+
+ // Otherwise if we're continuing around the loop then update candidates
+ // for the next round.
+ runSessionLocked([&] {
+ LLVM_DEBUG(dbgs() << " Updating candidate set post-generation\n");
+ Err = IL_updateCandidatesFor(
+ JD, JDLookupFlags, IPLS->DefGeneratorCandidates,
+ JD.DefGenerators.empty() ? nullptr
+ : &IPLS->DefGeneratorNonCandidates);
+ });
+
+ // If updating candidates failed then fail the query.
+ if (Err) {
+ LLVM_DEBUG(dbgs() << " Error encountered while updating candidates\n");
+ return IPLS->fail(std::move(Err));
+ }
+ }
+
+ // If we get here then we've moved on to the next JITDylib.
+ LLVM_DEBUG(dbgs() << "Phase 1 moving to next JITDylib.\n");
+ ++IPLS->CurSearchOrderIndex;
+ IPLS->NewJITDylib = true;
+ }
+
+ // Remove any weakly referenced candidates that could not be found/generated.
+ IPLS->DefGeneratorCandidates.remove_if(
+ [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
+ return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
+ });
+
+ // If we get here then we've finished searching all JITDylibs.
+ // If we matched all symbols then move to phase 2, otherwise fail the query
+ // with a SymbolsNotFound error.
+ if (IPLS->DefGeneratorCandidates.empty()) {
+ LLVM_DEBUG(dbgs() << "Phase 1 succeeded.\n");
+ IPLS->complete(std::move(IPLS));
+ } else {
+ LLVM_DEBUG(dbgs() << "Phase 1 failed with unresolved symbols.\n");
+ IPLS->fail(make_error<SymbolsNotFound>(
+ IPLS->DefGeneratorCandidates.getSymbolNames()));
+ }
+}
+
+void ExecutionSession::OL_completeLookup(
+ std::unique_ptr<InProgressLookupState> IPLS,
+ std::shared_ptr<AsynchronousSymbolQuery> Q,
+ RegisterDependenciesFunction RegisterDependencies) {
+
+ LLVM_DEBUG({
+ dbgs() << "Entering OL_completeLookup:\n"
+ << " Lookup kind: " << IPLS->K << "\n"
+ << " Search order: " << IPLS->SearchOrder
+ << ", Current index = " << IPLS->CurSearchOrderIndex
+ << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
+ << " Lookup set: " << IPLS->LookupSet << "\n"
+ << " Definition generator candidates: "
+ << IPLS->DefGeneratorCandidates << "\n"
+ << " Definition generator non-candidates: "
+ << IPLS->DefGeneratorNonCandidates << "\n";
+ });
+
+ bool QueryComplete = false;
+ DenseMap<JITDylib *, JITDylib::UnmaterializedInfosList> CollectedUMIs;
+
+ auto LodgingErr = runSessionLocked([&]() -> Error {
+ for (auto &KV : IPLS->SearchOrder) {
+ auto &JD = *KV.first;
+ auto JDLookupFlags = KV.second;
+ LLVM_DEBUG({
+ dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
+ << ") with lookup set " << IPLS->LookupSet << ":\n";
+ });
+
+ auto Err = IPLS->LookupSet.forEachWithRemoval(
+ [&](const SymbolStringPtr &Name,
+ SymbolLookupFlags SymLookupFlags) -> Expected<bool> {
+ LLVM_DEBUG({
+ dbgs() << " Attempting to match \"" << Name << "\" ("
+ << SymLookupFlags << ")... ";
+ });
+
+ /// Search for the symbol. If not found then continue without
+ /// removal.
+ auto SymI = JD.Symbols.find(Name);
+ if (SymI == JD.Symbols.end()) {
+ LLVM_DEBUG(dbgs() << "skipping: not present\n");
+ return false;
+ }
+
+ // If this is a non-exported symbol and we're matching exported
+ // symbols only then skip this symbol without removal.
+ if (!SymI->second.getFlags().isExported() &&
+ JDLookupFlags ==
+ JITDylibLookupFlags::MatchExportedSymbolsOnly) {
+ LLVM_DEBUG(dbgs() << "skipping: not exported\n");
+ return false;
+ }
+
+ // If we match against a materialization-side-effects only symbol
+ // then make sure it is weakly-referenced. Otherwise bail out with
+ // an error.
+ // FIXME: Use a "materialization-side-effects-only symbols must be
+ // weakly referenced" specific error here to reduce confusion.
+ if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
+ SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol) {
+ LLVM_DEBUG({
+ dbgs() << "error: "
+ "required, but symbol is has-side-effects-only\n";
+ });
+ return make_error<SymbolsNotFound>(SymbolNameVector({Name}));
+ }
+
+ // If we matched against this symbol but it is in the error state
+ // then bail out and treat it as a failure to materialize.
+ if (SymI->second.getFlags().hasError()) {
+ LLVM_DEBUG(dbgs() << "error: symbol is in error state\n");
+ auto FailedSymbolsMap = std::make_shared<SymbolDependenceMap>();
+ (*FailedSymbolsMap)[&JD] = {Name};
+ return make_error<FailedToMaterialize>(
+ std::move(FailedSymbolsMap));
+ }
+
+ // Otherwise this is a match.
+
+ // If this symbol is already in the requried state then notify the
+ // query, remove the symbol and continue.
+ if (SymI->second.getState() >= Q->getRequiredState()) {
+ LLVM_DEBUG(dbgs()
+ << "matched, symbol already in required state\n");
+ Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
+ return true;
+ }
+
+ // Otherwise this symbol does not yet meet the required state. Check
+ // whether it has a materializer attached, and if so prepare to run
+ // it.
+ if (SymI->second.hasMaterializerAttached()) {
+ assert(SymI->second.getAddress() == 0 &&
+ "Symbol not resolved but already has address?");
+ auto UMII = JD.UnmaterializedInfos.find(Name);
+ assert(UMII != JD.UnmaterializedInfos.end() &&
+ "Lazy symbol should have UnmaterializedInfo");
+
+ auto UMI = UMII->second;
+ assert(UMI->MU && "Materializer should not be null");
+ assert(UMI->RT && "Tracker should not be null");
+ LLVM_DEBUG({
+ dbgs() << "matched, preparing to dispatch MU@" << UMI->MU.get()
+ << " (" << UMI->MU->getName() << ")\n";
+ });
+
+ // Move all symbols associated with this MaterializationUnit into
+ // materializing state.
+ for (auto &KV : UMI->MU->getSymbols()) {
+ auto SymK = JD.Symbols.find(KV.first);
+ assert(SymK != JD.Symbols.end() &&
+ "No entry for symbol covered by MaterializationUnit");
+ SymK->second.setMaterializerAttached(false);
+ SymK->second.setState(SymbolState::Materializing);
+ JD.UnmaterializedInfos.erase(KV.first);
+ }
+
+ // Add MU to the list of MaterializationUnits to be materialized.
+ CollectedUMIs[&JD].push_back(std::move(UMI));
+ } else
+ LLVM_DEBUG(dbgs() << "matched, registering query");
+
+ // Add the query to the PendingQueries list and continue, deleting
+ // the element from the lookup set.
+ assert(SymI->second.getState() != SymbolState::NeverSearched &&
+ SymI->second.getState() != SymbolState::Ready &&
+ "By this line the symbol should be materializing");
+ auto &MI = JD.MaterializingInfos[Name];
+ MI.addQuery(Q);
+ Q->addQueryDependence(JD, Name);
+
+ return true;
+ });
+
+ // Handle failure.
+ if (Err) {
+
+ LLVM_DEBUG({
+ dbgs() << "Lookup failed. Detaching query and replacing MUs.\n";
+ });
+
+ // Detach the query.
+ Q->detach();
+
+ // Replace the MUs.
+ for (auto &KV : CollectedUMIs) {
+ auto &JD = *KV.first;
+ for (auto &UMI : KV.second)
+ for (auto &KV2 : UMI->MU->getSymbols()) {
+ assert(!JD.UnmaterializedInfos.count(KV2.first) &&
+ "Unexpected materializer in map");
+ auto SymI = JD.Symbols.find(KV2.first);
+ assert(SymI != JD.Symbols.end() && "Missing symbol entry");
+ assert(SymI->second.getState() == SymbolState::Materializing &&
+ "Can not replace symbol that is not materializing");
+ assert(!SymI->second.hasMaterializerAttached() &&
+ "MaterializerAttached flag should not be set");
+ SymI->second.setMaterializerAttached(true);
+ JD.UnmaterializedInfos[KV2.first] = UMI;
+ }
+ }
+
+ return Err;
+ }
+ }
+
+ LLVM_DEBUG(dbgs() << "Stripping unmatched weakly-refererced symbols\n");
+ IPLS->LookupSet.forEachWithRemoval(
+ [&](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
+ if (SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol) {
+ Q->dropSymbol(Name);
+ return true;
+ } else
+ return false;
+ });
+
+ if (!IPLS->LookupSet.empty()) {
+ LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
+ return make_error<SymbolsNotFound>(IPLS->LookupSet.getSymbolNames());
+ }
+
+ // Record whether the query completed.
+ QueryComplete = Q->isComplete();
+
+ LLVM_DEBUG({
+ dbgs() << "Query successfully "
+ << (QueryComplete ? "completed" : "lodged") << "\n";
+ });
+
+ // Move the collected MUs to the OutstandingMUs list.
+ if (!CollectedUMIs.empty()) {
+ std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex);
+
+ LLVM_DEBUG(dbgs() << "Adding MUs to dispatch:\n");
+ for (auto &KV : CollectedUMIs) {
+ auto &JD = *KV.first;
+ LLVM_DEBUG({
+ dbgs() << " For " << JD.getName() << ": Adding " << KV.second.size()
+ << " MUs.\n";
+ });
+ for (auto &UMI : KV.second) {
+ std::unique_ptr<MaterializationResponsibility> MR(
+ new MaterializationResponsibility(
+ &JD, std::move(UMI->MU->SymbolFlags),
+ std::move(UMI->MU->InitSymbol)));
+ JD.MRTrackers[MR.get()] = UMI->RT;
+ OutstandingMUs.push_back(
+ std::make_pair(std::move(UMI->MU), std::move(MR)));
+ }
+ }
+ } else
+ LLVM_DEBUG(dbgs() << "No MUs to dispatch.\n");
+
+ if (RegisterDependencies && !Q->QueryRegistrations.empty()) {
+ LLVM_DEBUG(dbgs() << "Registering dependencies\n");
+ RegisterDependencies(Q->QueryRegistrations);
+ } else
+ LLVM_DEBUG(dbgs() << "No dependencies to register\n");
+
+ return Error::success();
+ });
+
+ if (LodgingErr) {
+ LLVM_DEBUG(dbgs() << "Failing query\n");
+ Q->detach();
+ Q->handleFailed(std::move(LodgingErr));
+ return;
+ }
+
+ if (QueryComplete) {
+ LLVM_DEBUG(dbgs() << "Completing query\n");
+ Q->handleComplete();
+ }
+
+ dispatchOutstandingMUs();
+}
+
+void ExecutionSession::OL_completeLookupFlags(
+ std::unique_ptr<InProgressLookupState> IPLS,
+ unique_function<void(Expected<SymbolFlagsMap>)> OnComplete) {
+
+ auto Result = runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
+ LLVM_DEBUG({
+ dbgs() << "Entering OL_completeLookupFlags:\n"
+ << " Lookup kind: " << IPLS->K << "\n"
+ << " Search order: " << IPLS->SearchOrder
+ << ", Current index = " << IPLS->CurSearchOrderIndex
+ << (IPLS->NewJITDylib ? " (entering new JITDylib)" : "") << "\n"
+ << " Lookup set: " << IPLS->LookupSet << "\n"
+ << " Definition generator candidates: "
+ << IPLS->DefGeneratorCandidates << "\n"
+ << " Definition generator non-candidates: "
+ << IPLS->DefGeneratorNonCandidates << "\n";
+ });
+
+ SymbolFlagsMap Result;
+
+ // Attempt to find flags for each symbol.
+ for (auto &KV : IPLS->SearchOrder) {
+ auto &JD = *KV.first;
+ auto JDLookupFlags = KV.second;
+ LLVM_DEBUG({
+ dbgs() << "Visiting \"" << JD.getName() << "\" (" << JDLookupFlags
+ << ") with lookup set " << IPLS->LookupSet << ":\n";
+ });
+
+ IPLS->LookupSet.forEachWithRemoval([&](const SymbolStringPtr &Name,
+ SymbolLookupFlags SymLookupFlags) {
+ LLVM_DEBUG({
+ dbgs() << " Attempting to match \"" << Name << "\" ("
+ << SymLookupFlags << ")... ";
+ });
+
+ // Search for the symbol. If not found then continue without removing
+ // from the lookup set.
+ auto SymI = JD.Symbols.find(Name);
+ if (SymI == JD.Symbols.end()) {
+ LLVM_DEBUG(dbgs() << "skipping: not present\n");
+ return false;
+ }
+
+ // If this is a non-exported symbol then it doesn't match. Skip it.
+ if (!SymI->second.getFlags().isExported() &&
+ JDLookupFlags == JITDylibLookupFlags::MatchExportedSymbolsOnly) {
+ LLVM_DEBUG(dbgs() << "skipping: not exported\n");
+ return false;
+ }
+
+ LLVM_DEBUG({
+ dbgs() << "matched, \"" << Name << "\" -> " << SymI->second.getFlags()
+ << "\n";
+ });
+ Result[Name] = SymI->second.getFlags();
+ return true;
+ });
+ }
+
+ // Remove any weakly referenced symbols that haven't been resolved.
+ IPLS->LookupSet.remove_if(
+ [](const SymbolStringPtr &Name, SymbolLookupFlags SymLookupFlags) {
+ return SymLookupFlags == SymbolLookupFlags::WeaklyReferencedSymbol;
+ });
+
+ if (!IPLS->LookupSet.empty()) {
+ LLVM_DEBUG(dbgs() << "Failing due to unresolved symbols\n");
+ return make_error<SymbolsNotFound>(IPLS->LookupSet.getSymbolNames());
+ }
+
+ LLVM_DEBUG(dbgs() << "Succeded, result = " << Result << "\n");
+ return Result;
+ });
+
+ // Run the callback on the result.
+ LLVM_DEBUG(dbgs() << "Sending result to handler.\n");
+ OnComplete(std::move(Result));
+}
+
+void ExecutionSession::OL_destroyMaterializationResponsibility(
+ MaterializationResponsibility &MR) {
+
+ assert(MR.SymbolFlags.empty() &&
+ "All symbols should have been explicitly materialized or failed");
+ MR.JD->unlinkMaterializationResponsibility(MR);
+}
+
+SymbolNameSet ExecutionSession::OL_getRequestedSymbols(
+ const MaterializationResponsibility &MR) {
+ return MR.JD->getRequestedSymbols(MR.SymbolFlags);
+}
+
+Error ExecutionSession::OL_notifyResolved(MaterializationResponsibility &MR,
+ const SymbolMap &Symbols) {
+ LLVM_DEBUG({
+ dbgs() << "In " << MR.JD->getName() << " resolving " << Symbols << "\n";
+ });
+#ifndef NDEBUG
+ for (auto &KV : Symbols) {
+ auto WeakFlags = JITSymbolFlags::Weak | JITSymbolFlags::Common;
+ auto I = MR.SymbolFlags.find(KV.first);
+ assert(I != MR.SymbolFlags.end() &&
+ "Resolving symbol outside this responsibility set");
+ assert(!I->second.hasMaterializationSideEffectsOnly() &&
+ "Can't resolve materialization-side-effects-only symbol");
+ assert((KV.second.getFlags() & ~WeakFlags) == (I->second & ~WeakFlags) &&
+ "Resolving symbol with incorrect flags");
+ }
+#endif
+
+ return MR.JD->resolve(MR, Symbols);
+}
+
+Error ExecutionSession::OL_notifyEmitted(MaterializationResponsibility &MR) {
+ LLVM_DEBUG({
+ dbgs() << "In " << MR.JD->getName() << " emitting " << MR.SymbolFlags << "\n";
+ });
+
+ if (auto Err = MR.JD->emit(MR, MR.SymbolFlags))
+ return Err;
+
+ MR.SymbolFlags.clear();
+ return Error::success();
+}
+
+Error ExecutionSession::OL_defineMaterializing(
+ MaterializationResponsibility &MR, SymbolFlagsMap NewSymbolFlags) {
+
+ LLVM_DEBUG({
+ dbgs() << "In " << MR.JD->getName() << " defining materializing symbols "
+ << NewSymbolFlags << "\n";
+ });
+ if (auto AcceptedDefs = MR.JD->defineMaterializing(std::move(NewSymbolFlags))) {
+ // Add all newly accepted symbols to this responsibility object.
+ for (auto &KV : *AcceptedDefs)
+ MR.SymbolFlags.insert(KV);
+ return Error::success();
+ } else
+ return AcceptedDefs.takeError();
+}
+
+void ExecutionSession::OL_notifyFailed(MaterializationResponsibility &MR) {
+
+ LLVM_DEBUG({
+ dbgs() << "In " << MR.JD->getName() << " failing materialization for "
+ << MR.SymbolFlags << "\n";
+ });
+
+ JITDylib::FailedSymbolsWorklist Worklist;
+
+ for (auto &KV : MR.SymbolFlags)
+ Worklist.push_back(std::make_pair(MR.JD.get(), KV.first));
+ MR.SymbolFlags.clear();
+
+ if (Worklist.empty())
+ return;
+
+ JITDylib::AsynchronousSymbolQuerySet FailedQueries;
+ std::shared_ptr<SymbolDependenceMap> FailedSymbols;
+
+ runSessionLocked([&]() {
+ auto RTI = MR.JD->MRTrackers.find(&MR);
+ assert(RTI != MR.JD->MRTrackers.end() && "No tracker for this");
+ if (RTI->second->isDefunct())
+ return;
+
+ std::tie(FailedQueries, FailedSymbols) =
+ JITDylib::failSymbols(std::move(Worklist));
+ });
+
+ for (auto &Q : FailedQueries)
+ Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
+}
+
+Error ExecutionSession::OL_replace(MaterializationResponsibility &MR,
+ std::unique_ptr<MaterializationUnit> MU) {
+ for (auto &KV : MU->getSymbols()) {
+ assert(MR.SymbolFlags.count(KV.first) &&
+ "Replacing definition outside this responsibility set");
+ MR.SymbolFlags.erase(KV.first);
+ }
+
+ if (MU->getInitializerSymbol() == MR.InitSymbol)
+ MR.InitSymbol = nullptr;
+
+ LLVM_DEBUG(MR.JD->getExecutionSession().runSessionLocked([&]() {
+ dbgs() << "In " << MR.JD->getName() << " replacing symbols with " << *MU
+ << "\n";
+ }););
+
+ return MR.JD->replace(MR, std::move(MU));
+}
+
+Expected<std::unique_ptr<MaterializationResponsibility>>
+ExecutionSession::OL_delegate(MaterializationResponsibility &MR,
+ const SymbolNameSet &Symbols) {
+
+ SymbolStringPtr DelegatedInitSymbol;
+ SymbolFlagsMap DelegatedFlags;
+
+ for (auto &Name : Symbols) {
+ auto I = MR.SymbolFlags.find(Name);
+ assert(I != MR.SymbolFlags.end() &&
+ "Symbol is not tracked by this MaterializationResponsibility "
+ "instance");
+
+ DelegatedFlags[Name] = std::move(I->second);
+ if (Name == MR.InitSymbol)
+ std::swap(MR.InitSymbol, DelegatedInitSymbol);
+
+ MR.SymbolFlags.erase(I);
+ }
+
+ return MR.JD->delegate(MR, std::move(DelegatedFlags),
+ std::move(DelegatedInitSymbol));
+}
+
+void ExecutionSession::OL_addDependencies(
+ MaterializationResponsibility &MR, const SymbolStringPtr &Name,
+ const SymbolDependenceMap &Dependencies) {
+ LLVM_DEBUG({
+ dbgs() << "Adding dependencies for " << Name << ": " << Dependencies
+ << "\n";
+ });
+ assert(MR.SymbolFlags.count(Name) &&
+ "Symbol not covered by this MaterializationResponsibility instance");
+ MR.JD->addDependencies(Name, Dependencies);
+}
+
+void ExecutionSession::OL_addDependenciesForAll(
+ MaterializationResponsibility &MR,
+ const SymbolDependenceMap &Dependencies) {
+ LLVM_DEBUG({
+ dbgs() << "Adding dependencies for all symbols in " << MR.SymbolFlags << ": "
+ << Dependencies << "\n";
+ });
+ for (auto &KV : MR.SymbolFlags)
+ MR.JD->addDependencies(KV.first, Dependencies);
}
#ifndef NDEBUG
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
index 4d255cd66c1b..6a1a41a13a1b 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
@@ -21,32 +21,6 @@
namespace llvm {
namespace orc {
-int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
- Optional<StringRef> ProgramName) {
- std::vector<std::unique_ptr<char[]>> ArgVStorage;
- std::vector<char *> ArgV;
-
- ArgVStorage.reserve(Args.size() + (ProgramName ? 1 : 0));
- ArgV.reserve(Args.size() + 1 + (ProgramName ? 1 : 0));
-
- if (ProgramName) {
- ArgVStorage.push_back(std::make_unique<char[]>(ProgramName->size() + 1));
- llvm::copy(*ProgramName, &ArgVStorage.back()[0]);
- ArgVStorage.back()[ProgramName->size()] = '\0';
- ArgV.push_back(ArgVStorage.back().get());
- }
-
- for (auto &Arg : Args) {
- ArgVStorage.push_back(std::make_unique<char[]>(Arg.size() + 1));
- llvm::copy(Arg, &ArgVStorage.back()[0]);
- ArgVStorage.back()[Arg.size()] = '\0';
- ArgV.push_back(ArgVStorage.back().get());
- }
- ArgV.push_back(nullptr);
-
- return Main(Args.size() + !!ProgramName, ArgV.data());
-}
-
CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
: InitList(
GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
@@ -261,8 +235,8 @@ DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
}
Error DynamicLibrarySearchGenerator::tryToGenerate(
- LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
- const SymbolLookupSet &Symbols) {
+ LookupState &LS, LookupKind K, JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
orc::SymbolMap NewSymbols;
bool HasGlobalPrefix = (GlobalPrefix != '\0');
@@ -322,7 +296,8 @@ StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName,
auto ObjTT = Obj.getTriple();
if (ObjTT.getArch() == TT.getArch() &&
ObjTT.getSubArch() == TT.getSubArch() &&
- ObjTT.getVendor() == TT.getVendor()) {
+ (TT.getVendor() == Triple::UnknownVendor ||
+ ObjTT.getVendor() == TT.getVendor())) {
// We found a match. Create an instance from a buffer covering this
// slice.
auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(),
@@ -364,8 +339,8 @@ StaticLibraryDefinitionGenerator::Create(
}
Error StaticLibraryDefinitionGenerator::tryToGenerate(
- LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
- const SymbolLookupSet &Symbols) {
+ LookupState &LS, LookupKind K, JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
// Don't materialize symbols from static archives unless this is a static
// lookup.
@@ -396,8 +371,7 @@ Error StaticLibraryDefinitionGenerator::tryToGenerate(
MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
ChildBufferInfo.second);
- if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false),
- VModuleKey()))
+ if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false)))
return Err;
}
diff --git a/llvm/lib/ExecutionEngine/Orc/IRCompileLayer.cpp b/llvm/lib/ExecutionEngine/Orc/IRCompileLayer.cpp
index 023940dc8298..aadc437c80c4 100644
--- a/llvm/lib/ExecutionEngine/Orc/IRCompileLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/IRCompileLayer.cpp
@@ -25,7 +25,7 @@ void IRCompileLayer::setNotifyCompiled(NotifyCompiledFunction NotifyCompiled) {
this->NotifyCompiled = std::move(NotifyCompiled);
}
-void IRCompileLayer::emit(MaterializationResponsibility R,
+void IRCompileLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
ThreadSafeModule TSM) {
assert(TSM && "Module must not be null");
@@ -33,13 +33,13 @@ void IRCompileLayer::emit(MaterializationResponsibility R,
{
std::lock_guard<std::mutex> Lock(IRLayerMutex);
if (NotifyCompiled)
- NotifyCompiled(R.getVModuleKey(), std::move(TSM));
+ NotifyCompiled(*R, std::move(TSM));
else
TSM = ThreadSafeModule();
}
BaseLayer.emit(std::move(R), std::move(*Obj));
} else {
- R.failMaterialization();
+ R->failMaterialization();
getExecutionSession().reportError(Obj.takeError());
}
}
diff --git a/llvm/lib/ExecutionEngine/Orc/IRTransformLayer.cpp b/llvm/lib/ExecutionEngine/Orc/IRTransformLayer.cpp
index 511248f83b25..d5b11349277c 100644
--- a/llvm/lib/ExecutionEngine/Orc/IRTransformLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/IRTransformLayer.cpp
@@ -17,14 +17,14 @@ IRTransformLayer::IRTransformLayer(ExecutionSession &ES, IRLayer &BaseLayer,
: IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer),
Transform(std::move(Transform)) {}
-void IRTransformLayer::emit(MaterializationResponsibility R,
+void IRTransformLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
ThreadSafeModule TSM) {
assert(TSM && "Module must not be null");
- if (auto TransformedTSM = Transform(std::move(TSM), R))
+ if (auto TransformedTSM = Transform(std::move(TSM), *R))
BaseLayer.emit(std::move(R), std::move(*TransformedTSM));
else {
- R.failMaterialization();
+ R->failMaterialization();
getExecutionSession().reportError(TransformedTSM.takeError());
}
}
diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
index 031b1afefc9d..1cfcf8ae943d 100644
--- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp
@@ -25,20 +25,20 @@ public:
using CompileFunction = JITCompileCallbackManager::CompileFunction;
CompileCallbackMaterializationUnit(SymbolStringPtr Name,
- CompileFunction Compile, VModuleKey K)
+ CompileFunction Compile)
: MaterializationUnit(SymbolFlagsMap({{Name, JITSymbolFlags::Exported}}),
- nullptr, std::move(K)),
+ nullptr),
Name(std::move(Name)), Compile(std::move(Compile)) {}
StringRef getName() const override { return "<Compile Callbacks>"; }
private:
- void materialize(MaterializationResponsibility R) override {
+ void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
SymbolMap Result;
Result[Name] = JITEvaluatedSymbol(Compile(), JITSymbolFlags::Exported);
// No dependencies, so these calls cannot fail.
- cantFail(R.notifyResolved(Result));
- cantFail(R.notifyEmitted());
+ cantFail(R->notifyResolved(Result));
+ cantFail(R->notifyEmitted());
}
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
@@ -54,8 +54,8 @@ private:
namespace llvm {
namespace orc {
+TrampolinePool::~TrampolinePool() {}
void IndirectStubsManager::anchor() {}
-void TrampolinePool::anchor() {}
Expected<JITTargetAddress>
JITCompileCallbackManager::getCompileCallback(CompileFunction Compile) {
@@ -65,10 +65,9 @@ JITCompileCallbackManager::getCompileCallback(CompileFunction Compile) {
std::lock_guard<std::mutex> Lock(CCMgrMutex);
AddrToSymbol[*TrampolineAddr] = CallbackName;
- cantFail(CallbacksJD.define(
- std::make_unique<CompileCallbackMaterializationUnit>(
- std::move(CallbackName), std::move(Compile),
- ES.allocateVModule())));
+ cantFail(
+ CallbacksJD.define(std::make_unique<CompileCallbackMaterializationUnit>(
+ std::move(CallbackName), std::move(Compile))));
return *TrampolineAddr;
} else
return TrampolineAddr.takeError();
@@ -149,7 +148,7 @@ createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
}
case Triple::x86_64: {
- if ( T.getOS() == Triple::OSType::Win32 ) {
+ if (T.getOS() == Triple::OSType::Win32) {
typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_Win32> CCMgrT;
return CCMgrT::Create(ES, ErrorHandlerAddress);
} else {
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 713a48fbf3eb..c368c1e37134 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -11,8 +11,10 @@
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
-#include "llvm/ExecutionEngine/Orc/OrcError.h"
+#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
@@ -87,8 +89,9 @@ class GenericLLVMIRPlatform : public Platform {
public:
GenericLLVMIRPlatform(GenericLLVMIRPlatformSupport &S) : S(S) {}
Error setupJITDylib(JITDylib &JD) override;
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) override;
- Error notifyRemoving(JITDylib &JD, VModuleKey K) override {
+ Error notifyAdding(ResourceTracker &RT,
+ const MaterializationUnit &MU) override;
+ Error notifyRemoving(ResourceTracker &RT) override {
// Noop -- Nothing to do (yet).
return Error::success();
}
@@ -186,7 +189,8 @@ public:
return J.addIRModule(JD, ThreadSafeModule(std::move(M), std::move(Ctx)));
}
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) {
+ Error notifyAdding(ResourceTracker &RT, const MaterializationUnit &MU) {
+ auto &JD = RT.getJITDylib();
if (auto &InitSym = MU.getInitializerSymbol())
InitSymbols[&JD].add(InitSym, SymbolLookupFlags::WeaklyReferencedSymbol);
else {
@@ -235,7 +239,7 @@ public:
});
for (auto DeinitFnAddr : *Deinitializers) {
LLVM_DEBUG({
- dbgs() << " Running init " << formatv("{0:x16}", DeinitFnAddr)
+ dbgs() << " Running deinit " << formatv("{0:x16}", DeinitFnAddr)
<< "...\n";
});
auto *DeinitFn = jitTargetAddressToFunction<void (*)()>(DeinitFnAddr);
@@ -260,23 +264,23 @@ private:
return std::move(Err);
DenseMap<JITDylib *, SymbolLookupSet> LookupSymbols;
- std::vector<JITDylib *> DFSLinkOrder;
+ std::vector<JITDylibSP> DFSLinkOrder;
getExecutionSession().runSessionLocked([&]() {
- DFSLinkOrder = getDFSLinkOrder(JD);
+ DFSLinkOrder = JD.getDFSLinkOrder();
- for (auto *NextJD : DFSLinkOrder) {
- auto IFItr = InitFunctions.find(NextJD);
- if (IFItr != InitFunctions.end()) {
- LookupSymbols[NextJD] = std::move(IFItr->second);
- InitFunctions.erase(IFItr);
- }
+ for (auto &NextJD : DFSLinkOrder) {
+ auto IFItr = InitFunctions.find(NextJD.get());
+ if (IFItr != InitFunctions.end()) {
+ LookupSymbols[NextJD.get()] = std::move(IFItr->second);
+ InitFunctions.erase(IFItr);
}
- });
+ }
+ });
LLVM_DEBUG({
dbgs() << "JITDylib init order is [ ";
- for (auto *JD : llvm::reverse(DFSLinkOrder))
+ for (auto &JD : llvm::reverse(DFSLinkOrder))
dbgs() << "\"" << JD->getName() << "\" ";
dbgs() << "]\n";
dbgs() << "Looking up init functions:\n";
@@ -310,26 +314,26 @@ private:
auto LLJITRunAtExits = J.mangleAndIntern("__lljit_run_atexits");
DenseMap<JITDylib *, SymbolLookupSet> LookupSymbols;
- std::vector<JITDylib *> DFSLinkOrder;
+ std::vector<JITDylibSP> DFSLinkOrder;
ES.runSessionLocked([&]() {
- DFSLinkOrder = getDFSLinkOrder(JD);
+ DFSLinkOrder = JD.getDFSLinkOrder();
- for (auto *NextJD : DFSLinkOrder) {
- auto &JDLookupSymbols = LookupSymbols[NextJD];
- auto DIFItr = DeInitFunctions.find(NextJD);
- if (DIFItr != DeInitFunctions.end()) {
- LookupSymbols[NextJD] = std::move(DIFItr->second);
- DeInitFunctions.erase(DIFItr);
- }
- JDLookupSymbols.add(LLJITRunAtExits,
+ for (auto &NextJD : DFSLinkOrder) {
+ auto &JDLookupSymbols = LookupSymbols[NextJD.get()];
+ auto DIFItr = DeInitFunctions.find(NextJD.get());
+ if (DIFItr != DeInitFunctions.end()) {
+ LookupSymbols[NextJD.get()] = std::move(DIFItr->second);
+ DeInitFunctions.erase(DIFItr);
+ }
+ JDLookupSymbols.add(LLJITRunAtExits,
SymbolLookupFlags::WeaklyReferencedSymbol);
}
});
LLVM_DEBUG({
dbgs() << "JITDylib deinit order is [ ";
- for (auto *JD : DFSLinkOrder)
+ for (auto &JD : DFSLinkOrder)
dbgs() << "\"" << JD->getName() << "\" ";
dbgs() << "]\n";
dbgs() << "Looking up deinit functions:\n";
@@ -343,8 +347,8 @@ private:
return LookupResult.takeError();
std::vector<JITTargetAddress> DeInitializers;
- for (auto *NextJD : DFSLinkOrder) {
- auto DeInitsItr = LookupResult->find(NextJD);
+ for (auto &NextJD : DFSLinkOrder) {
+ auto DeInitsItr = LookupResult->find(NextJD.get());
assert(DeInitsItr != LookupResult->end() &&
"Every JD should have at least __lljit_run_atexits");
@@ -360,46 +364,23 @@ private:
return DeInitializers;
}
- // Returns a DFS traversal order of the JITDylibs reachable (via
- // links-against edges) from JD, starting with JD itself.
- static std::vector<JITDylib *> getDFSLinkOrder(JITDylib &JD) {
- std::vector<JITDylib *> DFSLinkOrder;
- std::vector<JITDylib *> WorkStack({&JD});
- DenseSet<JITDylib *> Visited;
-
- while (!WorkStack.empty()) {
- auto &NextJD = *WorkStack.back();
- WorkStack.pop_back();
- if (Visited.count(&NextJD))
- continue;
- Visited.insert(&NextJD);
- DFSLinkOrder.push_back(&NextJD);
- NextJD.withLinkOrderDo([&](const JITDylibSearchOrder &LinkOrder) {
- for (auto &KV : LinkOrder)
- WorkStack.push_back(KV.first);
- });
- }
-
- return DFSLinkOrder;
- }
-
/// Issue lookups for all init symbols required to initialize JD (and any
/// JITDylibs that it depends on).
Error issueInitLookups(JITDylib &JD) {
DenseMap<JITDylib *, SymbolLookupSet> RequiredInitSymbols;
- std::vector<JITDylib *> DFSLinkOrder;
+ std::vector<JITDylibSP> DFSLinkOrder;
getExecutionSession().runSessionLocked([&]() {
- DFSLinkOrder = getDFSLinkOrder(JD);
+ DFSLinkOrder = JD.getDFSLinkOrder();
- for (auto *NextJD : DFSLinkOrder) {
- auto ISItr = InitSymbols.find(NextJD);
- if (ISItr != InitSymbols.end()) {
- RequiredInitSymbols[NextJD] = std::move(ISItr->second);
- InitSymbols.erase(ISItr);
- }
+ for (auto &NextJD : DFSLinkOrder) {
+ auto ISItr = InitSymbols.find(NextJD.get());
+ if (ISItr != InitSymbols.end()) {
+ RequiredInitSymbols[NextJD.get()] = std::move(ISItr->second);
+ InitSymbols.erase(ISItr);
}
- });
+ }
+ });
return Platform::lookupInitSymbols(getExecutionSession(),
RequiredInitSymbols)
@@ -468,9 +449,9 @@ Error GenericLLVMIRPlatform::setupJITDylib(JITDylib &JD) {
return S.setupJITDylib(JD);
}
-Error GenericLLVMIRPlatform::notifyAdding(JITDylib &JD,
+Error GenericLLVMIRPlatform::notifyAdding(ResourceTracker &RT,
const MaterializationUnit &MU) {
- return S.notifyAdding(JD, MU);
+ return S.notifyAdding(RT, MU);
}
Expected<ThreadSafeModule>
@@ -927,7 +908,7 @@ LLJIT::PlatformSupport::~PlatformSupport() {}
Error LLJITBuilderState::prepareForConstruction() {
- LLVM_DEBUG(dbgs() << "Preparing to create LLIT instance...\n");
+ LLVM_DEBUG(dbgs() << "Preparing to create LLJIT instance...\n");
if (!JTMB) {
LLVM_DEBUG({
@@ -973,12 +954,18 @@ Error LLJITBuilderState::prepareForConstruction() {
JTMB->setRelocationModel(Reloc::PIC_);
JTMB->setCodeModel(CodeModel::Small);
CreateObjectLinkingLayer =
- [](ExecutionSession &ES,
- const Triple &) -> std::unique_ptr<ObjectLayer> {
- auto ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>(
- ES, std::make_unique<jitlink::InProcessMemoryManager>());
+ [TPC = this->TPC](
+ ExecutionSession &ES,
+ const Triple &) -> Expected<std::unique_ptr<ObjectLayer>> {
+ std::unique_ptr<ObjectLinkingLayer> ObjLinkingLayer;
+ if (TPC)
+ ObjLinkingLayer =
+ std::make_unique<ObjectLinkingLayer>(ES, TPC->getMemMgr());
+ else
+ ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>(
+ ES, std::make_unique<jitlink::InProcessMemoryManager>());
ObjLinkingLayer->addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
- jitlink::InProcessEHFrameRegistrar::getInstance()));
+ ES, std::make_unique<jitlink::InProcessEHFrameRegistrar>()));
return std::move(ObjLinkingLayer);
};
}
@@ -990,23 +977,33 @@ Error LLJITBuilderState::prepareForConstruction() {
LLJIT::~LLJIT() {
if (CompileThreads)
CompileThreads->wait();
+ if (auto Err = ES->endSession())
+ ES->reportError(std::move(Err));
}
-Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
+Error LLJIT::addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM) {
assert(TSM && "Can not add null module");
if (auto Err =
TSM.withModuleDo([&](Module &M) { return applyDataLayout(M); }))
return Err;
- return InitHelperTransformLayer->add(JD, std::move(TSM),
- ES->allocateVModule());
+ return InitHelperTransformLayer->add(std::move(RT), std::move(TSM));
}
-Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
+Error LLJIT::addIRModule(JITDylib &JD, ThreadSafeModule TSM) {
+ return addIRModule(JD.getDefaultResourceTracker(), std::move(TSM));
+}
+
+Error LLJIT::addObjectFile(ResourceTrackerSP RT,
+ std::unique_ptr<MemoryBuffer> Obj) {
assert(Obj && "Can not add null object");
- return ObjTransformLayer.add(JD, std::move(Obj), ES->allocateVModule());
+ return ObjTransformLayer->add(std::move(RT), std::move(Obj));
+}
+
+Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
+ return addObjectFile(JD.getDefaultResourceTracker(), std::move(Obj));
}
Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
@@ -1015,7 +1012,7 @@ Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols), Name);
}
-std::unique_ptr<ObjectLayer>
+Expected<std::unique_ptr<ObjectLayer>>
LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES) {
// If the config state provided an ObjectLinkingLayer factory then use it.
@@ -1061,9 +1058,7 @@ LLJIT::createCompileFunction(LLJITBuilderState &S,
LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
: ES(S.ES ? std::move(S.ES) : std::make_unique<ExecutionSession>()), Main(),
- DL(""), TT(S.JTMB->getTargetTriple()),
- ObjLinkingLayer(createObjectLinkingLayer(S, *ES)),
- ObjTransformLayer(*this->ES, *ObjLinkingLayer) {
+ DL(""), TT(S.JTMB->getTargetTriple()) {
ErrorAsOutParameter _(&Err);
@@ -1083,6 +1078,15 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
return;
}
+ auto ObjLayer = createObjectLinkingLayer(S, *ES);
+ if (!ObjLayer) {
+ Err = ObjLayer.takeError();
+ return;
+ }
+ ObjLinkingLayer = std::move(*ObjLayer);
+ ObjTransformLayer =
+ std::make_unique<ObjectTransformLayer>(*ES, *ObjLinkingLayer);
+
{
auto CompileFunction = createCompileFunction(S, std::move(*S.JTMB));
if (!CompileFunction) {
@@ -1090,7 +1094,7 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
return;
}
CompileLayer = std::make_unique<IRCompileLayer>(
- *ES, ObjTransformLayer, std::move(*CompileFunction));
+ *ES, *ObjTransformLayer, std::move(*CompileFunction));
TransformLayer = std::make_unique<IRTransformLayer>(*ES, *CompileLayer);
InitHelperTransformLayer =
std::make_unique<IRTransformLayer>(*ES, *TransformLayer);
@@ -1102,15 +1106,17 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
std::make_unique<ThreadPool>(hardware_concurrency(S.NumCompileThreads));
ES->setDispatchMaterialization(
[this](std::unique_ptr<MaterializationUnit> MU,
- MaterializationResponsibility MR) {
- // FIXME: Switch to move capture once ThreadPool uses unique_function.
- auto SharedMU = std::shared_ptr<MaterializationUnit>(std::move(MU));
- auto SharedMR =
- std::make_shared<MaterializationResponsibility>(std::move(MR));
- auto Work = [SharedMU, SharedMR]() mutable {
- SharedMU->materialize(std::move(*SharedMR));
- };
- CompileThreads->async(std::move(Work));
+ std::unique_ptr<MaterializationResponsibility> MR) {
+ // FIXME: We should be able to use move-capture here, but ThreadPool's
+ // AsyncTaskTys are std::functions rather than unique_functions
+ // (because MSVC's std::packaged_tasks don't support move-only types).
+ // Fix this when all the above gets sorted out.
+ CompileThreads->async(
+ [UnownedMU = MU.release(), UnownedMR = MR.release()]() mutable {
+ std::unique_ptr<MaterializationUnit> MU(UnownedMU);
+ std::unique_ptr<MaterializationResponsibility> MR(UnownedMR);
+ MU->materialize(std::move(MR));
+ });
});
}
@@ -1172,7 +1178,7 @@ Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
[&](Module &M) -> Error { return applyDataLayout(M); }))
return Err;
- return CODLayer->add(JD, std::move(TSM), ES->allocateVModule());
+ return CODLayer->add(JD, std::move(TSM));
}
LLLazyJIT::LLLazyJIT(LLLazyJITBuilderState &S, Error &Err) : LLJIT(S, Err) {
diff --git a/llvm/lib/ExecutionEngine/Orc/Layer.cpp b/llvm/lib/ExecutionEngine/Orc/Layer.cpp
index 61e7ab5ae68b..5e27e343d23b 100644
--- a/llvm/lib/ExecutionEngine/Orc/Layer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Layer.cpp
@@ -22,16 +22,18 @@ namespace orc {
IRLayer::~IRLayer() {}
-Error IRLayer::add(JITDylib &JD, ThreadSafeModule TSM, VModuleKey K) {
+Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM) {
+ assert(RT && "RT can not be null");
+ auto &JD = RT->getJITDylib();
return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
- *this, *getManglingOptions(), std::move(TSM), std::move(K)));
+ *this, *getManglingOptions(), std::move(TSM)),
+ std::move(RT));
}
IRMaterializationUnit::IRMaterializationUnit(
ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,
- ThreadSafeModule TSM, VModuleKey K)
- : MaterializationUnit(SymbolFlagsMap(), nullptr, std::move(K)),
- TSM(std::move(TSM)) {
+ ThreadSafeModule TSM)
+ : MaterializationUnit(SymbolFlagsMap(), nullptr), TSM(std::move(TSM)) {
assert(this->TSM && "Module must not be null");
@@ -83,26 +85,22 @@ IRMaterializationUnit::IRMaterializationUnit(
if (!llvm::empty(getStaticInitGVs(M))) {
size_t Counter = 0;
- while (true) {
+ do {
std::string InitSymbolName;
raw_string_ostream(InitSymbolName)
<< "$." << M.getModuleIdentifier() << ".__inits." << Counter++;
InitSymbol = ES.intern(InitSymbolName);
- if (SymbolFlags.count(InitSymbol))
- continue;
- SymbolFlags[InitSymbol] =
- JITSymbolFlags::MaterializationSideEffectsOnly;
- break;
- }
+ } while (SymbolFlags.count(InitSymbol));
+
+ SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
}
});
}
IRMaterializationUnit::IRMaterializationUnit(
- ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags,
+ ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags,
SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition)
- : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol),
- std::move(K)),
+ : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol)),
TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {}
StringRef IRMaterializationUnit::getName() const {
@@ -129,14 +127,12 @@ void IRMaterializationUnit::discard(const JITDylib &JD,
}
BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
- IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM,
- VModuleKey K)
- : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM),
- std::move(K)),
- L(L), K(std::move(K)) {}
+ IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM)
+ : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM)), L(L) {
+}
void BasicIRLayerMaterializationUnit::materialize(
- MaterializationResponsibility R) {
+ std::unique_ptr<MaterializationResponsibility> R) {
// Throw away the SymbolToDefinition map: it's not usable after we hand
// off the module.
@@ -147,8 +143,8 @@ void BasicIRLayerMaterializationUnit::materialize(
TSM = cloneToNewContext(TSM);
#ifndef NDEBUG
- auto &ES = R.getTargetJITDylib().getExecutionSession();
- auto &N = R.getTargetJITDylib().getName();
+ auto &ES = R->getTargetJITDylib().getExecutionSession();
+ auto &N = R->getTargetJITDylib().getName();
#endif // NDEBUG
LLVM_DEBUG(ES.runSessionLocked(
@@ -163,17 +159,17 @@ ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
ObjectLayer::~ObjectLayer() {}
-Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O,
- VModuleKey K) {
- auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(K),
- std::move(O));
+Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O) {
+ assert(RT && "RT can not be null");
+ auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(O));
if (!ObjMU)
return ObjMU.takeError();
- return JD.define(std::move(*ObjMU));
+ auto &JD = RT->getJITDylib();
+ return JD.define(std::move(*ObjMU), std::move(RT));
}
Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
-BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K,
+BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L,
std::unique_ptr<MemoryBuffer> O) {
auto ObjSymInfo =
getObjectSymbolInfo(L.getExecutionSession(), O->getMemBufferRef());
@@ -186,15 +182,14 @@ BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K,
return std::unique_ptr<BasicObjectLayerMaterializationUnit>(
new BasicObjectLayerMaterializationUnit(
- L, K, std::move(O), std::move(SymbolFlags), std::move(InitSymbol)));
+ L, std::move(O), std::move(SymbolFlags), std::move(InitSymbol)));
}
BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(
- ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O,
- SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol)
- : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol),
- std::move(K)),
- L(L), O(std::move(O)) {}
+ ObjectLayer &L, std::unique_ptr<MemoryBuffer> O, SymbolFlagsMap SymbolFlags,
+ SymbolStringPtr InitSymbol)
+ : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol)), L(L),
+ O(std::move(O)) {}
StringRef BasicObjectLayerMaterializationUnit::getName() const {
if (O)
@@ -203,7 +198,7 @@ StringRef BasicObjectLayerMaterializationUnit::getName() const {
}
void BasicObjectLayerMaterializationUnit::materialize(
- MaterializationResponsibility R) {
+ std::unique_ptr<MaterializationResponsibility> R) {
L.emit(std::move(R), std::move(O));
}
diff --git a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
index 153f6b80784f..e1f494415e86 100644
--- a/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
@@ -75,27 +75,31 @@ void LazyCallThroughManager::resolveTrampolineLandingAddress(
if (!Entry)
return NotifyLandingResolved(reportCallThroughError(Entry.takeError()));
- ES.lookup(
- LookupKind::Static,
- makeJITDylibSearchOrder(Entry->SourceJD,
- JITDylibLookupFlags::MatchAllSymbols),
- SymbolLookupSet({Entry->SymbolName}), SymbolState::Ready,
- [this, TrampolineAddr, SymbolName = Entry->SymbolName,
- NotifyLandingResolved = std::move(NotifyLandingResolved)](
- Expected<SymbolMap> Result) mutable {
- if (Result) {
- assert(Result->size() == 1 && "Unexpected result size");
- assert(Result->count(SymbolName) && "Unexpected result value");
- JITTargetAddress LandingAddr = (*Result)[SymbolName].getAddress();
+ // Declaring SLS and the callback outside of the call to ES.lookup is a
+ // workaround to fix build failures on AIX and on z/OS platforms.
+ SymbolLookupSet SLS({Entry->SymbolName});
+ auto Callback = [this, TrampolineAddr, SymbolName = Entry->SymbolName,
+ NotifyLandingResolved = std::move(NotifyLandingResolved)](
+ Expected<SymbolMap> Result) mutable {
+ if (Result) {
+ assert(Result->size() == 1 && "Unexpected result size");
+ assert(Result->count(SymbolName) && "Unexpected result value");
+ JITTargetAddress LandingAddr = (*Result)[SymbolName].getAddress();
- if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))
- NotifyLandingResolved(reportCallThroughError(std::move(Err)));
- else
- NotifyLandingResolved(LandingAddr);
- } else
- NotifyLandingResolved(reportCallThroughError(Result.takeError()));
- },
- NoDependenciesToRegister);
+ if (auto Err = notifyResolved(TrampolineAddr, LandingAddr))
+ NotifyLandingResolved(reportCallThroughError(std::move(Err)));
+ else
+ NotifyLandingResolved(LandingAddr);
+ } else {
+ NotifyLandingResolved(reportCallThroughError(Result.takeError()));
+ }
+ };
+
+ ES.lookup(LookupKind::Static,
+ makeJITDylibSearchOrder(Entry->SourceJD,
+ JITDylibLookupFlags::MatchAllSymbols),
+ std::move(SLS), SymbolState::Ready, std::move(Callback),
+ NoDependenciesToRegister);
}
Expected<std::unique_ptr<LazyCallThroughManager>>
@@ -139,9 +143,8 @@ createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
- JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc,
- VModuleKey K)
- : MaterializationUnit(extractFlags(CallableAliases), nullptr, std::move(K)),
+ JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc)
+ : MaterializationUnit(extractFlags(CallableAliases), nullptr),
LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
CallableAliases(std::move(CallableAliases)), AliaseeTable(SrcJDLoc) {}
@@ -150,8 +153,8 @@ StringRef LazyReexportsMaterializationUnit::getName() const {
}
void LazyReexportsMaterializationUnit::materialize(
- MaterializationResponsibility R) {
- auto RequestedSymbols = R.getRequestedSymbols();
+ std::unique_ptr<MaterializationResponsibility> R) {
+ auto RequestedSymbols = R->getRequestedSymbols();
SymbolAliasMap RequestedAliases;
for (auto &RequestedSymbol : RequestedSymbols) {
@@ -162,8 +165,13 @@ void LazyReexportsMaterializationUnit::materialize(
}
if (!CallableAliases.empty())
- R.replace(lazyReexports(LCTManager, ISManager, SourceJD,
- std::move(CallableAliases), AliaseeTable));
+ if (auto Err = R->replace(lazyReexports(LCTManager, ISManager, SourceJD,
+ std::move(CallableAliases),
+ AliaseeTable))) {
+ R->getExecutionSession().reportError(std::move(Err));
+ R->failMaterialization();
+ return;
+ }
IndirectStubsManager::StubInitsMap StubInits;
for (auto &Alias : RequestedAliases) {
@@ -178,7 +186,7 @@ void LazyReexportsMaterializationUnit::materialize(
if (!CallThroughTrampoline) {
SourceJD.getExecutionSession().reportError(
CallThroughTrampoline.takeError());
- R.failMaterialization();
+ R->failMaterialization();
return;
}
@@ -191,7 +199,7 @@ void LazyReexportsMaterializationUnit::materialize(
if (auto Err = ISManager.createStubs(StubInits)) {
SourceJD.getExecutionSession().reportError(std::move(Err));
- R.failMaterialization();
+ R->failMaterialization();
return;
}
@@ -200,8 +208,8 @@ void LazyReexportsMaterializationUnit::materialize(
Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
// No registered dependencies, so these calls cannot fail.
- cantFail(R.notifyResolved(Stubs));
- cantFail(R.notifyEmitted());
+ cantFail(R->notifyResolved(Stubs));
+ cantFail(R->notifyEmitted());
}
void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
diff --git a/llvm/lib/ExecutionEngine/Orc/Legacy.cpp b/llvm/lib/ExecutionEngine/Orc/Legacy.cpp
deleted file mode 100644
index 67b804c37287..000000000000
--- a/llvm/lib/ExecutionEngine/Orc/Legacy.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-//===------- Legacy.cpp - Adapters for ExecutionEngine API interop --------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ExecutionEngine/Orc/Legacy.h"
-
-namespace llvm {
-namespace orc {
-
-void SymbolResolver::anchor() {}
-
-JITSymbolResolverAdapter::JITSymbolResolverAdapter(
- ExecutionSession &ES, SymbolResolver &R, MaterializationResponsibility *MR)
- : ES(ES), R(R), MR(MR) {}
-
-void JITSymbolResolverAdapter::lookup(const LookupSet &Symbols,
- OnResolvedFunction OnResolved) {
- SymbolNameSet InternedSymbols;
- for (auto &S : Symbols)
- InternedSymbols.insert(ES.intern(S));
-
- auto OnResolvedWithUnwrap = [OnResolved = std::move(OnResolved)](
- Expected<SymbolMap> InternedResult) mutable {
- if (!InternedResult) {
- OnResolved(InternedResult.takeError());
- return;
- }
-
- LookupResult Result;
- for (auto &KV : *InternedResult)
- Result[*KV.first] = std::move(KV.second);
- OnResolved(Result);
- };
-
- auto Q = std::make_shared<AsynchronousSymbolQuery>(
- SymbolLookupSet(InternedSymbols), SymbolState::Resolved,
- std::move(OnResolvedWithUnwrap));
-
- auto Unresolved = R.lookup(Q, InternedSymbols);
- if (Unresolved.empty()) {
- if (MR)
- MR->addDependenciesForAll(Q->QueryRegistrations);
- } else
- ES.legacyFailQuery(*Q, make_error<SymbolsNotFound>(std::move(Unresolved)));
-}
-
-Expected<JITSymbolResolverAdapter::LookupSet>
-JITSymbolResolverAdapter::getResponsibilitySet(const LookupSet &Symbols) {
- SymbolNameSet InternedSymbols;
- for (auto &S : Symbols)
- InternedSymbols.insert(ES.intern(S));
-
- auto InternedResult = R.getResponsibilitySet(InternedSymbols);
- LookupSet Result;
- for (auto &S : InternedResult) {
- ResolvedStrings.insert(S);
- Result.insert(*S);
- }
-
- return Result;
-}
-
-} // End namespace orc.
-} // End namespace llvm.
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index 15c3aa79a2a8..17b9465a0541 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -159,7 +159,9 @@ Error MachOPlatform::setupJITDylib(JITDylib &JD) {
return ObjLinkingLayer.add(JD, std::move(ObjBuffer));
}
-Error MachOPlatform::notifyAdding(JITDylib &JD, const MaterializationUnit &MU) {
+Error MachOPlatform::notifyAdding(ResourceTracker &RT,
+ const MaterializationUnit &MU) {
+ auto &JD = RT.getJITDylib();
const auto &InitSym = MU.getInitializerSymbol();
if (!InitSym)
return Error::success();
@@ -173,7 +175,7 @@ Error MachOPlatform::notifyAdding(JITDylib &JD, const MaterializationUnit &MU) {
return Error::success();
}
-Error MachOPlatform::notifyRemoving(JITDylib &JD, VModuleKey K) {
+Error MachOPlatform::notifyRemoving(ResourceTracker &RT) {
llvm_unreachable("Not supported yet");
}
@@ -185,19 +187,19 @@ MachOPlatform::getInitializerSequence(JITDylib &JD) {
<< JD.getName() << "\n";
});
- std::vector<JITDylib *> DFSLinkOrder;
+ std::vector<JITDylibSP> DFSLinkOrder;
while (true) {
DenseMap<JITDylib *, SymbolLookupSet> NewInitSymbols;
ES.runSessionLocked([&]() {
- DFSLinkOrder = getDFSLinkOrder(JD);
+ DFSLinkOrder = JD.getDFSLinkOrder();
- for (auto *InitJD : DFSLinkOrder) {
- auto RISItr = RegisteredInitSymbols.find(InitJD);
+ for (auto &InitJD : DFSLinkOrder) {
+ auto RISItr = RegisteredInitSymbols.find(InitJD.get());
if (RISItr != RegisteredInitSymbols.end()) {
- NewInitSymbols[InitJD] = std::move(RISItr->second);
+ NewInitSymbols[InitJD.get()] = std::move(RISItr->second);
RegisteredInitSymbols.erase(RISItr);
}
}
@@ -229,14 +231,14 @@ MachOPlatform::getInitializerSequence(JITDylib &JD) {
InitializerSequence FullInitSeq;
{
std::lock_guard<std::mutex> Lock(InitSeqsMutex);
- for (auto *InitJD : reverse(DFSLinkOrder)) {
+ for (auto &InitJD : reverse(DFSLinkOrder)) {
LLVM_DEBUG({
dbgs() << "MachOPlatform: Appending inits for \"" << InitJD->getName()
<< "\" to sequence\n";
});
- auto ISItr = InitSeqs.find(InitJD);
+ auto ISItr = InitSeqs.find(InitJD.get());
if (ISItr != InitSeqs.end()) {
- FullInitSeq.emplace_back(InitJD, std::move(ISItr->second));
+ FullInitSeq.emplace_back(InitJD.get(), std::move(ISItr->second));
InitSeqs.erase(ISItr);
}
}
@@ -247,39 +249,19 @@ MachOPlatform::getInitializerSequence(JITDylib &JD) {
Expected<MachOPlatform::DeinitializerSequence>
MachOPlatform::getDeinitializerSequence(JITDylib &JD) {
- std::vector<JITDylib *> DFSLinkOrder = getDFSLinkOrder(JD);
+ std::vector<JITDylibSP> DFSLinkOrder = JD.getDFSLinkOrder();
DeinitializerSequence FullDeinitSeq;
{
std::lock_guard<std::mutex> Lock(InitSeqsMutex);
- for (auto *DeinitJD : DFSLinkOrder) {
- FullDeinitSeq.emplace_back(DeinitJD, MachOJITDylibDeinitializers());
+ for (auto &DeinitJD : DFSLinkOrder) {
+ FullDeinitSeq.emplace_back(DeinitJD.get(), MachOJITDylibDeinitializers());
}
}
return FullDeinitSeq;
}
-std::vector<JITDylib *> MachOPlatform::getDFSLinkOrder(JITDylib &JD) {
- std::vector<JITDylib *> Result, WorkStack({&JD});
- DenseSet<JITDylib *> Visited;
-
- while (!WorkStack.empty()) {
- auto *NextJD = WorkStack.back();
- WorkStack.pop_back();
- if (Visited.count(NextJD))
- continue;
- Visited.insert(NextJD);
- Result.push_back(NextJD);
- NextJD->withLinkOrderDo([&](const JITDylibSearchOrder &LO) {
- for (auto &KV : LO)
- WorkStack.push_back(KV.first);
- });
- }
-
- return Result;
-}
-
void MachOPlatform::registerInitInfo(
JITDylib &JD, JITTargetAddress ObjCImageInfoAddr,
MachOJITDylibInitializers::SectionExtent ModInits,
@@ -319,13 +301,16 @@ void MachOPlatform::InitScraperPlugin::modifyPassConfig(
MaterializationResponsibility &MR, const Triple &TT,
jitlink::PassConfiguration &Config) {
+ if (!MR.getInitializerSymbol())
+ return;
+
Config.PrePrunePasses.push_back([this, &MR](jitlink::LinkGraph &G) -> Error {
JITLinkSymbolVector InitSectionSymbols;
preserveInitSectionIfPresent(InitSectionSymbols, G, "__mod_init_func");
preserveInitSectionIfPresent(InitSectionSymbols, G, "__objc_selrefs");
preserveInitSectionIfPresent(InitSectionSymbols, G, "__objc_classlist");
- if (!InitSymbolDeps.empty()) {
+ if (!InitSectionSymbols.empty()) {
std::lock_guard<std::mutex> Lock(InitScraperMutex);
InitSymbolDeps[&MR] = std::move(InitSectionSymbols);
}
@@ -343,10 +328,8 @@ void MachOPlatform::InitScraperPlugin::modifyPassConfig(
JITTargetAddress ObjCImageInfoAddr = 0;
if (auto *ObjCImageInfoSec = G.findSectionByName("__objc_image_info")) {
- if (auto Addr = jitlink::SectionRange(*ObjCImageInfoSec).getStart()) {
+ if (auto Addr = jitlink::SectionRange(*ObjCImageInfoSec).getStart())
ObjCImageInfoAddr = Addr;
- dbgs() << "Recorded __objc_imageinfo @ " << formatv("{0:x16}", Addr);
- }
}
// Record __mod_init_func.
diff --git a/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp b/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp
deleted file mode 100644
index 5b4345b870bb..000000000000
--- a/llvm/lib/ExecutionEngine/Orc/NullResolver.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//===---------- NullResolver.cpp - Reject symbol lookup requests ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ExecutionEngine/Orc/NullResolver.h"
-
-#include "llvm/Support/ErrorHandling.h"
-
-namespace llvm {
-namespace orc {
-
-SymbolNameSet NullResolver::getResponsibilitySet(const SymbolNameSet &Symbols) {
- return Symbols;
-}
-
-SymbolNameSet
-NullResolver::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols) {
- assert(Symbols.empty() && "Null resolver: Symbols must be empty");
- return Symbols;
-}
-
-JITSymbol NullLegacyResolver::findSymbol(const std::string &Name) {
- llvm_unreachable("Unexpected cross-object symbol reference");
-}
-
-JITSymbol
-NullLegacyResolver::findSymbolInLogicalDylib(const std::string &Name) {
- llvm_unreachable("Unexpected cross-object symbol reference");
-}
-
-} // End namespace orc.
-} // End namespace llvm.
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
index 02066b458dfc..26f77acd91fc 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
@@ -24,34 +24,34 @@ namespace orc {
class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
public:
- ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer,
- MaterializationResponsibility MR,
- std::unique_ptr<MemoryBuffer> ObjBuffer)
- : Layer(Layer), MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
+ ObjectLinkingLayerJITLinkContext(
+ ObjectLinkingLayer &Layer,
+ std::unique_ptr<MaterializationResponsibility> MR,
+ std::unique_ptr<MemoryBuffer> ObjBuffer)
+ : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),
+ MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
~ObjectLinkingLayerJITLinkContext() {
// If there is an object buffer return function then use it to
// return ownership of the buffer.
- if (Layer.ReturnObjectBuffer)
+ if (Layer.ReturnObjectBuffer && ObjBuffer)
Layer.ReturnObjectBuffer(std::move(ObjBuffer));
}
- JITLinkMemoryManager &getMemoryManager() override { return *Layer.MemMgr; }
-
- MemoryBufferRef getObjectBuffer() const override {
- return ObjBuffer->getMemBufferRef();
- }
+ JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
void notifyFailed(Error Err) override {
+ for (auto &P : Layer.Plugins)
+ Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
Layer.getExecutionSession().reportError(std::move(Err));
- MR.failMaterialization();
+ MR->failMaterialization();
}
void lookup(const LookupMap &Symbols,
std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
JITDylibSearchOrder LinkOrder;
- MR.getTargetJITDylib().withLinkOrderDo(
+ MR->getTargetJITDylib().withLinkOrderDo(
[&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
auto &ES = Layer.getExecutionSession();
@@ -71,9 +71,8 @@ public:
}
// OnResolve -- De-intern the symbols and pass the result to the linker.
- auto OnResolve = [this, LookupContinuation = std::move(LC)](
- Expected<SymbolMap> Result) mutable {
- auto Main = Layer.getExecutionSession().intern("_main");
+ auto OnResolve = [LookupContinuation =
+ std::move(LC)](Expected<SymbolMap> Result) mutable {
if (!Result)
LookupContinuation->run(Result.takeError());
else {
@@ -86,8 +85,8 @@ public:
for (auto &KV : InternalNamedSymbolDeps) {
SymbolDependenceMap InternalDeps;
- InternalDeps[&MR.getTargetJITDylib()] = std::move(KV.second);
- MR.addDependencies(KV.first, InternalDeps);
+ InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second);
+ MR->addDependencies(KV.first, InternalDeps);
}
ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),
@@ -97,7 +96,7 @@ public:
});
}
- void notifyResolved(LinkGraph &G) override {
+ Error notifyResolved(LinkGraph &G) override {
auto &ES = Layer.getExecutionSession();
SymbolFlagsMap ExtraSymbolsToClaim;
@@ -116,7 +115,7 @@ public:
InternedResult[InternedName] =
JITEvaluatedSymbol(Sym->getAddress(), Flags);
- if (AutoClaim && !MR.getSymbols().count(InternedName)) {
+ if (AutoClaim && !MR->getSymbols().count(InternedName)) {
assert(!ExtraSymbolsToClaim.count(InternedName) &&
"Duplicate symbol to claim?");
ExtraSymbolsToClaim[InternedName] = Flags;
@@ -134,7 +133,7 @@ public:
Flags |= JITSymbolFlags::Weak;
InternedResult[InternedName] =
JITEvaluatedSymbol(Sym->getAddress(), Flags);
- if (AutoClaim && !MR.getSymbols().count(InternedName)) {
+ if (AutoClaim && !MR->getSymbols().count(InternedName)) {
assert(!ExtraSymbolsToClaim.count(InternedName) &&
"Duplicate symbol to claim?");
ExtraSymbolsToClaim[InternedName] = Flags;
@@ -142,19 +141,19 @@ public:
}
if (!ExtraSymbolsToClaim.empty())
- if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
- return notifyFailed(std::move(Err));
+ if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
+ return Err;
{
- // Check that InternedResult matches up with MR.getSymbols().
+ // Check that InternedResult matches up with MR->getSymbols().
// This guards against faulty transformations / compilers / object caches.
// First check that there aren't any missing symbols.
size_t NumMaterializationSideEffectsOnlySymbols = 0;
SymbolNameVector ExtraSymbols;
SymbolNameVector MissingSymbols;
- for (auto &KV : MR.getSymbols()) {
+ for (auto &KV : MR->getSymbols()) {
// If this is a materialization-side-effects only symbol then bump
// the counter and make sure it's *not* defined, otherwise make
@@ -169,49 +168,42 @@ public:
}
// If there were missing symbols then report the error.
- if (!MissingSymbols.empty()) {
- ES.reportError(make_error<MissingSymbolDefinitions>(
- G.getName(), std::move(MissingSymbols)));
- MR.failMaterialization();
- return;
- }
+ if (!MissingSymbols.empty())
+ return make_error<MissingSymbolDefinitions>(G.getName(),
+ std::move(MissingSymbols));
// If there are more definitions than expected, add them to the
// ExtraSymbols vector.
if (InternedResult.size() >
- MR.getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
+ MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
for (auto &KV : InternedResult)
- if (!MR.getSymbols().count(KV.first))
+ if (!MR->getSymbols().count(KV.first))
ExtraSymbols.push_back(KV.first);
}
// If there were extra definitions then report the error.
- if (!ExtraSymbols.empty()) {
- ES.reportError(make_error<UnexpectedSymbolDefinitions>(
- G.getName(), std::move(ExtraSymbols)));
- MR.failMaterialization();
- return;
- }
+ if (!ExtraSymbols.empty())
+ return make_error<UnexpectedSymbolDefinitions>(G.getName(),
+ std::move(ExtraSymbols));
}
- if (auto Err = MR.notifyResolved(InternedResult)) {
- Layer.getExecutionSession().reportError(std::move(Err));
- MR.failMaterialization();
- return;
- }
- Layer.notifyLoaded(MR);
+ if (auto Err = MR->notifyResolved(InternedResult))
+ return Err;
+
+ Layer.notifyLoaded(*MR);
+ return Error::success();
}
void notifyFinalized(
std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
- if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
+ if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) {
Layer.getExecutionSession().reportError(std::move(Err));
- MR.failMaterialization();
+ MR->failMaterialization();
return;
}
- if (auto Err = MR.notifyEmitted()) {
+ if (auto Err = MR->notifyEmitted()) {
Layer.getExecutionSession().reportError(std::move(Err));
- MR.failMaterialization();
+ MR->failMaterialization();
}
}
@@ -222,10 +214,11 @@ public:
Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override {
// Add passes to mark duplicate defs as should-discard, and to walk the
// link graph to build the symbol dependence graph.
- Config.PrePrunePasses.push_back(
- [this](LinkGraph &G) { return externalizeWeakAndCommonSymbols(G); });
+ Config.PrePrunePasses.push_back([this](LinkGraph &G) {
+ return claimOrExternalizeWeakAndCommonSymbols(G);
+ });
- Layer.modifyPassConfig(MR, TT, Config);
+ Layer.modifyPassConfig(*MR, TT, Config);
Config.PostPrunePasses.push_back(
[this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
@@ -241,19 +234,38 @@ private:
using LocalSymbolNamedDependenciesMap =
DenseMap<const Symbol *, LocalSymbolNamedDependencies>;
- Error externalizeWeakAndCommonSymbols(LinkGraph &G) {
+ Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
auto &ES = Layer.getExecutionSession();
- for (auto *Sym : G.defined_symbols())
+
+ SymbolFlagsMap NewSymbolsToClaim;
+ std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
+
+ auto ProcessSymbol = [&](Symbol *Sym) {
if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
- if (!MR.getSymbols().count(ES.intern(Sym->getName())))
- G.makeExternal(*Sym);
+ auto Name = ES.intern(Sym->getName());
+ if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {
+ JITSymbolFlags SF = JITSymbolFlags::Weak;
+ if (Sym->getScope() == Scope::Default)
+ SF |= JITSymbolFlags::Exported;
+ NewSymbolsToClaim[Name] = SF;
+ NameToSym.push_back(std::make_pair(std::move(Name), Sym));
+ }
}
+ };
+ for (auto *Sym : G.defined_symbols())
+ ProcessSymbol(Sym);
for (auto *Sym : G.absolute_symbols())
- if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
- if (!MR.getSymbols().count(ES.intern(Sym->getName())))
- G.makeExternal(*Sym);
- }
+ ProcessSymbol(Sym);
+
+ // Attempt to claim all weak defs that we're not already responsible for.
+ // This cannot fail -- any clashes will just result in rejection of our
+ // claim, at which point we'll externalize that symbol.
+ cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim)));
+
+ for (auto &KV : NameToSym)
+ if (!MR->getSymbols().count(KV.first))
+ G.makeExternal(*KV.second);
return Error::success();
}
@@ -261,13 +273,13 @@ private:
Error markResponsibilitySymbolsLive(LinkGraph &G) const {
auto &ES = Layer.getExecutionSession();
for (auto *Sym : G.defined_symbols())
- if (Sym->hasName() && MR.getSymbols().count(ES.intern(Sym->getName())))
+ if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName())))
Sym->setLive(true);
return Error::success();
}
Error computeNamedSymbolDependencies(LinkGraph &G) {
- auto &ES = MR.getTargetJITDylib().getExecutionSession();
+ auto &ES = MR->getTargetJITDylib().getExecutionSession();
auto LocalDeps = computeLocalDeps(G);
// Compute dependencies for symbols defined in the JITLink graph.
@@ -314,7 +326,7 @@ private:
}
for (auto &P : Layer.Plugins) {
- auto SyntheticLocalDeps = P->getSyntheticSymbolLocalDependencies(MR);
+ auto SyntheticLocalDeps = P->getSyntheticSymbolLocalDependencies(*MR);
if (SyntheticLocalDeps.empty())
continue;
@@ -434,12 +446,12 @@ private:
SymbolDeps.erase(&SourceJD);
}
- MR.addDependencies(Name, SymbolDeps);
+ MR->addDependencies(Name, SymbolDeps);
}
}
ObjectLinkingLayer &Layer;
- MaterializationResponsibility MR;
+ std::unique_ptr<MaterializationResponsibility> MR;
std::unique_ptr<MemoryBuffer> ObjBuffer;
DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps;
DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps;
@@ -447,20 +459,39 @@ private:
ObjectLinkingLayer::Plugin::~Plugin() {}
+ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
+ JITLinkMemoryManager &MemMgr)
+ : ObjectLayer(ES), MemMgr(MemMgr) {
+ ES.registerResourceManager(*this);
+}
+
ObjectLinkingLayer::ObjectLinkingLayer(
ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
- : ObjectLayer(ES), MemMgr(std::move(MemMgr)) {}
+ : ObjectLayer(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
+ ES.registerResourceManager(*this);
+}
ObjectLinkingLayer::~ObjectLinkingLayer() {
- if (auto Err = removeAllModules())
- getExecutionSession().reportError(std::move(Err));
+ assert(Allocs.empty() && "Layer destroyed with resources still attached");
+ getExecutionSession().deregisterResourceManager(*this);
}
-void ObjectLinkingLayer::emit(MaterializationResponsibility R,
+void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
std::unique_ptr<MemoryBuffer> O) {
assert(O && "Object must not be null");
- jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
- *this, std::move(R), std::move(O)));
+ auto ObjBuffer = O->getMemBufferRef();
+ auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
+ *this, std::move(R), std::move(O));
+ if (auto G = createLinkGraphFromObject(std::move(ObjBuffer)))
+ link(std::move(*G), std::move(Ctx));
+ else
+ Ctx->notifyFailed(G.takeError());
+}
+
+void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
+ std::unique_ptr<LinkGraph> G) {
+ link(std::move(G), std::make_unique<ObjectLinkingLayerJITLinkContext>(
+ *this, std::move(R), nullptr));
}
void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
@@ -484,63 +515,56 @@ Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
if (Err)
return Err;
- {
- std::lock_guard<std::mutex> Lock(LayerMutex);
- UntrackedAllocs.push_back(std::move(Alloc));
- }
-
- return Error::success();
+ return MR.withResourceKeyDo(
+ [&](ResourceKey K) { Allocs[K].push_back(std::move(Alloc)); });
}
-Error ObjectLinkingLayer::removeModule(VModuleKey K) {
+Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
+
Error Err = Error::success();
for (auto &P : Plugins)
- Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
+ Err = joinErrors(std::move(Err), P->notifyRemovingResources(K));
- AllocPtr Alloc;
+ std::vector<AllocPtr> AllocsToRemove;
+ getExecutionSession().runSessionLocked([&] {
+ auto I = Allocs.find(K);
+ if (I != Allocs.end()) {
+ std::swap(AllocsToRemove, I->second);
+ Allocs.erase(I);
+ }
+ });
- {
- std::lock_guard<std::mutex> Lock(LayerMutex);
- auto AllocItr = TrackedAllocs.find(K);
- Alloc = std::move(AllocItr->second);
- TrackedAllocs.erase(AllocItr);
+ while (!AllocsToRemove.empty()) {
+ Err = joinErrors(std::move(Err), AllocsToRemove.back()->deallocate());
+ AllocsToRemove.pop_back();
}
- assert(Alloc && "No allocation for key K");
-
- return joinErrors(std::move(Err), Alloc->deallocate());
+ return Err;
}
-Error ObjectLinkingLayer::removeAllModules() {
+void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
+ ResourceKey SrcKey) {
+ auto I = Allocs.find(SrcKey);
+ if (I != Allocs.end()) {
+ auto &SrcAllocs = I->second;
+ auto &DstAllocs = Allocs[DstKey];
+ DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
+ for (auto &Alloc : SrcAllocs)
+ DstAllocs.push_back(std::move(Alloc));
- Error Err = Error::success();
-
- for (auto &P : Plugins)
- Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
-
- std::vector<AllocPtr> Allocs;
- {
- std::lock_guard<std::mutex> Lock(LayerMutex);
- Allocs = std::move(UntrackedAllocs);
-
- for (auto &KV : TrackedAllocs)
- Allocs.push_back(std::move(KV.second));
-
- TrackedAllocs.clear();
- }
-
- while (!Allocs.empty()) {
- Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
- Allocs.pop_back();
+ // Erase SrcKey entry using value rather than iterator I: I may have been
+ // invalidated when we looked up DstKey.
+ Allocs.erase(SrcKey);
}
- return Err;
+ for (auto &P : Plugins)
+ P->notifyTransferringResources(DstKey, SrcKey);
}
EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
- EHFrameRegistrar &Registrar)
- : Registrar(Registrar) {}
+ ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
+ : ES(ES), Registrar(std::move(Registrar)) {}
void EHFrameRegistrationPlugin::modifyPassConfig(
MaterializationResponsibility &MR, const Triple &TT,
@@ -559,65 +583,70 @@ void EHFrameRegistrationPlugin::modifyPassConfig(
Error EHFrameRegistrationPlugin::notifyEmitted(
MaterializationResponsibility &MR) {
- std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
-
- auto EHFrameRangeItr = InProcessLinks.find(&MR);
- if (EHFrameRangeItr == InProcessLinks.end())
- return Error::success();
-
- auto EHFrameRange = EHFrameRangeItr->second;
- assert(EHFrameRange.Addr &&
- "eh-frame addr to register can not be null");
-
- InProcessLinks.erase(EHFrameRangeItr);
- if (auto Key = MR.getVModuleKey())
- TrackedEHFrameRanges[Key] = EHFrameRange;
- else
- UntrackedEHFrameRanges.push_back(EHFrameRange);
- return Registrar.registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
-}
-
-Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
- std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
+ EHFrameRange EmittedRange;
+ {
+ std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
- auto EHFrameRangeItr = TrackedEHFrameRanges.find(K);
- if (EHFrameRangeItr == TrackedEHFrameRanges.end())
- return Error::success();
+ auto EHFrameRangeItr = InProcessLinks.find(&MR);
+ if (EHFrameRangeItr == InProcessLinks.end())
+ return Error::success();
- auto EHFrameRange = EHFrameRangeItr->second;
- assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null");
+ EmittedRange = EHFrameRangeItr->second;
+ assert(EmittedRange.Addr && "eh-frame addr to register can not be null");
+ InProcessLinks.erase(EHFrameRangeItr);
+ }
- TrackedEHFrameRanges.erase(EHFrameRangeItr);
+ if (auto Err = MR.withResourceKeyDo(
+ [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
+ return Err;
- return Registrar.deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
+ return Registrar->registerEHFrames(EmittedRange.Addr, EmittedRange.Size);
}
-Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
+Error EHFrameRegistrationPlugin::notifyFailed(
+ MaterializationResponsibility &MR) {
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
+ InProcessLinks.erase(&MR);
+ return Error::success();
+}
- std::vector<EHFrameRange> EHFrameRanges =
- std::move(UntrackedEHFrameRanges);
- EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size());
-
- for (auto &KV : TrackedEHFrameRanges)
- EHFrameRanges.push_back(KV.second);
+Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) {
+ std::vector<EHFrameRange> RangesToRemove;
- TrackedEHFrameRanges.clear();
+ ES.runSessionLocked([&] {
+ auto I = EHFrameRanges.find(K);
+ if (I != EHFrameRanges.end()) {
+ RangesToRemove = std::move(I->second);
+ EHFrameRanges.erase(I);
+ }
+ });
Error Err = Error::success();
-
- while (!EHFrameRanges.empty()) {
- auto EHFrameRange = EHFrameRanges.back();
- assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null");
- EHFrameRanges.pop_back();
- Err = joinErrors(std::move(Err),
- Registrar.deregisterEHFrames(EHFrameRange.Addr,
- EHFrameRange.Size));
+ while (!RangesToRemove.empty()) {
+ auto RangeToRemove = RangesToRemove.back();
+ RangesToRemove.pop_back();
+ assert(RangeToRemove.Addr && "Untracked eh-frame range must not be null");
+ Err = joinErrors(
+ std::move(Err),
+ Registrar->deregisterEHFrames(RangeToRemove.Addr, RangeToRemove.Size));
}
return Err;
}
+void EHFrameRegistrationPlugin::notifyTransferringResources(
+ ResourceKey DstKey, ResourceKey SrcKey) {
+ auto SI = EHFrameRanges.find(SrcKey);
+ if (SI != EHFrameRanges.end()) {
+ auto &SrcRanges = SI->second;
+ auto &DstRanges = EHFrameRanges[DstKey];
+ DstRanges.reserve(DstRanges.size() + SrcRanges.size());
+ for (auto &SrcRange : SrcRanges)
+ DstRanges.push_back(std::move(SrcRange));
+ EHFrameRanges.erase(SI);
+ }
+}
+
} // End namespace orc.
} // End namespace llvm.
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectTransformLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectTransformLayer.cpp
index d18eb38a4142..a57662e10a79 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectTransformLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectTransformLayer.cpp
@@ -17,8 +17,9 @@ ObjectTransformLayer::ObjectTransformLayer(ExecutionSession &ES,
TransformFunction Transform)
: ObjectLayer(ES), BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
-void ObjectTransformLayer::emit(MaterializationResponsibility R,
- std::unique_ptr<MemoryBuffer> O) {
+void ObjectTransformLayer::emit(
+ std::unique_ptr<MaterializationResponsibility> R,
+ std::unique_ptr<MemoryBuffer> O) {
assert(O && "Module must not be null");
// If there is a transform set then apply it.
@@ -26,7 +27,7 @@ void ObjectTransformLayer::emit(MaterializationResponsibility R,
if (auto TransformedObj = Transform(std::move(O)))
O = std::move(*TransformedObj);
else {
- R.failMaterialization();
+ R->failMaterialization();
getExecutionSession().reportError(TransformedObj.takeError());
return;
}
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp
deleted file mode 100644
index 28c8479abba4..000000000000
--- a/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-//===----------- OrcCBindings.cpp - C bindings for the Orc APIs -----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "OrcCBindingsStack.h"
-#include "llvm-c/OrcBindings.h"
-#include "llvm/ExecutionEngine/JITEventListener.h"
-
-using namespace llvm;
-
-LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM) {
- TargetMachine *TM2(unwrap(TM));
-
- Triple T(TM2->getTargetTriple());
-
- auto IndirectStubsMgrBuilder =
- orc::createLocalIndirectStubsManagerBuilder(T);
-
- OrcCBindingsStack *JITStack =
- new OrcCBindingsStack(*TM2, std::move(IndirectStubsMgrBuilder));
-
- return wrap(JITStack);
-}
-
-const char *LLVMOrcGetErrorMsg(LLVMOrcJITStackRef JITStack) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- return J.getErrorMessage().c_str();
-}
-
-void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledName,
- const char *SymbolName) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- std::string Mangled = J.mangle(SymbolName);
- *MangledName = new char[Mangled.size() + 1];
- strcpy(*MangledName, Mangled.c_str());
-}
-
-void LLVMOrcDisposeMangledSymbol(char *MangledName) { delete[] MangledName; }
-
-LLVMErrorRef LLVMOrcCreateLazyCompileCallback(
- LLVMOrcJITStackRef JITStack, LLVMOrcTargetAddress *RetAddr,
- LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- if (auto Addr = J.createLazyCompileCallback(Callback, CallbackCtx)) {
- *RetAddr = *Addr;
- return LLVMErrorSuccess;
- } else
- return wrap(Addr.takeError());
-}
-
-LLVMErrorRef LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
- const char *StubName,
- LLVMOrcTargetAddress InitAddr) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- return wrap(J.createIndirectStub(StubName, InitAddr));
-}
-
-LLVMErrorRef LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
- const char *StubName,
- LLVMOrcTargetAddress NewAddr) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- return wrap(J.setIndirectStubPointer(StubName, NewAddr));
-}
-
-LLVMErrorRef LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
- LLVMOrcModuleHandle *RetHandle,
- LLVMModuleRef Mod,
- LLVMOrcSymbolResolverFn SymbolResolver,
- void *SymbolResolverCtx) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- std::unique_ptr<Module> M(unwrap(Mod));
- if (auto Handle =
- J.addIRModuleEager(std::move(M), SymbolResolver, SymbolResolverCtx)) {
- *RetHandle = *Handle;
- return LLVMErrorSuccess;
- } else
- return wrap(Handle.takeError());
-}
-
-LLVMErrorRef LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
- LLVMOrcModuleHandle *RetHandle,
- LLVMModuleRef Mod,
- LLVMOrcSymbolResolverFn SymbolResolver,
- void *SymbolResolverCtx) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- std::unique_ptr<Module> M(unwrap(Mod));
- if (auto Handle =
- J.addIRModuleLazy(std::move(M), SymbolResolver, SymbolResolverCtx)) {
- *RetHandle = *Handle;
- return LLVMErrorSuccess;
- } else
- return wrap(Handle.takeError());
-}
-
-LLVMErrorRef LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
- LLVMOrcModuleHandle *RetHandle,
- LLVMMemoryBufferRef Obj,
- LLVMOrcSymbolResolverFn SymbolResolver,
- void *SymbolResolverCtx) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- std::unique_ptr<MemoryBuffer> O(unwrap(Obj));
- if (auto Handle =
- J.addObject(std::move(O), SymbolResolver, SymbolResolverCtx)) {
- *RetHandle = *Handle;
- return LLVMErrorSuccess;
- } else
- return wrap(Handle.takeError());
-}
-
-LLVMErrorRef LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack,
- LLVMOrcModuleHandle H) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- return wrap(J.removeModule(H));
-}
-
-LLVMErrorRef LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
- LLVMOrcTargetAddress *RetAddr,
- const char *SymbolName) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- if (auto Addr = J.findSymbolAddress(SymbolName, true)) {
- *RetAddr = *Addr;
- return LLVMErrorSuccess;
- } else
- return wrap(Addr.takeError());
-}
-
-LLVMErrorRef LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack,
- LLVMOrcTargetAddress *RetAddr,
- LLVMOrcModuleHandle H,
- const char *SymbolName) {
- OrcCBindingsStack &J = *unwrap(JITStack);
- if (auto Addr = J.findSymbolAddressIn(H, SymbolName, true)) {
- *RetAddr = *Addr;
- return LLVMErrorSuccess;
- } else
- return wrap(Addr.takeError());
-}
-
-LLVMErrorRef LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack) {
- auto *J = unwrap(JITStack);
- auto Err = J->shutdown();
- delete J;
- return wrap(std::move(Err));
-}
-
-void LLVMOrcRegisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L)
-{
- unwrap(JITStack)->RegisterJITEventListener(unwrap(L));
-}
-
-void LLVMOrcUnregisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L)
-{
- unwrap(JITStack)->UnregisterJITEventListener(unwrap(L));
-}
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
deleted file mode 100644
index 87bb4398765d..000000000000
--- a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
+++ /dev/null
@@ -1,534 +0,0 @@
-//===- OrcCBindingsStack.h - Orc JIT stack for C bindings -----*- C++ -*---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
-#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
-
-#include "llvm-c/OrcBindings.h"
-#include "llvm-c/TargetMachine.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/JITEventListener.h"
-#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
-#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
-#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
-#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
-#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
-#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/Mangler.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/CBindingWrapping.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetMachine.h"
-#include <algorithm>
-#include <cstdint>
-#include <functional>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-namespace llvm {
-
-class OrcCBindingsStack;
-
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
-
-namespace detail {
-
-// FIXME: Kill this off once the Layer concept becomes an interface.
-class GenericLayer {
-public:
- virtual ~GenericLayer() = default;
-
- virtual JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
- bool ExportedSymbolsOnly) = 0;
- virtual Error removeModule(orc::VModuleKey K) = 0;
- };
-
- template <typename LayerT> class GenericLayerImpl : public GenericLayer {
- public:
- GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
-
- JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
- bool ExportedSymbolsOnly) override {
- return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
- }
-
- Error removeModule(orc::VModuleKey K) override {
- return Layer.removeModule(K);
- }
-
- private:
- LayerT &Layer;
- };
-
- template <>
- class GenericLayerImpl<orc::LegacyRTDyldObjectLinkingLayer> : public GenericLayer {
- private:
- using LayerT = orc::LegacyRTDyldObjectLinkingLayer;
- public:
- GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
-
- JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
- bool ExportedSymbolsOnly) override {
- return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
- }
-
- Error removeModule(orc::VModuleKey K) override {
- return Layer.removeObject(K);
- }
-
- private:
- LayerT &Layer;
- };
-
- template <typename LayerT>
- std::unique_ptr<GenericLayerImpl<LayerT>> createGenericLayer(LayerT &Layer) {
- return std::make_unique<GenericLayerImpl<LayerT>>(Layer);
- }
-
-} // end namespace detail
-
-class OrcCBindingsStack {
-public:
-
- using CompileCallbackMgr = orc::JITCompileCallbackManager;
- using ObjLayerT = orc::LegacyRTDyldObjectLinkingLayer;
- using CompileLayerT = orc::LegacyIRCompileLayer<ObjLayerT, orc::SimpleCompiler>;
- using CODLayerT =
- orc::LegacyCompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>;
-
- using CallbackManagerBuilder =
- std::function<std::unique_ptr<CompileCallbackMgr>()>;
-
- using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
-
-private:
-
- using OwningObject = object::OwningBinary<object::ObjectFile>;
-
- class CBindingsResolver : public orc::SymbolResolver {
- public:
- CBindingsResolver(OrcCBindingsStack &Stack,
- LLVMOrcSymbolResolverFn ExternalResolver,
- void *ExternalResolverCtx)
- : Stack(Stack), ExternalResolver(std::move(ExternalResolver)),
- ExternalResolverCtx(std::move(ExternalResolverCtx)) {}
-
- orc::SymbolNameSet
- getResponsibilitySet(const orc::SymbolNameSet &Symbols) override {
- orc::SymbolNameSet Result;
-
- for (auto &S : Symbols) {
- if (auto Sym = findSymbol(std::string(*S))) {
- if (!Sym.getFlags().isStrong())
- Result.insert(S);
- } else if (auto Err = Sym.takeError()) {
- Stack.reportError(std::move(Err));
- return orc::SymbolNameSet();
- }
- }
-
- return Result;
- }
-
- orc::SymbolNameSet
- lookup(std::shared_ptr<orc::AsynchronousSymbolQuery> Query,
- orc::SymbolNameSet Symbols) override {
- orc::SymbolNameSet UnresolvedSymbols;
-
- for (auto &S : Symbols) {
- if (auto Sym = findSymbol(std::string(*S))) {
- if (auto Addr = Sym.getAddress()) {
- Query->notifySymbolMetRequiredState(
- S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
- } else {
- Stack.ES.legacyFailQuery(*Query, Addr.takeError());
- return orc::SymbolNameSet();
- }
- } else if (auto Err = Sym.takeError()) {
- Stack.ES.legacyFailQuery(*Query, std::move(Err));
- return orc::SymbolNameSet();
- } else
- UnresolvedSymbols.insert(S);
- }
-
- if (Query->isComplete())
- Query->handleComplete();
-
- return UnresolvedSymbols;
- }
-
- private:
- JITSymbol findSymbol(const std::string &Name) {
- // Search order:
- // 1. JIT'd symbols.
- // 2. Runtime overrides.
- // 3. External resolver (if present).
-
- if (Stack.CODLayer) {
- if (auto Sym = Stack.CODLayer->findSymbol(Name, true))
- return Sym;
- else if (auto Err = Sym.takeError())
- return Sym.takeError();
- } else {
- if (auto Sym = Stack.CompileLayer.findSymbol(Name, true))
- return Sym;
- else if (auto Err = Sym.takeError())
- return Sym.takeError();
- }
-
- if (auto Sym = Stack.CXXRuntimeOverrides.searchOverrides(Name))
- return Sym;
-
- if (ExternalResolver)
- return JITSymbol(ExternalResolver(Name.c_str(), ExternalResolverCtx),
- JITSymbolFlags::Exported);
-
- return JITSymbol(nullptr);
- }
-
- OrcCBindingsStack &Stack;
- LLVMOrcSymbolResolverFn ExternalResolver;
- void *ExternalResolverCtx = nullptr;
- };
-
-public:
- OrcCBindingsStack(TargetMachine &TM,
- IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
- : CCMgr(createCompileCallbackManager(TM, ES)), DL(TM.createDataLayout()),
- IndirectStubsMgr(IndirectStubsMgrBuilder()),
- ObjectLayer(
- AcknowledgeORCv1Deprecation, ES,
- [this](orc::VModuleKey K) {
- auto ResolverI = Resolvers.find(K);
- assert(ResolverI != Resolvers.end() &&
- "No resolver for module K");
- auto Resolver = std::move(ResolverI->second);
- Resolvers.erase(ResolverI);
- return ObjLayerT::Resources{
- std::make_shared<SectionMemoryManager>(), Resolver};
- },
- nullptr,
- [this](orc::VModuleKey K, const object::ObjectFile &Obj,
- const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
- this->notifyFinalized(K, Obj, LoadedObjInfo);
- },
- [this](orc::VModuleKey K, const object::ObjectFile &Obj) {
- this->notifyFreed(K, Obj);
- }),
- CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer,
- orc::SimpleCompiler(TM)),
- CODLayer(createCODLayer(ES, CompileLayer, CCMgr.get(),
- std::move(IndirectStubsMgrBuilder), Resolvers)),
- CXXRuntimeOverrides(
- AcknowledgeORCv1Deprecation,
- [this](const std::string &S) { return mangle(S); }) {}
-
- Error shutdown() {
- // Run any destructors registered with __cxa_atexit.
- CXXRuntimeOverrides.runDestructors();
- // Run any IR destructors.
- for (auto &DtorRunner : IRStaticDestructorRunners)
- if (auto Err = DtorRunner.runViaLayer(*this))
- return Err;
- return Error::success();
- }
-
- std::string mangle(StringRef Name) {
- std::string MangledName;
- {
- raw_string_ostream MangledNameStream(MangledName);
- Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
- }
- return MangledName;
- }
-
- template <typename PtrTy>
- static PtrTy fromTargetAddress(JITTargetAddress Addr) {
- return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
- }
-
- Expected<JITTargetAddress>
- createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback,
- void *CallbackCtx) {
- auto WrappedCallback = [=]() -> JITTargetAddress {
- return Callback(wrap(this), CallbackCtx);
- };
-
- return CCMgr->getCompileCallback(std::move(WrappedCallback));
- }
-
- Error createIndirectStub(StringRef StubName, JITTargetAddress Addr) {
- return IndirectStubsMgr->createStub(StubName, Addr,
- JITSymbolFlags::Exported);
- }
-
- Error setIndirectStubPointer(StringRef Name, JITTargetAddress Addr) {
- return IndirectStubsMgr->updatePointer(Name, Addr);
- }
-
- template <typename LayerT>
- Expected<orc::VModuleKey>
- addIRModule(LayerT &Layer, std::unique_ptr<Module> M,
- std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
- LLVMOrcSymbolResolverFn ExternalResolver,
- void *ExternalResolverCtx) {
-
- // Attach a data-layout if one isn't already present.
- if (M->getDataLayout().isDefault())
- M->setDataLayout(DL);
-
- // Record the static constructors and destructors. We have to do this before
- // we hand over ownership of the module to the JIT.
- std::vector<std::string> CtorNames, DtorNames;
- for (auto Ctor : orc::getConstructors(*M))
- CtorNames.push_back(mangle(Ctor.Func->getName()));
- for (auto Dtor : orc::getDestructors(*M))
- DtorNames.push_back(mangle(Dtor.Func->getName()));
-
- // Add the module to the JIT.
- auto K = ES.allocateVModule();
- Resolvers[K] = std::make_shared<CBindingsResolver>(*this, ExternalResolver,
- ExternalResolverCtx);
- if (auto Err = Layer.addModule(K, std::move(M)))
- return std::move(Err);
-
- KeyLayers[K] = detail::createGenericLayer(Layer);
-
- // Run the static constructors, and save the static destructor runner for
- // execution when the JIT is torn down.
- orc::LegacyCtorDtorRunner<OrcCBindingsStack> CtorRunner(
- AcknowledgeORCv1Deprecation, std::move(CtorNames), K);
- if (auto Err = CtorRunner.runViaLayer(*this))
- return std::move(Err);
-
- IRStaticDestructorRunners.emplace_back(AcknowledgeORCv1Deprecation,
- std::move(DtorNames), K);
-
- return K;
- }
-
- Expected<orc::VModuleKey>
- addIRModuleEager(std::unique_ptr<Module> M,
- LLVMOrcSymbolResolverFn ExternalResolver,
- void *ExternalResolverCtx) {
- return addIRModule(CompileLayer, std::move(M),
- std::make_unique<SectionMemoryManager>(),
- std::move(ExternalResolver), ExternalResolverCtx);
- }
-
- Expected<orc::VModuleKey>
- addIRModuleLazy(std::unique_ptr<Module> M,
- LLVMOrcSymbolResolverFn ExternalResolver,
- void *ExternalResolverCtx) {
- if (!CODLayer)
- return make_error<StringError>("Can not add lazy module: No compile "
- "callback manager available",
- inconvertibleErrorCode());
-
- return addIRModule(*CODLayer, std::move(M),
- std::make_unique<SectionMemoryManager>(),
- std::move(ExternalResolver), ExternalResolverCtx);
- }
-
- Error removeModule(orc::VModuleKey K) {
- // FIXME: Should error release the module key?
- if (auto Err = KeyLayers[K]->removeModule(K))
- return Err;
- ES.releaseVModule(K);
- KeyLayers.erase(K);
- return Error::success();
- }
-
- Expected<orc::VModuleKey> addObject(std::unique_ptr<MemoryBuffer> ObjBuffer,
- LLVMOrcSymbolResolverFn ExternalResolver,
- void *ExternalResolverCtx) {
- if (auto Obj = object::ObjectFile::createObjectFile(
- ObjBuffer->getMemBufferRef())) {
-
- auto K = ES.allocateVModule();
- Resolvers[K] = std::make_shared<CBindingsResolver>(
- *this, ExternalResolver, ExternalResolverCtx);
-
- if (auto Err = ObjectLayer.addObject(K, std::move(ObjBuffer)))
- return std::move(Err);
-
- KeyLayers[K] = detail::createGenericLayer(ObjectLayer);
-
- return K;
- } else
- return Obj.takeError();
- }
-
- JITSymbol findSymbol(const std::string &Name,
- bool ExportedSymbolsOnly) {
- if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
- return Sym;
- if (CODLayer)
- return CODLayer->findSymbol(mangle(Name), ExportedSymbolsOnly);
- return CompileLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
- }
-
- JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
- bool ExportedSymbolsOnly) {
- assert(KeyLayers.count(K) && "looking up symbol in unknown module");
- return KeyLayers[K]->findSymbolIn(K, mangle(Name), ExportedSymbolsOnly);
- }
-
- Expected<JITTargetAddress> findSymbolAddress(const std::string &Name,
- bool ExportedSymbolsOnly) {
- if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) {
- // Successful lookup, non-null symbol:
- if (auto AddrOrErr = Sym.getAddress())
- return *AddrOrErr;
- else
- return AddrOrErr.takeError();
- } else if (auto Err = Sym.takeError()) {
- // Lookup failure - report error.
- return std::move(Err);
- }
-
- // No symbol not found. Return 0.
- return 0;
- }
-
- Expected<JITTargetAddress> findSymbolAddressIn(orc::VModuleKey K,
- const std::string &Name,
- bool ExportedSymbolsOnly) {
- if (auto Sym = findSymbolIn(K, Name, ExportedSymbolsOnly)) {
- // Successful lookup, non-null symbol:
- if (auto AddrOrErr = Sym.getAddress())
- return *AddrOrErr;
- else
- return AddrOrErr.takeError();
- } else if (auto Err = Sym.takeError()) {
- // Lookup failure - report error.
- return std::move(Err);
- }
-
- // Symbol not found. Return 0.
- return 0;
- }
-
- const std::string &getErrorMessage() const { return ErrMsg; }
-
- void RegisterJITEventListener(JITEventListener *L) {
- if (!L)
- return;
- EventListeners.push_back(L);
- }
-
- void UnregisterJITEventListener(JITEventListener *L) {
- if (!L)
- return;
-
- auto I = find(reverse(EventListeners), L);
- if (I != EventListeners.rend()) {
- std::swap(*I, EventListeners.back());
- EventListeners.pop_back();
- }
- }
-
-private:
- using ResolverMap =
- std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>>;
-
- static std::unique_ptr<CompileCallbackMgr>
- createCompileCallbackManager(TargetMachine &TM, orc::ExecutionSession &ES) {
- auto CCMgr = createLocalCompileCallbackManager(TM.getTargetTriple(), ES, 0);
- if (!CCMgr) {
- // FIXME: It would be good if we could report this somewhere, but we do
- // have an instance yet.
- logAllUnhandledErrors(CCMgr.takeError(), errs(), "ORC error: ");
- return nullptr;
- }
- return std::move(*CCMgr);
- }
-
- static std::unique_ptr<CODLayerT>
- createCODLayer(orc::ExecutionSession &ES, CompileLayerT &CompileLayer,
- CompileCallbackMgr *CCMgr,
- IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
- ResolverMap &Resolvers) {
- // If there is no compile callback manager available we can not create a
- // compile on demand layer.
- if (!CCMgr)
- return nullptr;
-
- return std::make_unique<CODLayerT>(
- AcknowledgeORCv1Deprecation, ES, CompileLayer,
- [&Resolvers](orc::VModuleKey K) {
- auto ResolverI = Resolvers.find(K);
- assert(ResolverI != Resolvers.end() && "No resolver for module K");
- return ResolverI->second;
- },
- [&Resolvers](orc::VModuleKey K,
- std::shared_ptr<orc::SymbolResolver> Resolver) {
- assert(!Resolvers.count(K) && "Resolver already present");
- Resolvers[K] = std::move(Resolver);
- },
- [](Function &F) { return std::set<Function *>({&F}); }, *CCMgr,
- std::move(IndirectStubsMgrBuilder), false);
- }
-
- void reportError(Error Err) {
- // FIXME: Report errors on the execution session.
- logAllUnhandledErrors(std::move(Err), errs(), "ORC error: ");
- };
-
- void notifyFinalized(orc::VModuleKey K,
- const object::ObjectFile &Obj,
- const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
- uint64_t Key = static_cast<uint64_t>(
- reinterpret_cast<uintptr_t>(Obj.getData().data()));
- for (auto &Listener : EventListeners)
- Listener->notifyObjectLoaded(Key, Obj, LoadedObjInfo);
- }
-
- void notifyFreed(orc::VModuleKey K, const object::ObjectFile &Obj) {
- uint64_t Key = static_cast<uint64_t>(
- reinterpret_cast<uintptr_t>(Obj.getData().data()));
- for (auto &Listener : EventListeners)
- Listener->notifyFreeingObject(Key);
- }
-
- orc::ExecutionSession ES;
- std::unique_ptr<CompileCallbackMgr> CCMgr;
-
- std::vector<JITEventListener *> EventListeners;
-
- DataLayout DL;
- SectionMemoryManager CCMgrMemMgr;
-
- std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr;
-
- ObjLayerT ObjectLayer;
- CompileLayerT CompileLayer;
- std::unique_ptr<CODLayerT> CODLayer;
-
- std::map<orc::VModuleKey, std::unique_ptr<detail::GenericLayer>> KeyLayers;
-
- orc::LegacyLocalCXXRuntimeOverrides CXXRuntimeOverrides;
- std::vector<orc::LegacyCtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
- std::string ErrMsg;
-
- ResolverMap Resolvers;
-};
-
-} // end namespace llvm
-
-#endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp
deleted file mode 100644
index 772a9c2c4ab2..000000000000
--- a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-//===-------- OrcMCJITReplacement.cpp - Orc-based MCJIT replacement -------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "OrcMCJITReplacement.h"
-#include "llvm/ExecutionEngine/GenericValue.h"
-
-namespace {
-
-static struct RegisterJIT {
- RegisterJIT() { llvm::orc::OrcMCJITReplacement::Register(); }
-} JITRegistrator;
-
-}
-
-extern "C" void LLVMLinkInOrcMCJITReplacement() {}
-
-namespace llvm {
-namespace orc {
-
-GenericValue
-OrcMCJITReplacement::runFunction(Function *F,
- ArrayRef<GenericValue> ArgValues) {
- assert(F && "Function *F was null at entry to run()");
-
- void *FPtr = getPointerToFunction(F);
- assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
- FunctionType *FTy = F->getFunctionType();
- Type *RetTy = FTy->getReturnType();
-
- assert((FTy->getNumParams() == ArgValues.size() ||
- (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
- "Wrong number of arguments passed into function!");
- assert(FTy->getNumParams() == ArgValues.size() &&
- "This doesn't support passing arguments through varargs (yet)!");
-
- // Handle some common cases first. These cases correspond to common `main'
- // prototypes.
- if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
- switch (ArgValues.size()) {
- case 3:
- if (FTy->getParamType(0)->isIntegerTy(32) &&
- FTy->getParamType(1)->isPointerTy() &&
- FTy->getParamType(2)->isPointerTy()) {
- int (*PF)(int, char **, const char **) =
- (int (*)(int, char **, const char **))(intptr_t)FPtr;
-
- // Call the function.
- GenericValue rv;
- rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
- (char **)GVTOP(ArgValues[1]),
- (const char **)GVTOP(ArgValues[2])));
- return rv;
- }
- break;
- case 2:
- if (FTy->getParamType(0)->isIntegerTy(32) &&
- FTy->getParamType(1)->isPointerTy()) {
- int (*PF)(int, char **) = (int (*)(int, char **))(intptr_t)FPtr;
-
- // Call the function.
- GenericValue rv;
- rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
- (char **)GVTOP(ArgValues[1])));
- return rv;
- }
- break;
- case 1:
- if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) {
- GenericValue rv;
- int (*PF)(int) = (int (*)(int))(intptr_t)FPtr;
- rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
- return rv;
- }
- break;
- }
- }
-
- // Handle cases where no arguments are passed first.
- if (ArgValues.empty()) {
- GenericValue rv;
- switch (RetTy->getTypeID()) {
- default:
- llvm_unreachable("Unknown return type for function call!");
- case Type::IntegerTyID: {
- unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
- if (BitWidth == 1)
- rv.IntVal = APInt(BitWidth, ((bool (*)())(intptr_t)FPtr)());
- else if (BitWidth <= 8)
- rv.IntVal = APInt(BitWidth, ((char (*)())(intptr_t)FPtr)());
- else if (BitWidth <= 16)
- rv.IntVal = APInt(BitWidth, ((short (*)())(intptr_t)FPtr)());
- else if (BitWidth <= 32)
- rv.IntVal = APInt(BitWidth, ((int (*)())(intptr_t)FPtr)());
- else if (BitWidth <= 64)
- rv.IntVal = APInt(BitWidth, ((int64_t (*)())(intptr_t)FPtr)());
- else
- llvm_unreachable("Integer types > 64 bits not supported");
- return rv;
- }
- case Type::VoidTyID:
- rv.IntVal = APInt(32, ((int (*)())(intptr_t)FPtr)());
- return rv;
- case Type::FloatTyID:
- rv.FloatVal = ((float (*)())(intptr_t)FPtr)();
- return rv;
- case Type::DoubleTyID:
- rv.DoubleVal = ((double (*)())(intptr_t)FPtr)();
- return rv;
- case Type::X86_FP80TyID:
- case Type::FP128TyID:
- case Type::PPC_FP128TyID:
- llvm_unreachable("long double not supported yet");
- case Type::PointerTyID:
- return PTOGV(((void *(*)())(intptr_t)FPtr)());
- }
- }
-
- llvm_unreachable("Full-featured argument passing not supported yet!");
-}
-
-void OrcMCJITReplacement::runStaticConstructorsDestructors(bool isDtors) {
- auto &CtorDtorsMap = isDtors ? UnexecutedDestructors : UnexecutedConstructors;
-
- for (auto &KV : CtorDtorsMap)
- cantFail(LegacyCtorDtorRunner<LazyEmitLayerT>(
- AcknowledgeORCv1Deprecation, std::move(KV.second), KV.first)
- .runViaLayer(LazyEmitLayer));
-
- CtorDtorsMap.clear();
-}
-
-} // End namespace orc.
-} // End namespace llvm.
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
deleted file mode 100644
index 139572bd6977..000000000000
--- a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
+++ /dev/null
@@ -1,502 +0,0 @@
-//===- OrcMCJITReplacement.h - Orc based MCJIT replacement ------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Orc based MCJIT replacement.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
-#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/GenericValue.h"
-#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
-#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
-#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
-#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
-#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/Mangler.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Object/Archive.h"
-#include "llvm/Object/Binary.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetMachine.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-namespace llvm {
-
-class ObjectCache;
-
-namespace orc {
-
-class OrcMCJITReplacement : public ExecutionEngine {
-
- // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that
- // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are
- // expecting - see finalizeMemory.
- class MCJITReplacementMemMgr : public MCJITMemoryManager {
- public:
- MCJITReplacementMemMgr(OrcMCJITReplacement &M,
- std::shared_ptr<MCJITMemoryManager> ClientMM)
- : M(M), ClientMM(std::move(ClientMM)) {}
-
- uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID,
- StringRef SectionName) override {
- uint8_t *Addr =
- ClientMM->allocateCodeSection(Size, Alignment, SectionID,
- SectionName);
- M.SectionsAllocatedSinceLastLoad.insert(Addr);
- return Addr;
- }
-
- uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID, StringRef SectionName,
- bool IsReadOnly) override {
- uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID,
- SectionName, IsReadOnly);
- M.SectionsAllocatedSinceLastLoad.insert(Addr);
- return Addr;
- }
-
- void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
- uintptr_t RODataSize, uint32_t RODataAlign,
- uintptr_t RWDataSize,
- uint32_t RWDataAlign) override {
- return ClientMM->reserveAllocationSpace(CodeSize, CodeAlign,
- RODataSize, RODataAlign,
- RWDataSize, RWDataAlign);
- }
-
- bool needsToReserveAllocationSpace() override {
- return ClientMM->needsToReserveAllocationSpace();
- }
-
- void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
- size_t Size) override {
- return ClientMM->registerEHFrames(Addr, LoadAddr, Size);
- }
-
- void deregisterEHFrames() override {
- return ClientMM->deregisterEHFrames();
- }
-
- void notifyObjectLoaded(RuntimeDyld &RTDyld,
- const object::ObjectFile &O) override {
- return ClientMM->notifyObjectLoaded(RTDyld, O);
- }
-
- void notifyObjectLoaded(ExecutionEngine *EE,
- const object::ObjectFile &O) override {
- return ClientMM->notifyObjectLoaded(EE, O);
- }
-
- bool finalizeMemory(std::string *ErrMsg = nullptr) override {
- // Each set of objects loaded will be finalized exactly once, but since
- // symbol lookup during relocation may recursively trigger the
- // loading/relocation of other modules, and since we're forwarding all
- // finalizeMemory calls to a single underlying memory manager, we need to
- // defer forwarding the call on until all necessary objects have been
- // loaded. Otherwise, during the relocation of a leaf object, we will end
- // up finalizing memory, causing a crash further up the stack when we
- // attempt to apply relocations to finalized memory.
- // To avoid finalizing too early, look at how many objects have been
- // loaded but not yet finalized. This is a bit of a hack that relies on
- // the fact that we're lazily emitting object files: The only way you can
- // get more than one set of objects loaded but not yet finalized is if
- // they were loaded during relocation of another set.
- if (M.UnfinalizedSections.size() == 1)
- return ClientMM->finalizeMemory(ErrMsg);
- return false;
- }
-
- private:
- OrcMCJITReplacement &M;
- std::shared_ptr<MCJITMemoryManager> ClientMM;
- };
-
- class LinkingORCResolver : public orc::SymbolResolver {
- public:
- LinkingORCResolver(OrcMCJITReplacement &M) : M(M) {}
-
- SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) override {
- SymbolNameSet Result;
-
- for (auto &S : Symbols) {
- if (auto Sym = M.findMangledSymbol(*S)) {
- if (!Sym.getFlags().isStrong())
- Result.insert(S);
- } else if (auto Err = Sym.takeError()) {
- M.reportError(std::move(Err));
- return SymbolNameSet();
- } else {
- if (auto Sym2 =
- M.ClientResolver->findSymbolInLogicalDylib(std::string(*S))) {
- if (!Sym2.getFlags().isStrong())
- Result.insert(S);
- } else if (auto Err = Sym2.takeError()) {
- M.reportError(std::move(Err));
- return SymbolNameSet();
- } else
- Result.insert(S);
- }
- }
-
- return Result;
- }
-
- SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
- SymbolNameSet Symbols) override {
- SymbolNameSet UnresolvedSymbols;
- bool NewSymbolsResolved = false;
-
- for (auto &S : Symbols) {
- if (auto Sym = M.findMangledSymbol(*S)) {
- if (auto Addr = Sym.getAddress()) {
- Query->notifySymbolMetRequiredState(
- S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
- NewSymbolsResolved = true;
- } else {
- M.ES.legacyFailQuery(*Query, Addr.takeError());
- return SymbolNameSet();
- }
- } else if (auto Err = Sym.takeError()) {
- M.ES.legacyFailQuery(*Query, std::move(Err));
- return SymbolNameSet();
- } else {
- if (auto Sym2 = M.ClientResolver->findSymbol(std::string(*S))) {
- if (auto Addr = Sym2.getAddress()) {
- Query->notifySymbolMetRequiredState(
- S, JITEvaluatedSymbol(*Addr, Sym2.getFlags()));
- NewSymbolsResolved = true;
- } else {
- M.ES.legacyFailQuery(*Query, Addr.takeError());
- return SymbolNameSet();
- }
- } else if (auto Err = Sym2.takeError()) {
- M.ES.legacyFailQuery(*Query, std::move(Err));
- return SymbolNameSet();
- } else
- UnresolvedSymbols.insert(S);
- }
- }
-
- if (NewSymbolsResolved && Query->isComplete())
- Query->handleComplete();
-
- return UnresolvedSymbols;
- }
-
- private:
- OrcMCJITReplacement &M;
- };
-
-private:
- static ExecutionEngine *
- createOrcMCJITReplacement(std::string *ErrorMsg,
- std::shared_ptr<MCJITMemoryManager> MemMgr,
- std::shared_ptr<LegacyJITSymbolResolver> Resolver,
- std::unique_ptr<TargetMachine> TM) {
- return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
- std::move(TM));
- }
-
- void reportError(Error Err) {
- logAllUnhandledErrors(std::move(Err), errs(), "MCJIT error: ");
- }
-
-public:
- OrcMCJITReplacement(std::shared_ptr<MCJITMemoryManager> MemMgr,
- std::shared_ptr<LegacyJITSymbolResolver> ClientResolver,
- std::unique_ptr<TargetMachine> TM)
- : ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)),
- MemMgr(
- std::make_shared<MCJITReplacementMemMgr>(*this, std::move(MemMgr))),
- Resolver(std::make_shared<LinkingORCResolver>(*this)),
- ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this),
- NotifyFinalized(*this),
- ObjectLayer(
- AcknowledgeORCv1Deprecation, ES,
- [this](VModuleKey K) {
- return ObjectLayerT::Resources{this->MemMgr, this->Resolver};
- },
- NotifyObjectLoaded, NotifyFinalized),
- CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer,
- SimpleCompiler(*this->TM),
- [this](VModuleKey K, std::unique_ptr<Module> M) {
- Modules.push_back(std::move(M));
- }),
- LazyEmitLayer(AcknowledgeORCv1Deprecation, CompileLayer) {}
-
- static void Register() {
- OrcMCJITReplacementCtor = createOrcMCJITReplacement;
- }
-
- void addModule(std::unique_ptr<Module> M) override {
- // If this module doesn't have a DataLayout attached then attach the
- // default.
- if (M->getDataLayout().isDefault()) {
- M->setDataLayout(getDataLayout());
- } else {
- assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
- }
-
- // Rename, bump linkage and record static constructors and destructors.
- // We have to do this before we hand over ownership of the module to the
- // JIT.
- std::vector<std::string> CtorNames, DtorNames;
- {
- unsigned CtorId = 0, DtorId = 0;
- for (auto Ctor : orc::getConstructors(*M)) {
- std::string NewCtorName = ("__ORCstatic_ctor." + Twine(CtorId++)).str();
- Ctor.Func->setName(NewCtorName);
- Ctor.Func->setLinkage(GlobalValue::ExternalLinkage);
- Ctor.Func->setVisibility(GlobalValue::HiddenVisibility);
- CtorNames.push_back(mangle(NewCtorName));
- }
- for (auto Dtor : orc::getDestructors(*M)) {
- std::string NewDtorName = ("__ORCstatic_dtor." + Twine(DtorId++)).str();
- dbgs() << "Found dtor: " << NewDtorName << "\n";
- Dtor.Func->setName(NewDtorName);
- Dtor.Func->setLinkage(GlobalValue::ExternalLinkage);
- Dtor.Func->setVisibility(GlobalValue::HiddenVisibility);
- DtorNames.push_back(mangle(NewDtorName));
- }
- }
-
- auto K = ES.allocateVModule();
-
- UnexecutedConstructors[K] = std::move(CtorNames);
- UnexecutedDestructors[K] = std::move(DtorNames);
-
- cantFail(LazyEmitLayer.addModule(K, std::move(M)));
- }
-
- void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
- cantFail(ObjectLayer.addObject(
- ES.allocateVModule(), MemoryBuffer::getMemBufferCopy(O->getData())));
- }
-
- void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
- std::unique_ptr<object::ObjectFile> Obj;
- std::unique_ptr<MemoryBuffer> ObjBuffer;
- std::tie(Obj, ObjBuffer) = O.takeBinary();
- cantFail(ObjectLayer.addObject(ES.allocateVModule(), std::move(ObjBuffer)));
- }
-
- void addArchive(object::OwningBinary<object::Archive> A) override {
- Archives.push_back(std::move(A));
- }
-
- bool removeModule(Module *M) override {
- auto I = Modules.begin();
- for (auto E = Modules.end(); I != E; ++I)
- if (I->get() == M)
- break;
- if (I == Modules.end())
- return false;
- Modules.erase(I);
- return true;
- }
-
- uint64_t getSymbolAddress(StringRef Name) {
- return cantFail(findSymbol(Name).getAddress());
- }
-
- JITSymbol findSymbol(StringRef Name) {
- return findMangledSymbol(mangle(Name));
- }
-
- void finalizeObject() override {
- // This is deprecated - Aim to remove in ExecutionEngine.
- // REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
- }
-
- void mapSectionAddress(const void *LocalAddress,
- uint64_t TargetAddress) override {
- for (auto &P : UnfinalizedSections)
- if (P.second.count(LocalAddress))
- ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
- }
-
- uint64_t getGlobalValueAddress(const std::string &Name) override {
- return getSymbolAddress(Name);
- }
-
- uint64_t getFunctionAddress(const std::string &Name) override {
- return getSymbolAddress(Name);
- }
-
- void *getPointerToFunction(Function *F) override {
- uint64_t FAddr = getSymbolAddress(F->getName());
- return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr));
- }
-
- void *getPointerToNamedFunction(StringRef Name,
- bool AbortOnFailure = true) override {
- uint64_t Addr = getSymbolAddress(Name);
- if (!Addr && AbortOnFailure)
- llvm_unreachable("Missing symbol!");
- return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
- }
-
- GenericValue runFunction(Function *F,
- ArrayRef<GenericValue> ArgValues) override;
-
- void setObjectCache(ObjectCache *NewCache) override {
- CompileLayer.getCompiler().setObjectCache(NewCache);
- }
-
- void setProcessAllSections(bool ProcessAllSections) override {
- ObjectLayer.setProcessAllSections(ProcessAllSections);
- }
-
- void runStaticConstructorsDestructors(bool isDtors) override;
-
-private:
- JITSymbol findMangledSymbol(StringRef Name) {
- if (auto Sym = LazyEmitLayer.findSymbol(std::string(Name), false))
- return Sym;
- if (auto Sym = ClientResolver->findSymbol(std::string(Name)))
- return Sym;
- if (auto Sym = scanArchives(Name))
- return Sym;
-
- return nullptr;
- }
-
- JITSymbol scanArchives(StringRef Name) {
- for (object::OwningBinary<object::Archive> &OB : Archives) {
- object::Archive *A = OB.getBinary();
- // Look for our symbols in each Archive
- auto OptionalChildOrErr = A->findSym(Name);
- if (!OptionalChildOrErr)
- report_fatal_error(OptionalChildOrErr.takeError());
- auto &OptionalChild = *OptionalChildOrErr;
- if (OptionalChild) {
- // FIXME: Support nested archives?
- Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =
- OptionalChild->getAsBinary();
- if (!ChildBinOrErr) {
- // TODO: Actually report errors helpfully.
- consumeError(ChildBinOrErr.takeError());
- continue;
- }
- std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
- if (ChildBin->isObject()) {
- cantFail(ObjectLayer.addObject(
- ES.allocateVModule(),
- MemoryBuffer::getMemBufferCopy(ChildBin->getData())));
- if (auto Sym = ObjectLayer.findSymbol(Name, true))
- return Sym;
- }
- }
- }
- return nullptr;
- }
-
- class NotifyObjectLoadedT {
- public:
- using LoadedObjInfoListT =
- std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>;
-
- NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
-
- void operator()(VModuleKey K, const object::ObjectFile &Obj,
- const RuntimeDyld::LoadedObjectInfo &Info) const {
- M.UnfinalizedSections[K] = std::move(M.SectionsAllocatedSinceLastLoad);
- M.SectionsAllocatedSinceLastLoad = SectionAddrSet();
- M.MemMgr->notifyObjectLoaded(&M, Obj);
- }
- private:
- OrcMCJITReplacement &M;
- };
-
- class NotifyFinalizedT {
- public:
- NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
-
- void operator()(VModuleKey K, const object::ObjectFile &Obj,
- const RuntimeDyld::LoadedObjectInfo &Info) {
- M.UnfinalizedSections.erase(K);
- }
-
- private:
- OrcMCJITReplacement &M;
- };
-
- std::string mangle(StringRef Name) {
- std::string MangledName;
- {
- raw_string_ostream MangledNameStream(MangledName);
- Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout());
- }
- return MangledName;
- }
-
- using ObjectLayerT = LegacyRTDyldObjectLinkingLayer;
- using CompileLayerT = LegacyIRCompileLayer<ObjectLayerT, orc::SimpleCompiler>;
- using LazyEmitLayerT = LazyEmittingLayer<CompileLayerT>;
-
- ExecutionSession ES;
-
- std::unique_ptr<TargetMachine> TM;
- std::shared_ptr<MCJITReplacementMemMgr> MemMgr;
- std::shared_ptr<LinkingORCResolver> Resolver;
- std::shared_ptr<LegacyJITSymbolResolver> ClientResolver;
- Mangler Mang;
-
- // IMPORTANT: ShouldDelete *must* come before LocalModules: The shared_ptr
- // delete blocks in LocalModules refer to the ShouldDelete map, so
- // LocalModules needs to be destructed before ShouldDelete.
- std::map<Module*, bool> ShouldDelete;
-
- NotifyObjectLoadedT NotifyObjectLoaded;
- NotifyFinalizedT NotifyFinalized;
-
- ObjectLayerT ObjectLayer;
- CompileLayerT CompileLayer;
- LazyEmitLayerT LazyEmitLayer;
-
- std::map<VModuleKey, std::vector<std::string>> UnexecutedConstructors;
- std::map<VModuleKey, std::vector<std::string>> UnexecutedDestructors;
-
- // We need to store ObjLayerT::ObjSetHandles for each of the object sets
- // that have been emitted but not yet finalized so that we can forward the
- // mapSectionAddress calls appropriately.
- using SectionAddrSet = std::set<const void *>;
- SectionAddrSet SectionsAllocatedSinceLastLoad;
- std::map<VModuleKey, SectionAddrSet> UnfinalizedSections;
-
- std::vector<object::OwningBinary<object::Archive>> Archives;
-};
-
-} // end namespace orc
-
-} // end namespace llvm
-
-#endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index 5933c2e666d1..dfdd2c6c669f 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -6,11 +6,15 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm-c/LLJIT.h"
#include "llvm-c/Orc.h"
+#include "llvm-c/OrcEE.h"
#include "llvm-c/TargetMachine.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
using namespace llvm;
using namespace llvm::orc;
@@ -18,6 +22,8 @@ using namespace llvm::orc;
namespace llvm {
namespace orc {
+class InProgressLookupState;
+
class OrcV2CAPIHelper {
public:
using PoolEntry = SymbolStringPtr::PoolEntry;
@@ -29,58 +35,278 @@ public:
return Result;
}
+ static SymbolStringPtr retainSymbolStringPtr(PoolEntryPtr P) {
+ return SymbolStringPtr(P);
+ }
+
static PoolEntryPtr getRawPoolEntryPtr(const SymbolStringPtr &S) {
return S.S;
}
+ static void retainPoolEntry(PoolEntryPtr P) {
+ SymbolStringPtr S(P);
+ S.S = nullptr;
+ }
+
static void releasePoolEntry(PoolEntryPtr P) {
SymbolStringPtr S;
S.S = P;
}
+
+ static InProgressLookupState *extractLookupState(LookupState &LS) {
+ return LS.IPLS.release();
+ }
+
+ static void resetLookupState(LookupState &LS, InProgressLookupState *IPLS) {
+ return LS.reset(IPLS);
+ }
};
-} // end namespace orc
-} // end namespace llvm
+} // namespace orc
+} // namespace llvm
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionSession, LLVMOrcExecutionSessionRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SymbolStringPool, LLVMOrcSymbolStringPoolRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcV2CAPIHelper::PoolEntry,
LLVMOrcSymbolStringPoolEntryRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MaterializationUnit,
+ LLVMOrcMaterializationUnitRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib, LLVMOrcJITDylibRef)
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib::DefinitionGenerator,
- LLVMOrcJITDylibDefinitionGeneratorRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ResourceTracker, LLVMOrcResourceTrackerRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DefinitionGenerator,
+ LLVMOrcDefinitionGeneratorRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(InProgressLookupState, LLVMOrcLookupStateRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeContext,
LLVMOrcThreadSafeContextRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITTargetMachineBuilder,
LLVMOrcJITTargetMachineBuilderRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ObjectLayer, LLVMOrcObjectLayerRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJIT, LLVMOrcLLJITRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
+namespace llvm {
+namespace orc {
+
+class CAPIDefinitionGenerator final : public DefinitionGenerator {
+public:
+ CAPIDefinitionGenerator(
+ void *Ctx,
+ LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction TryToGenerate)
+ : Ctx(Ctx), TryToGenerate(TryToGenerate) {}
+
+ Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags,
+ const SymbolLookupSet &LookupSet) override {
+
+ // Take the lookup state.
+ LLVMOrcLookupStateRef LSR = ::wrap(OrcV2CAPIHelper::extractLookupState(LS));
+
+ // Translate the lookup kind.
+ LLVMOrcLookupKind CLookupKind;
+ switch (K) {
+ case LookupKind::Static:
+ CLookupKind = LLVMOrcLookupKindStatic;
+ break;
+ case LookupKind::DLSym:
+ CLookupKind = LLVMOrcLookupKindDLSym;
+ break;
+ }
+
+ // Translate the JITDylibSearchFlags.
+ LLVMOrcJITDylibLookupFlags CJDLookupFlags;
+ switch (JDLookupFlags) {
+ case JITDylibLookupFlags::MatchExportedSymbolsOnly:
+ CJDLookupFlags = LLVMOrcJITDylibLookupFlagsMatchExportedSymbolsOnly;
+ break;
+ case JITDylibLookupFlags::MatchAllSymbols:
+ CJDLookupFlags = LLVMOrcJITDylibLookupFlagsMatchAllSymbols;
+ break;
+ }
+
+ // Translate the lookup set.
+ std::vector<LLVMOrcCLookupSetElement> CLookupSet;
+ CLookupSet.reserve(LookupSet.size());
+ for (auto &KV : LookupSet) {
+ LLVMOrcSymbolLookupFlags SLF;
+ LLVMOrcSymbolStringPoolEntryRef Name =
+ ::wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(KV.first));
+ switch (KV.second) {
+ case SymbolLookupFlags::RequiredSymbol:
+ SLF = LLVMOrcSymbolLookupFlagsRequiredSymbol;
+ break;
+ case SymbolLookupFlags::WeaklyReferencedSymbol:
+ SLF = LLVMOrcSymbolLookupFlagsWeaklyReferencedSymbol;
+ break;
+ }
+ CLookupSet.push_back({Name, SLF});
+ }
+
+ // Run the C TryToGenerate function.
+ auto Err = unwrap(TryToGenerate(::wrap(this), Ctx, &LSR, CLookupKind,
+ ::wrap(&JD), CJDLookupFlags,
+ CLookupSet.data(), CLookupSet.size()));
+
+ // Restore the lookup state.
+ OrcV2CAPIHelper::resetLookupState(LS, ::unwrap(LSR));
+
+ return Err;
+ }
+
+private:
+ void *Ctx;
+ LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction TryToGenerate;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+void LLVMOrcExecutionSessionSetErrorReporter(
+ LLVMOrcExecutionSessionRef ES, LLVMOrcErrorReporterFunction ReportError,
+ void *Ctx) {
+ unwrap(ES)->setErrorReporter(
+ [=](Error Err) { ReportError(Ctx, wrap(std::move(Err))); });
+}
+
+LLVMOrcSymbolStringPoolRef
+LLVMOrcExecutionSessionGetSymbolStringPool(LLVMOrcExecutionSessionRef ES) {
+ return wrap(unwrap(ES)->getSymbolStringPool().get());
+}
+
+void LLVMOrcSymbolStringPoolClearDeadEntries(LLVMOrcSymbolStringPoolRef SSP) {
+ unwrap(SSP)->clearDeadEntries();
+}
+
LLVMOrcSymbolStringPoolEntryRef
LLVMOrcExecutionSessionIntern(LLVMOrcExecutionSessionRef ES, const char *Name) {
return wrap(
OrcV2CAPIHelper::releaseSymbolStringPtr(unwrap(ES)->intern(Name)));
}
+void LLVMOrcRetainSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S) {
+ OrcV2CAPIHelper::retainPoolEntry(unwrap(S));
+}
+
void LLVMOrcReleaseSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S) {
OrcV2CAPIHelper::releasePoolEntry(unwrap(S));
}
-void LLVMOrcDisposeJITDylibDefinitionGenerator(
- LLVMOrcJITDylibDefinitionGeneratorRef DG) {
- delete unwrap(DG);
+const char *LLVMOrcSymbolStringPoolEntryStr(LLVMOrcSymbolStringPoolEntryRef S) {
+ return unwrap(S)->getKey().data();
+}
+
+LLVMOrcResourceTrackerRef
+LLVMOrcJITDylibCreateResourceTracker(LLVMOrcJITDylibRef JD) {
+ auto RT = unwrap(JD)->createResourceTracker();
+ // Retain the pointer for the C API client.
+ RT->Retain();
+ return wrap(RT.get());
+}
+
+LLVMOrcResourceTrackerRef
+LLVMOrcJITDylibGetDefaultResourceTracker(LLVMOrcJITDylibRef JD) {
+ auto RT = unwrap(JD)->getDefaultResourceTracker();
+ // Retain the pointer for the C API client.
+ return wrap(RT.get());
+}
+
+void LLVMOrcReleaseResourceTracker(LLVMOrcResourceTrackerRef RT) {
+ ResourceTrackerSP TmpRT(unwrap(RT));
+ TmpRT->Release();
+}
+
+void LLVMOrcResourceTrackerTransferTo(LLVMOrcResourceTrackerRef SrcRT,
+ LLVMOrcResourceTrackerRef DstRT) {
+ ResourceTrackerSP TmpRT(unwrap(SrcRT));
+ TmpRT->transferTo(*unwrap(DstRT));
+}
+
+LLVMErrorRef LLVMOrcResourceTrackerRemove(LLVMOrcResourceTrackerRef RT) {
+ ResourceTrackerSP TmpRT(unwrap(RT));
+ return wrap(TmpRT->remove());
+}
+
+void LLVMOrcDisposeDefinitionGenerator(LLVMOrcDefinitionGeneratorRef DG) {
+ std::unique_ptr<DefinitionGenerator> TmpDG(unwrap(DG));
+}
+
+void LLVMOrcDisposeMaterializationUnit(LLVMOrcMaterializationUnitRef MU) {
+ std::unique_ptr<MaterializationUnit> TmpMU(unwrap(MU));
+}
+
+LLVMOrcMaterializationUnitRef
+LLVMOrcAbsoluteSymbols(LLVMOrcCSymbolMapPairs Syms, size_t NumPairs) {
+ SymbolMap SM;
+ for (size_t I = 0; I != NumPairs; ++I) {
+ JITSymbolFlags Flags;
+
+ if (Syms[I].Sym.Flags.GenericFlags & LLVMJITSymbolGenericFlagsExported)
+ Flags |= JITSymbolFlags::Exported;
+ if (Syms[I].Sym.Flags.GenericFlags & LLVMJITSymbolGenericFlagsWeak)
+ Flags |= JITSymbolFlags::Weak;
+
+ Flags.getTargetFlags() = Syms[I].Sym.Flags.TargetFlags;
+
+ SM[OrcV2CAPIHelper::retainSymbolStringPtr(unwrap(Syms[I].Name))] =
+ JITEvaluatedSymbol(Syms[I].Sym.Address, Flags);
+ }
+
+ return wrap(absoluteSymbols(std::move(SM)).release());
+}
+
+LLVMOrcJITDylibRef
+LLVMOrcExecutionSessionCreateBareJITDylib(LLVMOrcExecutionSessionRef ES,
+ const char *Name) {
+ return wrap(&unwrap(ES)->createBareJITDylib(Name));
+}
+
+LLVMErrorRef
+LLVMOrcExecutionSessionCreateJITDylib(LLVMOrcExecutionSessionRef ES,
+ LLVMOrcJITDylibRef *Result,
+ const char *Name) {
+ auto JD = unwrap(ES)->createJITDylib(Name);
+ if (!JD)
+ return wrap(JD.takeError());
+ *Result = wrap(&*JD);
+ return LLVMErrorSuccess;
+}
+
+LLVMOrcJITDylibRef
+LLVMOrcExecutionSessionGetJITDylibByName(LLVMOrcExecutionSessionRef ES,
+ const char *Name) {
+ return wrap(unwrap(ES)->getJITDylibByName(Name));
+}
+
+LLVMErrorRef LLVMOrcJITDylibDefine(LLVMOrcJITDylibRef JD,
+ LLVMOrcMaterializationUnitRef MU) {
+ std::unique_ptr<MaterializationUnit> TmpMU(unwrap(MU));
+
+ if (auto Err = unwrap(JD)->define(TmpMU)) {
+ TmpMU.release();
+ return wrap(std::move(Err));
+ }
+ return LLVMErrorSuccess;
+}
+
+LLVMErrorRef LLVMOrcJITDylibClear(LLVMOrcJITDylibRef JD) {
+ return wrap(unwrap(JD)->clear());
}
void LLVMOrcJITDylibAddGenerator(LLVMOrcJITDylibRef JD,
- LLVMOrcJITDylibDefinitionGeneratorRef DG) {
- unwrap(JD)->addGenerator(
- std::unique_ptr<JITDylib::DefinitionGenerator>(unwrap(DG)));
+ LLVMOrcDefinitionGeneratorRef DG) {
+ unwrap(JD)->addGenerator(std::unique_ptr<DefinitionGenerator>(unwrap(DG)));
+}
+
+LLVMOrcDefinitionGeneratorRef LLVMOrcCreateCustomCAPIDefinitionGenerator(
+ LLVMOrcCAPIDefinitionGeneratorTryToGenerateFunction F, void *Ctx) {
+ auto DG = std::make_unique<CAPIDefinitionGenerator>(Ctx, F);
+ return wrap(DG.release());
}
LLVMErrorRef LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
- LLVMOrcJITDylibDefinitionGeneratorRef *Result, char GlobalPrefix,
+ LLVMOrcDefinitionGeneratorRef *Result, char GlobalPrefix,
LLVMOrcSymbolPredicate Filter, void *FilterCtx) {
assert(Result && "Result can not be null");
assert((Filter || !FilterCtx) &&
@@ -89,7 +315,7 @@ LLVMErrorRef LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
DynamicLibrarySearchGenerator::SymbolPredicate Pred;
if (Filter)
Pred = [=](const SymbolStringPtr &Name) -> bool {
- return Filter(wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Name)), FilterCtx);
+ return Filter(FilterCtx, wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Name)));
};
auto ProcessSymsGenerator =
@@ -143,7 +369,7 @@ LLVMErrorRef LLVMOrcJITTargetMachineBuilderDetectHost(
}
LLVMOrcJITTargetMachineBuilderRef
-LLVMOrcJITTargetMachineBuilderFromTargetMachine(LLVMTargetMachineRef TM) {
+LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM) {
auto *TemplateTM = unwrap(TM);
auto JTMB =
@@ -167,6 +393,10 @@ void LLVMOrcDisposeJITTargetMachineBuilder(
delete unwrap(JTMB);
}
+void lLVMOrcDisposeObjectLayer(LLVMOrcObjectLayerRef ObjLayer) {
+ delete unwrap(ObjLayer);
+}
+
LLVMOrcLLJITBuilderRef LLVMOrcCreateLLJITBuilder(void) {
return wrap(new LLJITBuilder());
}
@@ -180,6 +410,17 @@ void LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(
unwrap(Builder)->setJITTargetMachineBuilder(*unwrap(JTMB));
}
+void LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(
+ LLVMOrcLLJITBuilderRef Builder,
+ LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction F, void *Ctx) {
+ unwrap(Builder)->setObjectLinkingLayerCreator(
+ [=](ExecutionSession &ES, const Triple &TT) {
+ auto TTStr = TT.str();
+ return std::unique_ptr<ObjectLayer>(
+ unwrap(F(Ctx, wrap(&ES), TTStr.c_str())));
+ });
+}
+
LLVMErrorRef LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result,
LLVMOrcLLJITBuilderRef Builder) {
assert(Result && "Result can not be null");
@@ -232,10 +473,27 @@ LLVMErrorRef LLVMOrcLLJITAddObjectFile(LLVMOrcLLJITRef J, LLVMOrcJITDylibRef JD,
*unwrap(JD), std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer))));
}
+LLVMErrorRef LLVMOrcLLJITAddObjectFileWithRT(LLVMOrcLLJITRef J,
+ LLVMOrcResourceTrackerRef RT,
+ LLVMMemoryBufferRef ObjBuffer) {
+ return wrap(unwrap(J)->addObjectFile(
+ ResourceTrackerSP(unwrap(RT)),
+ std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer))));
+}
+
LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J,
LLVMOrcJITDylibRef JD,
LLVMOrcThreadSafeModuleRef TSM) {
- return wrap(unwrap(J)->addIRModule(*unwrap(JD), std::move(*unwrap(TSM))));
+ std::unique_ptr<ThreadSafeModule> TmpTSM(unwrap(TSM));
+ return wrap(unwrap(J)->addIRModule(*unwrap(JD), std::move(*TmpTSM)));
+}
+
+LLVMErrorRef LLVMOrcLLJITAddLLVMIRModuleWithRT(LLVMOrcLLJITRef J,
+ LLVMOrcResourceTrackerRef RT,
+ LLVMOrcThreadSafeModuleRef TSM) {
+ std::unique_ptr<ThreadSafeModule> TmpTSM(unwrap(TSM));
+ return wrap(unwrap(J)->addIRModule(ResourceTrackerSP(unwrap(RT)),
+ std::move(*TmpTSM)));
}
LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J,
@@ -252,3 +510,20 @@ LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J,
*Result = Sym->getAddress();
return LLVMErrorSuccess;
}
+
+LLVMOrcObjectLayerRef
+LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(
+ LLVMOrcExecutionSessionRef ES) {
+ assert(ES && "ES must not be null");
+ return wrap(new RTDyldObjectLinkingLayer(
+ *unwrap(ES), [] { return std::make_unique<SectionMemoryManager>(); }));
+}
+
+void LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(
+ LLVMOrcObjectLayerRef RTDyldObjLinkingLayer,
+ LLVMJITEventListenerRef Listener) {
+ assert(RTDyldObjLinkingLayer && "RTDyldObjLinkingLayer must not be null");
+ assert(Listener && "Listener must not be null");
+ reinterpret_cast<RTDyldObjectLinkingLayer *>(unwrap(RTDyldObjLinkingLayer))
+ ->registerJITEventListener(*unwrap(Listener));
+}
diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
index 21925726072e..0ad666ebbebd 100644
--- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
@@ -18,7 +18,7 @@ class JITDylibSearchOrderResolver : public JITSymbolResolver {
public:
JITDylibSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {}
- void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) {
+ void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override {
auto &ES = MR.getTargetJITDylib().getExecutionSession();
SymbolLookupSet InternedSymbols;
@@ -55,7 +55,7 @@ public:
RegisterDependencies);
}
- Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) {
+ Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override {
LookupSet Result;
for (auto &KV : MR.getSymbols()) {
@@ -77,35 +77,26 @@ namespace orc {
RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer(
ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)
- : ObjectLayer(ES), GetMemoryManager(GetMemoryManager) {}
+ : ObjectLayer(ES), GetMemoryManager(GetMemoryManager) {
+ ES.registerResourceManager(*this);
+}
RTDyldObjectLinkingLayer::~RTDyldObjectLinkingLayer() {
- std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
- for (auto &MemMgr : MemMgrs) {
- for (auto *L : EventListeners)
- L->notifyFreeingObject(
- static_cast<uint64_t>(reinterpret_cast<uintptr_t>(MemMgr.get())));
- MemMgr->deregisterEHFrames();
- }
+ assert(MemMgrs.empty() && "Layer destroyed with resources still attached");
}
-void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R,
- std::unique_ptr<MemoryBuffer> O) {
+void RTDyldObjectLinkingLayer::emit(
+ std::unique_ptr<MaterializationResponsibility> R,
+ std::unique_ptr<MemoryBuffer> O) {
assert(O && "Object must not be null");
- // This method launches an asynchronous link step that will fulfill our
- // materialization responsibility. We need to switch R to be heap
- // allocated before that happens so it can live as long as the asynchronous
- // link needs it to (i.e. it must be able to outlive this method).
- auto SharedR = std::make_shared<MaterializationResponsibility>(std::move(R));
-
auto &ES = getExecutionSession();
auto Obj = object::ObjectFile::createObjectFile(*O);
if (!Obj) {
getExecutionSession().reportError(Obj.takeError());
- SharedR->failMaterialization();
+ R->failMaterialization();
return;
}
@@ -121,7 +112,7 @@ void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R,
continue;
} else {
ES.reportError(SymType.takeError());
- R.failMaterialization();
+ R->failMaterialization();
return;
}
@@ -129,7 +120,7 @@ void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R,
if (!SymFlagsOrErr) {
// TODO: Test this error.
ES.reportError(SymFlagsOrErr.takeError());
- R.failMaterialization();
+ R->failMaterialization();
return;
}
@@ -139,46 +130,44 @@ void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R,
InternalSymbols->insert(*SymName);
else {
ES.reportError(SymName.takeError());
- R.failMaterialization();
+ R->failMaterialization();
return;
}
}
}
}
- auto K = R.getVModuleKey();
- RuntimeDyld::MemoryManager *MemMgr = nullptr;
+ auto MemMgr = GetMemoryManager();
+ auto &MemMgrRef = *MemMgr;
- // Create a record a memory manager for this object.
- {
- auto Tmp = GetMemoryManager();
- std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
- MemMgrs.push_back(std::move(Tmp));
- MemMgr = MemMgrs.back().get();
- }
+ // Switch to shared ownership of MR so that it can be captured by both
+ // lambdas below.
+ std::shared_ptr<MaterializationResponsibility> SharedR(std::move(R));
JITDylibSearchOrderResolver Resolver(*SharedR);
jitLinkForORC(
object::OwningBinary<object::ObjectFile>(std::move(*Obj), std::move(O)),
- *MemMgr, Resolver, ProcessAllSections,
- [this, K, SharedR, MemMgr, InternalSymbols](
+ MemMgrRef, Resolver, ProcessAllSections,
+ [this, SharedR, &MemMgrRef, InternalSymbols](
const object::ObjectFile &Obj,
- std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
+ RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) {
- return onObjLoad(K, *SharedR, Obj, MemMgr, std::move(LoadedObjInfo),
+ return onObjLoad(*SharedR, Obj, MemMgrRef, LoadedObjInfo,
ResolvedSymbols, *InternalSymbols);
},
- [this, K, SharedR, MemMgr](object::OwningBinary<object::ObjectFile> Obj,
- Error Err) mutable {
- onObjEmit(K, *SharedR, std::move(Obj), MemMgr, std::move(Err));
+ [this, SharedR, MemMgr = std::move(MemMgr)](
+ object::OwningBinary<object::ObjectFile> Obj,
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
+ Error Err) mutable {
+ onObjEmit(*SharedR, std::move(Obj), std::move(MemMgr),
+ std::move(LoadedObjInfo), std::move(Err));
});
}
void RTDyldObjectLinkingLayer::registerJITEventListener(JITEventListener &L) {
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
- assert(llvm::none_of(EventListeners,
- [&](JITEventListener *O) { return O == &L; }) &&
+ assert(!llvm::is_contained(EventListeners, &L) &&
"Listener has already been registered");
EventListeners.push_back(&L);
}
@@ -191,9 +180,9 @@ void RTDyldObjectLinkingLayer::unregisterJITEventListener(JITEventListener &L) {
}
Error RTDyldObjectLinkingLayer::onObjLoad(
- VModuleKey K, MaterializationResponsibility &R,
- const object::ObjectFile &Obj, RuntimeDyld::MemoryManager *MemMgr,
- std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
+ MaterializationResponsibility &R, const object::ObjectFile &Obj,
+ RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::LoadedObjectInfo &LoadedObjInfo,
std::map<StringRef, JITEvaluatedSymbol> Resolved,
std::set<StringRef> &InternalSymbols) {
SymbolFlagsMap ExtraSymbolsToClaim;
@@ -274,19 +263,16 @@ Error RTDyldObjectLinkingLayer::onObjLoad(
}
if (NotifyLoaded)
- NotifyLoaded(K, Obj, *LoadedObjInfo);
-
- std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
- assert(!LoadedObjInfos.count(MemMgr) && "Duplicate loaded info for MemMgr");
- LoadedObjInfos[MemMgr] = std::move(LoadedObjInfo);
+ NotifyLoaded(R, Obj, LoadedObjInfo);
return Error::success();
}
void RTDyldObjectLinkingLayer::onObjEmit(
- VModuleKey K, MaterializationResponsibility &R,
+ MaterializationResponsibility &R,
object::OwningBinary<object::ObjectFile> O,
- RuntimeDyld::MemoryManager *MemMgr, Error Err) {
+ std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo, Error Err) {
if (Err) {
getExecutionSession().reportError(std::move(Err));
R.failMaterialization();
@@ -306,27 +292,60 @@ void RTDyldObjectLinkingLayer::onObjEmit(
// Run EventListener notifyLoaded callbacks.
{
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
- auto LOIItr = LoadedObjInfos.find(MemMgr);
- assert(LOIItr != LoadedObjInfos.end() && "LoadedObjInfo missing");
for (auto *L : EventListeners)
- L->notifyObjectLoaded(
- static_cast<uint64_t>(reinterpret_cast<uintptr_t>(MemMgr)), *Obj,
- *LOIItr->second);
- LoadedObjInfos.erase(MemMgr);
+ L->notifyObjectLoaded(pointerToJITTargetAddress(MemMgr.get()), *Obj,
+ *LoadedObjInfo);
}
if (NotifyEmitted)
- NotifyEmitted(K, std::move(ObjBuffer));
+ NotifyEmitted(R, std::move(ObjBuffer));
+
+ if (auto Err = R.withResourceKeyDo(
+ [&](ResourceKey K) { MemMgrs[K].push_back(std::move(MemMgr)); })) {
+ getExecutionSession().reportError(std::move(Err));
+ R.failMaterialization();
+ }
}
-LegacyRTDyldObjectLinkingLayer::LegacyRTDyldObjectLinkingLayer(
- ExecutionSession &ES, ResourcesGetter GetResources,
- NotifyLoadedFtor NotifyLoaded, NotifyFinalizedFtor NotifyFinalized,
- NotifyFreedFtor NotifyFreed)
- : ES(ES), GetResources(std::move(GetResources)),
- NotifyLoaded(std::move(NotifyLoaded)),
- NotifyFinalized(std::move(NotifyFinalized)),
- NotifyFreed(std::move(NotifyFreed)), ProcessAllSections(false) {}
+Error RTDyldObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
+
+ std::vector<MemoryManagerUP> MemMgrsToRemove;
+
+ getExecutionSession().runSessionLocked([&] {
+ auto I = MemMgrs.find(K);
+ if (I != MemMgrs.end()) {
+ std::swap(MemMgrsToRemove, I->second);
+ MemMgrs.erase(I);
+ }
+ });
+
+ {
+ std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
+ for (auto &MemMgr : MemMgrsToRemove) {
+ for (auto *L : EventListeners)
+ L->notifyFreeingObject(pointerToJITTargetAddress(MemMgr.get()));
+ MemMgr->deregisterEHFrames();
+ }
+ }
+
+ return Error::success();
+}
+
+void RTDyldObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
+ ResourceKey SrcKey) {
+ auto I = MemMgrs.find(SrcKey);
+ if (I != MemMgrs.end()) {
+ auto &SrcMemMgrs = I->second;
+ auto &DstMemMgrs = MemMgrs[DstKey];
+ DstMemMgrs.reserve(DstMemMgrs.size() + SrcMemMgrs.size());
+ for (auto &MemMgr : SrcMemMgrs)
+ DstMemMgrs.push_back(std::move(MemMgr));
+
+ // Erase SrcKey entry using value rather than iterator I: I may have been
+ // invalidated when we looked up DstKey.
+ MemMgrs.erase(SrcKey);
+ }
+}
} // End namespace orc.
} // End namespace llvm.
diff --git a/llvm/lib/ExecutionEngine/OrcError/OrcError.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
index cc99e154fbec..fdad90cbcfb7 100644
--- a/llvm/lib/ExecutionEngine/OrcError/OrcError.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
@@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ExecutionEngine/Orc/OrcError.h"
+#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
@@ -71,7 +71,7 @@ public:
};
static ManagedStatic<OrcErrorCategory> OrcErrCat;
-}
+} // namespace
namespace llvm {
namespace orc {
@@ -84,9 +84,8 @@ std::error_code orcError(OrcErrorCode ErrCode) {
return std::error_code(static_cast<UT>(ErrCode), *OrcErrCat);
}
-
DuplicateDefinition::DuplicateDefinition(std::string SymbolName)
- : SymbolName(std::move(SymbolName)) {}
+ : SymbolName(std::move(SymbolName)) {}
std::error_code DuplicateDefinition::convertToErrorCode() const {
return orcError(OrcErrorCode::DuplicateDefinition);
@@ -101,7 +100,7 @@ const std::string &DuplicateDefinition::getSymbolName() const {
}
JITSymbolNotFound::JITSymbolNotFound(std::string SymbolName)
- : SymbolName(std::move(SymbolName)) {}
+ : SymbolName(std::move(SymbolName)) {}
std::error_code JITSymbolNotFound::convertToErrorCode() const {
typedef std::underlying_type<OrcErrorCode>::type UT;
@@ -117,5 +116,5 @@ const std::string &JITSymbolNotFound::getSymbolName() const {
return SymbolName;
}
-}
-}
+} // namespace orc
+} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/OrcError/RPCError.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/RPCError.cpp
index 3cf78fd9f7ba..a55cb220f218 100644
--- a/llvm/lib/ExecutionEngine/OrcError/RPCError.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/RPCError.cpp
@@ -10,21 +10,21 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ExecutionEngine/Orc/RPC/RPCUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
-#include <system_error>
#include <string>
+#include <system_error>
-char llvm::orc::rpc::RPCFatalError::ID = 0;
-char llvm::orc::rpc::ConnectionClosed::ID = 0;
-char llvm::orc::rpc::ResponseAbandoned::ID = 0;
-char llvm::orc::rpc::CouldNotNegotiate::ID = 0;
+char llvm::orc::shared::RPCFatalError::ID = 0;
+char llvm::orc::shared::ConnectionClosed::ID = 0;
+char llvm::orc::shared::ResponseAbandoned::ID = 0;
+char llvm::orc::shared::CouldNotNegotiate::ID = 0;
namespace llvm {
namespace orc {
-namespace rpc {
+namespace shared {
std::error_code ConnectionClosed::convertToErrorCode() const {
return orcError(OrcErrorCode::RPCConnectionClosed);
@@ -53,7 +53,6 @@ void CouldNotNegotiate::log(raw_ostream &OS) const {
OS << "Could not negotiate RPC function " << Signature;
}
-
-} // end namespace rpc
+} // end namespace shared
} // end namespace orc
} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.cpp
new file mode 100644
index 000000000000..52d11f0741d4
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.cpp
@@ -0,0 +1,44 @@
+//===---------- TargetProcessControlTypes.cpp - Shared TPC types ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// TargetProcessControl types.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
+
+namespace llvm {
+namespace orc {
+namespace tpctypes {
+
+WrapperFunctionResult WrapperFunctionResult::from(StringRef S) {
+ CWrapperFunctionResult R;
+ zeroInit(R);
+ R.Size = S.size();
+ if (R.Size > sizeof(uint64_t)) {
+ R.Data.ValuePtr = new uint8_t[R.Size];
+ memcpy(R.Data.ValuePtr, S.data(), R.Size);
+ R.Destroy = destroyWithDeleteArray;
+ } else
+ memcpy(R.Data.Value, S.data(), R.Size);
+ return R;
+}
+
+void WrapperFunctionResult::destroyWithFree(CWrapperFunctionResultData Data,
+ uint64_t Size) {
+ free(Data.ValuePtr);
+}
+
+void WrapperFunctionResult::destroyWithDeleteArray(
+ CWrapperFunctionResultData Data, uint64_t Size) {
+ delete[] Data.ValuePtr;
+}
+
+} // end namespace tpctypes
+} // end namespace orc
+} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp b/llvm/lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp
index 7240c1ed0ce9..c2fa4466eab6 100644
--- a/llvm/lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/SpeculateAnalyses.cpp
@@ -106,11 +106,10 @@ BlockFreqQuery::ResultTy BlockFreqQuery::operator()(Function &F) {
assert(IBBs.size() == BBFreqs.size() && "BB Count Mismatch");
- llvm::sort(BBFreqs.begin(), BBFreqs.end(),
- [](decltype(BBFreqs)::const_reference BBF,
- decltype(BBFreqs)::const_reference BBS) {
- return BBF.second > BBS.second ? true : false;
- });
+ llvm::sort(BBFreqs, [](decltype(BBFreqs)::const_reference BBF,
+ decltype(BBFreqs)::const_reference BBS) {
+ return BBF.second > BBS.second ? true : false;
+ });
// ignoring number of direct calls in a BB
auto Topk = numBBToGet(BBFreqs.size());
diff --git a/llvm/lib/ExecutionEngine/Orc/Speculation.cpp b/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
index 0530b1a97b67..0b4755fe23cf 100644
--- a/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Speculation.cpp
@@ -16,9 +16,6 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Verifier.h"
-#include "llvm/Support/Debug.h"
-
-#include <vector>
namespace llvm {
@@ -58,7 +55,7 @@ Error Speculator::addSpeculationRuntime(JITDylib &JD,
// If two modules, share the same LLVMContext, different threads must
// not access them concurrently without locking the associated LLVMContext
// this implementation follows this contract.
-void IRSpeculationLayer::emit(MaterializationResponsibility R,
+void IRSpeculationLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
ThreadSafeModule TSM) {
assert(TSM && "Speculation Layer received Null Module ?");
@@ -130,7 +127,7 @@ void IRSpeculationLayer::emit(MaterializationResponsibility R,
assert(Mutator.GetInsertBlock()->getParent() == &Fn &&
"IR builder association mismatch?");
S.registerSymbols(internToJITSymbols(IRNames.getValue()),
- &R.getTargetJITDylib());
+ &R->getTargetJITDylib());
}
}
}
diff --git a/llvm/lib/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.cpp
new file mode 100644
index 000000000000..bbf3ada1d4ba
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.cpp
@@ -0,0 +1,70 @@
+//===---------------- TPCDynamicLibrarySearchGenerator.cpp ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h"
+
+namespace llvm {
+namespace orc {
+
+Expected<std::unique_ptr<TPCDynamicLibrarySearchGenerator>>
+TPCDynamicLibrarySearchGenerator::Load(TargetProcessControl &TPC,
+ const char *LibraryPath,
+ SymbolPredicate Allow) {
+ auto Handle = TPC.loadDylib(LibraryPath);
+ if (!Handle)
+ return Handle.takeError();
+
+ return std::make_unique<TPCDynamicLibrarySearchGenerator>(TPC, *Handle,
+ std::move(Allow));
+}
+
+Error TPCDynamicLibrarySearchGenerator::tryToGenerate(
+ LookupState &LS, LookupKind K, JITDylib &JD,
+ JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
+
+ if (Symbols.empty())
+ return Error::success();
+
+ SymbolLookupSet LookupSymbols;
+
+ for (auto &KV : Symbols) {
+ // Skip symbols that don't match the filter.
+ if (Allow && !Allow(KV.first))
+ continue;
+ LookupSymbols.add(KV.first, SymbolLookupFlags::WeaklyReferencedSymbol);
+ }
+
+ SymbolMap NewSymbols;
+
+ TargetProcessControl::LookupRequest Request(H, LookupSymbols);
+ auto Result = TPC.lookupSymbols(Request);
+ if (!Result)
+ return Result.takeError();
+
+ assert(Result->size() == 1 && "Results for more than one library returned");
+ assert(Result->front().size() == LookupSymbols.size() &&
+ "Result has incorrect number of elements");
+
+ auto ResultI = Result->front().begin();
+ for (auto &KV : LookupSymbols) {
+ if (*ResultI)
+ NewSymbols[KV.first] =
+ JITEvaluatedSymbol(*ResultI, JITSymbolFlags::Exported);
+ ++ResultI;
+ }
+
+ // If there were no resolved symbols bail out.
+ if (NewSymbols.empty())
+ return Error::success();
+
+ // Define resolved symbols.
+ return JD.define(absoluteSymbols(std::move(NewSymbols)));
+}
+
+} // end namespace orc
+} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/TPCEHFrameRegistrar.cpp b/llvm/lib/ExecutionEngine/Orc/TPCEHFrameRegistrar.cpp
new file mode 100644
index 000000000000..4f901ce6d445
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/TPCEHFrameRegistrar.cpp
@@ -0,0 +1,80 @@
+//===------ TPCEHFrameRegistrar.cpp - TPC-based eh-frame registration -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+
+namespace llvm {
+namespace orc {
+
+Expected<std::unique_ptr<TPCEHFrameRegistrar>>
+TPCEHFrameRegistrar::Create(TargetProcessControl &TPC) {
+ // FIXME: Proper mangling here -- we really need to decouple linker mangling
+ // from DataLayout.
+
+ // Find the addresses of the registration/deregistration functions in the
+ // target process.
+ auto ProcessHandle = TPC.loadDylib(nullptr);
+ if (!ProcessHandle)
+ return ProcessHandle.takeError();
+
+ std::string RegisterWrapperName, DeregisterWrapperName;
+ if (TPC.getTargetTriple().isOSBinFormatMachO()) {
+ RegisterWrapperName += '_';
+ DeregisterWrapperName += '_';
+ }
+ RegisterWrapperName += "llvm_orc_registerEHFrameSectionWrapper";
+ DeregisterWrapperName += "llvm_orc_deregisterEHFrameSectionWrapper";
+
+ SymbolLookupSet RegistrationSymbols;
+ RegistrationSymbols.add(TPC.intern(RegisterWrapperName));
+ RegistrationSymbols.add(TPC.intern(DeregisterWrapperName));
+
+ auto Result = TPC.lookupSymbols({{*ProcessHandle, RegistrationSymbols}});
+ if (!Result)
+ return Result.takeError();
+
+ assert(Result->size() == 1 && "Unexpected number of dylibs in result");
+ assert((*Result)[0].size() == 2 &&
+ "Unexpected number of addresses in result");
+
+ auto RegisterEHFrameWrapperFnAddr = (*Result)[0][0];
+ auto DeregisterEHFrameWrapperFnAddr = (*Result)[0][1];
+
+ return std::make_unique<TPCEHFrameRegistrar>(
+ TPC, RegisterEHFrameWrapperFnAddr, DeregisterEHFrameWrapperFnAddr);
+}
+
+Error TPCEHFrameRegistrar::registerEHFrames(JITTargetAddress EHFrameSectionAddr,
+ size_t EHFrameSectionSize) {
+ constexpr size_t ArgBufferSize = sizeof(uint64_t) + sizeof(uint64_t);
+ uint8_t ArgBuffer[ArgBufferSize];
+ BinaryStreamWriter ArgWriter(
+ MutableArrayRef<uint8_t>(ArgBuffer, ArgBufferSize),
+ support::endianness::big);
+ cantFail(ArgWriter.writeInteger(static_cast<uint64_t>(EHFrameSectionAddr)));
+ cantFail(ArgWriter.writeInteger(static_cast<uint64_t>(EHFrameSectionSize)));
+
+ return TPC.runWrapper(RegisterEHFrameWrapperFnAddr, ArgBuffer).takeError();
+}
+
+Error TPCEHFrameRegistrar::deregisterEHFrames(
+ JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
+ constexpr size_t ArgBufferSize = sizeof(uint64_t) + sizeof(uint64_t);
+ uint8_t ArgBuffer[ArgBufferSize];
+ BinaryStreamWriter ArgWriter(
+ MutableArrayRef<uint8_t>(ArgBuffer, ArgBufferSize),
+ support::endianness::big);
+ cantFail(ArgWriter.writeInteger(static_cast<uint64_t>(EHFrameSectionAddr)));
+ cantFail(ArgWriter.writeInteger(static_cast<uint64_t>(EHFrameSectionSize)));
+
+ return TPC.runWrapper(DeregisterEHFrameWrapperFnAddr, ArgBuffer).takeError();
+}
+
+} // end namespace orc
+} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp
new file mode 100644
index 000000000000..7989ec41952d
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/TPCIndirectionUtils.cpp
@@ -0,0 +1,423 @@
+//===------ TargetProcessControl.cpp -- Target process control APIs -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/TPCIndirectionUtils.h"
+
+#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
+#include "llvm/Support/MathExtras.h"
+
+#include <future>
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace llvm {
+namespace orc {
+
+class TPCIndirectionUtilsAccess {
+public:
+ using IndirectStubInfo = TPCIndirectionUtils::IndirectStubInfo;
+ using IndirectStubInfoVector = TPCIndirectionUtils::IndirectStubInfoVector;
+
+ static Expected<IndirectStubInfoVector>
+ getIndirectStubs(TPCIndirectionUtils &TPCIU, unsigned NumStubs) {
+ return TPCIU.getIndirectStubs(NumStubs);
+ };
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+namespace {
+
+class TPCTrampolinePool : public TrampolinePool {
+public:
+ TPCTrampolinePool(TPCIndirectionUtils &TPCIU);
+ Error deallocatePool();
+
+protected:
+ Error grow() override;
+
+ using Allocation = jitlink::JITLinkMemoryManager::Allocation;
+
+ TPCIndirectionUtils &TPCIU;
+ unsigned TrampolineSize = 0;
+ unsigned TrampolinesPerPage = 0;
+ std::vector<std::unique_ptr<Allocation>> TrampolineBlocks;
+};
+
+class TPCIndirectStubsManager : public IndirectStubsManager,
+ private TPCIndirectionUtilsAccess {
+public:
+ TPCIndirectStubsManager(TPCIndirectionUtils &TPCIU) : TPCIU(TPCIU) {}
+
+ Error deallocateStubs();
+
+ Error createStub(StringRef StubName, JITTargetAddress StubAddr,
+ JITSymbolFlags StubFlags) override;
+
+ Error createStubs(const StubInitsMap &StubInits) override;
+
+ JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override;
+
+ JITEvaluatedSymbol findPointer(StringRef Name) override;
+
+ Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override;
+
+private:
+ using StubInfo = std::pair<IndirectStubInfo, JITSymbolFlags>;
+
+ std::mutex ISMMutex;
+ TPCIndirectionUtils &TPCIU;
+ StringMap<StubInfo> StubInfos;
+};
+
+TPCTrampolinePool::TPCTrampolinePool(TPCIndirectionUtils &TPCIU)
+ : TPCIU(TPCIU) {
+ auto &TPC = TPCIU.getTargetProcessControl();
+ auto &ABI = TPCIU.getABISupport();
+
+ TrampolineSize = ABI.getTrampolineSize();
+ TrampolinesPerPage =
+ (TPC.getPageSize() - ABI.getPointerSize()) / TrampolineSize;
+}
+
+Error TPCTrampolinePool::deallocatePool() {
+ Error Err = Error::success();
+ for (auto &Alloc : TrampolineBlocks)
+ Err = joinErrors(std::move(Err), Alloc->deallocate());
+ return Err;
+}
+
+Error TPCTrampolinePool::grow() {
+ assert(AvailableTrampolines.empty() &&
+ "Grow called with trampolines still available");
+
+ auto ResolverAddress = TPCIU.getResolverBlockAddress();
+ assert(ResolverAddress && "Resolver address can not be null");
+
+ auto &TPC = TPCIU.getTargetProcessControl();
+ constexpr auto TrampolinePagePermissions =
+ static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
+ sys::Memory::MF_EXEC);
+ auto PageSize = TPC.getPageSize();
+ jitlink::JITLinkMemoryManager::SegmentsRequestMap Request;
+ Request[TrampolinePagePermissions] = {PageSize, static_cast<size_t>(PageSize),
+ 0};
+ auto Alloc = TPC.getMemMgr().allocate(nullptr, Request);
+
+ if (!Alloc)
+ return Alloc.takeError();
+
+ unsigned NumTrampolines = TrampolinesPerPage;
+
+ auto WorkingMemory = (*Alloc)->getWorkingMemory(TrampolinePagePermissions);
+ auto TargetAddress = (*Alloc)->getTargetMemory(TrampolinePagePermissions);
+
+ TPCIU.getABISupport().writeTrampolines(WorkingMemory.data(), TargetAddress,
+ ResolverAddress, NumTrampolines);
+
+ auto TargetAddr = (*Alloc)->getTargetMemory(TrampolinePagePermissions);
+ for (unsigned I = 0; I < NumTrampolines; ++I)
+ AvailableTrampolines.push_back(TargetAddr + (I * TrampolineSize));
+
+ if (auto Err = (*Alloc)->finalize())
+ return Err;
+
+ TrampolineBlocks.push_back(std::move(*Alloc));
+
+ return Error::success();
+}
+
+Error TPCIndirectStubsManager::createStub(StringRef StubName,
+ JITTargetAddress StubAddr,
+ JITSymbolFlags StubFlags) {
+ StubInitsMap SIM;
+ SIM[StubName] = std::make_pair(StubAddr, StubFlags);
+ return createStubs(SIM);
+}
+
+Error TPCIndirectStubsManager::createStubs(const StubInitsMap &StubInits) {
+ auto AvailableStubInfos = getIndirectStubs(TPCIU, StubInits.size());
+ if (!AvailableStubInfos)
+ return AvailableStubInfos.takeError();
+
+ {
+ std::lock_guard<std::mutex> Lock(ISMMutex);
+ unsigned ASIdx = 0;
+ for (auto &SI : StubInits) {
+ auto &A = (*AvailableStubInfos)[ASIdx++];
+ StubInfos[SI.first()] = std::make_pair(A, SI.second.second);
+ }
+ }
+
+ auto &MemAccess = TPCIU.getTargetProcessControl().getMemoryAccess();
+ switch (TPCIU.getABISupport().getPointerSize()) {
+ case 4: {
+ unsigned ASIdx = 0;
+ std::vector<tpctypes::UInt32Write> PtrUpdates;
+ for (auto &SI : StubInits)
+ PtrUpdates.push_back({(*AvailableStubInfos)[ASIdx++].PointerAddress,
+ static_cast<uint32_t>(SI.second.first)});
+ return MemAccess.writeUInt32s(PtrUpdates);
+ }
+ case 8: {
+ unsigned ASIdx = 0;
+ std::vector<tpctypes::UInt64Write> PtrUpdates;
+ for (auto &SI : StubInits)
+ PtrUpdates.push_back({(*AvailableStubInfos)[ASIdx++].PointerAddress,
+ static_cast<uint64_t>(SI.second.first)});
+ return MemAccess.writeUInt64s(PtrUpdates);
+ }
+ default:
+ return make_error<StringError>("Unsupported pointer size",
+ inconvertibleErrorCode());
+ }
+}
+
+JITEvaluatedSymbol TPCIndirectStubsManager::findStub(StringRef Name,
+ bool ExportedStubsOnly) {
+ std::lock_guard<std::mutex> Lock(ISMMutex);
+ auto I = StubInfos.find(Name);
+ if (I == StubInfos.end())
+ return nullptr;
+ return {I->second.first.StubAddress, I->second.second};
+}
+
+JITEvaluatedSymbol TPCIndirectStubsManager::findPointer(StringRef Name) {
+ std::lock_guard<std::mutex> Lock(ISMMutex);
+ auto I = StubInfos.find(Name);
+ if (I == StubInfos.end())
+ return nullptr;
+ return {I->second.first.PointerAddress, I->second.second};
+}
+
+Error TPCIndirectStubsManager::updatePointer(StringRef Name,
+ JITTargetAddress NewAddr) {
+
+ JITTargetAddress PtrAddr = 0;
+ {
+ std::lock_guard<std::mutex> Lock(ISMMutex);
+ auto I = StubInfos.find(Name);
+ if (I == StubInfos.end())
+ return make_error<StringError>("Unknown stub name",
+ inconvertibleErrorCode());
+ PtrAddr = I->second.first.PointerAddress;
+ }
+
+ auto &MemAccess = TPCIU.getTargetProcessControl().getMemoryAccess();
+ switch (TPCIU.getABISupport().getPointerSize()) {
+ case 4: {
+ tpctypes::UInt32Write PUpdate(PtrAddr, NewAddr);
+ return MemAccess.writeUInt32s(PUpdate);
+ }
+ case 8: {
+ tpctypes::UInt64Write PUpdate(PtrAddr, NewAddr);
+ return MemAccess.writeUInt64s(PUpdate);
+ }
+ default:
+ return make_error<StringError>("Unsupported pointer size",
+ inconvertibleErrorCode());
+ }
+}
+
+} // end anonymous namespace.
+
+namespace llvm {
+namespace orc {
+
+TPCIndirectionUtils::ABISupport::~ABISupport() {}
+
+Expected<std::unique_ptr<TPCIndirectionUtils>>
+TPCIndirectionUtils::Create(TargetProcessControl &TPC) {
+ const auto &TT = TPC.getTargetTriple();
+ switch (TT.getArch()) {
+ default:
+ return make_error<StringError>(
+ std::string("No TPCIndirectionUtils available for ") + TT.str(),
+ inconvertibleErrorCode());
+ case Triple::aarch64:
+ case Triple::aarch64_32:
+ return CreateWithABI<OrcAArch64>(TPC);
+
+ case Triple::x86:
+ return CreateWithABI<OrcI386>(TPC);
+
+ case Triple::mips:
+ return CreateWithABI<OrcMips32Be>(TPC);
+
+ case Triple::mipsel:
+ return CreateWithABI<OrcMips32Le>(TPC);
+
+ case Triple::mips64:
+ case Triple::mips64el:
+ return CreateWithABI<OrcMips64>(TPC);
+
+ case Triple::x86_64:
+ if (TT.getOS() == Triple::OSType::Win32)
+ return CreateWithABI<OrcX86_64_Win32>(TPC);
+ else
+ return CreateWithABI<OrcX86_64_SysV>(TPC);
+ }
+}
+
+Error TPCIndirectionUtils::cleanup() {
+ Error Err = Error::success();
+
+ for (auto &A : IndirectStubAllocs)
+ Err = joinErrors(std::move(Err), A->deallocate());
+
+ if (TP)
+ Err = joinErrors(std::move(Err),
+ static_cast<TPCTrampolinePool &>(*TP).deallocatePool());
+
+ if (ResolverBlock)
+ Err = joinErrors(std::move(Err), ResolverBlock->deallocate());
+
+ return Err;
+}
+
+Expected<JITTargetAddress>
+TPCIndirectionUtils::writeResolverBlock(JITTargetAddress ReentryFnAddr,
+ JITTargetAddress ReentryCtxAddr) {
+ assert(ABI && "ABI can not be null");
+ constexpr auto ResolverBlockPermissions =
+ static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
+ sys::Memory::MF_EXEC);
+ auto ResolverSize = ABI->getResolverCodeSize();
+
+ jitlink::JITLinkMemoryManager::SegmentsRequestMap Request;
+ Request[ResolverBlockPermissions] = {TPC.getPageSize(),
+ static_cast<size_t>(ResolverSize), 0};
+ auto Alloc = TPC.getMemMgr().allocate(nullptr, Request);
+ if (!Alloc)
+ return Alloc.takeError();
+
+ auto WorkingMemory = (*Alloc)->getWorkingMemory(ResolverBlockPermissions);
+ ResolverBlockAddr = (*Alloc)->getTargetMemory(ResolverBlockPermissions);
+ ABI->writeResolverCode(WorkingMemory.data(), ResolverBlockAddr, ReentryFnAddr,
+ ReentryCtxAddr);
+
+ if (auto Err = (*Alloc)->finalize())
+ return std::move(Err);
+
+ ResolverBlock = std::move(*Alloc);
+ return ResolverBlockAddr;
+}
+
+std::unique_ptr<IndirectStubsManager>
+TPCIndirectionUtils::createIndirectStubsManager() {
+ return std::make_unique<TPCIndirectStubsManager>(*this);
+}
+
+TrampolinePool &TPCIndirectionUtils::getTrampolinePool() {
+ if (!TP)
+ TP = std::make_unique<TPCTrampolinePool>(*this);
+ return *TP;
+}
+
+LazyCallThroughManager &TPCIndirectionUtils::createLazyCallThroughManager(
+ ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr) {
+ assert(!LCTM &&
+ "createLazyCallThroughManager can not have been called before");
+ LCTM = std::make_unique<LazyCallThroughManager>(ES, ErrorHandlerAddr,
+ &getTrampolinePool());
+ return *LCTM;
+}
+
+TPCIndirectionUtils::TPCIndirectionUtils(TargetProcessControl &TPC,
+ std::unique_ptr<ABISupport> ABI)
+ : TPC(TPC), ABI(std::move(ABI)) {
+ assert(this->ABI && "ABI can not be null");
+
+ assert(TPC.getPageSize() > getABISupport().getStubSize() &&
+ "Stubs larger than one page are not supported");
+}
+
+Expected<TPCIndirectionUtils::IndirectStubInfoVector>
+TPCIndirectionUtils::getIndirectStubs(unsigned NumStubs) {
+
+ std::lock_guard<std::mutex> Lock(TPCUIMutex);
+
+ // If there aren't enough stubs available then allocate some more.
+ if (NumStubs > AvailableIndirectStubs.size()) {
+ auto NumStubsToAllocate = NumStubs;
+ auto PageSize = TPC.getPageSize();
+ auto StubBytes = alignTo(NumStubsToAllocate * ABI->getStubSize(), PageSize);
+ NumStubsToAllocate = StubBytes / ABI->getStubSize();
+ auto PointerBytes =
+ alignTo(NumStubsToAllocate * ABI->getPointerSize(), PageSize);
+
+ constexpr auto StubPagePermissions =
+ static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
+ sys::Memory::MF_EXEC);
+ constexpr auto PointerPagePermissions =
+ static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
+ sys::Memory::MF_WRITE);
+
+ jitlink::JITLinkMemoryManager::SegmentsRequestMap Request;
+ Request[StubPagePermissions] = {PageSize, static_cast<size_t>(StubBytes),
+ 0};
+ Request[PointerPagePermissions] = {PageSize, 0, PointerBytes};
+ auto Alloc = TPC.getMemMgr().allocate(nullptr, Request);
+ if (!Alloc)
+ return Alloc.takeError();
+
+ auto StubTargetAddr = (*Alloc)->getTargetMemory(StubPagePermissions);
+ auto PointerTargetAddr = (*Alloc)->getTargetMemory(PointerPagePermissions);
+
+ ABI->writeIndirectStubsBlock(
+ (*Alloc)->getWorkingMemory(StubPagePermissions).data(), StubTargetAddr,
+ PointerTargetAddr, NumStubsToAllocate);
+
+ if (auto Err = (*Alloc)->finalize())
+ return std::move(Err);
+
+ for (unsigned I = 0; I != NumStubsToAllocate; ++I) {
+ AvailableIndirectStubs.push_back(
+ IndirectStubInfo(StubTargetAddr, PointerTargetAddr));
+ StubTargetAddr += ABI->getStubSize();
+ PointerTargetAddr += ABI->getPointerSize();
+ }
+
+ IndirectStubAllocs.push_back(std::move(*Alloc));
+ }
+
+ assert(NumStubs <= AvailableIndirectStubs.size() &&
+ "Sufficient stubs should have been allocated above");
+
+ IndirectStubInfoVector Result;
+ while (NumStubs--) {
+ Result.push_back(AvailableIndirectStubs.back());
+ AvailableIndirectStubs.pop_back();
+ }
+
+ return std::move(Result);
+}
+
+static JITTargetAddress reentry(JITTargetAddress LCTMAddr,
+ JITTargetAddress TrampolineAddr) {
+ auto &LCTM = *jitTargetAddressToPointer<LazyCallThroughManager *>(LCTMAddr);
+ std::promise<JITTargetAddress> LandingAddrP;
+ auto LandingAddrF = LandingAddrP.get_future();
+ LCTM.resolveTrampolineLandingAddress(
+ TrampolineAddr,
+ [&](JITTargetAddress Addr) { LandingAddrP.set_value(Addr); });
+ return LandingAddrF.get();
+}
+
+Error setUpInProcessLCTMReentryViaTPCIU(TPCIndirectionUtils &TPCIU) {
+ auto &LCTM = TPCIU.getLazyCallThroughManager();
+ return TPCIU
+ .writeResolverBlock(pointerToJITTargetAddress(&reentry),
+ pointerToJITTargetAddress(&LCTM))
+ .takeError();
+}
+
+} // end namespace orc
+} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
new file mode 100644
index 000000000000..aff7296cb6e3
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
@@ -0,0 +1,208 @@
+//===--------- RegisterEHFrames.cpp - Register EH frame sections ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
+
+#include "llvm/Config/config.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "llvm/Support/FormatVariadic.h"
+
+#define DEBUG_TYPE "orc"
+
+using namespace llvm;
+using namespace llvm::orc;
+using namespace llvm::orc::tpctypes;
+
+namespace llvm {
+namespace orc {
+
+#if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \
+ !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+
+extern "C" void __register_frame(const void *);
+extern "C" void __deregister_frame(const void *);
+
+Error registerFrameWrapper(const void *P) {
+ __register_frame(P);
+ return Error::success();
+}
+
+Error deregisterFrameWrapper(const void *P) {
+ __deregister_frame(P);
+ return Error::success();
+}
+
+#else
+
+// The building compiler does not have __(de)register_frame but
+// it may be found at runtime in a dynamically-loaded library.
+// For example, this happens when building LLVM with Visual C++
+// but using the MingW runtime.
+static Error registerFrameWrapper(const void *P) {
+ static void((*RegisterFrame)(const void *)) = 0;
+
+ if (!RegisterFrame)
+ *(void **)&RegisterFrame =
+ llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
+
+ if (RegisterFrame) {
+ RegisterFrame(P);
+ return Error::success();
+ }
+
+ return make_error<StringError>("could not register eh-frame: "
+ "__register_frame function not found",
+ inconvertibleErrorCode());
+}
+
+static Error deregisterFrameWrapper(const void *P) {
+ static void((*DeregisterFrame)(const void *)) = 0;
+
+ if (!DeregisterFrame)
+ *(void **)&DeregisterFrame =
+ llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
+ "__deregister_frame");
+
+ if (DeregisterFrame) {
+ DeregisterFrame(P);
+ return Error::success();
+ }
+
+ return make_error<StringError>("could not deregister eh-frame: "
+ "__deregister_frame function not found",
+ inconvertibleErrorCode());
+}
+#endif
+
+#ifdef __APPLE__
+
+template <typename HandleFDEFn>
+Error walkAppleEHFrameSection(const char *const SectionStart,
+ size_t SectionSize, HandleFDEFn HandleFDE) {
+ const char *CurCFIRecord = SectionStart;
+ const char *End = SectionStart + SectionSize;
+ uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
+
+ while (CurCFIRecord != End && Size != 0) {
+ const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
+ if (Size == 0xffffffff)
+ Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
+ else
+ Size += 4;
+ uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
+
+ LLVM_DEBUG({
+ dbgs() << "Registering eh-frame section:\n";
+ dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
+ << (void *)CurCFIRecord << ": [";
+ for (unsigned I = 0; I < Size; ++I)
+ dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
+ dbgs() << " ]\n";
+ });
+
+ if (Offset != 0)
+ if (auto Err = HandleFDE(CurCFIRecord))
+ return Err;
+
+ CurCFIRecord += Size;
+
+ Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
+ }
+
+ return Error::success();
+}
+
+#endif // __APPLE__
+
+Error registerEHFrameSection(const void *EHFrameSectionAddr,
+ size_t EHFrameSectionSize) {
+#ifdef __APPLE__
+ // On Darwin __register_frame has to be called for each FDE entry.
+ return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
+ EHFrameSectionSize, registerFrameWrapper);
+#else
+ // On Linux __register_frame takes a single argument:
+ // a pointer to the start of the .eh_frame section.
+
+ // How can it find the end? Because crtendS.o is linked
+ // in and it has an .eh_frame section with four zero chars.
+ return registerFrameWrapper(EHFrameSectionAddr);
+#endif
+}
+
+Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
+ size_t EHFrameSectionSize) {
+#ifdef __APPLE__
+ return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
+ EHFrameSectionSize, deregisterFrameWrapper);
+#else
+ return deregisterFrameWrapper(EHFrameSectionAddr);
+#endif
+}
+
+} // end namespace orc
+} // end namespace llvm
+
+extern "C" CWrapperFunctionResult
+llvm_orc_registerEHFrameSectionWrapper(uint8_t *Data, uint64_t Size) {
+ if (Size != sizeof(uint64_t) + sizeof(uint64_t))
+ return WrapperFunctionResult::from(
+ "Invalid arguments to llvm_orc_registerEHFrameSectionWrapper")
+ .release();
+
+ uint64_t EHFrameSectionAddr;
+ uint64_t EHFrameSectionSize;
+
+ {
+ BinaryStreamReader ArgReader(ArrayRef<uint8_t>(Data, Size),
+ support::endianness::big);
+ cantFail(ArgReader.readInteger(EHFrameSectionAddr));
+ cantFail(ArgReader.readInteger(EHFrameSectionSize));
+ }
+
+ if (auto Err = registerEHFrameSection(
+ jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
+ EHFrameSectionSize)) {
+ auto ErrMsg = toString(std::move(Err));
+ return WrapperFunctionResult::from(ErrMsg).release();
+ }
+ return WrapperFunctionResult().release();
+}
+
+extern "C" CWrapperFunctionResult
+llvm_orc_deregisterEHFrameSectionWrapper(uint8_t *Data, uint64_t Size) {
+ if (Size != sizeof(uint64_t) + sizeof(uint64_t))
+ return WrapperFunctionResult::from(
+ "Invalid arguments to llvm_orc_registerEHFrameSectionWrapper")
+ .release();
+
+ uint64_t EHFrameSectionAddr;
+ uint64_t EHFrameSectionSize;
+
+ {
+ BinaryStreamReader ArgReader(ArrayRef<uint8_t>(Data, Size),
+ support::endianness::big);
+ cantFail(ArgReader.readInteger(EHFrameSectionAddr));
+ cantFail(ArgReader.readInteger(EHFrameSectionSize));
+ }
+
+ if (auto Err = deregisterEHFrameSection(
+ jitTargetAddressToPointer<void *>(EHFrameSectionAddr),
+ EHFrameSectionSize)) {
+ auto ErrMsg = toString(std::move(Err));
+ return WrapperFunctionResult::from(ErrMsg).release();
+ }
+ return WrapperFunctionResult().release();
+}
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
new file mode 100644
index 000000000000..a8e6c049cf4b
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
@@ -0,0 +1,43 @@
+//===--- TargetExecutionUtils.cpp - Execution utils for target processes --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
+
+#include <vector>
+
+namespace llvm {
+namespace orc {
+
+int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
+ Optional<StringRef> ProgramName) {
+ std::vector<std::unique_ptr<char[]>> ArgVStorage;
+ std::vector<char *> ArgV;
+
+ ArgVStorage.reserve(Args.size() + (ProgramName ? 1 : 0));
+ ArgV.reserve(Args.size() + 1 + (ProgramName ? 1 : 0));
+
+ if (ProgramName) {
+ ArgVStorage.push_back(std::make_unique<char[]>(ProgramName->size() + 1));
+ llvm::copy(*ProgramName, &ArgVStorage.back()[0]);
+ ArgVStorage.back()[ProgramName->size()] = '\0';
+ ArgV.push_back(ArgVStorage.back().get());
+ }
+
+ for (const auto &Arg : Args) {
+ ArgVStorage.push_back(std::make_unique<char[]>(Arg.size() + 1));
+ llvm::copy(Arg, &ArgVStorage.back()[0]);
+ ArgVStorage.back()[Arg.size()] = '\0';
+ ArgV.push_back(ArgVStorage.back().get());
+ }
+ ArgV.push_back(nullptr);
+
+ return Main(Args.size() + !!ProgramName, ArgV.data());
+}
+
+} // End namespace orc.
+} // End namespace llvm.
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcessControl.cpp
new file mode 100644
index 000000000000..7bf874e88c26
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcessControl.cpp
@@ -0,0 +1,153 @@
+//===------ TargetProcessControl.cpp -- Target process control APIs -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Process.h"
+
+#include <mutex>
+
+namespace llvm {
+namespace orc {
+
+TargetProcessControl::MemoryAccess::~MemoryAccess() {}
+
+TargetProcessControl::~TargetProcessControl() {}
+
+SelfTargetProcessControl::SelfTargetProcessControl(
+ std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple,
+ unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
+ : TargetProcessControl(std::move(SSP)) {
+
+ OwnedMemMgr = std::move(MemMgr);
+ if (!OwnedMemMgr)
+ OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>();
+
+ this->TargetTriple = std::move(TargetTriple);
+ this->PageSize = PageSize;
+ this->MemMgr = OwnedMemMgr.get();
+ this->MemAccess = this;
+ if (this->TargetTriple.isOSBinFormatMachO())
+ GlobalManglingPrefix = '_';
+}
+
+Expected<std::unique_ptr<SelfTargetProcessControl>>
+SelfTargetProcessControl::Create(
+ std::shared_ptr<SymbolStringPool> SSP,
+ std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
+ auto PageSize = sys::Process::getPageSize();
+ if (!PageSize)
+ return PageSize.takeError();
+
+ Triple TT(sys::getProcessTriple());
+
+ return std::make_unique<SelfTargetProcessControl>(
+ std::move(SSP), std::move(TT), *PageSize, std::move(MemMgr));
+}
+
+Expected<tpctypes::DylibHandle>
+SelfTargetProcessControl::loadDylib(const char *DylibPath) {
+ std::string ErrMsg;
+ auto Dylib = std::make_unique<sys::DynamicLibrary>(
+ sys::DynamicLibrary::getPermanentLibrary(DylibPath, &ErrMsg));
+ if (!Dylib->isValid())
+ return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
+ DynamicLibraries.push_back(std::move(Dylib));
+ return pointerToJITTargetAddress(DynamicLibraries.back().get());
+}
+
+Expected<std::vector<tpctypes::LookupResult>>
+SelfTargetProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) {
+ std::vector<tpctypes::LookupResult> R;
+
+ for (auto &Elem : Request) {
+ auto *Dylib = jitTargetAddressToPointer<sys::DynamicLibrary *>(Elem.Handle);
+ assert(llvm::any_of(DynamicLibraries,
+ [=](const std::unique_ptr<sys::DynamicLibrary> &DL) {
+ return DL.get() == Dylib;
+ }) &&
+ "Invalid handle");
+
+ R.push_back(std::vector<JITTargetAddress>());
+ for (auto &KV : Elem.Symbols) {
+ auto &Sym = KV.first;
+ std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
+ (*Sym).size() - !!GlobalManglingPrefix);
+ void *Addr = Dylib->getAddressOfSymbol(Tmp.c_str());
+ if (!Addr && KV.second == SymbolLookupFlags::RequiredSymbol) {
+ // FIXME: Collect all failing symbols before erroring out.
+ SymbolNameVector MissingSymbols;
+ MissingSymbols.push_back(Sym);
+ return make_error<SymbolsNotFound>(std::move(MissingSymbols));
+ }
+ R.back().push_back(pointerToJITTargetAddress(Addr));
+ }
+ }
+
+ return R;
+}
+
+Expected<int32_t>
+SelfTargetProcessControl::runAsMain(JITTargetAddress MainFnAddr,
+ ArrayRef<std::string> Args) {
+ using MainTy = int (*)(int, char *[]);
+ return orc::runAsMain(jitTargetAddressToFunction<MainTy>(MainFnAddr), Args);
+}
+
+Expected<tpctypes::WrapperFunctionResult>
+SelfTargetProcessControl::runWrapper(JITTargetAddress WrapperFnAddr,
+ ArrayRef<uint8_t> ArgBuffer) {
+ using WrapperFnTy =
+ tpctypes::CWrapperFunctionResult (*)(const uint8_t *Data, uint64_t Size);
+ auto *WrapperFn = jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr);
+ return WrapperFn(ArgBuffer.data(), ArgBuffer.size());
+}
+
+Error SelfTargetProcessControl::disconnect() { return Error::success(); }
+
+void SelfTargetProcessControl::writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
+ WriteResultFn OnWriteComplete) {
+ for (auto &W : Ws)
+ *jitTargetAddressToPointer<uint8_t *>(W.Address) = W.Value;
+ OnWriteComplete(Error::success());
+}
+
+void SelfTargetProcessControl::writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
+ WriteResultFn OnWriteComplete) {
+ for (auto &W : Ws)
+ *jitTargetAddressToPointer<uint16_t *>(W.Address) = W.Value;
+ OnWriteComplete(Error::success());
+}
+
+void SelfTargetProcessControl::writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
+ WriteResultFn OnWriteComplete) {
+ for (auto &W : Ws)
+ *jitTargetAddressToPointer<uint32_t *>(W.Address) = W.Value;
+ OnWriteComplete(Error::success());
+}
+
+void SelfTargetProcessControl::writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
+ WriteResultFn OnWriteComplete) {
+ for (auto &W : Ws)
+ *jitTargetAddressToPointer<uint64_t *>(W.Address) = W.Value;
+ OnWriteComplete(Error::success());
+}
+
+void SelfTargetProcessControl::writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
+ WriteResultFn OnWriteComplete) {
+ for (auto &W : Ws)
+ memcpy(jitTargetAddressToPointer<char *>(W.Address), W.Buffer.data(),
+ W.Buffer.size());
+ OnWriteComplete(Error::success());
+}
+
+} // end namespace orc
+} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/ThreadSafeModule.cpp b/llvm/lib/ExecutionEngine/Orc/ThreadSafeModule.cpp
index 1f4e6f132115..2e128dd23744 100644
--- a/llvm/lib/ExecutionEngine/Orc/ThreadSafeModule.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ThreadSafeModule.cpp
@@ -15,7 +15,7 @@
namespace llvm {
namespace orc {
-ThreadSafeModule cloneToNewContext(ThreadSafeModule &TSM,
+ThreadSafeModule cloneToNewContext(const ThreadSafeModule &TSM,
GVPredicate ShouldCloneDef,
GVModifier UpdateClonedDefSource) {
assert(TSM && "Can not clone null module");
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp
index 46604ff4000c..b6ccd02405c1 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp
@@ -31,16 +31,8 @@ namespace llvm {
RTDyldMemoryManager::~RTDyldMemoryManager() {}
-// Determine whether we can register EH tables.
-#if (defined(__GNUC__) && !defined(__ARM_EABI__) && !defined(__ia64__) && \
- !(defined(_AIX) && defined(__ibmxl__)) && !defined(__SEH__) && \
- !defined(__USING_SJLJ_EXCEPTIONS__))
-#define HAVE_EHTABLE_SUPPORT 1
-#else
-#define HAVE_EHTABLE_SUPPORT 0
-#endif
-
-#if HAVE_EHTABLE_SUPPORT
+#if defined(HAVE_REGISTER_FRAME) && defined(HAVE_DEREGISTER_FRAME) && \
+ !defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
extern "C" void __register_frame(void *);
extern "C" void __deregister_frame(void *);
#else
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index 7e9b0690ccea..e49e6e541f15 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -308,7 +308,9 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
<< " SID: " << SectionID
<< " Offset: " << format("%p", (uintptr_t)Addr)
<< " flags: " << *FlagsOrErr << "\n");
- GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, Addr, *JITSymFlags);
+ if (!Name.empty()) // Skip absolute symbol relocations.
+ GlobalSymbolTable[Name] =
+ SymbolTableEntry(SectionID, Addr, *JITSymFlags);
} else if (SymType == object::SymbolRef::ST_Function ||
SymType == object::SymbolRef::ST_Data ||
SymType == object::SymbolRef::ST_Unknown ||
@@ -340,8 +342,9 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
<< " SID: " << SectionID
<< " Offset: " << format("%p", (uintptr_t)SectOffset)
<< " flags: " << *FlagsOrErr << "\n");
- GlobalSymbolTable[Name] =
- SymbolTableEntry(SectionID, SectOffset, *JITSymFlags);
+ if (!Name.empty()) // Skip absolute symbol relocations
+ GlobalSymbolTable[Name] =
+ SymbolTableEntry(SectionID, SectOffset, *JITSymFlags);
}
}
@@ -769,8 +772,9 @@ Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
LLVM_DEBUG(dbgs() << "Allocating common symbol " << Name << " address "
<< format("%p", Addr) << "\n");
- GlobalSymbolTable[Name] =
- SymbolTableEntry(SectionID, Offset, std::move(*JITSymFlags));
+ if (!Name.empty()) // Skip absolute symbol relocations.
+ GlobalSymbolTable[Name] =
+ SymbolTableEntry(SectionID, Offset, std::move(*JITSymFlags));
Offset += Size;
Addr += Size;
}
@@ -930,6 +934,8 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE,
if (Loc == GlobalSymbolTable.end()) {
ExternalSymbolRelocations[SymbolName].push_back(RE);
} else {
+ assert(!SymbolName.empty() &&
+ "Empty symbol should not be in GlobalSymbolTable");
// Copy the RE since we want to modify its addend.
RelocationEntry RECopy = RE;
const auto &SymInfo = Loc->second;
@@ -1200,16 +1206,19 @@ Error RuntimeDyldImpl::resolveExternalSymbols() {
void RuntimeDyldImpl::finalizeAsync(
std::unique_ptr<RuntimeDyldImpl> This,
- unique_function<void(object::OwningBinary<object::ObjectFile>, Error)>
+ unique_function<void(object::OwningBinary<object::ObjectFile>,
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, Error)>
OnEmitted,
- object::OwningBinary<object::ObjectFile> O) {
+ object::OwningBinary<object::ObjectFile> O,
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info) {
auto SharedThis = std::shared_ptr<RuntimeDyldImpl>(std::move(This));
auto PostResolveContinuation =
- [SharedThis, OnEmitted = std::move(OnEmitted), O = std::move(O)](
+ [SharedThis, OnEmitted = std::move(OnEmitted), O = std::move(O),
+ Info = std::move(Info)](
Expected<JITSymbolResolver::LookupResult> Result) mutable {
if (!Result) {
- OnEmitted(std::move(O), Result.takeError());
+ OnEmitted(std::move(O), std::move(Info), Result.takeError());
return;
}
@@ -1223,18 +1232,19 @@ void RuntimeDyldImpl::finalizeAsync(
SharedThis->registerEHFrames();
std::string ErrMsg;
if (SharedThis->MemMgr.finalizeMemory(&ErrMsg))
- OnEmitted(std::move(O),
+ OnEmitted(std::move(O), std::move(Info),
make_error<StringError>(std::move(ErrMsg),
inconvertibleErrorCode()));
else
- OnEmitted(std::move(O), Error::success());
+ OnEmitted(std::move(O), std::move(Info), Error::success());
};
JITSymbolResolver::LookupSet Symbols;
for (auto &RelocKV : SharedThis->ExternalSymbolRelocations) {
StringRef Name = RelocKV.first();
- assert(!Name.empty() && "Symbol has no name?");
+ if (Name.empty()) // Skip absolute symbol relocations.
+ continue;
assert(!SharedThis->GlobalSymbolTable.count(Name) &&
"Name already processed. RuntimeDyld instances can not be re-used "
"when finalizing with finalizeAsync.");
@@ -1418,12 +1428,12 @@ void jitLinkForORC(
object::OwningBinary<object::ObjectFile> O,
RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver,
bool ProcessAllSections,
- unique_function<
- Error(const object::ObjectFile &Obj,
- std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObj,
- std::map<StringRef, JITEvaluatedSymbol>)>
+ unique_function<Error(const object::ObjectFile &Obj,
+ RuntimeDyld::LoadedObjectInfo &LoadedObj,
+ std::map<StringRef, JITEvaluatedSymbol>)>
OnLoaded,
- unique_function<void(object::OwningBinary<object::ObjectFile>, Error)>
+ unique_function<void(object::OwningBinary<object::ObjectFile>,
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo>, Error)>
OnEmitted) {
RuntimeDyld RTDyld(MemMgr, Resolver);
@@ -1432,17 +1442,17 @@ void jitLinkForORC(
auto Info = RTDyld.loadObject(*O.getBinary());
if (RTDyld.hasError()) {
- OnEmitted(std::move(O), make_error<StringError>(RTDyld.getErrorString(),
- inconvertibleErrorCode()));
+ OnEmitted(std::move(O), std::move(Info),
+ make_error<StringError>(RTDyld.getErrorString(),
+ inconvertibleErrorCode()));
return;
}
- if (auto Err =
- OnLoaded(*O.getBinary(), std::move(Info), RTDyld.getSymbolTable()))
- OnEmitted(std::move(O), std::move(Err));
+ if (auto Err = OnLoaded(*O.getBinary(), *Info, RTDyld.getSymbolTable()))
+ OnEmitted(std::move(O), std::move(Info), std::move(Err));
RuntimeDyldImpl::finalizeAsync(std::move(RTDyld.Dyld), std::move(OnEmitted),
- std::move(O));
+ std::move(O), std::move(Info));
}
} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
index e5e512672daa..2fbe707ce8df 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
@@ -352,7 +352,7 @@ private:
RemainingExpr = RemainingExpr.substr(1).ltrim();
uint64_t StubAddr;
- std::string ErrorMsg = "";
+ std::string ErrorMsg;
std::tie(StubAddr, ErrorMsg) = Checker.getStubOrGOTAddrFor(
StubContainerName, Symbol, PCtx.IsInsideLoad, IsStubAddr);
@@ -389,7 +389,7 @@ private:
RemainingExpr = RemainingExpr.substr(1).ltrim();
uint64_t StubAddr;
- std::string ErrorMsg = "";
+ std::string ErrorMsg;
std::tie(StubAddr, ErrorMsg) = Checker.getSectionAddr(
FileName, SectionName, PCtx.IsInsideLoad);
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index 7c39ddc8b1da..28e1faab5ac7 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -57,13 +57,6 @@ namespace {
template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
- typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
- typedef Elf_Sym_Impl<ELFT> Elf_Sym;
- typedef Elf_Rel_Impl<ELFT, false> Elf_Rel;
- typedef Elf_Rel_Impl<ELFT, true> Elf_Rela;
-
- typedef Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
-
typedef typename ELFT::uint addr_type;
DyldELFObject(ELFObjectFile<ELFT> &&Obj);
@@ -269,7 +262,7 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
uint64_t SymOffset) {
switch (Type) {
default:
- llvm_unreachable("Relocation type not implemented yet!");
+ report_fatal_error("Relocation type not implemented yet!");
break;
case ELF::R_X86_64_NONE:
break;
@@ -359,7 +352,7 @@ void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section,
default:
// There are other relocation types, but it appears these are the
// only ones currently used by the LLVM ELF object writer
- llvm_unreachable("Relocation type not implemented yet!");
+ report_fatal_error("Relocation type not implemented yet!");
break;
}
}
@@ -382,7 +375,7 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
switch (Type) {
default:
- llvm_unreachable("Relocation type not implemented yet!");
+ report_fatal_error("Relocation type not implemented yet!");
break;
case ELF::R_AARCH64_ABS16: {
uint64_t Result = Value + Addend;
@@ -721,7 +714,7 @@ void RuntimeDyldELF::resolvePPC32Relocation(const SectionEntry &Section,
uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
switch (Type) {
default:
- llvm_unreachable("Relocation type not implemented yet!");
+ report_fatal_error("Relocation type not implemented yet!");
break;
case ELF::R_PPC_ADDR16_LO:
writeInt16BE(LocalAddress, applyPPClo(Value + Addend));
@@ -741,7 +734,7 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section,
uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
switch (Type) {
default:
- llvm_unreachable("Relocation type not implemented yet!");
+ report_fatal_error("Relocation type not implemented yet!");
break;
case ELF::R_PPC64_ADDR16:
writeInt16BE(LocalAddress, applyPPClo(Value + Addend));
@@ -835,7 +828,7 @@ void RuntimeDyldELF::resolveSystemZRelocation(const SectionEntry &Section,
uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
switch (Type) {
default:
- llvm_unreachable("Relocation type not implemented yet!");
+ report_fatal_error("Relocation type not implemented yet!");
break;
case ELF::R_390_PC16DBL:
case ELF::R_390_PLT16DBL: {
@@ -890,7 +883,7 @@ void RuntimeDyldELF::resolveBPFRelocation(const SectionEntry &Section,
switch (Type) {
default:
- llvm_unreachable("Relocation type not implemented yet!");
+ report_fatal_error("Relocation type not implemented yet!");
break;
case ELF::R_BPF_NONE:
break;
@@ -961,7 +954,8 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type,
(uint32_t)(Addend & 0xffffffffL));
break;
- case Triple::ppc:
+ case Triple::ppc: // Fall through.
+ case Triple::ppcle:
resolvePPC32Relocation(Section, Offset, Value, Type, Addend);
break;
case Triple::ppc64: // Fall through.
@@ -1676,30 +1670,33 @@ RuntimeDyldELF::processRelocationRef(
if (Value.SymbolName) {
// This is a call to an external function.
// Look for an existing stub.
- SectionEntry &Section = Sections[SectionID];
+ SectionEntry *Section = &Sections[SectionID];
StubMap::const_iterator i = Stubs.find(Value);
uintptr_t StubAddress;
if (i != Stubs.end()) {
- StubAddress = uintptr_t(Section.getAddress()) + i->second;
+ StubAddress = uintptr_t(Section->getAddress()) + i->second;
LLVM_DEBUG(dbgs() << " Stub function found\n");
} else {
// Create a new stub function (equivalent to a PLT entry).
LLVM_DEBUG(dbgs() << " Create a new stub function\n");
- uintptr_t BaseAddress = uintptr_t(Section.getAddress());
+ uintptr_t BaseAddress = uintptr_t(Section->getAddress());
uintptr_t StubAlignment = getStubAlignment();
StubAddress =
- (BaseAddress + Section.getStubOffset() + StubAlignment - 1) &
+ (BaseAddress + Section->getStubOffset() + StubAlignment - 1) &
-StubAlignment;
unsigned StubOffset = StubAddress - BaseAddress;
Stubs[Value] = StubOffset;
createStubFunction((uint8_t *)StubAddress);
// Bump our stub offset counter
- Section.advanceStubOffset(getMaxStubSize());
+ Section->advanceStubOffset(getMaxStubSize());
// Allocate a GOT Entry
uint64_t GOTOffset = allocateGOTEntries(1);
+ // This potentially creates a new Section which potentially
+ // invalidates the Section pointer, so reload it.
+ Section = &Sections[SectionID];
// The load of the GOT address has an addend of -4
resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset - 4,
@@ -1712,7 +1709,7 @@ RuntimeDyldELF::processRelocationRef(
}
// Make the target call a call into the stub table.
- resolveRelocation(Section, Offset, StubAddress, ELF::R_X86_64_PC32,
+ resolveRelocation(*Section, Offset, StubAddress, ELF::R_X86_64_PC32,
Addend);
} else {
RelocationEntry RE(SectionID, Offset, ELF::R_X86_64_PC32, Value.Addend,
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
index a9346536fd09..d34fae9aaf0c 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
@@ -535,9 +535,12 @@ public:
static void finalizeAsync(
std::unique_ptr<RuntimeDyldImpl> This,
- unique_function<void(object::OwningBinary<object::ObjectFile>, Error)>
+ unique_function<void(object::OwningBinary<object::ObjectFile>,
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo>,
+ Error)>
OnEmitted,
- object::OwningBinary<object::ObjectFile> O);
+ object::OwningBinary<object::ObjectFile> O,
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info);
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h
index ebe3ca33d308..9df3e2e3c3bf 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFX86_64.h
@@ -113,11 +113,10 @@ public:
// The MemoryManager can make sure this is always true by forcing the
// memory layout to be: CodeSection < ReadOnlySection < ReadWriteSection.
const uint64_t ImageBase = getImageBase();
- if (Value < ImageBase || ((Value - ImageBase) > UINT32_MAX)) {
- llvm::errs() << "IMAGE_REL_AMD64_ADDR32NB relocation requires an"
- << "ordered section layout.\n";
- write32BitOffset(Target, 0, 0);
- } else {
+ if (Value < ImageBase || ((Value - ImageBase) > UINT32_MAX))
+ report_fatal_error("IMAGE_REL_AMD64_ADDR32NB relocation requires an "
+ "ordered section layout");
+ else {
write32BitOffset(Target, RE.Addend, Value - ImageBase);
}
break;
diff --git a/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp b/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
index 925049b2a1b4..6690dd07d99b 100644
--- a/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/SectionMemoryManager.cpp
@@ -112,6 +112,15 @@ uint8_t *SectionMemoryManager::allocateSection(
// Save this address as the basis for our next request
MemGroup.Near = MB;
+ // Copy the address to all the other groups, if they have not
+ // been initialized.
+ if (CodeMem.Near.base() == 0)
+ CodeMem.Near = MB;
+ if (RODataMem.Near.base() == 0)
+ RODataMem.Near = MB;
+ if (RWDataMem.Near.base() == 0)
+ RWDataMem.Near = MB;
+
// Remember that we allocated this memory
MemGroup.AllocatedMem.push_back(MB);
Addr = (uintptr_t)MB.base();
@@ -152,8 +161,7 @@ bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg) {
}
// Make read-only data memory read-only.
- ec = applyMemoryGroupPermissions(RODataMem,
- sys::Memory::MF_READ | sys::Memory::MF_EXEC);
+ ec = applyMemoryGroupPermissions(RODataMem, sys::Memory::MF_READ);
if (ec) {
if (ErrMsg) {
*ErrMsg = ec.message();
@@ -210,11 +218,9 @@ SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup,
}
// Remove all blocks which are now empty
- MemGroup.FreeMem.erase(remove_if(MemGroup.FreeMem,
- [](FreeMemBlock &FreeMB) {
- return FreeMB.Free.allocatedSize() == 0;
- }),
- MemGroup.FreeMem.end());
+ erase_if(MemGroup.FreeMem, [](FreeMemBlock &FreeMB) {
+ return FreeMB.Free.allocatedSize() == 0;
+ });
return std::error_code();
}