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