LLVM  10.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  // Register dependencies for all symbols contained in this set.
45  auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
46  MR.addDependenciesForAll(Deps);
47  };
48 
49  JITDylibSearchList SearchOrder;
50  MR.getTargetJITDylib().withSearchOrderDo(
51  [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
52  ES.lookup(SearchOrder, InternedSymbols, SymbolState::Resolved,
53  OnResolvedWithUnwrap, RegisterDependencies);
54  }
55 
56  Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) {
57  LookupSet Result;
58 
59  for (auto &KV : MR.getSymbols()) {
60  if (Symbols.count(*KV.first))
61  Result.insert(*KV.first);
62  }
63 
64  return Result;
65  }
66 
67 private:
69 };
70 
71 } // end anonymous namespace
72 
73 namespace llvm {
74 namespace orc {
75 
77  ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager)
78  : ObjectLayer(ES), GetMemoryManager(GetMemoryManager) {}
79 
81  std::unique_ptr<MemoryBuffer> O) {
82  assert(O && "Object must not be null");
83 
84  // This method launches an asynchronous link step that will fulfill our
85  // materialization responsibility. We need to switch R to be heap
86  // allocated before that happens so it can live as long as the asynchronous
87  // link needs it to (i.e. it must be able to outlive this method).
88  auto SharedR = std::make_shared<MaterializationResponsibility>(std::move(R));
89 
90  auto &ES = getExecutionSession();
91 
92  // Create a MemoryBufferRef backed MemoryBuffer (i.e. shallow) copy of the
93  // the underlying buffer to pass into RuntimeDyld. This allows us to hold
94  // ownership of the real underlying buffer and return it to the user once
95  // the object has been emitted.
96  auto ObjBuffer = MemoryBuffer::getMemBuffer(O->getMemBufferRef(), false);
97 
98  auto Obj = object::ObjectFile::createObjectFile(*ObjBuffer);
99 
100  if (!Obj) {
101  getExecutionSession().reportError(Obj.takeError());
102  SharedR->failMaterialization();
103  return;
104  }
105 
106  // Collect the internal symbols from the object file: We will need to
107  // filter these later.
108  auto InternalSymbols = std::make_shared<std::set<StringRef>>();
109  {
110  for (auto &Sym : (*Obj)->symbols()) {
111  if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) {
112  if (auto SymName = Sym.getName())
113  InternalSymbols->insert(*SymName);
114  else {
115  ES.reportError(SymName.takeError());
117  return;
118  }
119  }
120  }
121  }
122 
123  auto K = R.getVModuleKey();
124  RuntimeDyld::MemoryManager *MemMgr = nullptr;
125 
126  // Create a record a memory manager for this object.
127  {
128  auto Tmp = GetMemoryManager();
129  std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
130  MemMgrs.push_back(std::move(Tmp));
131  MemMgr = MemMgrs.back().get();
132  }
133 
134  JITDylibSearchOrderResolver Resolver(*SharedR);
135 
136  // FIXME: Switch to move-capture for the 'O' buffer once we have c++14.
137  MemoryBuffer *UnownedObjBuffer = O.release();
139  **Obj, std::move(O), *MemMgr, Resolver, ProcessAllSections,
140  [this, K, SharedR, &Obj, InternalSymbols](
141  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
142  std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) {
143  return onObjLoad(K, *SharedR, **Obj, std::move(LoadedObjInfo),
144  ResolvedSymbols, *InternalSymbols);
145  },
146  [this, K, SharedR, UnownedObjBuffer](Error Err) {
147  std::unique_ptr<MemoryBuffer> ObjBuffer(UnownedObjBuffer);
148  onObjEmit(K, std::move(ObjBuffer), *SharedR, std::move(Err));
149  });
150 }
151 
152 Error RTDyldObjectLinkingLayer::onObjLoad(
154  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
155  std::map<StringRef, JITEvaluatedSymbol> Resolved,
156  std::set<StringRef> &InternalSymbols) {
157  SymbolFlagsMap ExtraSymbolsToClaim;
158  SymbolMap Symbols;
159  for (auto &KV : Resolved) {
160  // Scan the symbols and add them to the Symbols map for resolution.
161 
162  // We never claim internal symbols.
163  if (InternalSymbols.count(KV.first))
164  continue;
165 
166  auto InternedName = getExecutionSession().intern(KV.first);
167  auto Flags = KV.second.getFlags();
168 
169  // Override object flags and claim responsibility for symbols if
170  // requested.
171  if (OverrideObjectFlags || AutoClaimObjectSymbols) {
172  auto I = R.getSymbols().find(InternedName);
173 
174  if (OverrideObjectFlags && I != R.getSymbols().end())
175  Flags = I->second;
176  else if (AutoClaimObjectSymbols && I == R.getSymbols().end())
177  ExtraSymbolsToClaim[InternedName] = Flags;
178  }
179 
180  Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags);
181  }
182 
183  if (!ExtraSymbolsToClaim.empty())
184  if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim))
185  return Err;
186 
187  R.notifyResolved(Symbols);
188 
189  if (NotifyLoaded)
190  NotifyLoaded(K, Obj, *LoadedObjInfo);
191 
192  return Error::success();
193 }
194 
195 void RTDyldObjectLinkingLayer::onObjEmit(
196  VModuleKey K, std::unique_ptr<MemoryBuffer> ObjBuffer,
198  if (Err) {
199  getExecutionSession().reportError(std::move(Err));
201  return;
202  }
203 
204  R.notifyEmitted();
205 
206  if (NotifyEmitted)
207  NotifyEmitted(K, std::move(ObjBuffer));
208 }
209 
211  ExecutionSession &ES, ResourcesGetter GetResources,
212  NotifyLoadedFtor NotifyLoaded, NotifyFinalizedFtor NotifyFinalized,
213  NotifyFreedFtor NotifyFreed)
214  : ES(ES), GetResources(std::move(GetResources)),
215  NotifyLoaded(std::move(NotifyLoaded)),
216  NotifyFinalized(std::move(NotifyFinalized)),
217  NotifyFreed(std::move(NotifyFreed)), ProcessAllSections(false) {}
218 
219 } // End namespace orc.
220 } // End namespace llvm.
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Definition: ObjectFile.cpp:163
Queried, materialization begun.
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:401
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)
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
Definition: Core.h:761
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:59
Tagged union holding either a T or a Error.
Definition: yaml2obj.h:21
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:171
ExecutionSession & getExecutionSession()
Returns the execution session for this layer.
Definition: Layer.h:119
void notifyResolved(const SymbolMap &Symbols)
Notifies the target JITDylib that the given symbols have been resolved.
Definition: Core.cpp:370
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:176
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
LegacyRTDyldObjectLinkingLayer(ORCv1DeprecationAcknowledgement, ExecutionSession &ES, ResourcesGetter GetResources, NotifyLoadedFtor NotifyLoaded=NotifyLoadedFtor(), NotifyFinalizedFtor NotifyFinalized=NotifyFinalizedFtor(), NotifyFreedFtor NotifyFreed=NotifyFreedFtor())
VModuleKey getVModuleKey() const
Returns the VModuleKey for this instance.
Definition: Core.h:188
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
Definition: Record.h:1863
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:187
Symbol resolution interface.
Definition: JITSymbol.h:324
void notifyEmitted()
Notifies the target JITDylib (and any pending queries on that JITDylib) that all symbols covered by t...
Definition: Core.cpp:391
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
std::function< std::unique_ptr< RuntimeDyld::MemoryManager >()> GetMemoryManagerFunction
An ExecutionSession represents a running JIT program.
Definition: Core.h:743
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:194
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:189
uint8_t uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:41
void reportError(Error Err)
Report a error for this execution session.
Definition: Core.h:808
#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:413
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
Interface for Layers that accept object files.
Definition: Layer.h:113
void emit(MaterializationResponsibility R, std::unique_ptr< MemoryBuffer > O) override
Emit the object.