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  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 
222  InternedResult[InternedName] =
223  JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
224  if (AutoClaim && !MR->getSymbols().count(InternedName)) {
225  assert(!ExtraSymbolsToClaim.count(InternedName) &&
226  "Duplicate symbol to claim?");
227  ExtraSymbolsToClaim[InternedName] = Flags;
228  }
229  }
230 
231  for (auto *Sym : G.absolute_symbols())
232  if (Sym->hasName() && Sym->getScope() != Scope::Local) {
233  auto InternedName = ES.intern(Sym->getName());
234  JITSymbolFlags Flags;
235  if (Sym->isCallable())
236  Flags |= JITSymbolFlags::Callable;
237  if (Sym->getScope() == Scope::Default)
238  Flags |= JITSymbolFlags::Exported;
239  if (Sym->getLinkage() == Linkage::Weak)
240  Flags |= JITSymbolFlags::Weak;
241  InternedResult[InternedName] =
242  JITEvaluatedSymbol(Sym->getAddress().getValue(), Flags);
243  if (AutoClaim && !MR->getSymbols().count(InternedName)) {
244  assert(!ExtraSymbolsToClaim.count(InternedName) &&
245  "Duplicate symbol to claim?");
246  ExtraSymbolsToClaim[InternedName] = Flags;
247  }
248  }
249 
250  if (!ExtraSymbolsToClaim.empty())
251  if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
252  return Err;
253 
254  {
255 
256  // Check that InternedResult matches up with MR->getSymbols(), overriding
257  // flags if requested.
258  // This guards against faulty transformations / compilers / object caches.
259 
260  // First check that there aren't any missing symbols.
261  size_t NumMaterializationSideEffectsOnlySymbols = 0;
262  SymbolNameVector ExtraSymbols;
263  SymbolNameVector MissingSymbols;
264  for (auto &KV : MR->getSymbols()) {
265 
266  auto I = InternedResult.find(KV.first);
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 (I != InternedResult.end())
274  ExtraSymbols.push_back(KV.first);
275  continue;
276  } else if (I == InternedResult.end())
277  MissingSymbols.push_back(KV.first);
278  else if (Layer.OverrideObjectFlags)
279  I->second.setFlags(KV.second);
280  }
281 
282  // If there were missing symbols then report the error.
283  if (!MissingSymbols.empty())
284  return make_error<MissingSymbolDefinitions>(
285  Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
286  std::move(MissingSymbols));
287 
288  // If there are more definitions than expected, add them to the
289  // ExtraSymbols vector.
290  if (InternedResult.size() >
291  MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
292  for (auto &KV : InternedResult)
293  if (!MR->getSymbols().count(KV.first))
294  ExtraSymbols.push_back(KV.first);
295  }
296 
297  // If there were extra definitions then report the error.
298  if (!ExtraSymbols.empty())
299  return make_error<UnexpectedSymbolDefinitions>(
300  Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
301  std::move(ExtraSymbols));
302  }
303 
304  if (auto Err = MR->notifyResolved(InternedResult))
305  return Err;
306 
307  Layer.notifyLoaded(*MR);
308  return Error::success();
309  }
310 
312  if (auto Err = Layer.notifyEmitted(*MR, std::move(A))) {
313  Layer.getExecutionSession().reportError(std::move(Err));
314  MR->failMaterialization();
315  return;
316  }
317  if (auto Err = MR->notifyEmitted()) {
318  Layer.getExecutionSession().reportError(std::move(Err));
319  MR->failMaterialization();
320  }
321  }
322 
323  LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
324  return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
325  }
326 
328  // Add passes to mark duplicate defs as should-discard, and to walk the
329  // link graph to build the symbol dependence graph.
330  Config.PrePrunePasses.push_back([this](LinkGraph &G) {
331  return claimOrExternalizeWeakAndCommonSymbols(G);
332  });
333 
334  Layer.modifyPassConfig(*MR, LG, Config);
335 
336  Config.PostPrunePasses.push_back(
337  [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
338 
339  return Error::success();
340  }
341 
342 private:
343  // Symbol name dependencies:
344  // Internal: Defined in this graph.
345  // External: Defined externally.
346  struct BlockSymbolDependencies {
347  SymbolNameSet Internal, External;
348  };
349 
350  // Lazily populated map of blocks to BlockSymbolDependencies values.
351  class BlockDependenciesMap {
352  public:
353  BlockDependenciesMap(ExecutionSession &ES,
354  DenseMap<const Block *, DenseSet<Block *>> BlockDeps)
355  : ES(ES), BlockDeps(std::move(BlockDeps)) {}
356 
357  const BlockSymbolDependencies &operator[](const Block &B) {
358  // Check the cache first.
359  auto I = BlockTransitiveDepsCache.find(&B);
360  if (I != BlockTransitiveDepsCache.end())
361  return I->second;
362 
363  // No value. Populate the cache.
364  BlockSymbolDependencies BTDCacheVal;
365  auto BDI = BlockDeps.find(&B);
366  assert(BDI != BlockDeps.end() && "No block dependencies");
367 
368  for (auto *BDep : BDI->second) {
369  auto &BID = getBlockImmediateDeps(*BDep);
370  for (auto &ExternalDep : BID.External)
371  BTDCacheVal.External.insert(ExternalDep);
372  for (auto &InternalDep : BID.Internal)
373  BTDCacheVal.Internal.insert(InternalDep);
374  }
375 
376  return BlockTransitiveDepsCache
377  .insert(std::make_pair(&B, std::move(BTDCacheVal)))
378  .first->second;
379  }
380 
381  SymbolStringPtr &getInternedName(Symbol &Sym) {
382  auto I = NameCache.find(&Sym);
383  if (I != NameCache.end())
384  return I->second;
385 
386  return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName())))
387  .first->second;
388  }
389 
390  private:
391  BlockSymbolDependencies &getBlockImmediateDeps(Block &B) {
392  // Check the cache first.
393  auto I = BlockImmediateDepsCache.find(&B);
394  if (I != BlockImmediateDepsCache.end())
395  return I->second;
396 
397  BlockSymbolDependencies BIDCacheVal;
398  for (auto &E : B.edges()) {
399  auto &Tgt = E.getTarget();
400  if (Tgt.getScope() != Scope::Local) {
401  if (Tgt.isExternal())
402  BIDCacheVal.External.insert(getInternedName(Tgt));
403  else
404  BIDCacheVal.Internal.insert(getInternedName(Tgt));
405  }
406  }
407 
408  return BlockImmediateDepsCache
409  .insert(std::make_pair(&B, std::move(BIDCacheVal)))
410  .first->second;
411  }
412 
413  ExecutionSession &ES;
416  DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache;
417  DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache;
418  };
419 
420  Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
421  auto &ES = Layer.getExecutionSession();
422 
423  SymbolFlagsMap NewSymbolsToClaim;
424  std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
425 
426  auto ProcessSymbol = [&](Symbol *Sym) {
427  if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&
428  Sym->getScope() != Scope::Local) {
429  auto Name = ES.intern(Sym->getName());
430  if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {
432  if (Sym->getScope() == Scope::Default)
434  NewSymbolsToClaim[Name] = SF;
435  NameToSym.push_back(std::make_pair(std::move(Name), Sym));
436  }
437  }
438  };
439 
440  for (auto *Sym : G.defined_symbols())
441  ProcessSymbol(Sym);
442  for (auto *Sym : G.absolute_symbols())
443  ProcessSymbol(Sym);
444 
445  // Attempt to claim all weak defs that we're not already responsible for.
446  // This cannot fail -- any clashes will just result in rejection of our
447  // claim, at which point we'll externalize that symbol.
448  cantFail(MR->defineMaterializing(std::move(NewSymbolsToClaim)));
449 
450  for (auto &KV : NameToSym)
451  if (!MR->getSymbols().count(KV.first))
452  G.makeExternal(*KV.second);
453 
454  return Error::success();
455  }
456 
457  Error markResponsibilitySymbolsLive(LinkGraph &G) const {
458  auto &ES = Layer.getExecutionSession();
459  for (auto *Sym : G.defined_symbols())
460  if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName())))
461  Sym->setLive(true);
462  return Error::success();
463  }
464 
465  Error computeNamedSymbolDependencies(LinkGraph &G) {
466  auto &ES = MR->getTargetJITDylib().getExecutionSession();
467  auto BlockDeps = computeBlockNonLocalDeps(G);
468 
469  // Compute dependencies for symbols defined in the JITLink graph.
470  for (auto *Sym : G.defined_symbols()) {
471 
472  // Skip local symbols: we do not track dependencies for these.
473  if (Sym->getScope() == Scope::Local)
474  continue;
475  assert(Sym->hasName() &&
476  "Defined non-local jitlink::Symbol should have a name");
477 
478  auto &SymDeps = BlockDeps[Sym->getBlock()];
479  if (SymDeps.External.empty() && SymDeps.Internal.empty())
480  continue;
481 
482  auto SymName = ES.intern(Sym->getName());
483  if (!SymDeps.External.empty())
484  ExternalNamedSymbolDeps[SymName] = SymDeps.External;
485  if (!SymDeps.Internal.empty())
486  InternalNamedSymbolDeps[SymName] = SymDeps.Internal;
487  }
488 
489  for (auto &P : Layer.Plugins) {
490  auto SynthDeps = P->getSyntheticSymbolDependencies(*MR);
491  if (SynthDeps.empty())
492  continue;
493 
494  DenseSet<Block *> BlockVisited;
495  for (auto &KV : SynthDeps) {
496  auto &Name = KV.first;
497  auto &DepsForName = KV.second;
498  for (auto *Sym : DepsForName) {
499  if (Sym->getScope() == Scope::Local) {
500  auto &BDeps = BlockDeps[Sym->getBlock()];
501  for (auto &S : BDeps.Internal)
502  InternalNamedSymbolDeps[Name].insert(S);
503  for (auto &S : BDeps.External)
504  ExternalNamedSymbolDeps[Name].insert(S);
505  } else {
506  if (Sym->isExternal())
507  ExternalNamedSymbolDeps[Name].insert(
508  BlockDeps.getInternedName(*Sym));
509  else
510  InternalNamedSymbolDeps[Name].insert(
511  BlockDeps.getInternedName(*Sym));
512  }
513  }
514  }
515  }
516 
517  return Error::success();
518  }
519 
520  BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) {
521  // First calculate the reachable-via-non-local-symbol blocks for each block.
522  struct BlockInfo {
523  DenseSet<Block *> Dependencies;
524  DenseSet<Block *> Dependants;
525  bool DependenciesChanged = true;
526  };
527  DenseMap<Block *, BlockInfo> BlockInfos;
528  SmallVector<Block *> WorkList;
529 
530  // Pre-allocate map entries. This prevents any iterator/reference
531  // invalidation in the next loop.
532  for (auto *B : G.blocks())
533  (void)BlockInfos[B];
534 
535  // Build initial worklist, record block dependencies/dependants and
536  // non-local symbol dependencies.
537  for (auto *B : G.blocks()) {
538  auto &BI = BlockInfos[B];
539  for (auto &E : B->edges()) {
540  if (E.getTarget().getScope() == Scope::Local) {
541  auto &TgtB = E.getTarget().getBlock();
542  if (&TgtB != B) {
543  BI.Dependencies.insert(&TgtB);
544  BlockInfos[&TgtB].Dependants.insert(B);
545  }
546  }
547  }
548 
549  // If this node has both dependants and dependencies then add it to the
550  // worklist to propagate the dependencies to the dependants.
551  if (!BI.Dependants.empty() && !BI.Dependencies.empty())
552  WorkList.push_back(B);
553  }
554 
555  // Propagate block-level dependencies through the block-dependence graph.
556  while (!WorkList.empty()) {
557  auto *B = WorkList.pop_back_val();
558 
559  auto &BI = BlockInfos[B];
560  assert(BI.DependenciesChanged &&
561  "Block in worklist has unchanged dependencies");
562  BI.DependenciesChanged = false;
563  for (auto *Dependant : BI.Dependants) {
564  auto &DependantBI = BlockInfos[Dependant];
565  for (auto *Dependency : BI.Dependencies) {
566  if (Dependant != Dependency &&
567  DependantBI.Dependencies.insert(Dependency).second)
568  if (!DependantBI.DependenciesChanged) {
569  DependantBI.DependenciesChanged = true;
570  WorkList.push_back(Dependant);
571  }
572  }
573  }
574  }
575 
577  for (auto &KV : BlockInfos)
578  BlockDeps[KV.first] = std::move(KV.second.Dependencies);
579 
580  return BlockDependenciesMap(Layer.getExecutionSession(),
581  std::move(BlockDeps));
582  }
583 
584  void registerDependencies(const SymbolDependenceMap &QueryDeps) {
585  for (auto &NamedDepsEntry : ExternalNamedSymbolDeps) {
586  auto &Name = NamedDepsEntry.first;
587  auto &NameDeps = NamedDepsEntry.second;
588  SymbolDependenceMap SymbolDeps;
589 
590  for (const auto &QueryDepsEntry : QueryDeps) {
591  JITDylib &SourceJD = *QueryDepsEntry.first;
592  const SymbolNameSet &Symbols = QueryDepsEntry.second;
593  auto &DepsForJD = SymbolDeps[&SourceJD];
594 
595  for (const auto &S : Symbols)
596  if (NameDeps.count(S))
597  DepsForJD.insert(S);
598 
599  if (DepsForJD.empty())
600  SymbolDeps.erase(&SourceJD);
601  }
602 
603  MR->addDependencies(Name, SymbolDeps);
604  }
605  }
606 
608  std::unique_ptr<MaterializationResponsibility> MR;
609  std::unique_ptr<MemoryBuffer> ObjBuffer;
610  DenseMap<SymbolStringPtr, SymbolNameSet> ExternalNamedSymbolDeps;
611  DenseMap<SymbolStringPtr, SymbolNameSet> InternalNamedSymbolDeps;
612 };
613 
614 ObjectLinkingLayer::Plugin::~Plugin() = default;
615 
617 
619 
620 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES)
621  : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
622  ES.registerResourceManager(*this);
623 }
624 
626  JITLinkMemoryManager &MemMgr)
627  : BaseT(ES), MemMgr(MemMgr) {
628  ES.registerResourceManager(*this);
629 }
630 
632  ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
633  : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
634  ES.registerResourceManager(*this);
635 }
636 
638  assert(Allocs.empty() && "Layer destroyed with resources still attached");
639  getExecutionSession().deregisterResourceManager(*this);
640 }
641 
643  std::unique_ptr<LinkGraph> G) {
644  auto &JD = RT->getJITDylib();
645  return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)),
646  std::move(RT));
647 }
648 
649 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
650  std::unique_ptr<MemoryBuffer> O) {
651  assert(O && "Object must not be null");
652  MemoryBufferRef ObjBuffer = O->getMemBufferRef();
653 
654  auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
655  *this, std::move(R), std::move(O));
656  if (auto G = createLinkGraphFromObject(ObjBuffer)) {
657  Ctx->notifyMaterializing(**G);
658  link(std::move(*G), std::move(Ctx));
659  } else {
660  Ctx->notifyFailed(G.takeError());
661  }
662 }
663 
664 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
665  std::unique_ptr<LinkGraph> G) {
666  auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
667  *this, std::move(R), nullptr);
668  Ctx->notifyMaterializing(*G);
669  link(std::move(G), std::move(Ctx));
670 }
671 
672 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
673  LinkGraph &G,
674  PassConfiguration &PassConfig) {
675  for (auto &P : Plugins)
676  P->modifyPassConfig(MR, G, PassConfig);
677 }
678 
679 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
680  for (auto &P : Plugins)
681  P->notifyLoaded(MR);
682 }
683 
684 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
685  FinalizedAlloc FA) {
686  Error Err = Error::success();
687  for (auto &P : Plugins)
688  Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
689 
690  if (Err)
691  return Err;
692 
693  return MR.withResourceKeyDo(
694  [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
695 }
696 
697 Error ObjectLinkingLayer::handleRemoveResources(ResourceKey K) {
698 
699  {
700  Error Err = Error::success();
701  for (auto &P : Plugins)
702  Err = joinErrors(std::move(Err), P->notifyRemovingResources(K));
703  if (Err)
704  return Err;
705  }
706 
707  std::vector<FinalizedAlloc> AllocsToRemove;
708  getExecutionSession().runSessionLocked([&] {
709  auto I = Allocs.find(K);
710  if (I != Allocs.end()) {
711  std::swap(AllocsToRemove, I->second);
712  Allocs.erase(I);
713  }
714  });
715 
716  if (AllocsToRemove.empty())
717  return Error::success();
718 
719  return MemMgr.deallocate(std::move(AllocsToRemove));
720 }
721 
722 void ObjectLinkingLayer::handleTransferResources(ResourceKey DstKey,
723  ResourceKey SrcKey) {
724  auto I = Allocs.find(SrcKey);
725  if (I != Allocs.end()) {
726  auto &SrcAllocs = I->second;
727  auto &DstAllocs = Allocs[DstKey];
728  DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
729  for (auto &Alloc : SrcAllocs)
730  DstAllocs.push_back(std::move(Alloc));
731 
732  // Erase SrcKey entry using value rather than iterator I: I may have been
733  // invalidated when we looked up DstKey.
734  Allocs.erase(SrcKey);
735  }
736 
737  for (auto &P : Plugins)
738  P->notifyTransferringResources(DstKey, SrcKey);
739 }
740 
742  ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
743  : ES(ES), Registrar(std::move(Registrar)) {}
744 
747  PassConfiguration &PassConfig) {
748 
749  PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
750  G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
751  if (Addr) {
752  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
753  assert(!InProcessLinks.count(&MR) &&
754  "Link for MR already being tracked?");
755  InProcessLinks[&MR] = {Addr, Size};
756  }
757  }));
758 }
759 
760 Error EHFrameRegistrationPlugin::notifyEmitted(
762 
763  ExecutorAddrRange EmittedRange;
764  {
765  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
766 
767  auto EHFrameRangeItr = InProcessLinks.find(&MR);
768  if (EHFrameRangeItr == InProcessLinks.end())
769  return Error::success();
770 
771  EmittedRange = EHFrameRangeItr->second;
772  assert(EmittedRange.Start && "eh-frame addr to register can not be null");
773  InProcessLinks.erase(EHFrameRangeItr);
774  }
775 
776  if (auto Err = MR.withResourceKeyDo(
777  [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
778  return Err;
779 
780  return Registrar->registerEHFrames(EmittedRange);
781 }
782 
783 Error EHFrameRegistrationPlugin::notifyFailed(
785  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
786  InProcessLinks.erase(&MR);
787  return Error::success();
788 }
789 
790 Error EHFrameRegistrationPlugin::notifyRemovingResources(ResourceKey K) {
791  std::vector<ExecutorAddrRange> RangesToRemove;
792 
793  ES.runSessionLocked([&] {
794  auto I = EHFrameRanges.find(K);
795  if (I != EHFrameRanges.end()) {
796  RangesToRemove = std::move(I->second);
797  EHFrameRanges.erase(I);
798  }
799  });
800 
801  Error Err = Error::success();
802  while (!RangesToRemove.empty()) {
803  auto RangeToRemove = RangesToRemove.back();
804  RangesToRemove.pop_back();
805  assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
806  Err = joinErrors(std::move(Err),
807  Registrar->deregisterEHFrames(RangeToRemove));
808  }
809 
810  return Err;
811 }
812 
813 void EHFrameRegistrationPlugin::notifyTransferringResources(
814  ResourceKey DstKey, ResourceKey SrcKey) {
815  auto SI = EHFrameRanges.find(SrcKey);
816  if (SI == EHFrameRanges.end())
817  return;
818 
819  auto DI = EHFrameRanges.find(DstKey);
820  if (DI != EHFrameRanges.end()) {
821  auto &SrcRanges = SI->second;
822  auto &DstRanges = DI->second;
823  DstRanges.reserve(DstRanges.size() + SrcRanges.size());
824  for (auto &SrcRange : SrcRanges)
825  DstRanges.push_back(std::move(SrcRange));
826  EHFrameRanges.erase(SI);
827  } else {
828  // We need to move SrcKey's ranges over without invalidating the SI
829  // iterator.
830  auto Tmp = std::move(SI->second);
831  EHFrameRanges.erase(SI);
832  EHFrameRanges[DstKey] = std::move(Tmp);
833  }
834 }
835 
836 } // End namespace orc.
837 } // 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:649
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: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:946
llvm::orc::EHFrameRegistrationPlugin::EHFrameRegistrationPlugin
EHFrameRegistrationPlugin(ExecutionSession &ES, std::unique_ptr< jitlink::EHFrameRegistrar > Registrar)
Definition: ObjectLinkingLayer.cpp:741
Optional.h
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: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: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:304
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:147
llvm::orc::EHFrameRegistrationPlugin::modifyPassConfig
void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::PassConfiguration &PassConfig) override
Definition: ObjectLinkingLayer.cpp:745
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:323
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:637
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::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:1409
llvm::orc::ExecutionSession::runSessionLocked
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
Definition: Core.h:1419
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:327
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:142
llvm::orc::MaterializationResponsibility::withResourceKeyDo
Error withResourceKeyDo(Func &&F) const
Returns the ResourceTracker for this instance.
Definition: Core.h:1772
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
llvm::DenseSet< SymbolStringPtr >
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:240
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:78
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: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:620
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:1675
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:311
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:1358
llvm::DenseMapBase::size
unsigned size() const
Definition: DenseMap.h:101
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::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38
llvm::orc::ObjectLinkingLayerJITLinkContext::notifyFailed
void notifyFailed(Error Err) override
Notify this context that linking failed.
Definition: ObjectLinkingLayer.cpp:149