ObjectLinkingLayer.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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. if (auto Err = MR.notifyResolved(InternedResult)) {
  107. Layer.getExecutionSession().reportError(std::move(Err));
  108. MR.failMaterialization();
  109. return;
  110. }
  111. Layer.notifyLoaded(MR);
  112. }
  113. void notifyFinalized(
  114. std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
  115. if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
  116. Layer.getExecutionSession().reportError(std::move(Err));
  117. MR.failMaterialization();
  118. return;
  119. }
  120. if (auto Err = MR.notifyEmitted()) {
  121. Layer.getExecutionSession().reportError(std::move(Err));
  122. MR.failMaterialization();
  123. }
  124. }
  125. AtomGraphPassFunction getMarkLivePass(const Triple &TT) const override {
  126. return [this](AtomGraph &G) { return markResponsibilitySymbolsLive(G); };
  127. }
  128. Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override {
  129. // Add passes to mark duplicate defs as should-discard, and to walk the
  130. // atom graph to build the symbol dependence graph.
  131. Config.PrePrunePasses.push_back(
  132. [this](AtomGraph &G) { return markSymbolsToDiscard(G); });
  133. Config.PostPrunePasses.push_back(
  134. [this](AtomGraph &G) { return computeNamedSymbolDependencies(G); });
  135. Layer.modifyPassConfig(MR, TT, Config);
  136. return Error::success();
  137. }
  138. private:
  139. using AnonAtomNamedDependenciesMap =
  140. DenseMap<const DefinedAtom *, SymbolNameSet>;
  141. Error markSymbolsToDiscard(AtomGraph &G) {
  142. auto &ES = Layer.getExecutionSession();
  143. for (auto *DA : G.defined_atoms())
  144. if (DA->isWeak() && DA->hasName()) {
  145. auto S = ES.intern(DA->getName());
  146. auto I = MR.getSymbols().find(S);
  147. if (I == MR.getSymbols().end())
  148. DA->setShouldDiscard(true);
  149. }
  150. for (auto *A : G.absolute_atoms())
  151. if (A->isWeak() && A->hasName()) {
  152. auto S = ES.intern(A->getName());
  153. auto I = MR.getSymbols().find(S);
  154. if (I == MR.getSymbols().end())
  155. A->setShouldDiscard(true);
  156. }
  157. return Error::success();
  158. }
  159. Error markResponsibilitySymbolsLive(AtomGraph &G) const {
  160. auto &ES = Layer.getExecutionSession();
  161. for (auto *DA : G.defined_atoms())
  162. if (DA->hasName() &&
  163. MR.getSymbols().count(ES.intern(DA->getName())))
  164. DA->setLive(true);
  165. return Error::success();
  166. }
  167. Error computeNamedSymbolDependencies(AtomGraph &G) {
  168. auto &ES = MR.getTargetJITDylib().getExecutionSession();
  169. auto AnonDeps = computeAnonDeps(G);
  170. for (auto *DA : G.defined_atoms()) {
  171. // Skip anonymous and non-global atoms: we do not need dependencies for
  172. // these.
  173. if (!DA->hasName() || !DA->isGlobal())
  174. continue;
  175. auto DAName = ES.intern(DA->getName());
  176. SymbolNameSet &DADeps = NamedSymbolDeps[DAName];
  177. for (auto &E : DA->edges()) {
  178. auto &TA = E.getTarget();
  179. if (TA.hasName())
  180. DADeps.insert(ES.intern(TA.getName()));
  181. else {
  182. assert(TA.isDefined() && "Anonymous atoms must be defined");
  183. auto &DTA = static_cast<DefinedAtom &>(TA);
  184. auto I = AnonDeps.find(&DTA);
  185. if (I != AnonDeps.end())
  186. for (auto &S : I->second)
  187. DADeps.insert(S);
  188. }
  189. }
  190. }
  191. return Error::success();
  192. }
  193. AnonAtomNamedDependenciesMap computeAnonDeps(AtomGraph &G) {
  194. auto &ES = MR.getTargetJITDylib().getExecutionSession();
  195. AnonAtomNamedDependenciesMap DepMap;
  196. // For all anonymous atoms:
  197. // (1) Add their named dependencies.
  198. // (2) Add them to the worklist for further iteration if they have any
  199. // depend on any other anonymous atoms.
  200. struct WorklistEntry {
  201. WorklistEntry(DefinedAtom *DA, DenseSet<DefinedAtom *> DAAnonDeps)
  202. : DA(DA), DAAnonDeps(std::move(DAAnonDeps)) {}
  203. DefinedAtom *DA = nullptr;
  204. DenseSet<DefinedAtom *> DAAnonDeps;
  205. };
  206. std::vector<WorklistEntry> Worklist;
  207. for (auto *DA : G.defined_atoms())
  208. if (!DA->hasName()) {
  209. auto &DANamedDeps = DepMap[DA];
  210. DenseSet<DefinedAtom *> DAAnonDeps;
  211. for (auto &E : DA->edges()) {
  212. auto &TA = E.getTarget();
  213. if (TA.hasName())
  214. DANamedDeps.insert(ES.intern(TA.getName()));
  215. else {
  216. assert(TA.isDefined() && "Anonymous atoms must be defined");
  217. DAAnonDeps.insert(static_cast<DefinedAtom *>(&TA));
  218. }
  219. }
  220. if (!DAAnonDeps.empty())
  221. Worklist.push_back(WorklistEntry(DA, std::move(DAAnonDeps)));
  222. }
  223. // Loop over all anonymous atoms with anonymous dependencies, propagating
  224. // their respective *named* dependencies. Iterate until we hit a stable
  225. // state.
  226. bool Changed;
  227. do {
  228. Changed = false;
  229. for (auto &WLEntry : Worklist) {
  230. auto *DA = WLEntry.DA;
  231. auto &DANamedDeps = DepMap[DA];
  232. auto &DAAnonDeps = WLEntry.DAAnonDeps;
  233. for (auto *TA : DAAnonDeps) {
  234. auto I = DepMap.find(TA);
  235. if (I != DepMap.end())
  236. for (const auto &S : I->second)
  237. Changed |= DANamedDeps.insert(S).second;
  238. }
  239. }
  240. } while (Changed);
  241. return DepMap;
  242. }
  243. void registerDependencies(const SymbolDependenceMap &QueryDeps) {
  244. for (auto &NamedDepsEntry : NamedSymbolDeps) {
  245. auto &Name = NamedDepsEntry.first;
  246. auto &NameDeps = NamedDepsEntry.second;
  247. SymbolDependenceMap SymbolDeps;
  248. for (const auto &QueryDepsEntry : QueryDeps) {
  249. JITDylib &SourceJD = *QueryDepsEntry.first;
  250. const SymbolNameSet &Symbols = QueryDepsEntry.second;
  251. auto &DepsForJD = SymbolDeps[&SourceJD];
  252. for (const auto &S : Symbols)
  253. if (NameDeps.count(S))
  254. DepsForJD.insert(S);
  255. if (DepsForJD.empty())
  256. SymbolDeps.erase(&SourceJD);
  257. }
  258. MR.addDependencies(Name, SymbolDeps);
  259. }
  260. }
  261. ObjectLinkingLayer &Layer;
  262. MaterializationResponsibility MR;
  263. std::unique_ptr<MemoryBuffer> ObjBuffer;
  264. DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps;
  265. };
  266. ObjectLinkingLayer::Plugin::~Plugin() {}
  267. ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
  268. JITLinkMemoryManager &MemMgr)
  269. : ObjectLayer(ES), MemMgr(MemMgr) {}
  270. ObjectLinkingLayer::~ObjectLinkingLayer() {
  271. if (auto Err = removeAllModules())
  272. getExecutionSession().reportError(std::move(Err));
  273. }
  274. void ObjectLinkingLayer::emit(MaterializationResponsibility R,
  275. std::unique_ptr<MemoryBuffer> O) {
  276. assert(O && "Object must not be null");
  277. jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
  278. *this, std::move(R), std::move(O)));
  279. }
  280. void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
  281. const Triple &TT,
  282. PassConfiguration &PassConfig) {
  283. for (auto &P : Plugins)
  284. P->modifyPassConfig(MR, TT, PassConfig);
  285. }
  286. void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
  287. for (auto &P : Plugins)
  288. P->notifyLoaded(MR);
  289. }
  290. Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
  291. AllocPtr Alloc) {
  292. Error Err = Error::success();
  293. for (auto &P : Plugins)
  294. Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
  295. if (Err)
  296. return Err;
  297. {
  298. std::lock_guard<std::mutex> Lock(LayerMutex);
  299. UntrackedAllocs.push_back(std::move(Alloc));
  300. }
  301. return Error::success();
  302. }
  303. Error ObjectLinkingLayer::removeModule(VModuleKey K) {
  304. Error Err = Error::success();
  305. for (auto &P : Plugins)
  306. Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
  307. AllocPtr Alloc;
  308. {
  309. std::lock_guard<std::mutex> Lock(LayerMutex);
  310. auto AllocItr = TrackedAllocs.find(K);
  311. Alloc = std::move(AllocItr->second);
  312. TrackedAllocs.erase(AllocItr);
  313. }
  314. assert(Alloc && "No allocation for key K");
  315. return joinErrors(std::move(Err), Alloc->deallocate());
  316. }
  317. Error ObjectLinkingLayer::removeAllModules() {
  318. Error Err = Error::success();
  319. for (auto &P : Plugins)
  320. Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
  321. std::vector<AllocPtr> Allocs;
  322. {
  323. std::lock_guard<std::mutex> Lock(LayerMutex);
  324. Allocs = std::move(UntrackedAllocs);
  325. for (auto &KV : TrackedAllocs)
  326. Allocs.push_back(std::move(KV.second));
  327. TrackedAllocs.clear();
  328. }
  329. while (!Allocs.empty()) {
  330. Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
  331. Allocs.pop_back();
  332. }
  333. return Err;
  334. }
  335. EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
  336. jitlink::EHFrameRegistrar &Registrar)
  337. : Registrar(Registrar) {}
  338. void EHFrameRegistrationPlugin::modifyPassConfig(
  339. MaterializationResponsibility &MR, const Triple &TT,
  340. PassConfiguration &PassConfig) {
  341. assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
  342. PassConfig.PostFixupPasses.push_back(
  343. createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) {
  344. if (Addr)
  345. InProcessLinks[&MR] = Addr;
  346. }));
  347. }
  348. Error EHFrameRegistrationPlugin::notifyEmitted(
  349. MaterializationResponsibility &MR) {
  350. auto EHFrameAddrItr = InProcessLinks.find(&MR);
  351. if (EHFrameAddrItr == InProcessLinks.end())
  352. return Error::success();
  353. auto EHFrameAddr = EHFrameAddrItr->second;
  354. assert(EHFrameAddr && "eh-frame addr to register can not be null");
  355. InProcessLinks.erase(EHFrameAddrItr);
  356. if (auto Key = MR.getVModuleKey())
  357. TrackedEHFrameAddrs[Key] = EHFrameAddr;
  358. else
  359. UntrackedEHFrameAddrs.push_back(EHFrameAddr);
  360. return Registrar.registerEHFrames(EHFrameAddr);
  361. }
  362. Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
  363. auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K);
  364. if (EHFrameAddrItr == TrackedEHFrameAddrs.end())
  365. return Error::success();
  366. auto EHFrameAddr = EHFrameAddrItr->second;
  367. assert(EHFrameAddr && "Tracked eh-frame addr must not be null");
  368. TrackedEHFrameAddrs.erase(EHFrameAddrItr);
  369. return Registrar.deregisterEHFrames(EHFrameAddr);
  370. }
  371. Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
  372. std::vector<JITTargetAddress> EHFrameAddrs = std::move(UntrackedEHFrameAddrs);
  373. EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size());
  374. for (auto &KV : TrackedEHFrameAddrs)
  375. EHFrameAddrs.push_back(KV.second);
  376. TrackedEHFrameAddrs.clear();
  377. Error Err = Error::success();
  378. while (!EHFrameAddrs.empty()) {
  379. auto EHFrameAddr = EHFrameAddrs.back();
  380. assert(EHFrameAddr && "Untracked eh-frame addr must not be null");
  381. EHFrameAddrs.pop_back();
  382. Err = joinErrors(std::move(Err), Registrar.deregisterEHFrames(EHFrameAddr));
  383. }
  384. return Err;
  385. }
  386. } // End namespace orc.
  387. } // End namespace llvm.