summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h7
-rw-r--r--llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h91
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp9
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp195
-rw-r--r--llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test7
-rw-r--r--llvm/tools/llvm-jitlink/llvm-jitlink.cpp28
6 files changed, 238 insertions, 99 deletions
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h b/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
index 5c1c276d372..1563e97fb08 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
@@ -27,14 +27,17 @@ Error registerEHFrameSection(const void *EHFrameSectionAddr);
/// Deregisters all FDEs in the given eh-frame section with the current process.
Error deregisterEHFrameSection(const void *EHFrameSectionAddr);
+using StoreFrameAddressFunction = std::function<void(JITTargetAddress)>;
+
/// Creates a pass that records the address of the EH frame section. If no
/// eh-frame section is found, it will set EHFrameAddr to zero.
///
/// Authors of JITLinkContexts can use this function to register a post-fixup
/// pass that records the address of the eh-frame section. This address can
/// be used after finalization to register and deregister the frame.
-AtomGraphPassFunction createEHFrameRecorderPass(const Triple &TT,
- JITTargetAddress &EHFrameAddr);
+AtomGraphPassFunction
+createEHFrameRecorderPass(const Triple &TT,
+ StoreFrameAddressFunction StoreFrameAddress);
} // end namespace jitlink
} // end namespace llvm
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
index f4cafb5cdcc..4a45ad2b92e 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
@@ -41,27 +41,48 @@ namespace orc {
class ObjectLinkingLayerJITLinkContext;
+/// An ObjectLayer implementation built on JITLink.
+///
+/// Clients can use this class to add relocatable object files to an
+/// ExecutionSession, and it typically serves as the base layer (underneath
+/// a compiling layer like IRCompileLayer) for the rest of the JIT.
class ObjectLinkingLayer : public ObjectLayer {
friend class ObjectLinkingLayerJITLinkContext;
public:
- /// Function object for receiving object-loaded notifications.
- using NotifyLoadedFunction = std::function<void(VModuleKey)>;
+ /// Plugin instances can be added to the ObjectLinkingLayer to receive
+ /// callbacks when code is loaded or emitted, and when JITLink is being
+ /// configured.
+ class Plugin {
+ public:
+ virtual ~Plugin();
+ virtual void modifyPassConfig(MaterializationResponsibility &MR,
+ const Triple &TT,
+ jitlink::PassConfiguration &Config) {}
+ virtual void notifyLoaded(MaterializationResponsibility &MR) {}
+ virtual Error notifyEmitted(MaterializationResponsibility &MR) {
+ return Error::success();
+ }
+ virtual Error notifyRemovingModule(VModuleKey K) {
+ return Error::success();
+ }
+ virtual Error notifyRemovingAllModules() { return Error::success(); }
+ };
- /// Function object for receiving finalization notifications.
- using NotifyEmittedFunction = std::function<void(VModuleKey)>;
+ /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
+ /// and NotifyEmitted functors.
+ ObjectLinkingLayer(ExecutionSession &ES,
+ jitlink::JITLinkMemoryManager &MemMgr);
- /// Function object for modifying PassConfiguration objects.
- using ModifyPassConfigFunction =
- std::function<void(const Triple &TT, jitlink::PassConfiguration &Config)>;
+ /// Destruct an ObjectLinkingLayer.
+ ~ObjectLinkingLayer();
- /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
- /// and NotifyEmitted functors.
- ObjectLinkingLayer(
- ExecutionSession &ES, jitlink::JITLinkMemoryManager &MemMgr,
- NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
- NotifyEmittedFunction NotifyEmitted = NotifyEmittedFunction(),
- ModifyPassConfigFunction ModifyPassConfig = ModifyPassConfigFunction());
+ /// Add a pass-config modifier.
+ ObjectLinkingLayer &addPlugin(std::unique_ptr<Plugin> P) {
+ std::lock_guard<std::mutex> Lock(LayerMutex);
+ Plugins.push_back(std::move(P));
+ return *this;
+ }
/// Emit the object.
void emit(MaterializationResponsibility R,
@@ -101,31 +122,35 @@ public:
private:
using AllocPtr = std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>;
- class ObjectResources {
- public:
- ObjectResources() = default;
- ObjectResources(AllocPtr Alloc, JITTargetAddress EHFrameAddr);
- ObjectResources(ObjectResources &&Other);
- ObjectResources &operator=(ObjectResources &&Other);
- ~ObjectResources();
-
- private:
- AllocPtr Alloc;
- JITTargetAddress EHFrameAddr = 0;
- };
+ void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
+ jitlink::PassConfiguration &PassConfig);
+ void notifyLoaded(MaterializationResponsibility &MR);
+ Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc);
- void notifyFinalized(ObjectResources OR) {
- ObjResources.push_back(std::move(OR));
- }
+ Error removeModule(VModuleKey K);
+ Error removeAllModules();
mutable std::mutex LayerMutex;
jitlink::JITLinkMemoryManager &MemMgr;
- NotifyLoadedFunction NotifyLoaded;
- NotifyEmittedFunction NotifyEmitted;
- ModifyPassConfigFunction ModifyPassConfig;
bool OverrideObjectFlags = false;
bool AutoClaimObjectSymbols = false;
- std::vector<ObjectResources> ObjResources;
+ DenseMap<VModuleKey, AllocPtr> TrackedAllocs;
+ std::vector<AllocPtr> UntrackedAllocs;
+ std::vector<std::unique_ptr<Plugin>> Plugins;
+};
+
+class LocalEHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin {
+public:
+ Error notifyEmitted(MaterializationResponsibility &MR) override;
+ void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
+ jitlink::PassConfiguration &PassConfig) override;
+ Error notifyRemovingModule(VModuleKey K) override;
+ Error notifyRemovingAllModules() override;
+
+private:
+ DenseMap<MaterializationResponsibility *, const void *> InProcessLinks;
+ DenseMap<VModuleKey, const void *> TrackedEHFrameAddrs;
+ std::vector<const void *> UntrackedEHFrameAddrs;
};
} // end namespace orc
diff --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
index c531df82446..b54fd378aa5 100644
--- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
@@ -507,8 +507,9 @@ Error deregisterEHFrameSection(const void *EHFrameSectionAddr) {
#endif
}
-AtomGraphPassFunction createEHFrameRecorderPass(const Triple &TT,
- JITTargetAddress &EHFrameAddr) {
+AtomGraphPassFunction
+createEHFrameRecorderPass(const Triple &TT,
+ StoreFrameAddressFunction StoreFrameAddress) {
const char *EHFrameSectionName = nullptr;
if (TT.getObjectFormat() == Triple::MachO)
EHFrameSectionName = "__eh_frame";
@@ -516,7 +517,7 @@ AtomGraphPassFunction createEHFrameRecorderPass(const Triple &TT,
EHFrameSectionName = ".eh_frame";
auto RecordEHFrame = [EHFrameSectionName,
- &EHFrameAddr](AtomGraph &G) -> Error {
+ StoreFrameAddress](AtomGraph &G) -> Error {
// Search for a non-empty eh-frame and record the address of the first atom
// in it.
JITTargetAddress Addr = 0;
@@ -529,7 +530,7 @@ AtomGraphPassFunction createEHFrameRecorderPass(const Triple &TT,
break;
}
- EHFrameAddr = Addr;
+ StoreFrameAddress(Addr);
return Error::success();
};
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
index 154d7040b76..eb0ea47e2d4 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
@@ -133,25 +133,19 @@ public:
MR.resolve(InternedResult);
- if (Layer.NotifyLoaded)
- Layer.NotifyLoaded(MR.getVModuleKey());
+ Layer.notifyLoaded(MR);
}
void notifyFinalized(
std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
- if (EHFrameAddr) {
- // If there is an eh-frame then try to register it.
- if (auto Err = registerEHFrameSection((void *)EHFrameAddr)) {
- Layer.getExecutionSession().reportError(std::move(Err));
- MR.failMaterialization();
- return;
- }
- }
+ if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
+ Layer.getExecutionSession().reportError(std::move(Err));
+ MR.failMaterialization();
+ return;
+ }
MR.emit();
- Layer.notifyFinalized(
- ObjectLinkingLayer::ObjectResources(std::move(A), EHFrameAddr));
}
AtomGraphPassFunction getMarkLivePass(const Triple &TT) const override {
@@ -166,11 +160,7 @@ public:
Config.PostPrunePasses.push_back(
[this](AtomGraph &G) { return computeNamedSymbolDependencies(G); });
- Config.PostFixupPasses.push_back(
- createEHFrameRecorderPass(TT, EHFrameAddr));
-
- if (Layer.ModifyPassConfig)
- Layer.ModifyPassConfig(TT, Config);
+ Layer.modifyPassConfig(MR, TT, Config);
return Error::success();
}
@@ -328,16 +318,18 @@ private:
MaterializationResponsibility MR;
std::unique_ptr<MemoryBuffer> ObjBuffer;
DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps;
- JITTargetAddress EHFrameAddr = 0;
};
-ObjectLinkingLayer::ObjectLinkingLayer(
- ExecutionSession &ES, JITLinkMemoryManager &MemMgr,
- NotifyLoadedFunction NotifyLoaded, NotifyEmittedFunction NotifyEmitted,
- ModifyPassConfigFunction ModifyPassConfig)
- : ObjectLayer(ES), MemMgr(MemMgr), NotifyLoaded(std::move(NotifyLoaded)),
- NotifyEmitted(std::move(NotifyEmitted)),
- ModifyPassConfig(std::move(ModifyPassConfig)) {}
+ObjectLinkingLayer::Plugin::~Plugin() {}
+
+ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
+ JITLinkMemoryManager &MemMgr)
+ : ObjectLayer(ES), MemMgr(MemMgr) {}
+
+ObjectLinkingLayer::~ObjectLinkingLayer() {
+ if (auto Err = removeAllModules())
+ getExecutionSession().reportError(std::move(Err));
+}
void ObjectLinkingLayer::emit(MaterializationResponsibility R,
std::unique_ptr<MemoryBuffer> O) {
@@ -346,36 +338,145 @@ void ObjectLinkingLayer::emit(MaterializationResponsibility R,
*this, std::move(R), std::move(O)));
}
-ObjectLinkingLayer::ObjectResources::ObjectResources(
- AllocPtr Alloc, JITTargetAddress EHFrameAddr)
- : Alloc(std::move(Alloc)), EHFrameAddr(EHFrameAddr) {}
+void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
+ const Triple &TT,
+ PassConfiguration &PassConfig) {
+ for (auto &P : Plugins)
+ P->modifyPassConfig(MR, TT, PassConfig);
+}
+
+void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
+ for (auto &P : Plugins)
+ P->notifyLoaded(MR);
+}
+
+Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
+ AllocPtr Alloc) {
+ Error Err = Error::success();
+ for (auto &P : Plugins)
+ Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
+
+ if (Err)
+ return Err;
+
+ {
+ std::lock_guard<std::mutex> Lock(LayerMutex);
+ UntrackedAllocs.push_back(std::move(Alloc));
+ }
-ObjectLinkingLayer::ObjectResources::ObjectResources(ObjectResources &&Other)
- : Alloc(std::move(Other.Alloc)), EHFrameAddr(Other.EHFrameAddr) {
- Other.EHFrameAddr = 0;
+ return Error::success();
}
-ObjectLinkingLayer::ObjectResources &
-ObjectLinkingLayer::ObjectResources::operator=(ObjectResources &&Other) {
- std::swap(Alloc, Other.Alloc);
- std::swap(EHFrameAddr, Other.EHFrameAddr);
- return *this;
+Error ObjectLinkingLayer::removeModule(VModuleKey K) {
+ Error Err = Error::success();
+
+ for (auto &P : Plugins)
+ Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
+
+ AllocPtr Alloc;
+
+ {
+ std::lock_guard<std::mutex> Lock(LayerMutex);
+ auto AllocItr = TrackedAllocs.find(K);
+ Alloc = std::move(AllocItr->second);
+ TrackedAllocs.erase(AllocItr);
+ }
+
+ assert(Alloc && "No allocation for key K");
+
+ return joinErrors(std::move(Err), Alloc->deallocate());
}
-ObjectLinkingLayer::ObjectResources::~ObjectResources() {
- const char *ErrBanner =
- "ObjectLinkingLayer received error deallocating object resources:";
+Error ObjectLinkingLayer::removeAllModules() {
- assert((EHFrameAddr == 0 || Alloc) &&
- "Non-null EHFrameAddr must have an associated allocation");
+ Error Err = Error::success();
- if (EHFrameAddr)
- if (auto Err = deregisterEHFrameSection((void *)EHFrameAddr))
- logAllUnhandledErrors(std::move(Err), llvm::errs(), ErrBanner);
+ 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();
+ }
+
+ return Err;
+}
+
+void LocalEHFrameRegistrationPlugin::modifyPassConfig(
+ MaterializationResponsibility &MR, const Triple &TT,
+ PassConfiguration &PassConfig) {
+ assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
+
+ PassConfig.PostFixupPasses.push_back(
+ createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) {
+ if (Addr)
+ InProcessLinks[&MR] = jitTargetAddressToPointer<void *>(Addr);
+ }));
+}
+
+Error LocalEHFrameRegistrationPlugin::notifyEmitted(
+ MaterializationResponsibility &MR) {
+
+ auto EHFrameAddrItr = InProcessLinks.find(&MR);
+ if (EHFrameAddrItr == InProcessLinks.end())
+ return Error::success();
+
+ const void *EHFrameAddr = EHFrameAddrItr->second;
+ assert(EHFrameAddr && "eh-frame addr to register can not be null");
+
+ InProcessLinks.erase(EHFrameAddrItr);
+ if (auto Key = MR.getVModuleKey())
+ TrackedEHFrameAddrs[Key] = EHFrameAddr;
+ else
+ UntrackedEHFrameAddrs.push_back(EHFrameAddr);
+
+ return registerEHFrameSection(EHFrameAddr);
+}
+
+Error LocalEHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
+ auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K);
+ if (EHFrameAddrItr == TrackedEHFrameAddrs.end())
+ return Error::success();
+
+ const void *EHFrameAddr = EHFrameAddrItr->second;
+ assert(EHFrameAddr && "Tracked eh-frame addr must not be null");
+
+ TrackedEHFrameAddrs.erase(EHFrameAddrItr);
+
+ return deregisterEHFrameSection(EHFrameAddr);
+}
+
+Error LocalEHFrameRegistrationPlugin::notifyRemovingAllModules() {
+
+ std::vector<const void *> EHFrameAddrs = std::move(UntrackedEHFrameAddrs);
+ EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size());
+
+ for (auto &KV : TrackedEHFrameAddrs)
+ EHFrameAddrs.push_back(KV.second);
+
+ TrackedEHFrameAddrs.clear();
+
+ Error Err = Error::success();
+
+ while (!EHFrameAddrs.empty()) {
+ const void *EHFrameAddr = EHFrameAddrs.back();
+ assert(EHFrameAddr && "Untracked eh-frame addr must not be null");
+ EHFrameAddrs.pop_back();
+ Err = joinErrors(std::move(Err), deregisterEHFrameSection(EHFrameAddr));
+ }
- if (Alloc)
- if (auto Err = Alloc->deallocate())
- logAllUnhandledErrors(std::move(Err), llvm::errs(), ErrBanner);
+ return Err;
}
} // End namespace orc.
diff --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test b/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test
index 5b01d033fd5..08c616f8f0f 100644
--- a/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test
+++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test
@@ -1,9 +1,4 @@
-# RUN: llvm-jitlink -noexec %S/Inputs/MachO_x86-64_ehframe.o
-#
-# FIXME: Produces these errors:
-# JIT session error: Symbols not found: { __ZTIi, ___gxx_personality_v0 }
-# llvm-jitlink.exe: Failed to materialize symbols: { biz, _main, baz }
-# XFAIL: windows-msvc
+# RUN: llvm-jitlink -noexec -define-abs __ZTIi=0x1 -define-abs ___gxx_personality_v0=0x2 %S/Inputs/MachO_x86-64_ehframe.o
#
# Perform a no-exec link of MachO_x86-64_ehframe and verify that it does not
# generate any errors despite the last FDE referring to the first CIE (rather
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 383442f8a4c..5ecf66ae9e4 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -214,13 +214,27 @@ static void dumpSectionContents(raw_ostream &OS, AtomGraph &G) {
}
}
-Session::Session(Triple TT)
- : ObjLayer(ES, MemMgr, ObjectLinkingLayer::NotifyLoadedFunction(),
- ObjectLinkingLayer::NotifyEmittedFunction(),
- [this](const Triple &TT, PassConfiguration &PassConfig) {
- modifyPassConfig(TT, PassConfig);
- }),
- TT(std::move(TT)) {}
+Session::Session(Triple TT) : ObjLayer(ES, MemMgr), TT(std::move(TT)) {
+
+ /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
+ /// Session.
+ class JITLinkSessionPlugin : public ObjectLinkingLayer::Plugin {
+ public:
+ JITLinkSessionPlugin(Session &S) : S(S) {}
+ void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
+ PassConfiguration &PassConfig) {
+ S.modifyPassConfig(TT, PassConfig);
+ }
+
+ private:
+ Session &S;
+ };
+
+ if (!NoExec && !TT.isOSWindows())
+ ObjLayer.addPlugin(llvm::make_unique<LocalEHFrameRegistrationPlugin>());
+
+ ObjLayer.addPlugin(llvm::make_unique<JITLinkSessionPlugin>(*this));
+}
void Session::dumpSessionInfo(raw_ostream &OS) {
OS << "Registered addresses:\n" << SymbolInfos << FileInfos;
OpenPOWER on IntegriCloud