LLVM  16.0.0git
ObjectLinkingLayer.cpp
Go to the documentation of this file.
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 
10 #include "llvm/ADT/Optional.h"
14 #include <string>
15 #include <vector>
16 
17 #define DEBUG_TYPE "orc"
18 
19 using namespace llvm;
20 using namespace llvm::jitlink;
21 using namespace llvm::orc;
22 
23 namespace {
24 
25 class LinkGraphMaterializationUnit : public MaterializationUnit {
26 public:
27  static std::unique_ptr<LinkGraphMaterializationUnit>
28  Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) {
29  auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G);
30  return std::unique_ptr<LinkGraphMaterializationUnit>(
31  new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G),
32  std::move(LGI)));
33  }
34 
35  StringRef getName() const override { return G->getName(); }
36  void materialize(std::unique_ptr<MaterializationResponsibility> MR) override {
37  ObjLinkingLayer.emit(std::move(MR), std::move(G));
38  }
39 
40 private:
41  static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) {
42 
43  Interface LGI;
44 
45  for (auto *Sym : G.defined_symbols()) {
46  // Skip local symbols.
47  if (Sym->getScope() == Scope::Local)
48  continue;
49  assert(Sym->hasName() && "Anonymous non-local symbol?");
50 
51  JITSymbolFlags Flags;
52  if (Sym->getScope() == Scope::Default)
53  Flags |= JITSymbolFlags::Exported;
54 
55  if (Sym->isCallable())
56  Flags |= JITSymbolFlags::Callable;
57 
58  LGI.SymbolFlags[ES.intern(Sym->getName())] = Flags;
59  }
60 
61  if ((G.getTargetTriple().isOSBinFormatMachO() && hasMachOInitSection(G)) ||
62  (G.getTargetTriple().isOSBinFormatELF() && hasELFInitSection(G)))
63  LGI.InitSymbol = makeInitSymbol(ES, G);
64 
65  return LGI;
66  }
67 
68  static bool hasMachOInitSection(LinkGraph &G) {
69  for (auto &Sec : G.sections())
70  if (Sec.getName() == "__DATA,__objc_selrefs" ||
71  Sec.getName() == "__DATA,__objc_classlist" ||
72  Sec.getName() == "__TEXT,__swift5_protos" ||
73  Sec.getName() == "__TEXT,__swift5_proto" ||
74  Sec.getName() == "__TEXT,__swift5_types" ||
75  Sec.getName() == "__DATA,__mod_init_func")
76  return true;
77  return false;
78  }
79 
80  static bool hasELFInitSection(LinkGraph &G) {
81  for (auto &Sec : G.sections()) {
82  auto SecName = Sec.getName();
83  if (SecName.consume_front(".init_array") &&
84  (SecName.empty() || SecName[0] == '.'))
85  return true;
86  }
87  return false;
88  }
89 
90  static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) {
91  std::string InitSymString;
92  raw_string_ostream(InitSymString)
93  << "$." << G.getName() << ".__inits" << Counter++;
94  return ES.intern(InitSymString);
95  }
96 
97  LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer,
98  std::unique_ptr<LinkGraph> G, Interface LGI)
99  : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer),
100  G(std::move(G)) {}
101 
102  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
103  for (auto *Sym : G->defined_symbols())
104  if (Sym->getName() == *Name) {
105  assert(Sym->getLinkage() == Linkage::Weak &&
106  "Discarding non-weak definition");
107  G->makeExternal(*Sym);
108  break;
109  }
110  }
111 
112  ObjectLinkingLayer &ObjLinkingLayer;
113  std::unique_ptr<LinkGraph> G;
114  static std::atomic<uint64_t> Counter;
115 };
116 
117 std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};
118 
119 } // end anonymous namespace
120 
121 namespace llvm {
122 namespace orc {
123 
125 public:
127  ObjectLinkingLayer &Layer,
128  std::unique_ptr<MaterializationResponsibility> MR,
129  std::unique_ptr<MemoryBuffer> ObjBuffer)
130  : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),
131  MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
132 
134  // If there is an object buffer return function then use it to
135  // return ownership of the buffer.
136  if (Layer.ReturnObjectBuffer && ObjBuffer)
137  Layer.ReturnObjectBuffer(std::move(ObjBuffer));
138  }
139 
140  JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
141 
143  for (auto &P : Layer.Plugins)
144  P->notifyMaterializing(*MR, G, *this,
145  ObjBuffer ? ObjBuffer->getMemBufferRef()
146  : MemoryBufferRef());
147  }
148 
149  void notifyFailed(Error Err) override {
150  for (auto &P : Layer.Plugins)
151  Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
152  Layer.getExecutionSession().reportError(std::move(Err));
153  MR->failMaterialization();
154  }
155 
156  void lookup(const LookupMap &Symbols,
157  std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
158 
159  JITDylibSearchOrder LinkOrder;
160  MR->getTargetJITDylib().withLinkOrderDo(
161  [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
162 
163  auto &ES = Layer.getExecutionSession();
164 
165  SymbolLookupSet LookupSet;
166  for (auto &KV : Symbols) {
167  orc::SymbolLookupFlags LookupFlags;
168  switch (KV.second) {
171  break;
174  break;
175  }
176  LookupSet.add(ES.intern(KV.first), LookupFlags);
177  }
178 
179  // OnResolve -- De-intern the symbols and pass the result to the linker.
180  auto OnResolve = [LookupContinuation =
181  std::move(LC)](Expected<SymbolMap> Result) mutable {
182  if (!Result)
183  LookupContinuation->run(Result.takeError());
184  else {
186  for (auto &KV : *Result)
187  LR[*KV.first] = KV.second;
188  LookupContinuation->run(std::move(LR));
189  }
190  };
191 
192  for (auto &KV : InternalNamedSymbolDeps) {
193  SymbolDependenceMap InternalDeps;
194  InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second);
195  MR->addDependencies(KV.first, InternalDeps);
196  }
197 
198  ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),
199  SymbolState::Resolved, std::move(OnResolve),
200  [this](const SymbolDependenceMap &Deps) {
201  registerDependencies(Deps);
202  });
203  }
204 
206  auto &ES = Layer.getExecutionSession();
207 
208  SymbolFlagsMap ExtraSymbolsToClaim;
209  bool AutoClaim = Layer.AutoClaimObjectSymbols;
210 
211  SymbolMap InternedResult;
212  for (auto *Sym : G.defined_symbols())
213  if (Sym->hasName() && Sym->getScope() != Scope::Local) {
214  auto InternedName = ES.intern(Sym->getName());
215  JITSymbolFlags Flags;
216 
217  if (Sym->isCallable())
218  Flags |= JITSymbolFlags::Callable;
219  if (Sym->getScope() == Scope::Default)
220  Flags |= JITSymbolFlags::Exported;
221  if (Sym->getLinkage() == Linkage::Weak)
222  Flags |= JITSymbolFlags::Weak;
223 
224  InternedResult[InternedName] =
225  JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
226  if (AutoClaim && !MR->getSymbols().count(InternedName)) {
227  assert(!ExtraSymbolsToClaim.count(InternedName) &&
228  "Duplicate symbol to claim?");
229  ExtraSymbolsToClaim[InternedName] = Flags;
230  }
231  }
232 
233  for (auto *Sym : G.absolute_symbols())
234  if (Sym->hasName() && Sym->getScope() != Scope::Local) {
235  auto InternedName = ES.intern(Sym->getName());
236  JITSymbolFlags Flags;
237  if (Sym->isCallable())
238  Flags |= JITSymbolFlags::Callable;
239  if (Sym->getScope() == Scope::Default)
240  Flags |= JITSymbolFlags::Exported;
241  if (Sym->getLinkage() == Linkage::Weak)
242  Flags |= JITSymbolFlags::Weak;
243  InternedResult[InternedName] =
244  JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
245  if (AutoClaim && !MR->getSymbols().count(InternedName)) {
246  assert(!ExtraSymbolsToClaim.count(InternedName) &&
247  "Duplicate symbol to claim?");
248  ExtraSymbolsToClaim[InternedName] = Flags;
249  }
250  }
251 
252  if (!ExtraSymbolsToClaim.empty())
253  if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
254  return Err;
255 
256  {
257 
258  // Check that InternedResult matches up with MR->getSymbols(), overriding
259  // flags if requested.
260  // This guards against faulty transformations / compilers / object caches.
261 
262  // First check that there aren't any missing symbols.
263  size_t NumMaterializationSideEffectsOnlySymbols = 0;
264  SymbolNameVector ExtraSymbols;
265  SymbolNameVector MissingSymbols;
266  for (auto &KV : MR->getSymbols()) {
267 
268  auto I = InternedResult.find(KV.first);
269 
270  // If this is a materialization-side-effects only symbol then bump
271  // the counter and make sure it's *not* defined, otherwise make
272  // sure that it is defined.
273  if (KV.second.hasMaterializationSideEffectsOnly()) {
274  ++NumMaterializationSideEffectsOnlySymbols;
275  if (I != InternedResult.end())
276  ExtraSymbols.push_back(KV.first);
277  continue;
278  } else if (I == InternedResult.end())
279  MissingSymbols.push_back(KV.first);
280  else if (Layer.OverrideObjectFlags)
281  I->second.setFlags(KV.second);
282  }
283 
284  // If there were missing symbols then report the error.
285  if (!MissingSymbols.empty())
286  return make_error<MissingSymbolDefinitions>(
287  Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
288  std::move(MissingSymbols));
289 
290  // If there are more definitions than expected, add them to the
291  // ExtraSymbols vector.
292  if (InternedResult.size() >
293  MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
294  for (auto &KV : InternedResult)
295  if (!MR->getSymbols().count(KV.first))
296  ExtraSymbols.push_back(KV.first);
297  }
298 
299  // If there were extra definitions then report the error.
300  if (!ExtraSymbols.empty())
301  return make_error<UnexpectedSymbolDefinitions>(
302  Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
303  std::move(ExtraSymbols));
304  }
305 
306  if (auto Err = MR->notifyResolved(InternedResult))
307  return Err;
308 
309  Layer.notifyLoaded(*MR);
310  return Error::success();
311  }
312 
314  if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) {
315  Layer.getExecutionSession().reportError(std::move(Err));
316  MR->failMaterialization();
317  return;
318  }
319  if (auto Err = MR->notifyEmitted()) {
320  Layer.getExecutionSession().reportError(std::move(Err));
321  MR->failMaterialization();
322  }
323  }
324 
325  LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
326  return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
327  }
328 
330  // Add passes to mark duplicate defs as should-discard, and to walk the
331  // link graph to build the symbol dependence graph.
332  Config.PrePrunePasses.push_back([this](LinkGraph &G) {
333  return claimOrExternalizeWeakAndCommonSymbols(G);
334  });
335 
336  Layer.modifyPassConfig(*MR, LG, Config);
337 
338  Config.PostPrunePasses.push_back(
339  [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
340 
341  return Error::success();
342  }
343 
344 private:
345  // Symbol name dependencies:
346  // Internal: Defined in this graph.
347  // External: Defined externally.
348  struct BlockSymbolDependencies {
349  SymbolNameSet Internal, External;
350  };
351 
352  // Lazily populated map of blocks to BlockSymbolDependencies values.
353  class BlockDependenciesMap {
354  public:
355  BlockDependenciesMap(ExecutionSession &ES,
356  DenseMap<const Block *, DenseSet<Block *>> BlockDeps)
357  : ES(ES), BlockDeps(std::move(BlockDeps)) {}
358 
359  const BlockSymbolDependencies &operator[](const Block &B) {
360  // Check the cache first.
361  auto I = BlockTransitiveDepsCache.find(&B);
362  if (I != BlockTransitiveDepsCache.end())
363  return I->second;
364 
365  // No value. Populate the cache.
366  BlockSymbolDependencies BTDCacheVal;
367  auto BDI = BlockDeps.find(&B);
368  assert(BDI != BlockDeps.end() && "No block dependencies");
369 
370  for (auto *BDep : BDI->second) {
371  auto &BID = getBlockImmediateDeps(*BDep);
372  for (auto &ExternalDep : BID.External)
373  BTDCacheVal.External.insert(ExternalDep);
374  for (auto &InternalDep : BID.Internal)
375  BTDCacheVal.Internal.insert(InternalDep);
376  }
377 
378  return BlockTransitiveDepsCache
379  .insert(std::make_pair(&B, std::move(BTDCacheVal)))
380  .first->second;
381  }
382 
383  SymbolStringPtr &getInternedName(Symbol &Sym) {
384  auto I = NameCache.find(&Sym);
385  if (I != NameCache.end())
386  return I->second;
387 
388  return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName())))
389  .first->second;
390  }
391 
392  private:
393  BlockSymbolDependencies &getBlockImmediateDeps(Block &B) {
394  // Check the cache first.
395  auto I = BlockImmediateDepsCache.find(&B);
396  if (I != BlockImmediateDepsCache.end())
397  return I->second;
398 
399  BlockSymbolDependencies BIDCacheVal;
400  for (auto &E : B.edges()) {
401  auto &Tgt = E.getTarget();
402  if (Tgt.getScope() != Scope::Local) {
403  if (Tgt.isExternal())
404  BIDCacheVal.External.insert(getInternedName(Tgt));
405  else
406  BIDCacheVal.Internal.insert(getInternedName(Tgt));
407  }
408  }
409 
410  return BlockImmediateDepsCache
411  .insert(std::make_pair(&B, std::move(BIDCacheVal)))
412  .first->second;
413  }
414 
415  ExecutionSession &ES;
418  DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache;
419  DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache;
420  };
421 
422  Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
423  auto &ES = Layer.getExecutionSession();
424 
425  SymbolFlagsMap NewSymbolsToClaim;
426  std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
427 
428  auto ProcessSymbol = [&](Symbol *Sym) {
429  if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&
430  Sym->getScope() != Scope::Local) {
431  auto Name = ES.intern(Sym->getName());
432  if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {
434  if (Sym->getScope() == Scope::Default)
436  NewSymbolsToClaim[Name] = SF;
437  NameToSym.push_back(std::make_pair(std::move(Name), Sym));
438  }
439  }
440  };
441 
442  for (auto *Sym : G.defined_symbols())
443  ProcessSymbol(Sym);
444  for (auto *Sym : G.absolute_symbols())
445  ProcessSymbol(Sym);
446 
447  // Attempt to claim all weak defs that we're not already responsible for.
448  // This cannot fail -- any clashes will just result in rejection of our
449  // claim, at which point we'll externalize that symbol.
450  cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim)));
451 
452  // Walk the list of symbols that we just tried to claim. Symbols that we're
453  // responsible for are marked live. Symbols that we're not responsible for
454  // are turned into external references.
455  for (auto &KV : NameToSym) {
456  if (MR->getSymbols().count(KV.first))
457  KV.second->setLive(true);
458  else
459  G.makeExternal(*KV.second);
460  }
461 
462  return Error::success();
463  }
464 
465  Error markResponsibilitySymbolsLive(LinkGraph &G) const {
466  auto &ES = Layer.getExecutionSession();
467  for (auto *Sym : G.defined_symbols())
468  if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName())))
469  Sym->setLive(true);
470  return Error::success();
471  }
472 
473  Error computeNamedSymbolDependencies(LinkGraph &G) {
474  auto &ES = MR->getTargetJITDylib().getExecutionSession();
475  auto BlockDeps = computeBlockNonLocalDeps(G);
476 
477  // Compute dependencies for symbols defined in the JITLink graph.
478  for (auto *Sym : G.defined_symbols()) {
479 
480  // Skip local symbols: we do not track dependencies for these.
481  if (Sym->getScope() == Scope::Local)
482  continue;
483  assert(Sym->hasName() &&
484  "Defined non-local jitlink::Symbol should have a name");
485 
486  auto &SymDeps = BlockDeps[Sym->getBlock()];
487  if (SymDeps.External.empty() && SymDeps.Internal.empty())
488  continue;
489 
490  auto SymName = ES.intern(Sym->getName());
491  if (!SymDeps.External.empty())
492  ExternalNamedSymbolDeps[SymName] = SymDeps.External;
493  if (!SymDeps.Internal.empty())
494  InternalNamedSymbolDeps[SymName] = SymDeps.Internal;
495  }
496 
497  for (auto &P : Layer.Plugins) {
498  auto SynthDeps = P->getSyntheticSymbolDependencies(*MR);
499  if (SynthDeps.empty())
500  continue;
501 
502  DenseSet<Block *> BlockVisited;
503  for (auto &KV : SynthDeps) {
504  auto &Name = KV.first;
505  auto &DepsForName = KV.second;
506  for (auto *Sym : DepsForName) {
507  if (Sym->getScope() == Scope::Local) {
508  auto &BDeps = BlockDeps[Sym->getBlock()];
509  for (auto &S : BDeps.Internal)
510  InternalNamedSymbolDeps[Name].insert(S);
511  for (auto &S : BDeps.External)
512  ExternalNamedSymbolDeps[Name].insert(S);
513  } else {
514  if (Sym->isExternal())
515  ExternalNamedSymbolDeps[Name].insert(
516  BlockDeps.getInternedName(*Sym));
517  else
518  InternalNamedSymbolDeps[Name].insert(
519  BlockDeps.getInternedName(*Sym));
520  }
521  }
522  }
523  }
524 
525  return Error::success();
526  }
527 
528  BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) {
529  // First calculate the reachable-via-non-local-symbol blocks for each block.
530  struct BlockInfo {
531  DenseSet<Block *> Dependencies;
532  DenseSet<Block *> Dependants;
533  bool DependenciesChanged = true;
534  };
535  DenseMap<Block *, BlockInfo> BlockInfos;
536  SmallVector<Block *> WorkList;
537 
538  // Pre-allocate map entries. This prevents any iterator/reference
539  // invalidation in the next loop.
540  for (auto *B : G.blocks())
541  (void)BlockInfos[B];
542 
543  // Build initial worklist, record block dependencies/dependants and
544  // non-local symbol dependencies.
545  for (auto *B : G.blocks()) {
546  auto &BI = BlockInfos[B];
547  for (auto &E : B->edges()) {
548  if (E.getTarget().getScope() == Scope::Local &&
549  !E.getTarget().isAbsolute()) {
550  auto &TgtB = E.getTarget().getBlock();
551  if (&TgtB != B) {
552  BI.Dependencies.insert(&TgtB);
553  BlockInfos[&TgtB].Dependants.insert(B);
554  }
555  }
556  }
557 
558  // If this node has both dependants and dependencies then add it to the
559  // worklist to propagate the dependencies to the dependants.
560  if (!BI.Dependants.empty() && !BI.Dependencies.empty())
561  WorkList.push_back(B);
562  }
563 
564  // Propagate block-level dependencies through the block-dependence graph.
565  while (!WorkList.empty()) {
566  auto *B = WorkList.pop_back_val();
567 
568  auto &BI = BlockInfos[B];
569  assert(BI.DependenciesChanged &&
570  "Block in worklist has unchanged dependencies");
571  BI.DependenciesChanged = false;
572  for (auto *Dependant : BI.Dependants) {
573  auto &DependantBI = BlockInfos[Dependant];
574  for (auto *Dependency : BI.Dependencies) {
575  if (Dependant != Dependency &&
576  DependantBI.Dependencies.insert(Dependency).second)
577  if (!DependantBI.DependenciesChanged) {
578  DependantBI.DependenciesChanged = true;
579  WorkList.push_back(Dependant);
580  }
581  }
582  }
583  }
584 
586  for (auto &KV : BlockInfos)
587  BlockDeps[KV.first] = std::move(KV.second.Dependencies);
588 
589  return BlockDependenciesMap(Layer.getExecutionSession(),
590  std::move(BlockDeps));
591  }
592 
593  void registerDependencies(const SymbolDependenceMap &QueryDeps) {
594  for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) {
595  auto &Name = NamedDepsEntry.first;
596  auto &NameDeps = NamedDepsEntry.second;
597  SymbolDependenceMap SymbolDeps;
598 
599  for (const auto &QueryDepsEntry : QueryDeps) {
600  JITDylib &SourceJD = *QueryDepsEntry.first;
601  const SymbolNameSet &Symbols = QueryDepsEntry.second;
602  auto &DepsForJD = SymbolDeps[&SourceJD];
603 
604  for (const auto &S : Symbols)
605  if (NameDeps.count(S))
606  DepsForJD.insert(S);
607 
608  if (DepsForJD.empty())
609  SymbolDeps.erase(&SourceJD);
610  }
611 
612  MR->addDependencies(Name, SymbolDeps);
613  }
614  }
615 
616  ObjectLinkingLayer &Layer;
617  std::unique_ptr<MaterializationResponsibility> MR;
618  std::unique_ptr<MemoryBuffer> ObjBuffer;
619  DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps;
620  DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps;
621 };
622 
623 ObjectLinkingLayer::Plugin::~Plugin() = default;
624 
626 
628 
629 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES)
630  : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
631  ES.registerResourceManager(*this);
632 }
633 
635  JITLinkMemoryManager &MemMgr)
636  : BaseT(ES), MemMgr(MemMgr) {
637  ES.registerResourceManager(*this);
638 }
639 
641  ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
642  : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
643  ES.registerResourceManager(*this);
644 }
645 
647  assert(Allocs.empty() && "Layer destroyed with resources still attached");
648  getExecutionSession().deregisterResourceManager(*this);
649 }
650 
652  std::unique_ptr<LinkGraph> G) {
653  auto &JD = RT->getJITDylib();
654  return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)),
655  std::move(RT));
656 }
657 
658 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
659  std::unique_ptr<MemoryBuffer> O) {
660  assert(O && "Object must not be null");
661  MemoryBufferRef ObjBuffer = O->getMemBufferRef();
662 
663  auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
664  *this, std::move(R), std::move(O));
665  if (auto G = createLinkGraphFromObject(ObjBuffer)) {
666  Ctx->notifyMaterializing(**G);
667  link(std::move(*G), std::move(Ctx));
668  } else {
669  Ctx->notifyFailed(G.takeError());
670  }
671 }
672 
673 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
674  std::unique_ptr<LinkGraph> G) {
675  auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
676  *this, std::move(R), nullptr);
677  Ctx->notifyMaterializing(*G);
678  link(std::move(G), std::move(Ctx));
679 }
680 
681 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
682  LinkGraph &G,
683  PassConfiguration &PassConfig) {
684  for (auto &P : Plugins)
685  P->modifyPassConfig(MR, G, PassConfig);
686 }
687 
688 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
689  for (auto &P : Plugins)
690  P->notifyLoaded(MR);
691 }
692 
693 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
694  FinalizedAlloc FA) {
695  Error Err = Error::success();
696  for (auto &P : Plugins)
697  Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
698 
699  if (Err)
700  return Err;
701 
702  return MR.withResourceKeyDo(
703  [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
704 }
705 
706 Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
707 
708  {
709  Error Err = Error::success();
710  for (auto &P : Plugins)
711  Err = joinErrors(std::move(Err), P->notifyRemovingResources(K));
712  if (Err)
713  return Err;
714  }
715 
716  std::vector<FinalizedAlloc> AllocsToRemove;
717  getExecutionSession().runSessionLocked([&] {
718  auto I = Allocs.find(K);
719  if (I != Allocs.end()) {
720  std::swap(AllocsToRemove, I->second);
721  Allocs.erase(I);
722  }
723  });
724 
725  if (AllocsToRemove.empty())
726  return Error::success();
727 
728  return MemMgr.deallocate(std::move(AllocsToRemove));
729 }
730 
731 void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
732  ResourceKey SrcKey) {
733  auto I = Allocs.find(SrcKey);
734  if (I != Allocs.end()) {
735  auto &SrcAllocs = I->second;
736  auto &DstAllocs = Allocs[DstKey];
737  DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
738  for (auto &Alloc : SrcAllocs)
739  DstAllocs.push_back(std::move(Alloc));
740 
741  // Erase SrcKey entry using value rather than iterator I: I may have been
742  // invalidated when we looked up DstKey.
743  Allocs.erase(SrcKey);
744  }
745 
746  for (auto &P : Plugins)
747  P->notifyTransferringResources(DstKey, SrcKey);
748 }
749 
751  ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
752  : ES(ES), Registrar(std::move(Registrar)) {}
753 
756  PassConfiguration &PassConfig) {
757 
758  PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
759  G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
760  if (Addr) {
761  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
762  assert(!InProcessLinks.count(&MR) &&
763  "Link for MR already being tracked?");
764  InProcessLinks[&MR] = {Addr, Size};
765  }
766  }));
767 }
768 
769 Error EHFrameRegistrationPlugin::notifyEmitted(
771 
772  ExecutorAddrRange EmittedRange;
773  {
774  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
775 
776  auto EHFrameRangeItr = InProcessLinks.find(&MR);
777  if (EHFrameRangeItr == InProcessLinks.end())
778  return Error::success();
779 
780  EmittedRange = EHFrameRangeItr->second;
781  assert(EmittedRange.Start && "eh-frame addr to register can not be null");
782  InProcessLinks.erase(EHFrameRangeItr);
783  }
784 
785  if (auto Err = MR.withResourceKeyDo(
786  [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
787  return Err;
788 
789  return Registrar->registerEHFrames(EmittedRange);
790 }
791 
792 Error EHFrameRegistrationPlugin::notifyFailed(
794  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
795  InProcessLinks.erase(&MR);
796  return Error::success();
797 }
798 
799 Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) {
800  std::vector<ExecutorAddrRange> RangesToRemove;
801 
802  ES.runSessionLocked([&] {
803  auto I = EHFrameRanges.find(K);
804  if (I != EHFrameRanges.end()) {
805  RangesToRemove = std::move(I->second);
806  EHFrameRanges.erase(I);
807  }
808  });
809 
810  Error Err = Error::success();
811  while (!RangesToRemove.empty()) {
812  auto RangeToRemove = RangesToRemove.back();
813  RangesToRemove.pop_back();
814  assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
815  Err = joinErrors(std::move(Err),
816  Registrar->deregisterEHFrames(RangeToRemove));
817  }
818 
819  return Err;
820 }
821 
822 void EHFrameRegistrationPlugin::notifyTransferringResources(
823  ResourceKey DstKey, ResourceKey SrcKey) {
824  auto SI = EHFrameRanges.find(SrcKey);
825  if (SI == EHFrameRanges.end())
826  return;
827 
828  auto DI = EHFrameRanges.find(DstKey);
829  if (DI != EHFrameRanges.end()) {
830  auto &SrcRanges = SI->second;
831  auto &DstRanges = DI->second;
832  DstRanges.reserve(DstRanges.size() + SrcRanges.size());
833  for (auto &SrcRange : SrcRanges)
834  DstRanges.push_back(std::move(SrcRange));
835  EHFrameRanges.erase(SI);
836  } else {
837  // We need to move SrcKey's ranges over without invalidating the SI
838  // iterator.
839  auto Tmp = std::move(SI->second);
840  EHFrameRanges.erase(SI);
841  EHFrameRanges[DstKey] = std::move(Tmp);
842  }
843 }
844 
845 } // End namespace orc.
846 } // End namespace llvm.
llvm::orc::ExecutorAddr
Represents an address in the executor process.
Definition: ExecutorAddress.h:31
llvm::orc::ResourceKey
uintptr_t ResourceKey
Definition: Core.h:50
MemoryBuffer.h
llvm::orc::ObjectLinkingLayer::emit
void emit(std::unique_ptr< MaterializationResponsibility > R, std::unique_ptr< MemoryBuffer > O) override
Emit an object file.
Definition: ObjectLinkingLayer.cpp:658
llvm::orc::MaterializationResponsibility
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:519
llvm::AArch64CC::LO
@ LO
Definition: AArch64BaseInfo.h:258
getName
static StringRef getName(Value *V)
Definition: ProvenanceAnalysisEvaluator.cpp:20
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::orc::JITDylib
Represents a JIT'd dynamic library.
Definition: Core.h:953
llvm::orc::EHFrameRegistrationPlugin::EHFrameRegistrationPlugin
EHFrameRegistrationPlugin(ExecutionSession &ES, std::unique_ptr< jitlink::EHFrameRegistrar > Registrar)
Definition: ObjectLinkingLayer.cpp:750
Optional.h
llvm::AArch64PACKey::ID
ID
Definition: AArch64BaseInfo.h:818
llvm::orc::ObjectLinkingLayerJITLinkContext::ObjectLinkingLayerJITLinkContext
ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer, std::unique_ptr< MaterializationResponsibility > MR, std::unique_ptr< MemoryBuffer > ObjBuffer)
Definition: ObjectLinkingLayer.cpp:126
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:629
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::orc::SymbolLookupSet
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Definition: Core.h:175
llvm::orc::SymbolStringPtr
Pointer to a pooled string representing a symbol name.
Definition: SymbolStringPool.h:57
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
llvm::DenseMapBase::erase
bool erase(const KeyT &Val)
Definition: DenseMap.h:302
llvm::orc::ObjectLinkingLayerJITLinkContext::~ObjectLinkingLayerJITLinkContext
~ObjectLinkingLayerJITLinkContext()
Definition: ObjectLinkingLayer.cpp:133
llvm::orc::ExecutionSession::registerResourceManager
void registerResourceManager(ResourceManager &RM)
Register the given ResourceManager with this ExecutionSession.
Definition: Core.cpp:1914
llvm::DenseMapBase::count
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:145
llvm::orc::EHFrameRegistrationPlugin::modifyPassConfig
void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::PassConfiguration &PassConfig) override
Definition: ObjectLinkingLayer.cpp:754
llvm::orc::ObjectLinkingLayerJITLinkContext::getMarkLivePass
LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override
Returns the mark-live pass to be used for this link.
Definition: ObjectLinkingLayer.cpp:325
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::orc::ObjectLinkingLayer::~ObjectLinkingLayer
~ObjectLinkingLayer()
Destruct an ObjectLinkingLayer.
Definition: ObjectLinkingLayer.cpp:646
llvm::JITSymbolFlags
Flags for symbols in the JIT.
Definition: JITSymbol.h:74
llvm::MemoryBufferRef
Definition: MemoryBufferRef.h:22
llvm::orc::MaterializationUnit
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Definition: Core.h:665
llvm::orc::ObjectLinkingLayer::add
Error add(ResourceTrackerSP, std::unique_ptr< jitlink::LinkGraph > G)
Add a LinkGraph to the JITDylib targeted by the given tracker.
llvm::JITEvaluatedSymbol
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:229
llvm::orc::ObjectLinkingLayerJITLinkContext::notifyResolved
Error notifyResolved(LinkGraph &G) override
Called by JITLink once all defined symbols in the graph have been assigned their final memory locatio...
Definition: ObjectLinkingLayer.cpp:205
EHFrameSupport.h
llvm::orc::SymbolLookupFlags
SymbolLookupFlags
Lookup flags that apply to each symbol in a lookup.
Definition: Core.h:137
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::orc
Definition: COFFPlatform.h:30
SI
@ SI
Definition: SIInstrInfo.cpp:7966
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::orc::ExecutionSession::intern
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:1416
llvm::orc::ExecutionSession::runSessionLocked
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
Definition: Core.h:1426
llvm::orc::SymbolLookupSet::add
SymbolLookupSet & add(SymbolStringPtr Name, SymbolLookupFlags Flags=SymbolLookupFlags::RequiredSymbol)
Add an element to the set.
Definition: Core.h:236
llvm::orc::ObjectLinkingLayerJITLinkContext::modifyPassConfig
Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override
Called by JITLink to modify the pass pipeline prior to linking.
Definition: ObjectLinkingLayer.cpp:329
llvm::orc::ExecutorAddrRange
Represents an address range in the exceutor process.
Definition: ExecutorAddress.h:191
llvm::RTTIExtends< ObjectLinkingLayer, ObjectLayer >
llvm::orc::SymbolLookupFlags::WeaklyReferencedSymbol
@ WeaklyReferencedSymbol
llvm::orc::ObjectLinkingLayerJITLinkContext::notifyMaterializing
void notifyMaterializing(LinkGraph &G)
Definition: ObjectLinkingLayer.cpp:142
llvm::orc::MaterializationResponsibility::withResourceKeyDo
Error withResourceKeyDo(Func &&F) const
Returns the ResourceTracker for this instance.
Definition: Core.h:1779
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
llvm::DenseSet< SymbolStringPtr >
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:264
llvm::orc::ObjectLinkingLayerJITLinkContext::lookup
void lookup(const LookupMap &Symbols, std::unique_ptr< JITLinkAsyncLookupContinuation > LC) override
Called by JITLink to resolve external symbols.
Definition: ObjectLinkingLayer.cpp:156
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:79
llvm::orc::ObjectLinkingLayerJITLinkContext::getMemoryManager
JITLinkMemoryManager & getMemoryManager() override
Return the MemoryManager to be used for this link.
Definition: ObjectLinkingLayer.cpp:140
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::DenseMap
Definition: DenseMap.h:714
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::JITSymbolFlags::Callable
@ Callable
Definition: JITSymbol.h:86
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:426
llvm::orc::ObjectLinkingLayer::ObjectLinkingLayer
ObjectLinkingLayer(ExecutionSession &ES)
Construct an ObjectLinkingLayer using the ExecutorProcessControl instance's memory manager.
Definition: ObjectLinkingLayer.cpp:629
llvm::orc::ResourceTrackerSP
uint8_t IntrusiveRefCntPtr< ResourceTracker > ResourceTrackerSP
Definition: Core.h:47
llvm::DenseMapBase::find
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1861
llvm::orc::ObjectLinkingLayerJITLinkContext::notifyFinalized
void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override
Called by JITLink to notify the context that the object has been finalized (i.e.
Definition: ObjectLinkingLayer.cpp:313
DebugObjectManagerPlugin.h
llvm::orc::JITDylibSearchOrder
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
Definition: Core.h:154
llvm::orc::ExecutorAddrRange::Start
ExecutorAddr Start
Definition: ExecutorAddress.h:214
llvm::DenseMapBase::empty
bool empty() const
Definition: DenseMap.h:98
llvm::JITSymbolFlags::Weak
@ Weak
Definition: JITSymbol.h:82
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::Reloc::Static
@ Static
Definition: CodeGen.h:22
llvm::cantFail
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:744
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::DenseMapBase< DenseMap< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::insert
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:207
llvm::orc::ObjectLinkingLayer
An ObjectLayer implementation built on JITLink.
Definition: ObjectLinkingLayer.h:50
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
std
Definition: BitVector.h:851
llvm::DenseMapBase::end
iterator end()
Definition: DenseMap.h:84
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::orc::ExecutionSession
An ExecutionSession represents a running JIT program.
Definition: Core.h:1365
llvm::DenseMapBase::size
unsigned size() const
Definition: DenseMap.h:99
llvm::SmallVectorImpl::pop_back_val
T pop_back_val()
Definition: SmallVector.h:677
llvm::orc::ObjectLinkingLayerJITLinkContext
Definition: ObjectLinkingLayer.cpp:124
ObjectLinkingLayer.h
llvm::orc::SymbolLookupFlags::RequiredSymbol
@ RequiredSymbol
llvm::orc::SymbolNameVector
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
Definition: Core.h:109
llvm::JITSymbolFlags::Exported
@ Exported
Definition: JITSymbol.h:85
llvm::orc::ObjectLinkingLayerJITLinkContext::notifyFailed
void notifyFailed(Error Err) override
Notify this context that linking failed.
Definition: ObjectLinkingLayer.cpp:149