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