ObjectLinkingLayer.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
  9. #include "llvm/ADT/Optional.h"
  10. #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
  11. #include <vector>
  12. #define DEBUG_TYPE "orc"
  13. using namespace llvm;
  14. using namespace llvm::jitlink;
  15. using namespace llvm::orc;
  16. namespace llvm {
  17. namespace orc {
  18. class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
  19. public:
  20. ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer,
  21. MaterializationResponsibility MR,
  22. std::unique_ptr<MemoryBuffer> ObjBuffer)
  23. : Layer(Layer), MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
  24. JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
  25. MemoryBufferRef getObjectBuffer() const override {
  26. return ObjBuffer->getMemBufferRef();
  27. }
  28. void notifyFailed(Error Err) override {
  29. Layer.getExecutionSession().reportError(std::move(Err));
  30. MR.failMaterialization();
  31. }
  32. void lookup(const DenseSet<StringRef> &Symbols,
  33. JITLinkAsyncLookupContinuation LookupContinuation) override {
  34. JITDylibSearchList SearchOrder;
  35. MR.getTargetJITDylib().withSearchOrderDo(
  36. [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
  37. auto &ES = Layer.getExecutionSession();
  38. SymbolNameSet InternedSymbols;
  39. for (auto &S : Symbols)
  40. InternedSymbols.insert(ES.intern(S));
  41. // OnResolve -- De-intern the symbols and pass the result to the linker.
  42. // FIXME: Capture LookupContinuation by move once we have c++14.
  43. auto SharedLookupContinuation =
  44. std::make_shared<JITLinkAsyncLookupContinuation>(
  45. std::move(LookupContinuation));
  46. auto OnResolve = [SharedLookupContinuation](Expected<SymbolMap> Result) {
  47. if (!Result)
  48. (*SharedLookupContinuation)(Result.takeError());
  49. else {
  50. AsyncLookupResult LR;
  51. for (auto &KV : *Result)
  52. LR[*KV.first] = KV.second;
  53. (*SharedLookupContinuation)(std::move(LR));
  54. }
  55. };
  56. ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved,
  57. std::move(OnResolve), [this](const SymbolDependenceMap &Deps) {
  58. registerDependencies(Deps);
  59. });
  60. }
  61. void notifyResolved(AtomGraph &G) override {
  62. auto &ES = Layer.getExecutionSession();
  63. SymbolFlagsMap ExtraSymbolsToClaim;
  64. bool AutoClaim = Layer.AutoClaimObjectSymbols;
  65. SymbolMap InternedResult;
  66. for (auto *DA : G.defined_atoms())
  67. if (DA->hasName() && DA->isGlobal()) {
  68. auto InternedName = ES.intern(DA->getName());
  69. JITSymbolFlags Flags;
  70. if (DA->isExported())
  71. Flags |= JITSymbolFlags::Exported;
  72. if (DA->isWeak())
  73. Flags |= JITSymbolFlags::Weak;
  74. if (DA->isCallable())
  75. Flags |= JITSymbolFlags::Callable;
  76. if (DA->isCommon())
  77. Flags |= JITSymbolFlags::Common;
  78. InternedResult[InternedName] =
  79. JITEvaluatedSymbol(DA->getAddress(), Flags);
  80. if (AutoClaim && !MR.getSymbols().count(InternedName)) {
  81. assert(!ExtraSymbolsToClaim.count(InternedName) &&
  82. "Duplicate symbol to claim?");
  83. ExtraSymbolsToClaim[InternedName] = Flags;
  84. }
  85. }
  86. for (auto *A : G.absolute_atoms())
  87. if (A->hasName()) {
  88. auto InternedName = ES.intern(A->getName());
  89. JITSymbolFlags Flags;
  90. Flags |= JITSymbolFlags::Absolute;
  91. if (A->isWeak())
  92. Flags |= JITSymbolFlags::Weak;
  93. if (A->isCallable())
  94. Flags |= JITSymbolFlags::Callable;
  95. InternedResult[InternedName] =
  96. JITEvaluatedSymbol(A->getAddress(), Flags);
  97. if (AutoClaim && !MR.getSymbols().count(InternedName)) {
  98. assert(!ExtraSymbolsToClaim.count(InternedName) &&
  99. "Duplicate symbol to claim?");
  100. ExtraSymbolsToClaim[InternedName] = Flags;
  101. }
  102. }
  103. if (!ExtraSymbolsToClaim.empty())
  104. if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
  105. return notifyFailed(std::move(Err));
  106. MR.resolve(InternedResult);
  107. Layer.notifyLoaded(MR);
  108. }
  109. void notifyFinalized(
  110. std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
  111. if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
  112. Layer.getExecutionSession().reportError(std::move(Err));
  113. MR.failMaterialization();
  114. return;
  115. }
  116. MR.emit();
  117. }
  118. AtomGraphPassFunction getMarkLivePass(const Triple &TT) const override {
  119. return [this](AtomGraph &G) { return markResponsibilitySymbolsLive(G); };
  120. }
  121. Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override {
  122. // Add passes to mark duplicate defs as should-discard, and to walk the
  123. // atom graph to build the symbol dependence graph.
  124. Config.PrePrunePasses.push_back(
  125. [this](AtomGraph &G) { return markSymbolsToDiscard(G); });
  126. Config.PostPrunePasses.push_back(
  127. [this](AtomGraph &G) { return computeNamedSymbolDependencies(G); });
  128. Layer.modifyPassConfig(MR, TT, Config);
  129. return Error::success();
  130. }
  131. private:
  132. using AnonAtomNamedDependenciesMap =
  133. DenseMap<const DefinedAtom *, SymbolNameSet>;
  134. Error markSymbolsToDiscard(AtomGraph &G) {
  135. auto &ES = Layer.getExecutionSession();
  136. for (auto *DA : G.defined_atoms())
  137. if (DA->isWeak() && DA->hasName()) {
  138. auto S = ES.intern(DA->getName());
  139. auto I = MR.getSymbols().find(S);
  140. if (I == MR.getSymbols().end())
  141. DA->setShouldDiscard(true);
  142. }
  143. for (auto *A : G.absolute_atoms())
  144. if (A->isWeak() && A->hasName()) {
  145. auto S = ES.intern(A->getName());
  146. auto I = MR.getSymbols().find(S);
  147. if (I == MR.getSymbols().end())
  148. A->setShouldDiscard(true);
  149. }
  150. return Error::success();
  151. }
  152. Error markResponsibilitySymbolsLive(AtomGraph &G) const {
  153. auto &ES = Layer.getExecutionSession();
  154. for (auto *DA : G.defined_atoms())
  155. if (DA->hasName() &&
  156. MR.getSymbols().count(ES.intern(DA->getName())))
  157. DA->setLive(true);
  158. return Error::success();
  159. }
  160. Error computeNamedSymbolDependencies(AtomGraph &G) {
  161. auto &ES = MR.getTargetJITDylib().getExecutionSession();
  162. auto AnonDeps = computeAnonDeps(G);
  163. for (auto *DA : G.defined_atoms()) {
  164. // Skip anonymous and non-global atoms: we do not need dependencies for
  165. // these.
  166. if (!DA->hasName() || !DA->isGlobal())
  167. continue;
  168. auto DAName = ES.intern(DA->getName());
  169. SymbolNameSet &DADeps = NamedSymbolDeps[DAName];
  170. for (auto &E : DA->edges()) {
  171. auto &TA = E.getTarget();
  172. if (TA.hasName())
  173. DADeps.insert(ES.intern(TA.getName()));
  174. else {
  175. assert(TA.isDefined() && "Anonymous atoms must be defined");
  176. auto &DTA = static_cast<DefinedAtom &>(TA);
  177. auto I = AnonDeps.find(&DTA);
  178. if (I != AnonDeps.end())
  179. for (auto &S : I->second)
  180. DADeps.insert(S);
  181. }
  182. }
  183. }
  184. return Error::success();
  185. }
  186. AnonAtomNamedDependenciesMap computeAnonDeps(AtomGraph &G) {
  187. auto &ES = MR.getTargetJITDylib().getExecutionSession();
  188. AnonAtomNamedDependenciesMap DepMap;
  189. // For all anonymous atoms:
  190. // (1) Add their named dependencies.
  191. // (2) Add them to the worklist for further iteration if they have any
  192. // depend on any other anonymous atoms.
  193. struct WorklistEntry {
  194. WorklistEntry(DefinedAtom *DA, DenseSet<DefinedAtom *> DAAnonDeps)
  195. : DA(DA), DAAnonDeps(std::move(DAAnonDeps)) {}
  196. DefinedAtom *DA = nullptr;
  197. DenseSet<DefinedAtom *> DAAnonDeps;
  198. };
  199. std::vector<WorklistEntry> Worklist;
  200. for (auto *DA : G.defined_atoms())
  201. if (!DA->hasName()) {
  202. auto &DANamedDeps = DepMap[DA];
  203. DenseSet<DefinedAtom *> DAAnonDeps;
  204. for (auto &E : DA->edges()) {
  205. auto &TA = E.getTarget();
  206. if (TA.hasName())
  207. DANamedDeps.insert(ES.intern(TA.getName()));
  208. else {
  209. assert(TA.isDefined() && "Anonymous atoms must be defined");
  210. DAAnonDeps.insert(static_cast<DefinedAtom *>(&TA));
  211. }
  212. }
  213. if (!DAAnonDeps.empty())
  214. Worklist.push_back(WorklistEntry(DA, std::move(DAAnonDeps)));
  215. }
  216. // Loop over all anonymous atoms with anonymous dependencies, propagating
  217. // their respective *named* dependencies. Iterate until we hit a stable
  218. // state.
  219. bool Changed;
  220. do {
  221. Changed = false;
  222. for (auto &WLEntry : Worklist) {
  223. auto *DA = WLEntry.DA;
  224. auto &DANamedDeps = DepMap[DA];
  225. auto &DAAnonDeps = WLEntry.DAAnonDeps;
  226. for (auto *TA : DAAnonDeps) {
  227. auto I = DepMap.find(TA);
  228. if (I != DepMap.end())
  229. for (const auto &S : I->second)
  230. Changed |= DANamedDeps.insert(S).second;
  231. }
  232. }
  233. } while (Changed);
  234. return DepMap;
  235. }
  236. void registerDependencies(const SymbolDependenceMap &QueryDeps) {
  237. for (auto &NamedDepsEntry : NamedSymbolDeps) {
  238. auto &Name = NamedDepsEntry.first;
  239. auto &NameDeps = NamedDepsEntry.second;
  240. SymbolDependenceMap SymbolDeps;
  241. for (const auto &QueryDepsEntry : QueryDeps) {
  242. JITDylib &SourceJD = *QueryDepsEntry.first;
  243. const SymbolNameSet &Symbols = QueryDepsEntry.second;
  244. auto &DepsForJD = SymbolDeps[&SourceJD];
  245. for (const auto &S : Symbols)
  246. if (NameDeps.count(S))
  247. DepsForJD.insert(S);
  248. if (DepsForJD.empty())
  249. SymbolDeps.erase(&SourceJD);
  250. }
  251. MR.addDependencies(Name, SymbolDeps);
  252. }
  253. }
  254. ObjectLinkingLayer &Layer;
  255. MaterializationResponsibility MR;
  256. std::unique_ptr<MemoryBuffer> ObjBuffer;
  257. DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps;
  258. };
  259. ObjectLinkingLayer::Plugin::~Plugin() {}
  260. ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
  261. JITLinkMemoryManager &MemMgr)
  262. : ObjectLayer(ES), MemMgr(MemMgr) {}
  263. ObjectLinkingLayer::~ObjectLinkingLayer() {
  264. if (auto Err = removeAllModules())
  265. getExecutionSession().reportError(std::move(Err));
  266. }
  267. void ObjectLinkingLayer::emit(MaterializationResponsibility R,
  268. std::unique_ptr<MemoryBuffer> O) {
  269. assert(O && "Object must not be null");
  270. jitLink(llvm::make_unique<ObjectLinkingLayerJITLinkContext>(
  271. *this, std::move(R), std::move(O)));
  272. }
  273. void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
  274. const Triple &TT,
  275. PassConfiguration &PassConfig) {
  276. for (auto &P : Plugins)
  277. P->modifyPassConfig(MR, TT, PassConfig);
  278. }
  279. void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
  280. for (auto &P : Plugins)
  281. P->notifyLoaded(MR);
  282. }
  283. Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
  284. AllocPtr Alloc) {
  285. Error Err = Error::success();
  286. for (auto &P : Plugins)
  287. Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
  288. if (Err)
  289. return Err;
  290. {
  291. std::lock_guard<std::mutex> Lock(LayerMutex);
  292. UntrackedAllocs.push_back(std::move(Alloc));
  293. }
  294. return Error::success();
  295. }
  296. Error ObjectLinkingLayer::removeModule(VModuleKey K) {
  297. Error Err = Error::success();
  298. for (auto &P : Plugins)
  299. Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
  300. AllocPtr Alloc;
  301. {
  302. std::lock_guard<std::mutex> Lock(LayerMutex);
  303. auto AllocItr = TrackedAllocs.find(K);
  304. Alloc = std::move(AllocItr->second);
  305. TrackedAllocs.erase(AllocItr);
  306. }
  307. assert(Alloc && "No allocation for key K");
  308. return joinErrors(std::move(Err), Alloc->deallocate());
  309. }
  310. Error ObjectLinkingLayer::removeAllModules() {
  311. Error Err = Error::success();
  312. for (auto &P : Plugins)
  313. Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
  314. std::vector<AllocPtr> Allocs;
  315. {
  316. std::lock_guard<std::mutex> Lock(LayerMutex);
  317. Allocs = std::move(UntrackedAllocs);
  318. for (auto &KV : TrackedAllocs)
  319. Allocs.push_back(std::move(KV.second));
  320. TrackedAllocs.clear();
  321. }
  322. while (!Allocs.empty()) {
  323. Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
  324. Allocs.pop_back();
  325. }
  326. return Err;
  327. }
  328. void LocalEHFrameRegistrationPlugin::modifyPassConfig(
  329. MaterializationResponsibility &MR, const Triple &TT,
  330. PassConfiguration &PassConfig) {
  331. assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
  332. PassConfig.PostFixupPasses.push_back(
  333. createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) {
  334. if (Addr)
  335. InProcessLinks[&MR] = jitTargetAddressToPointer<void *>(Addr);
  336. }));
  337. }
  338. Error LocalEHFrameRegistrationPlugin::notifyEmitted(
  339. MaterializationResponsibility &MR) {
  340. auto EHFrameAddrItr = InProcessLinks.find(&MR);
  341. if (EHFrameAddrItr == InProcessLinks.end())
  342. return Error::success();
  343. const void *EHFrameAddr = EHFrameAddrItr->second;
  344. assert(EHFrameAddr && "eh-frame addr to register can not be null");
  345. InProcessLinks.erase(EHFrameAddrItr);
  346. if (auto Key = MR.getVModuleKey())
  347. TrackedEHFrameAddrs[Key] = EHFrameAddr;
  348. else
  349. UntrackedEHFrameAddrs.push_back(EHFrameAddr);
  350. return registerEHFrameSection(EHFrameAddr);
  351. }
  352. Error LocalEHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
  353. auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K);
  354. if (EHFrameAddrItr == TrackedEHFrameAddrs.end())
  355. return Error::success();
  356. const void *EHFrameAddr = EHFrameAddrItr->second;
  357. assert(EHFrameAddr && "Tracked eh-frame addr must not be null");
  358. TrackedEHFrameAddrs.erase(EHFrameAddrItr);
  359. return deregisterEHFrameSection(EHFrameAddr);
  360. }
  361. Error LocalEHFrameRegistrationPlugin::notifyRemovingAllModules() {
  362. std::vector<const void *> EHFrameAddrs = std::move(UntrackedEHFrameAddrs);
  363. EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size());
  364. for (auto &KV : TrackedEHFrameAddrs)
  365. EHFrameAddrs.push_back(KV.second);
  366. TrackedEHFrameAddrs.clear();
  367. Error Err = Error::success();
  368. while (!EHFrameAddrs.empty()) {
  369. const void *EHFrameAddr = EHFrameAddrs.back();
  370. assert(EHFrameAddr && "Untracked eh-frame addr must not be null");
  371. EHFrameAddrs.pop_back();
  372. Err = joinErrors(std::move(Err), deregisterEHFrameSection(EHFrameAddr));
  373. }
  374. return Err;
  375. }
  376. } // End namespace orc.
  377. } // End namespace llvm.