LLVM  15.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,__obj_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  if (Sec.getName() == ".init_array")
83  return true;
84  return false;
85  }
86 
87  static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) {
88  std::string InitSymString;
89  raw_string_ostream(InitSymString)
90  << "$." << G.getName() << ".__inits" << Counter++;
91  return ES.intern(InitSymString);
92  }
93 
94  LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer,
95  std::unique_ptr<LinkGraph> G, Interface LGI)
96  : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer),
97  G(std::move(G)) {}
98 
99  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
100  for (auto *Sym : G->defined_symbols())
101  if (Sym->getName() == *Name) {
102  assert(Sym->getLinkage() == Linkage::Weak &&
103  "Discarding non-weak definition");
104  G->makeExternal(*Sym);
105  break;
106  }
107  }
108 
109  ObjectLinkingLayer &ObjLinkingLayer;
110  std::unique_ptr<LinkGraph> G;
111  static std::atomic<uint64_t> Counter;
112 };
113 
114 std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};
115 
116 } // end anonymous namespace
117 
118 namespace llvm {
119 namespace orc {
120 
122 public:
124  ObjectLinkingLayer &Layer,
125  std::unique_ptr<MaterializationResponsibility> MR,
126  std::unique_ptr<MemoryBuffer> ObjBuffer)
127  : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),
128  MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
129 
131  // If there is an object buffer return function then use it to
132  // return ownership of the buffer.
133  if (Layer.ReturnObjectBuffer && ObjBuffer)
134  Layer.ReturnObjectBuffer(std::move(ObjBuffer));
135  }
136 
137  JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
138 
140  for (auto &P : Layer.Plugins)
141  P->notifyMaterializing(*MR, G, *this,
142  ObjBuffer ? ObjBuffer->getMemBufferRef()
143  : MemoryBufferRef());
144  }
145 
146  void notifyFailed(Error Err) override {
147  for (auto &P : Layer.Plugins)
148  Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
149  Layer.getExecutionSession().reportError(std::move(Err));
150  MR->failMaterialization();
151  }
152 
153  void lookup(const LookupMap &Symbols,
154  std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
155 
156  JITDylibSearchOrder LinkOrder;
157  MR->getTargetJITDylib().withLinkOrderDo(
158  [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
159 
160  auto &ES = Layer.getExecutionSession();
161 
162  SymbolLookupSet LookupSet;
163  for (auto &KV : Symbols) {
164  orc::SymbolLookupFlags LookupFlags;
165  switch (KV.second) {
168  break;
171  break;
172  }
173  LookupSet.add(ES.intern(KV.first), LookupFlags);
174  }
175 
176  // OnResolve -- De-intern the symbols and pass the result to the linker.
177  auto OnResolve = [LookupContinuation =
178  std::move(LC)](Expected<SymbolMap> Result) mutable {
179  if (!Result)
180  LookupContinuation->run(Result.takeError());
181  else {
183  for (auto &KV : *Result)
184  LR[*KV.first] = KV.second;
185  LookupContinuation->run(std::move(LR));
186  }
187  };
188 
189  for (auto &KV : InternalNamedSymbolDeps) {
190  SymbolDependenceMap InternalDeps;
191  InternalDeps[&MR->getTargetJITDylib()] = std::move(KV.second);
192  MR->addDependencies(KV.first, InternalDeps);
193  }
194 
195  ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),
196  SymbolState::Resolved, std::move(OnResolve),
197  [this](const SymbolDependenceMap &Deps) {
198  registerDependencies(Deps);
199  });
200  }
201 
203  auto &ES = Layer.getExecutionSession();
204 
205  SymbolFlagsMap ExtraSymbolsToClaim;
206  bool AutoClaim = Layer.AutoClaimObjectSymbols;
207 
208  SymbolMap InternedResult;
209  for (auto *Sym : G.defined_symbols())
210  if (Sym->hasName() && Sym->getScope() != Scope::Local) {
211  auto InternedName = ES.intern(Sym->getName());
212  JITSymbolFlags Flags;
213 
214  if (Sym->isCallable())
215  Flags |= JITSymbolFlags::Callable;
216  if (Sym->getScope() == Scope::Default)
217  Flags |= JITSymbolFlags::Exported;
218 
219  InternedResult[InternedName] =
220  JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
221  if (AutoClaim && !MR->getSymbols().count(InternedName)) {
222  assert(!ExtraSymbolsToClaim.count(InternedName) &&
223  "Duplicate symbol to claim?");
224  ExtraSymbolsToClaim[InternedName] = Flags;
225  }
226  }
227 
228  for (auto *Sym : G.absolute_symbols())
229  if (Sym->hasName() && Sym->getScope() != Scope::Local) {
230  auto InternedName = ES.intern(Sym->getName());
231  JITSymbolFlags Flags;
232  if (Sym->isCallable())
233  Flags |= JITSymbolFlags::Callable;
234  if (Sym->getScope() == Scope::Default)
235  Flags |= JITSymbolFlags::Exported;
236  if (Sym->getLinkage() == Linkage::Weak)
237  Flags |= JITSymbolFlags::Weak;
238  InternedResult[InternedName] =
239  JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
240  if (AutoClaim && !MR->getSymbols().count(InternedName)) {
241  assert(!ExtraSymbolsToClaim.count(InternedName) &&
242  "Duplicate symbol to claim?");
243  ExtraSymbolsToClaim[InternedName] = Flags;
244  }
245  }
246 
247  if (!ExtraSymbolsToClaim.empty())
248  if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
249  return Err;
250 
251  {
252 
253  // Check that InternedResult matches up with MR->getSymbols(), overriding
254  // flags if requested.
255  // This guards against faulty transformations / compilers / object caches.
256 
257  // First check that there aren't any missing symbols.
258  size_t NumMaterializationSideEffectsOnlySymbols = 0;
259  SymbolNameVector ExtraSymbols;
260  SymbolNameVector MissingSymbols;
261  for (auto &KV : MR->getSymbols()) {
262 
263  auto I = InternedResult.find(KV.first);
264 
265  // If this is a materialization-side-effects only symbol then bump
266  // the counter and make sure it's *not* defined, otherwise make
267  // sure that it is defined.
268  if (KV.second.hasMaterializationSideEffectsOnly()) {
269  ++NumMaterializationSideEffectsOnlySymbols;
270  if (I != InternedResult.end())
271  ExtraSymbols.push_back(KV.first);
272  continue;
273  } else if (I == InternedResult.end())
274  MissingSymbols.push_back(KV.first);
275  else if (Layer.OverrideObjectFlags)
276  I->second.setFlags(KV.second);
277  }
278 
279  // If there were missing symbols then report the error.
280  if (!MissingSymbols.empty())
281  return make_error<MissingSymbolDefinitions>(
282  Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
283  std::move(MissingSymbols));
284 
285  // If there are more definitions than expected, add them to the
286  // ExtraSymbols vector.
287  if (InternedResult.size() >
288  MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
289  for (auto &KV : InternedResult)
290  if (!MR->getSymbols().count(KV.first))
291  ExtraSymbols.push_back(KV.first);
292  }
293 
294  // If there were extra definitions then report the error.
295  if (!ExtraSymbols.empty())
296  return make_error<UnexpectedSymbolDefinitions>(
297  Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
298  std::move(ExtraSymbols));
299  }
300 
301  if (auto Err = MR->notifyResolved(InternedResult))
302  return Err;
303 
304  Layer.notifyLoaded(*MR);
305  return Error::success();
306  }
307 
309  if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) {
310  Layer.getExecutionSession().reportError(std::move(Err));
311  MR->failMaterialization();
312  return;
313  }
314  if (auto Err = MR->notifyEmitted()) {
315  Layer.getExecutionSession().reportError(std::move(Err));
316  MR->failMaterialization();
317  }
318  }
319 
320  LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
321  return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
322  }
323 
325  // Add passes to mark duplicate defs as should-discard, and to walk the
326  // link graph to build the symbol dependence graph.
327  Config.PrePrunePasses.push_back([this](LinkGraph &G) {
328  return claimOrExternalizeWeakAndCommonSymbols(G);
329  });
330 
331  Layer.modifyPassConfig(*MR, LG, Config);
332 
333  Config.PostPrunePasses.push_back(
334  [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
335 
336  return Error::success();
337  }
338 
339 private:
340  // Symbol name dependencies:
341  // Internal: Defined in this graph.
342  // External: Defined externally.
343  struct BlockSymbolDependencies {
344  SymbolNameSet Internal, External;
345  };
346 
347  // Lazily populated map of blocks to BlockSymbolDependencies values.
348  class BlockDependenciesMap {
349  public:
350  BlockDependenciesMap(ExecutionSession &ES,
351  DenseMap<const Block *, DenseSet<Block *>> BlockDeps)
352  : ES(ES), BlockDeps(std::move(BlockDeps)) {}
353 
354  const BlockSymbolDependencies &operator[](const Block &B) {
355  // Check the cache first.
356  auto I = BlockTransitiveDepsCache.find(&B);
357  if (I != BlockTransitiveDepsCache.end())
358  return I->second;
359 
360  // No value. Populate the cache.
361  BlockSymbolDependencies BTDCacheVal;
362  auto BDI = BlockDeps.find(&B);
363  assert(BDI != BlockDeps.end() && "No block dependencies");
364 
365  for (auto *BDep : BDI->second) {
366  auto &BID = getBlockImmediateDeps(*BDep);
367  for (auto &ExternalDep : BID.External)
368  BTDCacheVal.External.insert(ExternalDep);
369  for (auto &InternalDep : BID.Internal)
370  BTDCacheVal.Internal.insert(InternalDep);
371  }
372 
373  return BlockTransitiveDepsCache
374  .insert(std::make_pair(&B, std::move(BTDCacheVal)))
375  .first->second;
376  }
377 
378  SymbolStringPtr &getInternedName(Symbol &Sym) {
379  auto I = NameCache.find(&Sym);
380  if (I != NameCache.end())
381  return I->second;
382 
383  return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName())))
384  .first->second;
385  }
386 
387  private:
388  BlockSymbolDependencies &getBlockImmediateDeps(Block &B) {
389  // Check the cache first.
390  auto I = BlockImmediateDepsCache.find(&B);
391  if (I != BlockImmediateDepsCache.end())
392  return I->second;
393 
394  BlockSymbolDependencies BIDCacheVal;
395  for (auto &E : B.edges()) {
396  auto &Tgt = E.getTarget();
397  if (Tgt.getScope() != Scope::Local) {
398  if (Tgt.isExternal())
399  BIDCacheVal.External.insert(getInternedName(Tgt));
400  else
401  BIDCacheVal.Internal.insert(getInternedName(Tgt));
402  }
403  }
404 
405  return BlockImmediateDepsCache
406  .insert(std::make_pair(&B, std::move(BIDCacheVal)))
407  .first->second;
408  }
409 
410  ExecutionSession &ES;
413  DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache;
414  DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache;
415  };
416 
417  Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
418  auto &ES = Layer.getExecutionSession();
419 
420  SymbolFlagsMap NewSymbolsToClaim;
421  std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
422 
423  auto ProcessSymbol = [&](Symbol *Sym) {
424  if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&
425  Sym->getScope() != Scope::Local) {
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 
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() = default;
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  if (AllocsToRemove.empty())
714  return Error::success();
715 
716  return MemMgr.deallocate(std::move(AllocsToRemove));
717 }
718 
719 void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
720  ResourceKey SrcKey) {
721  auto I = Allocs.find(SrcKey);
722  if (I != Allocs.end()) {
723  auto &SrcAllocs = I->second;
724  auto &DstAllocs = Allocs[DstKey];
725  DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
726  for (auto &Alloc : SrcAllocs)
727  DstAllocs.push_back(std::move(Alloc));
728 
729  // Erase SrcKey entry using value rather than iterator I: I may have been
730  // invalidated when we looked up DstKey.
731  Allocs.erase(SrcKey);
732  }
733 
734  for (auto &P : Plugins)
735  P->notifyTransferringResources(DstKey, SrcKey);
736 }
737 
739  ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
740  : ES(ES), Registrar(std::move(Registrar)) {}
741 
744  PassConfiguration &PassConfig) {
745 
746  PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
747  G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
748  if (Addr) {
749  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
750  assert(!InProcessLinks.count(&MR) &&
751  "Link for MR already being tracked?");
752  InProcessLinks[&MR] = {Addr, Size};
753  }
754  }));
755 }
756 
757 Error EHFrameRegistrationPlugin::notifyEmitted(
759 
760  ExecutorAddrRange EmittedRange;
761  {
762  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
763 
764  auto EHFrameRangeItr = InProcessLinks.find(&MR);
765  if (EHFrameRangeItr == InProcessLinks.end())
766  return Error::success();
767 
768  EmittedRange = EHFrameRangeItr->second;
769  assert(EmittedRange.Start && "eh-frame addr to register can not be null");
770  InProcessLinks.erase(EHFrameRangeItr);
771  }
772 
773  if (auto Err = MR.withResourceKeyDo(
774  [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
775  return Err;
776 
777  return Registrar->registerEHFrames(EmittedRange);
778 }
779 
780 Error EHFrameRegistrationPlugin::notifyFailed(
782  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
783  InProcessLinks.erase(&MR);
784  return Error::success();
785 }
786 
787 Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) {
788  std::vector<ExecutorAddrRange> RangesToRemove;
789 
790  ES.runSessionLocked([&] {
791  auto I = EHFrameRanges.find(K);
792  if (I != EHFrameRanges.end()) {
793  RangesToRemove = std::move(I->second);
794  EHFrameRanges.erase(I);
795  }
796  });
797 
798  Error Err = Error::success();
799  while (!RangesToRemove.empty()) {
800  auto RangeToRemove = RangesToRemove.back();
801  RangesToRemove.pop_back();
802  assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
803  Err = joinErrors(std::move(Err),
804  Registrar->deregisterEHFrames(RangeToRemove));
805  }
806 
807  return Err;
808 }
809 
810 void EHFrameRegistrationPlugin::notifyTransferringResources(
811  ResourceKey DstKey, ResourceKey SrcKey) {
812  auto SI = EHFrameRanges.find(SrcKey);
813  if (SI == EHFrameRanges.end())
814  return;
815 
816  auto DI = EHFrameRanges.find(DstKey);
817  if (DI != EHFrameRanges.end()) {
818  auto &SrcRanges = SI->second;
819  auto &DstRanges = DI->second;
820  DstRanges.reserve(DstRanges.size() + SrcRanges.size());
821  for (auto &SrcRange : SrcRanges)
822  DstRanges.push_back(std::move(SrcRange));
823  EHFrameRanges.erase(SI);
824  } else {
825  // We need to move SrcKey's ranges over without invalidating the SI
826  // iterator.
827  auto Tmp = std::move(SI->second);
828  EHFrameRanges.erase(SI);
829  EHFrameRanges[DstKey] = std::move(Tmp);
830  }
831 }
832 
833 } // End namespace orc.
834 } // End namespace llvm.
llvm::orc::ExecutorAddr
Represents an address in the executor process.
Definition: ExecutorAddress.h:30
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:523
llvm::AArch64CC::LO
@ LO
Definition: AArch64BaseInfo.h:258
getName
static StringRef getName(Value *V)
Definition: ProvenanceAnalysisEvaluator.cpp:42
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::orc::JITDylib
Represents a JIT'd dynamic library.
Definition: Core.h:950
llvm::orc::EHFrameRegistrationPlugin::EHFrameRegistrationPlugin
EHFrameRegistrationPlugin(ExecutionSession &ES, std::unique_ptr< jitlink::EHFrameRegistrar > Registrar)
Definition: ObjectLinkingLayer.cpp:738
Optional.h
llvm::orc::ObjectLinkingLayerJITLinkContext::ObjectLinkingLayerJITLinkContext
ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer, std::unique_ptr< MaterializationResponsibility > MR, std::unique_ptr< MemoryBuffer > ObjBuffer)
Definition: ObjectLinkingLayer.cpp:123
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:632
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
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: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:304
llvm::orc::ObjectLinkingLayerJITLinkContext::~ObjectLinkingLayerJITLinkContext
~ObjectLinkingLayerJITLinkContext()
Definition: ObjectLinkingLayer.cpp:130
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:147
llvm::orc::EHFrameRegistrationPlugin::modifyPassConfig
void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::PassConfiguration &PassConfig) override
Definition: ObjectLinkingLayer.cpp:742
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:320
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::SmallVectorImpl::pop_back_val
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:654
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::orc::MaterializationUnit
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
Definition: Core.h:669
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:202
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:54
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:1413
llvm::orc::ExecutionSession::runSessionLocked
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
Definition: Core.h:1423
llvm::SPIRV::BuiltIn::Layer
@ Layer
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:324
llvm::orc::ExecutorAddrRange
Represents an address range in the exceutor process.
Definition: ExecutorAddress.h:148
llvm::RTTIExtends< ObjectLinkingLayer, ObjectLayer >
llvm::orc::SymbolLookupFlags::WeaklyReferencedSymbol
@ WeaklyReferencedSymbol
llvm::orc::ObjectLinkingLayerJITLinkContext::notifyMaterializing
void notifyMaterializing(LinkGraph &G)
Definition: ObjectLinkingLayer.cpp:139
llvm::orc::MaterializationResponsibility::withResourceKeyDo
Error withResourceKeyDo(Func &&F) const
Returns the ResourceTracker for this instance.
Definition: Core.h:1776
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
llvm::DenseSet< SymbolStringPtr >
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:239
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:153
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:78
llvm::orc::ObjectLinkingLayerJITLinkContext::getMemoryManager
JITLinkMemoryManager & getMemoryManager() override
Return the MemoryManager to be used for this link.
Definition: ObjectLinkingLayer.cpp:137
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:716
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:617
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:152
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:1665
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:308
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:171
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:745
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:209
llvm::orc::ObjectLinkingLayer
An ObjectLayer implementation built on JITLink.
Definition: ObjectLinkingLayer.h:50
llvm::DenseMapBase::empty
LLVM_NODISCARD bool empty() const
Definition: DenseMap.h:98
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:1362
llvm::DenseMapBase::size
unsigned size() const
Definition: DenseMap.h:101
llvm::orc::ObjectLinkingLayerJITLinkContext
Definition: ObjectLinkingLayer.cpp:121
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:146