LLVM  10.0.0svn
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 
11 #include "llvm/ADT/Optional.h"
13 
14 #include <vector>
15 
16 #define DEBUG_TYPE "orc"
17 
18 using namespace llvm;
19 using namespace llvm::jitlink;
20 using namespace llvm::orc;
21 
22 namespace llvm {
23 namespace orc {
24 
26 public:
29  std::unique_ptr<MemoryBuffer> ObjBuffer)
30  : Layer(Layer), MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
31 
33  // If there is an object buffer return function then use it to
34  // return ownership of the buffer.
35  if (Layer.ReturnObjectBuffer)
36  Layer.ReturnObjectBuffer(std::move(ObjBuffer));
37  }
38 
39  JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
40 
41  MemoryBufferRef getObjectBuffer() const override {
42  return ObjBuffer->getMemBufferRef();
43  }
44 
45  void notifyFailed(Error Err) override {
46  Layer.getExecutionSession().reportError(std::move(Err));
47  MR.failMaterialization();
48  }
49 
50  void lookup(const DenseSet<StringRef> &Symbols,
51  std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
52 
53  JITDylibSearchList SearchOrder;
54  MR.getTargetJITDylib().withSearchOrderDo(
55  [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
56 
57  auto &ES = Layer.getExecutionSession();
58 
59  SymbolNameSet InternedSymbols;
60  for (auto &S : Symbols)
61  InternedSymbols.insert(ES.intern(S));
62 
63  // OnResolve -- De-intern the symbols and pass the result to the linker.
64  auto OnResolve = [this, LookupContinuation = std::move(LC)](
65  Expected<SymbolMap> Result) mutable {
66  auto Main = Layer.getExecutionSession().intern("_main");
67  if (!Result)
68  LookupContinuation->run(Result.takeError());
69  else {
71  for (auto &KV : *Result)
72  LR[*KV.first] = KV.second;
73  LookupContinuation->run(std::move(LR));
74  }
75  };
76 
77  ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved,
78  std::move(OnResolve), [this](const SymbolDependenceMap &Deps) {
79  registerDependencies(Deps);
80  });
81  }
82 
83  void notifyResolved(LinkGraph &G) override {
84  auto &ES = Layer.getExecutionSession();
85 
86  SymbolFlagsMap ExtraSymbolsToClaim;
87  bool AutoClaim = Layer.AutoClaimObjectSymbols;
88 
89  SymbolMap InternedResult;
90  for (auto *Sym : G.defined_symbols())
91  if (Sym->hasName() && Sym->getScope() != Scope::Local) {
92  auto InternedName = ES.intern(Sym->getName());
93  JITSymbolFlags Flags;
94 
95  if (Sym->isCallable())
96  Flags |= JITSymbolFlags::Callable;
97  if (Sym->getScope() == Scope::Default)
98  Flags |= JITSymbolFlags::Exported;
99 
100  InternedResult[InternedName] =
101  JITEvaluatedSymbol(Sym->getAddress(), Flags);
102  if (AutoClaim && !MR.getSymbols().count(InternedName)) {
103  assert(!ExtraSymbolsToClaim.count(InternedName) &&
104  "Duplicate symbol to claim?");
105  ExtraSymbolsToClaim[InternedName] = Flags;
106  }
107  }
108 
109  for (auto *Sym : G.absolute_symbols())
110  if (Sym->hasName()) {
111  auto InternedName = ES.intern(Sym->getName());
112  JITSymbolFlags Flags;
113  Flags |= JITSymbolFlags::Absolute;
114  if (Sym->isCallable())
115  Flags |= JITSymbolFlags::Callable;
116  if (Sym->getLinkage() == Linkage::Weak)
117  Flags |= JITSymbolFlags::Weak;
118  InternedResult[InternedName] =
119  JITEvaluatedSymbol(Sym->getAddress(), Flags);
120  if (AutoClaim && !MR.getSymbols().count(InternedName)) {
121  assert(!ExtraSymbolsToClaim.count(InternedName) &&
122  "Duplicate symbol to claim?");
123  ExtraSymbolsToClaim[InternedName] = Flags;
124  }
125  }
126 
127  if (!ExtraSymbolsToClaim.empty())
128  if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
129  return notifyFailed(std::move(Err));
130  if (auto Err = MR.notifyResolved(InternedResult)) {
131  Layer.getExecutionSession().reportError(std::move(Err));
132  MR.failMaterialization();
133  return;
134  }
135  Layer.notifyLoaded(MR);
136  }
137 
139  std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
140  if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
141  Layer.getExecutionSession().reportError(std::move(Err));
142  MR.failMaterialization();
143  return;
144  }
145  if (auto Err = MR.notifyEmitted()) {
146  Layer.getExecutionSession().reportError(std::move(Err));
147  MR.failMaterialization();
148  }
149  }
150 
152  return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
153  }
154 
155  Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override {
156  // Add passes to mark duplicate defs as should-discard, and to walk the
157  // link graph to build the symbol dependence graph.
158  Config.PrePrunePasses.push_back(
159  [this](LinkGraph &G) { return externalizeWeakAndCommonSymbols(G); });
160  Config.PostPrunePasses.push_back(
161  [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
162 
163  Layer.modifyPassConfig(MR, TT, Config);
164 
165  return Error::success();
166  }
167 
168 private:
170 
171  Error externalizeWeakAndCommonSymbols(LinkGraph &G) {
172  auto &ES = Layer.getExecutionSession();
173  for (auto *Sym : G.defined_symbols())
174  if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
175  if (!MR.getSymbols().count(ES.intern(Sym->getName())))
176  G.makeExternal(*Sym);
177  }
178 
179  for (auto *Sym : G.absolute_symbols())
180  if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
181  if (!MR.getSymbols().count(ES.intern(Sym->getName())))
182  G.makeExternal(*Sym);
183  }
184 
185  return Error::success();
186  }
187 
188  Error markResponsibilitySymbolsLive(LinkGraph &G) const {
189  auto &ES = Layer.getExecutionSession();
190  for (auto *Sym : G.defined_symbols())
191  if (Sym->hasName() && MR.getSymbols().count(ES.intern(Sym->getName())))
192  Sym->setLive(true);
193  return Error::success();
194  }
195 
196  Error computeNamedSymbolDependencies(LinkGraph &G) {
197  auto &ES = MR.getTargetJITDylib().getExecutionSession();
198  auto AnonDeps = computeAnonDeps(G);
199 
200  for (auto *Sym : G.defined_symbols()) {
201 
202  // Skip anonymous and non-global atoms: we do not need dependencies for
203  // these.
204  if (Sym->getScope() == Scope::Local)
205  continue;
206 
207  auto SymName = ES.intern(Sym->getName());
208  SymbolNameSet &SymDeps = NamedSymbolDeps[SymName];
209 
210  for (auto &E : Sym->getBlock().edges()) {
211  auto &TargetSym = E.getTarget();
212 
213  if (TargetSym.getScope() != Scope::Local)
214  SymDeps.insert(ES.intern(TargetSym.getName()));
215  else {
216  assert(TargetSym.isDefined() &&
217  "Anonymous/local symbols must be defined");
218  auto I = AnonDeps.find(&TargetSym);
219  if (I != AnonDeps.end())
220  for (auto &S : I->second)
221  SymDeps.insert(S);
222  }
223  }
224  }
225 
226  return Error::success();
227  }
228 
229  AnonToNamedDependenciesMap computeAnonDeps(LinkGraph &G) {
230 
231  auto &ES = MR.getTargetJITDylib().getExecutionSession();
233 
234  // For all anonymous symbols:
235  // (1) Add their named dependencies.
236  // (2) Add them to the worklist for further iteration if they have any
237  // depend on any other anonymous symbols.
238  struct WorklistEntry {
239  WorklistEntry(Symbol *Sym, DenseSet<Symbol *> SymAnonDeps)
240  : Sym(Sym), SymAnonDeps(std::move(SymAnonDeps)) {}
241 
242  Symbol *Sym = nullptr;
243  DenseSet<Symbol *> SymAnonDeps;
244  };
245  std::vector<WorklistEntry> Worklist;
246  for (auto *Sym : G.defined_symbols())
247  if (!Sym->hasName()) {
248  auto &SymNamedDeps = DepMap[Sym];
249  DenseSet<Symbol *> SymAnonDeps;
250 
251  for (auto &E : Sym->getBlock().edges()) {
252  auto &TargetSym = E.getTarget();
253  if (TargetSym.hasName())
254  SymNamedDeps.insert(ES.intern(TargetSym.getName()));
255  else {
256  assert(TargetSym.isDefined() &&
257  "Anonymous symbols must be defined");
258  SymAnonDeps.insert(&TargetSym);
259  }
260  }
261 
262  if (!SymAnonDeps.empty())
263  Worklist.push_back(WorklistEntry(Sym, std::move(SymAnonDeps)));
264  }
265 
266  // Loop over all anonymous symbols with anonymous dependencies, propagating
267  // their respective *named* dependencies. Iterate until we hit a stable
268  // state.
269  bool Changed;
270  do {
271  Changed = false;
272  for (auto &WLEntry : Worklist) {
273  auto *Sym = WLEntry.Sym;
274  auto &SymNamedDeps = DepMap[Sym];
275  auto &SymAnonDeps = WLEntry.SymAnonDeps;
276 
277  for (auto *TargetSym : SymAnonDeps) {
278  auto I = DepMap.find(TargetSym);
279  if (I != DepMap.end())
280  for (const auto &S : I->second)
281  Changed |= SymNamedDeps.insert(S).second;
282  }
283  }
284  } while (Changed);
285 
286  return DepMap;
287  }
288 
289  void registerDependencies(const SymbolDependenceMap &QueryDeps) {
290  for (auto &NamedDepsEntry : NamedSymbolDeps) {
291  auto &Name = NamedDepsEntry.first;
292  auto &NameDeps = NamedDepsEntry.second;
293  SymbolDependenceMap SymbolDeps;
294 
295  for (const auto &QueryDepsEntry : QueryDeps) {
296  JITDylib &SourceJD = *QueryDepsEntry.first;
297  const SymbolNameSet &Symbols = QueryDepsEntry.second;
298  auto &DepsForJD = SymbolDeps[&SourceJD];
299 
300  for (const auto &S : Symbols)
301  if (NameDeps.count(S))
302  DepsForJD.insert(S);
303 
304  if (DepsForJD.empty())
305  SymbolDeps.erase(&SourceJD);
306  }
307 
308  MR.addDependencies(Name, SymbolDeps);
309  }
310  }
311 
312  ObjectLinkingLayer &Layer;
314  std::unique_ptr<MemoryBuffer> ObjBuffer;
316 };
317 
318 ObjectLinkingLayer::Plugin::~Plugin() {}
319 
320 ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
321  JITLinkMemoryManager &MemMgr)
322  : ObjectLayer(ES), MemMgr(MemMgr) {}
323 
325  if (auto Err = removeAllModules())
326  getExecutionSession().reportError(std::move(Err));
327 }
328 
330  std::unique_ptr<MemoryBuffer> O) {
331  assert(O && "Object must not be null");
332  jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
333  *this, std::move(R), std::move(O)));
334 }
335 
336 void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
337  const Triple &TT,
338  PassConfiguration &PassConfig) {
339  for (auto &P : Plugins)
340  P->modifyPassConfig(MR, TT, PassConfig);
341 }
342 
343 void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
344  for (auto &P : Plugins)
345  P->notifyLoaded(MR);
346 }
347 
348 Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
349  AllocPtr Alloc) {
350  Error Err = Error::success();
351  for (auto &P : Plugins)
352  Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
353 
354  if (Err)
355  return Err;
356 
357  {
358  std::lock_guard<std::mutex> Lock(LayerMutex);
359  UntrackedAllocs.push_back(std::move(Alloc));
360  }
361 
362  return Error::success();
363 }
364 
365 Error ObjectLinkingLayer::removeModule(VModuleKey K) {
366  Error Err = Error::success();
367 
368  for (auto &P : Plugins)
369  Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
370 
371  AllocPtr Alloc;
372 
373  {
374  std::lock_guard<std::mutex> Lock(LayerMutex);
375  auto AllocItr = TrackedAllocs.find(K);
376  Alloc = std::move(AllocItr->second);
377  TrackedAllocs.erase(AllocItr);
378  }
379 
380  assert(Alloc && "No allocation for key K");
381 
382  return joinErrors(std::move(Err), Alloc->deallocate());
383 }
384 
385 Error ObjectLinkingLayer::removeAllModules() {
386 
387  Error Err = Error::success();
388 
389  for (auto &P : Plugins)
390  Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
391 
392  std::vector<AllocPtr> Allocs;
393  {
394  std::lock_guard<std::mutex> Lock(LayerMutex);
395  Allocs = std::move(UntrackedAllocs);
396 
397  for (auto &KV : TrackedAllocs)
398  Allocs.push_back(std::move(KV.second));
399 
400  TrackedAllocs.clear();
401  }
402 
403  while (!Allocs.empty()) {
404  Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
405  Allocs.pop_back();
406  }
407 
408  return Err;
409 }
410 
412  EHFrameRegistrar &Registrar)
413  : Registrar(Registrar) {}
414 
416  MaterializationResponsibility &MR, const Triple &TT,
417  PassConfiguration &PassConfig) {
418  assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
419 
420  PassConfig.PostFixupPasses.push_back(
421  createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr,
422  size_t Size) {
423  if (Addr)
424  InProcessLinks[&MR] = { Addr, Size };
425  }));
426 }
427 
430 
431  auto EHFrameRangeItr = InProcessLinks.find(&MR);
432  if (EHFrameRangeItr == InProcessLinks.end())
433  return Error::success();
434 
435  auto EHFrameRange = EHFrameRangeItr->second;
436  assert(EHFrameRange.Addr &&
437  "eh-frame addr to register can not be null");
438 
439  InProcessLinks.erase(EHFrameRangeItr);
440  if (auto Key = MR.getVModuleKey())
441  TrackedEHFrameRanges[Key] = EHFrameRange;
442  else
443  UntrackedEHFrameRanges.push_back(EHFrameRange);
444 
445  return Registrar.registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
446 }
447 
449  auto EHFrameRangeItr = TrackedEHFrameRanges.find(K);
450  if (EHFrameRangeItr == TrackedEHFrameRanges.end())
451  return Error::success();
452 
453  auto EHFrameRange = EHFrameRangeItr->second;
454  assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null");
455 
456  TrackedEHFrameRanges.erase(EHFrameRangeItr);
457 
458  return Registrar.deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
459 }
460 
462 
463  std::vector<EHFrameRange> EHFrameRanges =
464  std::move(UntrackedEHFrameRanges);
465  EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size());
466 
467  for (auto &KV : TrackedEHFrameRanges)
468  EHFrameRanges.push_back(KV.second);
469 
470  TrackedEHFrameRanges.clear();
471 
472  Error Err = Error::success();
473 
474  while (!EHFrameRanges.empty()) {
475  auto EHFrameRange = EHFrameRanges.back();
476  assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null");
477  EHFrameRanges.pop_back();
478  Err = joinErrors(std::move(Err),
479  Registrar.deregisterEHFrames(EHFrameRange.Addr,
480  EHFrameRange.Size));
481  }
482 
483  return Err;
484 }
485 
486 } // End namespace orc.
487 } // End namespace llvm.
void notifyResolved(LinkGraph &G) override
Called by JITLink once all defined symbols in the graph have been assigned their final memory locatio...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
Implements a dense probed hash-table based set.
Definition: DenseSet.h:249
static sys::Mutex Lock
EHFrameRegistrationPlugin(jitlink::EHFrameRegistrar &Registrar)
void notifyFailed(Error Err) override
Notify this context that linking failed.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: DenseMap.h:195
Definition: BitVector.h:937
void lookup(const DenseSet< StringRef > &Symbols, std::unique_ptr< JITLinkAsyncLookupContinuation > LC) override
Called by JITLink to resolve external symbols.
std::vector< std::pair< JITDylib *, bool > > JITDylibSearchList
A list of (JITDylib*, bool) pairs.
Definition: Core.h:59
An ObjectLayer implementation built on JITLink.
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, jitlink::PassConfiguration &PassConfig) override
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:171
Key
PAL metadata keys.
ExecutionSession & getExecutionSession()
Returns the execution session for this layer.
Definition: Layer.h:119
uint64_t JITTargetAddress
Represents an address in the target process&#39;s address space.
Definition: JITSymbol.h:41
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
#define P(N)
bool erase(const KeyT &Val)
Definition: DenseMap.h:272
VModuleKey getVModuleKey() const
Returns the VModuleKey for this instance.
Definition: Core.h:188
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:187
Flags for symbols in the JIT.
Definition: JITSymbol.h:56
unsigned size() const
Definition: DenseMap.h:99
Error notifyRemovingModule(VModuleKey K) override
LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override
Returns the mark-live pass to be used for this link.
~ObjectLinkingLayer()
Destruct an ObjectLinkingLayer.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:43
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
void notifyFinalized(std::unique_ptr< JITLinkMemoryManager::Allocation > A) override
Called by JITLink to notify the context that the object has been finalized (i.e.
MemoryBufferRef getObjectBuffer() const override
Returns a StringRef for the object buffer.
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
Error notifyEmitted(MaterializationResponsibility &MR) override
An ExecutionSession represents a running JIT program.
Definition: Core.h:761
ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer, MaterializationResponsibility MR, std::unique_ptr< MemoryBuffer > ObjBuffer)
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:190
uint8_t uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:42
void reportError(Error Err)
Report a error for this execution session.
Definition: Core.h:826
Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override
Called by JITLink to modify the pass pipeline prior to linking.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:423
#define I(x, y, z)
Definition: MD5.cpp:58
void emit(MaterializationResponsibility R, std::unique_ptr< MemoryBuffer > O) override
Emit the object.
iterator end()
Definition: DenseMap.h:82
uint32_t Size
Definition: Profile.cpp:46
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_NODISCARD bool empty() const
Definition: DenseMap.h:96
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition: DenseMap.h:185
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
Interface for Layers that accept object files.
Definition: Layer.h:113
JITLinkMemoryManager & getMemoryManager() override
Return the MemoryManager to be used for this link.
A symbol table that supports asynchoronous symbol queries.
Definition: Core.h:495