LLVM  3.7.0
CompileOnDemandLayer.h
Go to the documentation of this file.
1 //===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // JIT layer for breaking up modules and inserting callbacks to allow
11 // individual functions to be compiled on demand.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
16 #define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
17 
18 #include "IndirectionUtils.h"
19 #include "LambdaResolver.h"
20 #include "LogicalDylib.h"
21 #include "llvm/ADT/STLExtras.h"
24 #include <list>
25 #include <set>
26 
27 #include "llvm/Support/Debug.h"
28 
29 namespace llvm {
30 namespace orc {
31 
32 /// @brief Compile-on-demand layer.
33 ///
34 /// When a module is added to this layer a stub is created for each of its
35 /// function definitions. The stubs and other global values are immediately
36 /// added to the layer below. When a stub is called it triggers the extraction
37 /// of the function body from the original module. The extracted body is then
38 /// compiled and executed.
39 template <typename BaseLayerT, typename CompileCallbackMgrT,
40  typename PartitioningFtor =
41  std::function<std::set<Function*>(Function&)>>
43 private:
44 
45  // Utility class for MapValue. Only materializes declarations for global
46  // variables.
47  class GlobalDeclMaterializer : public ValueMaterializer {
48  public:
49  typedef std::set<const Function*> StubSet;
50 
51  GlobalDeclMaterializer(Module &Dst, const StubSet *StubsToClone = nullptr)
52  : Dst(Dst), StubsToClone(StubsToClone) {}
53 
54  Value* materializeValueFor(Value *V) final {
55  if (auto *GV = dyn_cast<GlobalVariable>(V))
56  return cloneGlobalVariableDecl(Dst, *GV);
57  else if (auto *F = dyn_cast<Function>(V)) {
58  auto *ClonedF = cloneFunctionDecl(Dst, *F);
59  if (StubsToClone && StubsToClone->count(F)) {
60  GlobalVariable *FnBodyPtr =
61  createImplPointer(*ClonedF->getType(), *ClonedF->getParent(),
62  ClonedF->getName() + "$orc_addr", nullptr);
63  makeStub(*ClonedF, *FnBodyPtr);
64  ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
65  ClonedF->addFnAttr(Attribute::AlwaysInline);
66  }
67  return ClonedF;
68  }
69  // Else.
70  return nullptr;
71  }
72  private:
73  Module &Dst;
74  const StubSet *StubsToClone;
75  };
76 
77  typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
78 
79  struct LogicalModuleResources {
80  std::shared_ptr<Module> SourceModule;
81  std::set<const Function*> StubsToClone;
82  };
83 
84  struct LogicalDylibResources {
85  typedef std::function<RuntimeDyld::SymbolInfo(const std::string&)>
86  SymbolResolverFtor;
87  SymbolResolverFtor ExternalSymbolResolver;
88  PartitioningFtor Partitioner;
89  };
90 
91  typedef LogicalDylib<BaseLayerT, LogicalModuleResources,
92  LogicalDylibResources> CODLogicalDylib;
93 
94  typedef typename CODLogicalDylib::LogicalModuleHandle LogicalModuleHandle;
95  typedef std::list<CODLogicalDylib> LogicalDylibList;
96 
97 public:
98  /// @brief Handle to a set of loaded modules.
99  typedef typename LogicalDylibList::iterator ModuleSetHandleT;
100 
101  /// @brief Construct a compile-on-demand layer instance.
102  CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr,
103  bool CloneStubsIntoPartitions)
104  : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr),
105  CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
106 
107  /// @brief Add a module to the compile-on-demand layer.
108  template <typename ModuleSetT, typename MemoryManagerPtrT,
109  typename SymbolResolverPtrT>
110  ModuleSetHandleT addModuleSet(ModuleSetT Ms,
111  MemoryManagerPtrT MemMgr,
112  SymbolResolverPtrT Resolver) {
113 
114  assert(MemMgr == nullptr &&
115  "User supplied memory managers not supported with COD yet.");
116 
117  LogicalDylibs.push_back(CODLogicalDylib(BaseLayer));
118  auto &LDResources = LogicalDylibs.back().getDylibResources();
119 
120  LDResources.ExternalSymbolResolver =
121  [Resolver](const std::string &Name) {
122  return Resolver->findSymbol(Name);
123  };
124 
125  LDResources.Partitioner =
126  [](Function &F) {
127  std::set<Function*> Partition;
128  Partition.insert(&F);
129  return Partition;
130  };
131 
132  // Process each of the modules in this module set.
133  for (auto &M : Ms)
134  addLogicalModule(LogicalDylibs.back(),
135  std::shared_ptr<Module>(std::move(M)));
136 
137  return std::prev(LogicalDylibs.end());
138  }
139 
140  /// @brief Remove the module represented by the given handle.
141  ///
142  /// This will remove all modules in the layers below that were derived from
143  /// the module represented by H.
144  void removeModuleSet(ModuleSetHandleT H) {
145  LogicalDylibs.erase(H);
146  }
147 
148  /// @brief Search for the given named symbol.
149  /// @param Name The name of the symbol to search for.
150  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
151  /// @return A handle for the given named symbol, if it exists.
152  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
153  return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
154  }
155 
156  /// @brief Get the address of a symbol provided by this layer, or some layer
157  /// below this one.
158  JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
159  bool ExportedSymbolsOnly) {
160  return H->findSymbol(Name, ExportedSymbolsOnly);
161  }
162 
163 private:
164 
165  void addLogicalModule(CODLogicalDylib &LD, std::shared_ptr<Module> SrcM) {
166 
167  // Bump the linkage and rename any anonymous/privote members in SrcM to
168  // ensure that everything will resolve properly after we partition SrcM.
170 
171  // Create a logical module handle for SrcM within the logical dylib.
172  auto LMH = LD.createLogicalModule();
173  auto &LMResources = LD.getLogicalModuleResources(LMH);
174  LMResources.SourceModule = SrcM;
175 
176  // Create the GVs-and-stubs module.
177  auto GVsAndStubsM = llvm::make_unique<Module>(
178  (SrcM->getName() + ".globals_and_stubs").str(),
179  SrcM->getContext());
180  GVsAndStubsM->setDataLayout(SrcM->getDataLayout());
181  ValueToValueMapTy VMap;
182 
183  // Process module and create stubs.
184  // We create the stubs before copying the global variables as we know the
185  // stubs won't refer to any globals (they only refer to their implementation
186  // pointer) so there's no ordering/value-mapping issues.
187  for (auto &F : *SrcM) {
188 
189  // Skip declarations.
190  if (F.isDeclaration())
191  continue;
192 
193  // Record all functions defined by this module.
194  if (CloneStubsIntoPartitions)
195  LMResources.StubsToClone.insert(&F);
196 
197  // For each definition: create a callback, a stub, and a function body
198  // pointer. Initialize the function body pointer to point at the callback,
199  // and set the callback to compile the function body.
200  auto CCInfo = CompileCallbackMgr.getCompileCallback(SrcM->getContext());
201  Function *StubF = cloneFunctionDecl(*GVsAndStubsM, F, &VMap);
202  GlobalVariable *FnBodyPtr =
203  createImplPointer(*StubF->getType(), *StubF->getParent(),
204  StubF->getName() + "$orc_addr",
206  CCInfo.getAddress()));
207  makeStub(*StubF, *FnBodyPtr);
208  CCInfo.setCompileAction(
209  [this, &LD, LMH, &F]() {
210  return this->extractAndCompile(LD, LMH, F);
211  });
212  }
213 
214  // Now clone the global variable declarations.
215  GlobalDeclMaterializer GDMat(*GVsAndStubsM);
216  for (auto &GV : SrcM->globals())
217  if (!GV.isDeclaration())
218  cloneGlobalVariableDecl(*GVsAndStubsM, GV, &VMap);
219 
220  // Then clone the initializers.
221  for (auto &GV : SrcM->globals())
222  if (!GV.isDeclaration())
223  moveGlobalVariableInitializer(GV, VMap, &GDMat);
224 
225  // Build a resolver for the stubs module and add it to the base layer.
226  auto GVsAndStubsResolver = createLambdaResolver(
227  [&LD](const std::string &Name) {
228  return LD.getDylibResources().ExternalSymbolResolver(Name);
229  },
230  [](const std::string &Name) {
231  return RuntimeDyld::SymbolInfo(nullptr);
232  });
233 
234  std::vector<std::unique_ptr<Module>> GVsAndStubsMSet;
235  GVsAndStubsMSet.push_back(std::move(GVsAndStubsM));
236  auto GVsAndStubsH =
237  BaseLayer.addModuleSet(std::move(GVsAndStubsMSet),
238  llvm::make_unique<SectionMemoryManager>(),
239  std::move(GVsAndStubsResolver));
240  LD.addToLogicalModule(LMH, GVsAndStubsH);
241  }
242 
243  static std::string Mangle(StringRef Name, const DataLayout &DL) {
244  std::string MangledName;
245  {
246  raw_string_ostream MangledNameStream(MangledName);
247  Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
248  }
249  return MangledName;
250  }
251 
252  TargetAddress extractAndCompile(CODLogicalDylib &LD,
253  LogicalModuleHandle LMH,
254  Function &F) {
255  Module &SrcM = *LD.getLogicalModuleResources(LMH).SourceModule;
256 
257  // If F is a declaration we must already have compiled it.
258  if (F.isDeclaration())
259  return 0;
260 
261  // Grab the name of the function being called here.
262  std::string CalledFnName = Mangle(F.getName(), SrcM.getDataLayout());
263 
264  auto Partition = LD.getDylibResources().Partitioner(F);
265  auto PartitionH = emitPartition(LD, LMH, Partition);
266 
267  TargetAddress CalledAddr = 0;
268  for (auto *SubF : Partition) {
269  std::string FName = SubF->getName();
270  auto FnBodySym =
271  BaseLayer.findSymbolIn(PartitionH, Mangle(FName, SrcM.getDataLayout()),
272  false);
273  auto FnPtrSym =
274  BaseLayer.findSymbolIn(*LD.moduleHandlesBegin(LMH),
275  Mangle(FName + "$orc_addr",
276  SrcM.getDataLayout()),
277  false);
278  assert(FnBodySym && "Couldn't find function body.");
279  assert(FnPtrSym && "Couldn't find function body pointer.");
280 
281  TargetAddress FnBodyAddr = FnBodySym.getAddress();
282  void *FnPtrAddr = reinterpret_cast<void*>(
283  static_cast<uintptr_t>(FnPtrSym.getAddress()));
284 
285  // If this is the function we're calling record the address so we can
286  // return it from this function.
287  if (SubF == &F)
288  CalledAddr = FnBodyAddr;
289 
290  memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t));
291  }
292 
293  return CalledAddr;
294  }
295 
296  template <typename PartitionT>
297  BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD,
298  LogicalModuleHandle LMH,
299  const PartitionT &Partition) {
300  auto &LMResources = LD.getLogicalModuleResources(LMH);
301  Module &SrcM = *LMResources.SourceModule;
302 
303  // Create the module.
304  std::string NewName = SrcM.getName();
305  for (auto *F : Partition) {
306  NewName += ".";
307  NewName += F->getName();
308  }
309 
310  auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
311  M->setDataLayout(SrcM.getDataLayout());
312  ValueToValueMapTy VMap;
313  GlobalDeclMaterializer GDM(*M, &LMResources.StubsToClone);
314 
315  // Create decls in the new module.
316  for (auto *F : Partition)
317  cloneFunctionDecl(*M, *F, &VMap);
318 
319  // Move the function bodies.
320  for (auto *F : Partition)
321  moveFunctionBody(*F, VMap, &GDM);
322 
323  // Create memory manager and symbol resolver.
324  auto MemMgr = llvm::make_unique<SectionMemoryManager>();
325  auto Resolver = createLambdaResolver(
326  [this, &LD, LMH](const std::string &Name) {
327  if (auto Symbol = LD.findSymbolInternally(LMH, Name))
328  return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
329  Symbol.getFlags());
330  return LD.getDylibResources().ExternalSymbolResolver(Name);
331  },
332  [this, &LD, LMH](const std::string &Name) {
333  if (auto Symbol = LD.findSymbolInternally(LMH, Name))
334  return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
335  Symbol.getFlags());
336  return RuntimeDyld::SymbolInfo(nullptr);
337  });
338  std::vector<std::unique_ptr<Module>> PartMSet;
339  PartMSet.push_back(std::move(M));
340  return BaseLayer.addModuleSet(std::move(PartMSet), std::move(MemMgr),
341  std::move(Resolver));
342  }
343 
344  BaseLayerT &BaseLayer;
345  CompileCallbackMgrT &CompileCallbackMgr;
346  LogicalDylibList LogicalDylibs;
347  bool CloneStubsIntoPartitions;
348 };
349 
350 } // End namespace orc.
351 } // End namespace llvm.
352 
353 #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: ValueMap.h:149
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:114
Available for inspection, not emission.
Definition: GlobalValue.h:41
F(f)
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:188
JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, bool ExportedSymbolsOnly)
Get the address of a symbol provided by this layer, or some layer below this one. ...
CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr, bool CloneStubsIntoPartitions)
Construct a compile-on-demand layer instance.
GlobalVariable * createImplPointer(PointerType &PT, Module &M, const Twine &Name, Constant *Initializer)
Create a function pointer with the given type, name, and initializer in the given Module...
ModuleSetHandleT addModuleSet(ModuleSetT Ms, MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver)
Add a module to the compile-on-demand layer.
Constant * createIRTypedAddress(FunctionType &FT, TargetAddress Addr)
Build a function pointer of FunctionType with the given constant address.
void moveGlobalVariableInitializer(GlobalVariable &OrigGV, ValueToValueMapTy &VMap, ValueMaterializer *Materializer=nullptr, GlobalVariable *NewGV=nullptr)
Move global variable GV from its parent module to cloned global declaration in a different module...
LogicalDylibList::iterator ModuleSetHandleT
Handle to a set of loaded modules.
GlobalVariable * cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, ValueToValueMapTy *VMap=nullptr)
Clone a global variable declaration into a new module.
ValueMaterializer - This is a class that can be implemented by clients to materialize Values on deman...
Definition: ValueMapper.h:39
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly)
Search for the given named symbol.
#define H(x, y, z)
Definition: MD5.cpp:53
Represents a symbol in the JIT.
Definition: JITSymbol.h:29
ValueMap< const Value *, WeakVH > ValueToValueMapTy
Definition: ValueMapper.h:22
Function * cloneFunctionDecl(Module &Dst, const Function &F, ValueToValueMapTy *VMap=nullptr)
Clone a function declaration into a new module.
LogicalModuleList::iterator LogicalModuleHandle
Definition: LogicalDylib.h:39
uint64_t TargetAddress
Represents an address in the target process's address space.
Definition: JITSymbol.h:26
void removeModuleSet(ModuleSetHandleT H)
Remove the module represented by the given handle.
std::unique_ptr< LambdaResolver< ExternalLookupFtorT, DylibLookupFtorT > > createLambdaResolver(ExternalLookupFtorT ExternalLookupFtor, DylibLookupFtorT DylibLookupFtor)
void makeAllSymbolsExternallyAccessible(Module &M)
Raise linkage types and rename as necessary to ensure that all symbols are accessible for other modul...
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:185
void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const
Print the appropriate prefix and the specified global variable's name.
Definition: Mangler.cpp:108
FunctionType * getFunctionType() const
Definition: Function.cpp:227
void makeStub(Function &F, GlobalVariable &ImplPointer)
Turn a function declaration into a stub function that makes an indirect call using the given function...
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:365
LLVM Value Representation.
Definition: Value.h:69
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap, ValueMaterializer *Materializer=nullptr, Function *NewF=nullptr)
Move the body of function 'F' to a cloned function declaration in a different module (See related clo...