LLVM  9.0.0svn
RTDyldObjectLinkingLayer.cpp
Go to the documentation of this file.
1 //===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld 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 namespace {
12 
13 using namespace llvm;
14 using namespace llvm::orc;
15 
16 class JITDylibSearchOrderResolver : public JITSymbolResolver {
17 public:
18  JITDylibSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {}
19 
20  void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) {
21  auto &ES = MR.getTargetJITDylib().getExecutionSession();
22  SymbolNameSet InternedSymbols;
23 
24  // Intern the requested symbols: lookup takes interned strings.
25  for (auto &S : Symbols)
26  InternedSymbols.insert(ES.intern(S));
27 
28  // Build an OnResolve callback to unwrap the interned strings and pass them
29  // to the OnResolved callback.
30  // FIXME: Switch to move capture of OnResolved once we have c++14.
31  auto OnResolvedWithUnwrap =
32  [OnResolved](Expected<SymbolMap> InternedResult) {
33  if (!InternedResult) {
34  OnResolved(InternedResult.takeError());
35  return;
36  }
37 
38  LookupResult Result;
39  for (auto &KV : *InternedResult)
40  Result[*KV.first] = std::move(KV.second);
41  OnResolved(Result);
42  };
43 
44  // We're not waiting for symbols to be ready. Just log any errors.
45  auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
46 
47  // Register dependencies for all symbols contained in this set.
48  auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
49  MR.addDependenciesForAll(Deps);
50  };
51 
52  JITDylibSearchList SearchOrder;
53  MR.getTargetJITDylib().withSearchOrderDo(
54  [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
55  ES.lookup(SearchOrder, InternedSymbols, OnResolvedWithUnwrap, OnReady,
56  RegisterDependencies);
57  }
58 
59  Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) {
60  LookupSet Result;
61 
62  for (auto &KV : MR.getSymbols()) {
63  if (Symbols.count(*KV.first))
64  Result.insert(*KV.first);
65  }
66 
67  return Result;
68  }
69 
70 private:
72 };
73 
74 } // end anonymous namespace
75 
76 namespace llvm {
77 namespace orc {
78 
80  ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)
81  : ObjectLayer(ES), GetMemoryManager(GetMemoryManager) {}
82 
84  std::unique_ptr<MemoryBuffer> O) {
85  assert(O && "Object must not be null");
86 
87  // This method launches an asynchronous link step that will fulfill our
88  // materialization responsibility. We need to switch R to be heap
89  // allocated before that happens so it can live as long as the asynchronous
90  // link needs it to (i.e. it must be able to outlive this method).
91  auto SharedR = std::make_shared<MaterializationResponsibility>(std::move(R));
92 
93  auto &ES = getExecutionSession();
94 
95  // Create a MemoryBufferRef backed MemoryBuffer (i.e. shallow) copy of the
96  // the underlying buffer to pass into RuntimeDyld. This allows us to hold
97  // ownership of the real underlying buffer and return it to the user once
98  // the object has been emitted.
99  auto ObjBuffer = MemoryBuffer::getMemBuffer(O->getMemBufferRef(), false);
100 
101  auto Obj = object::ObjectFile::createObjectFile(*ObjBuffer);
102 
103  if (!Obj) {
104  getExecutionSession().reportError(Obj.takeError());
105  SharedR->failMaterialization();
106  return;
107  }
108 
109  // Collect the internal symbols from the object file: We will need to
110  // filter these later.
111  auto InternalSymbols = std::make_shared<std::set<StringRef>>();
112  {
113  for (auto &Sym : (*Obj)->symbols()) {
114  if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) {
115  if (auto SymName = Sym.getName())
116  InternalSymbols->insert(*SymName);
117  else {
118  ES.reportError(SymName.takeError());
120  return;
121  }
122  }
123  }
124  }
125 
126  auto K = R.getVModuleKey();
127  RuntimeDyld::MemoryManager *MemMgr = nullptr;
128 
129  // Create a record a memory manager for this object.
130  {
131  auto Tmp = GetMemoryManager();
132  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
133  MemMgrs.push_back(std::move(Tmp));
134  MemMgr = MemMgrs.back().get();
135  }
136 
137  JITDylibSearchOrderResolver Resolver(*SharedR);
138 
139  // FIXME: Switch to move-capture for the 'O' buffer once we have c++14.
140  MemoryBuffer *UnownedObjBuffer = O.release();
142  **Obj, std::move(O), *MemMgr, Resolver, ProcessAllSections,
143  [this, K, SharedR, &Obj, InternalSymbols](
144  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
145  std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) {
146  return onObjLoad(K, *SharedR, **Obj, std::move(LoadedObjInfo),
147  ResolvedSymbols, *InternalSymbols);
148  },
149  [this, K, SharedR, UnownedObjBuffer](Error Err) {
150  std::unique_ptr<MemoryBuffer> ObjBuffer(UnownedObjBuffer);
151  onObjEmit(K, std::move(ObjBuffer), *SharedR, std::move(Err));
152  });
153 }
154 
155 Error RTDyldObjectLinkingLayer::onObjLoad(
157  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
158  std::map<StringRef, JITEvaluatedSymbol> Resolved,
159  std::set<StringRef> &InternalSymbols) {
160  SymbolFlagsMap ExtraSymbolsToClaim;
161  SymbolMap Symbols;
162  for (auto &KV : Resolved) {
163  // Scan the symbols and add them to the Symbols map for resolution.
164 
165  // We never claim internal symbols.
166  if (InternalSymbols.count(KV.first))
167  continue;
168 
169  auto InternedName = getExecutionSession().intern(KV.first);
170  auto Flags = KV.second.getFlags();
171 
172  // Override object flags and claim responsibility for symbols if
173  // requested.
174  if (OverrideObjectFlags || AutoClaimObjectSymbols) {
175  auto I = R.getSymbols().find(InternedName);
176 
177  if (OverrideObjectFlags && I != R.getSymbols().end())
178  Flags = JITSymbolFlags::stripTransientFlags(I->second);
179  else if (AutoClaimObjectSymbols && I == R.getSymbols().end())
180  ExtraSymbolsToClaim[InternedName] = Flags;
181  }
182 
183  Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags);
184  }
185 
186  if (!ExtraSymbolsToClaim.empty())
187  if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim))
188  return Err;
189 
190  R.resolve(Symbols);
191 
192  if (NotifyLoaded)
193  NotifyLoaded(K, Obj, *LoadedObjInfo);
194 
195  return Error::success();
196 }
197 
198 void RTDyldObjectLinkingLayer::onObjEmit(
199  VModuleKey K, std::unique_ptr<MemoryBuffer> ObjBuffer,
201  if (Err) {
202  getExecutionSession().reportError(std::move(Err));
204  return;
205  }
206 
207  R.emit();
208 
209  if (NotifyEmitted)
210  NotifyEmitted(K, std::move(ObjBuffer));
211 }
212 
213 } // End namespace orc.
214 } // End namespace llvm.
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition: ObjectFile.cpp:161
void emit()
Notifies the target JITDylib (and any pending queries on that JITDylib) that all symbols covered by t...
Definition: Core.cpp:412
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Error defineMaterializing(const SymbolFlagsMap &SymbolFlags)
Adds new symbols to the JITDylib and this responsibility instance.
Definition: Core.cpp:428
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
static sys::Mutex Lock
This class is the base class for all object file types.
Definition: ObjectFile.h:226
void jitLinkForORC(object::ObjectFile &Obj, std::unique_ptr< MemoryBuffer > UnderlyingBuffer, RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver, bool ProcessAllSections, std::function< Error(std::unique_ptr< LoadedObjectInfo >, std::map< StringRef, JITEvaluatedSymbol >)> OnLoaded, std::function< void(Error)> OnEmitted)
uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:39
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:714
RTDyldObjectLinkingLayer(ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)
Construct an ObjectLinkingLayer with the given NotifyLoaded, and NotifyEmitted functors.
std::vector< std::pair< JITDylib *, bool > > JITDylibSearchList
A list of (JITDylib*, bool) pairs.
Definition: Core.h:57
Tagged union holding either a T or a Error.
Definition: CachePruning.h:22
static const uint16_t * lookup(unsigned opcode, unsigned domain, ArrayRef< uint16_t[3]> Table)
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Definition: Core.h:154
ExecutionSession & getExecutionSession()
Returns the execution session for this layer.
Definition: Layer.h:119
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:176
VModuleKey getVModuleKey() const
Returns the VModuleKey for this instance.
Definition: Core.h:171
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition: Record.h:1856
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:187
Symbol resolution interface.
Definition: JITSymbol.h:343
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
void resolve(const SymbolMap &Symbols)
Notifies the target JITDylib that the given symbols have been resolved.
Definition: Core.cpp:390
std::function< std::unique_ptr< RuntimeDyld::MemoryManager >()> GetMemoryManagerFunction
An ExecutionSession represents a running JIT program.
Definition: Core.h:696
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:41
const SymbolFlagsMap & getSymbols() const
Returns the symbol flags map for this responsibility instance.
Definition: Core.h:177
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:208
void reportError(Error Err)
Report a error for this execution session.
Definition: Core.h:761
#define I(x, y, z)
Definition: MD5.cpp:58
iterator end()
Definition: DenseMap.h:108
LLVM_NODISCARD bool empty() const
Definition: DenseMap.h:122
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void failMaterialization()
Notify all not-yet-emitted covered by this MaterializationResponsibility instance that an error has o...
Definition: Core.cpp:445
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
static JITSymbolFlags stripTransientFlags(JITSymbolFlags Orig)
Definition: JITSymbol.h:73
Interface for Layers that accept object files.
Definition: Layer.h:113
void emit(MaterializationResponsibility R, std::unique_ptr< MemoryBuffer > O) override
Emit the object.