CompileOnDemandLayer.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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. #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
  15. #define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
  16. #include "IndirectionUtils.h"
  17. #include "LambdaResolver.h"
  18. #include "LogicalDylib.h"
  19. #include "llvm/ADT/STLExtras.h"
  20. #include "llvm/ExecutionEngine/SectionMemoryManager.h"
  21. #include "llvm/Transforms/Utils/Cloning.h"
  22. #include <list>
  23. #include <set>
  24. #include "llvm/Support/Debug.h"
  25. namespace llvm {
  26. namespace orc {
  27. /// @brief Compile-on-demand layer.
  28. ///
  29. /// When a module is added to this layer a stub is created for each of its
  30. /// function definitions. The stubs and other global values are immediately
  31. /// added to the layer below. When a stub is called it triggers the extraction
  32. /// of the function body from the original module. The extracted body is then
  33. /// compiled and executed.
  34. template <typename BaseLayerT, typename CompileCallbackMgrT,
  35. typename PartitioningFtor =
  36. std::function<std::set<Function*>(Function&)>>
  37. class CompileOnDemandLayer {
  38. private:
  39. // Utility class for MapValue. Only materializes declarations for global
  40. // variables.
  41. class GlobalDeclMaterializer : public ValueMaterializer {
  42. public:
  43. typedef std::set<const Function*> StubSet;
  44. GlobalDeclMaterializer(Module &Dst, const StubSet *StubsToClone = nullptr)
  45. : Dst(Dst), StubsToClone(StubsToClone) {}
  46. Value* materializeValueFor(Value *V) final {
  47. if (auto *GV = dyn_cast<GlobalVariable>(V))
  48. return cloneGlobalVariableDecl(Dst, *GV);
  49. else if (auto *F = dyn_cast<Function>(V)) {
  50. auto *ClonedF = cloneFunctionDecl(Dst, *F);
  51. if (StubsToClone && StubsToClone->count(F)) {
  52. GlobalVariable *FnBodyPtr =
  53. createImplPointer(*ClonedF->getType(), *ClonedF->getParent(),
  54. ClonedF->getName() + "$orc_addr", nullptr);
  55. makeStub(*ClonedF, *FnBodyPtr);
  56. ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
  57. ClonedF->addFnAttr(Attribute::AlwaysInline);
  58. }
  59. return ClonedF;
  60. }
  61. // Else.
  62. return nullptr;
  63. }
  64. private:
  65. Module &Dst;
  66. const StubSet *StubsToClone;
  67. };
  68. typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
  69. struct LogicalModuleResources {
  70. std::shared_ptr<Module> SourceModule;
  71. std::set<const Function*> StubsToClone;
  72. };
  73. struct LogicalDylibResources {
  74. typedef std::function<RuntimeDyld::SymbolInfo(const std::string&)>
  75. SymbolResolverFtor;
  76. SymbolResolverFtor ExternalSymbolResolver;
  77. PartitioningFtor Partitioner;
  78. };
  79. typedef LogicalDylib<BaseLayerT, LogicalModuleResources,
  80. LogicalDylibResources> CODLogicalDylib;
  81. typedef typename CODLogicalDylib::LogicalModuleHandle LogicalModuleHandle;
  82. typedef std::list<CODLogicalDylib> LogicalDylibList;
  83. public:
  84. /// @brief Handle to a set of loaded modules.
  85. typedef typename LogicalDylibList::iterator ModuleSetHandleT;
  86. /// @brief Construct a compile-on-demand layer instance.
  87. CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr,
  88. bool CloneStubsIntoPartitions)
  89. : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr),
  90. CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
  91. /// @brief Add a module to the compile-on-demand layer.
  92. template <typename ModuleSetT, typename MemoryManagerPtrT,
  93. typename SymbolResolverPtrT>
  94. ModuleSetHandleT addModuleSet(ModuleSetT Ms,
  95. MemoryManagerPtrT MemMgr,
  96. SymbolResolverPtrT Resolver) {
  97. assert(MemMgr == nullptr &&
  98. "User supplied memory managers not supported with COD yet.");
  99. LogicalDylibs.push_back(CODLogicalDylib(BaseLayer));
  100. auto &LDResources = LogicalDylibs.back().getDylibResources();
  101. LDResources.ExternalSymbolResolver =
  102. [Resolver](const std::string &Name) {
  103. return Resolver->findSymbol(Name);
  104. };
  105. LDResources.Partitioner =
  106. [](Function &F) {
  107. std::set<Function*> Partition;
  108. Partition.insert(&F);
  109. return Partition;
  110. };
  111. // Process each of the modules in this module set.
  112. for (auto &M : Ms)
  113. addLogicalModule(LogicalDylibs.back(),
  114. std::shared_ptr<Module>(std::move(M)));
  115. return std::prev(LogicalDylibs.end());
  116. }
  117. /// @brief Remove the module represented by the given handle.
  118. ///
  119. /// This will remove all modules in the layers below that were derived from
  120. /// the module represented by H.
  121. void removeModuleSet(ModuleSetHandleT H) {
  122. LogicalDylibs.erase(H);
  123. }
  124. /// @brief Search for the given named symbol.
  125. /// @param Name The name of the symbol to search for.
  126. /// @param ExportedSymbolsOnly If true, search only for exported symbols.
  127. /// @return A handle for the given named symbol, if it exists.
  128. JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
  129. return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
  130. }
  131. /// @brief Get the address of a symbol provided by this layer, or some layer
  132. /// below this one.
  133. JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
  134. bool ExportedSymbolsOnly) {
  135. return H->findSymbol(Name, ExportedSymbolsOnly);
  136. }
  137. private:
  138. void addLogicalModule(CODLogicalDylib &LD, std::shared_ptr<Module> SrcM) {
  139. // Bump the linkage and rename any anonymous/privote members in SrcM to
  140. // ensure that everything will resolve properly after we partition SrcM.
  141. makeAllSymbolsExternallyAccessible(*SrcM);
  142. // Create a logical module handle for SrcM within the logical dylib.
  143. auto LMH = LD.createLogicalModule();
  144. auto &LMResources = LD.getLogicalModuleResources(LMH);
  145. LMResources.SourceModule = SrcM;
  146. // Create the GVs-and-stubs module.
  147. auto GVsAndStubsM = llvm::make_unique<Module>(
  148. (SrcM->getName() + ".globals_and_stubs").str(),
  149. SrcM->getContext());
  150. GVsAndStubsM->setDataLayout(SrcM->getDataLayout());
  151. ValueToValueMapTy VMap;
  152. // Process module and create stubs.
  153. // We create the stubs before copying the global variables as we know the
  154. // stubs won't refer to any globals (they only refer to their implementation
  155. // pointer) so there's no ordering/value-mapping issues.
  156. for (auto &F : *SrcM) {
  157. // Skip declarations.
  158. if (F.isDeclaration())
  159. continue;
  160. // Record all functions defined by this module.
  161. if (CloneStubsIntoPartitions)
  162. LMResources.StubsToClone.insert(&F);
  163. // For each definition: create a callback, a stub, and a function body
  164. // pointer. Initialize the function body pointer to point at the callback,
  165. // and set the callback to compile the function body.
  166. auto CCInfo = CompileCallbackMgr.getCompileCallback(SrcM->getContext());
  167. Function *StubF = cloneFunctionDecl(*GVsAndStubsM, F, &VMap);
  168. GlobalVariable *FnBodyPtr =
  169. createImplPointer(*StubF->getType(), *StubF->getParent(),
  170. StubF->getName() + "$orc_addr",
  171. createIRTypedAddress(*StubF->getFunctionType(),
  172. CCInfo.getAddress()));
  173. makeStub(*StubF, *FnBodyPtr);
  174. CCInfo.setCompileAction(
  175. [this, &LD, LMH, &F]() {
  176. return this->extractAndCompile(LD, LMH, F);
  177. });
  178. }
  179. // Now clone the global variable declarations.
  180. GlobalDeclMaterializer GDMat(*GVsAndStubsM);
  181. for (auto &GV : SrcM->globals())
  182. if (!GV.isDeclaration())
  183. cloneGlobalVariableDecl(*GVsAndStubsM, GV, &VMap);
  184. // Then clone the initializers.
  185. for (auto &GV : SrcM->globals())
  186. if (!GV.isDeclaration())
  187. moveGlobalVariableInitializer(GV, VMap, &GDMat);
  188. // Build a resolver for the stubs module and add it to the base layer.
  189. auto GVsAndStubsResolver = createLambdaResolver(
  190. [&LD](const std::string &Name) {
  191. return LD.getDylibResources().ExternalSymbolResolver(Name);
  192. },
  193. [](const std::string &Name) {
  194. return RuntimeDyld::SymbolInfo(nullptr);
  195. });
  196. std::vector<std::unique_ptr<Module>> GVsAndStubsMSet;
  197. GVsAndStubsMSet.push_back(std::move(GVsAndStubsM));
  198. auto GVsAndStubsH =
  199. BaseLayer.addModuleSet(std::move(GVsAndStubsMSet),
  200. llvm::make_unique<SectionMemoryManager>(),
  201. std::move(GVsAndStubsResolver));
  202. LD.addToLogicalModule(LMH, GVsAndStubsH);
  203. }
  204. static std::string Mangle(StringRef Name, const DataLayout &DL) {
  205. std::string MangledName;
  206. {
  207. raw_string_ostream MangledNameStream(MangledName);
  208. Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
  209. }
  210. return MangledName;
  211. }
  212. TargetAddress extractAndCompile(CODLogicalDylib &LD,
  213. LogicalModuleHandle LMH,
  214. Function &F) {
  215. Module &SrcM = *LD.getLogicalModuleResources(LMH).SourceModule;
  216. // If F is a declaration we must already have compiled it.
  217. if (F.isDeclaration())
  218. return 0;
  219. // Grab the name of the function being called here.
  220. std::string CalledFnName = Mangle(F.getName(), SrcM.getDataLayout());
  221. auto Partition = LD.getDylibResources().Partitioner(F);
  222. auto PartitionH = emitPartition(LD, LMH, Partition);
  223. TargetAddress CalledAddr = 0;
  224. for (auto *SubF : Partition) {
  225. std::string FName = SubF->getName();
  226. auto FnBodySym =
  227. BaseLayer.findSymbolIn(PartitionH, Mangle(FName, SrcM.getDataLayout()),
  228. false);
  229. auto FnPtrSym =
  230. BaseLayer.findSymbolIn(*LD.moduleHandlesBegin(LMH),
  231. Mangle(FName + "$orc_addr",
  232. SrcM.getDataLayout()),
  233. false);
  234. assert(FnBodySym && "Couldn't find function body.");
  235. assert(FnPtrSym && "Couldn't find function body pointer.");
  236. TargetAddress FnBodyAddr = FnBodySym.getAddress();
  237. void *FnPtrAddr = reinterpret_cast<void*>(
  238. static_cast<uintptr_t>(FnPtrSym.getAddress()));
  239. // If this is the function we're calling record the address so we can
  240. // return it from this function.
  241. if (SubF == &F)
  242. CalledAddr = FnBodyAddr;
  243. memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t));
  244. }
  245. return CalledAddr;
  246. }
  247. template <typename PartitionT>
  248. BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD,
  249. LogicalModuleHandle LMH,
  250. const PartitionT &Partition) {
  251. auto &LMResources = LD.getLogicalModuleResources(LMH);
  252. Module &SrcM = *LMResources.SourceModule;
  253. // Create the module.
  254. std::string NewName = SrcM.getName();
  255. for (auto *F : Partition) {
  256. NewName += ".";
  257. NewName += F->getName();
  258. }
  259. auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
  260. M->setDataLayout(SrcM.getDataLayout());
  261. ValueToValueMapTy VMap;
  262. GlobalDeclMaterializer GDM(*M, &LMResources.StubsToClone);
  263. // Create decls in the new module.
  264. for (auto *F : Partition)
  265. cloneFunctionDecl(*M, *F, &VMap);
  266. // Move the function bodies.
  267. for (auto *F : Partition)
  268. moveFunctionBody(*F, VMap, &GDM);
  269. // Create memory manager and symbol resolver.
  270. auto MemMgr = llvm::make_unique<SectionMemoryManager>();
  271. auto Resolver = createLambdaResolver(
  272. [this, &LD, LMH](const std::string &Name) {
  273. if (auto Symbol = LD.findSymbolInternally(LMH, Name))
  274. return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
  275. Symbol.getFlags());
  276. return LD.getDylibResources().ExternalSymbolResolver(Name);
  277. },
  278. [this, &LD, LMH](const std::string &Name) {
  279. if (auto Symbol = LD.findSymbolInternally(LMH, Name))
  280. return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
  281. Symbol.getFlags());
  282. return RuntimeDyld::SymbolInfo(nullptr);
  283. });
  284. std::vector<std::unique_ptr<Module>> PartMSet;
  285. PartMSet.push_back(std::move(M));
  286. return BaseLayer.addModuleSet(std::move(PartMSet), std::move(MemMgr),
  287. std::move(Resolver));
  288. }
  289. BaseLayerT &BaseLayer;
  290. CompileCallbackMgrT &CompileCallbackMgr;
  291. LogicalDylibList LogicalDylibs;
  292. bool CloneStubsIntoPartitions;
  293. };
  294. } // End namespace orc.
  295. } // End namespace llvm.
  296. #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H