• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===//
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 //
9 // JIT layer for breaking up modules and inserting callbacks to allow
10 // individual functions to be compiled on demand.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
15 #define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
16 
17 #include "llvm/ADT/APInt.h"
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/Twine.h"
22 #include "llvm/ExecutionEngine/JITSymbol.h"
23 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
24 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
25 #include "llvm/ExecutionEngine/Orc/Layer.h"
26 #include "llvm/ExecutionEngine/Orc/LazyReexports.h"
27 #include "llvm/ExecutionEngine/Orc/Legacy.h"
28 #include "llvm/ExecutionEngine/Orc/OrcError.h"
29 #include "llvm/ExecutionEngine/Orc/Speculation.h"
30 #include "llvm/ExecutionEngine/RuntimeDyld.h"
31 #include "llvm/IR/Attributes.h"
32 #include "llvm/IR/Constant.h"
33 #include "llvm/IR/Constants.h"
34 #include "llvm/IR/DataLayout.h"
35 #include "llvm/IR/Function.h"
36 #include "llvm/IR/GlobalAlias.h"
37 #include "llvm/IR/GlobalValue.h"
38 #include "llvm/IR/GlobalVariable.h"
39 #include "llvm/IR/Instruction.h"
40 #include "llvm/IR/Mangler.h"
41 #include "llvm/IR/Module.h"
42 #include "llvm/IR/Type.h"
43 #include "llvm/Support/Casting.h"
44 #include "llvm/Support/raw_ostream.h"
45 #include "llvm/Transforms/Utils/ValueMapper.h"
46 #include <algorithm>
47 #include <cassert>
48 #include <functional>
49 #include <iterator>
50 #include <list>
51 #include <memory>
52 #include <set>
53 #include <string>
54 #include <utility>
55 #include <vector>
56 
57 namespace llvm {
58 
59 class Value;
60 
61 namespace orc {
62 
63 class ExtractingIRMaterializationUnit;
64 
65 class CompileOnDemandLayer : public IRLayer {
66   friend class PartitioningIRMaterializationUnit;
67 
68 public:
69   /// Builder for IndirectStubsManagers.
70   using IndirectStubsManagerBuilder =
71       std::function<std::unique_ptr<IndirectStubsManager>()>;
72 
73   using GlobalValueSet = std::set<const GlobalValue *>;
74 
75   /// Partitioning function.
76   using PartitionFunction =
77       std::function<Optional<GlobalValueSet>(GlobalValueSet Requested)>;
78 
79   /// Off-the-shelf partitioning which compiles all requested symbols (usually
80   /// a single function at a time).
81   static Optional<GlobalValueSet> compileRequested(GlobalValueSet Requested);
82 
83   /// Off-the-shelf partitioning which compiles whole modules whenever any
84   /// symbol in them is requested.
85   static Optional<GlobalValueSet> compileWholeModule(GlobalValueSet Requested);
86 
87   /// Construct a CompileOnDemandLayer.
88   CompileOnDemandLayer(ExecutionSession &ES, IRLayer &BaseLayer,
89                         LazyCallThroughManager &LCTMgr,
90                         IndirectStubsManagerBuilder BuildIndirectStubsManager);
91 
92   /// Sets the partition function.
93   void setPartitionFunction(PartitionFunction Partition);
94 
95   /// Sets the ImplSymbolMap
96   void setImplMap(ImplSymbolMap *Imp);
97   /// Emits the given module. This should not be called by clients: it will be
98   /// called by the JIT when a definition added via the add method is requested.
99   void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override;
100 
101 private:
102   struct PerDylibResources {
103   public:
PerDylibResourcesPerDylibResources104     PerDylibResources(JITDylib &ImplD,
105                       std::unique_ptr<IndirectStubsManager> ISMgr)
106         : ImplD(ImplD), ISMgr(std::move(ISMgr)) {}
getImplDylibPerDylibResources107     JITDylib &getImplDylib() { return ImplD; }
getISManagerPerDylibResources108     IndirectStubsManager &getISManager() { return *ISMgr; }
109 
110   private:
111     JITDylib &ImplD;
112     std::unique_ptr<IndirectStubsManager> ISMgr;
113   };
114 
115   using PerDylibResourcesMap = std::map<const JITDylib *, PerDylibResources>;
116 
117   PerDylibResources &getPerDylibResources(JITDylib &TargetD);
118 
119   void cleanUpModule(Module &M);
120 
121   void expandPartition(GlobalValueSet &Partition);
122 
123   void emitPartition(MaterializationResponsibility R, ThreadSafeModule TSM,
124                      IRMaterializationUnit::SymbolNameToDefinitionMap Defs);
125 
126   mutable std::mutex CODLayerMutex;
127 
128   IRLayer &BaseLayer;
129   LazyCallThroughManager &LCTMgr;
130   IndirectStubsManagerBuilder BuildIndirectStubsManager;
131   PerDylibResourcesMap DylibResources;
132   PartitionFunction Partition = compileRequested;
133   SymbolLinkagePromoter PromoteSymbols;
134   ImplSymbolMap *AliaseeImpls = nullptr;
135 };
136 
137 /// Compile-on-demand layer.
138 ///
139 ///   When a module is added to this layer a stub is created for each of its
140 /// function definitions. The stubs and other global values are immediately
141 /// added to the layer below. When a stub is called it triggers the extraction
142 /// of the function body from the original module. The extracted body is then
143 /// compiled and executed.
144 template <typename BaseLayerT,
145           typename CompileCallbackMgrT = JITCompileCallbackManager,
146           typename IndirectStubsMgrT = IndirectStubsManager>
147 class LegacyCompileOnDemandLayer {
148 private:
149   template <typename MaterializerFtor>
150   class LambdaMaterializer final : public ValueMaterializer {
151   public:
LambdaMaterializer(MaterializerFtor M)152     LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
153 
materialize(Value * V)154     Value *materialize(Value *V) final { return M(V); }
155 
156   private:
157     MaterializerFtor M;
158   };
159 
160   template <typename MaterializerFtor>
161   LambdaMaterializer<MaterializerFtor>
createLambdaMaterializer(MaterializerFtor M)162   createLambdaMaterializer(MaterializerFtor M) {
163     return LambdaMaterializer<MaterializerFtor>(std::move(M));
164   }
165 
166   // Provide type-erasure for the Modules and MemoryManagers.
167   template <typename ResourceT>
168   class ResourceOwner {
169   public:
170     ResourceOwner() = default;
171     ResourceOwner(const ResourceOwner &) = delete;
172     ResourceOwner &operator=(const ResourceOwner &) = delete;
173     virtual ~ResourceOwner() = default;
174 
175     virtual ResourceT& getResource() const = 0;
176   };
177 
178   template <typename ResourceT, typename ResourcePtrT>
179   class ResourceOwnerImpl : public ResourceOwner<ResourceT> {
180   public:
ResourceOwnerImpl(ResourcePtrT ResourcePtr)181     ResourceOwnerImpl(ResourcePtrT ResourcePtr)
182       : ResourcePtr(std::move(ResourcePtr)) {}
183 
getResource()184     ResourceT& getResource() const override { return *ResourcePtr; }
185 
186   private:
187     ResourcePtrT ResourcePtr;
188   };
189 
190   template <typename ResourceT, typename ResourcePtrT>
191   std::unique_ptr<ResourceOwner<ResourceT>>
wrapOwnership(ResourcePtrT ResourcePtr)192   wrapOwnership(ResourcePtrT ResourcePtr) {
193     using RO = ResourceOwnerImpl<ResourceT, ResourcePtrT>;
194     return std::make_unique<RO>(std::move(ResourcePtr));
195   }
196 
197   struct LogicalDylib {
198     struct SourceModuleEntry {
199       std::unique_ptr<Module> SourceMod;
200       std::set<Function*> StubsToClone;
201     };
202 
203     using SourceModulesList = std::vector<SourceModuleEntry>;
204     using SourceModuleHandle = typename SourceModulesList::size_type;
205 
206     LogicalDylib() = default;
207 
LogicalDylibLogicalDylib208     LogicalDylib(VModuleKey K, std::shared_ptr<SymbolResolver> BackingResolver,
209                  std::unique_ptr<IndirectStubsMgrT> StubsMgr)
210         : K(std::move(K)), BackingResolver(std::move(BackingResolver)),
211           StubsMgr(std::move(StubsMgr)) {}
212 
addSourceModuleLogicalDylib213     SourceModuleHandle addSourceModule(std::unique_ptr<Module> M) {
214       SourceModuleHandle H = SourceModules.size();
215       SourceModules.push_back(SourceModuleEntry());
216       SourceModules.back().SourceMod = std::move(M);
217       return H;
218     }
219 
getSourceModuleLogicalDylib220     Module& getSourceModule(SourceModuleHandle H) {
221       return *SourceModules[H].SourceMod;
222     }
223 
getStubsToCloneLogicalDylib224     std::set<Function*>& getStubsToClone(SourceModuleHandle H) {
225       return SourceModules[H].StubsToClone;
226     }
227 
findSymbolLogicalDylib228     JITSymbol findSymbol(BaseLayerT &BaseLayer, const std::string &Name,
229                          bool ExportedSymbolsOnly) {
230       if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly))
231         return Sym;
232       for (auto BLK : BaseLayerVModuleKeys)
233         if (auto Sym = BaseLayer.findSymbolIn(BLK, Name, ExportedSymbolsOnly))
234           return Sym;
235         else if (auto Err = Sym.takeError())
236           return std::move(Err);
237       return nullptr;
238     }
239 
removeModulesFromBaseLayerLogicalDylib240     Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
241       for (auto &BLK : BaseLayerVModuleKeys)
242         if (auto Err = BaseLayer.removeModule(BLK))
243           return Err;
244       return Error::success();
245     }
246 
247     VModuleKey K;
248     std::shared_ptr<SymbolResolver> BackingResolver;
249     std::unique_ptr<IndirectStubsMgrT> StubsMgr;
250     SymbolLinkagePromoter PromoteSymbols;
251     SourceModulesList SourceModules;
252     std::vector<VModuleKey> BaseLayerVModuleKeys;
253   };
254 
255 public:
256 
257   /// Module partitioning functor.
258   using PartitioningFtor = std::function<std::set<Function*>(Function&)>;
259 
260   /// Builder for IndirectStubsManagers.
261   using IndirectStubsManagerBuilderT =
262       std::function<std::unique_ptr<IndirectStubsMgrT>()>;
263 
264   using SymbolResolverGetter =
265       std::function<std::shared_ptr<SymbolResolver>(VModuleKey K)>;
266 
267   using SymbolResolverSetter =
268       std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>;
269 
270   /// Construct a compile-on-demand layer instance.
271   LLVM_ATTRIBUTE_DEPRECATED(
272       LegacyCompileOnDemandLayer(
273           ExecutionSession &ES, BaseLayerT &BaseLayer,
274           SymbolResolverGetter GetSymbolResolver,
275           SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition,
276           CompileCallbackMgrT &CallbackMgr,
277           IndirectStubsManagerBuilderT CreateIndirectStubsManager,
278           bool CloneStubsIntoPartitions = true),
279       "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please "
280       "use "
281       "the ORCv2 LegacyCompileOnDemandLayer instead");
282 
283   /// Legacy layer constructor with deprecation acknowledgement.
284   LegacyCompileOnDemandLayer(
285       ORCv1DeprecationAcknowledgement, ExecutionSession &ES,
286       BaseLayerT &BaseLayer, SymbolResolverGetter GetSymbolResolver,
287       SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition,
288       CompileCallbackMgrT &CallbackMgr,
289       IndirectStubsManagerBuilderT CreateIndirectStubsManager,
290       bool CloneStubsIntoPartitions = true)
ES(ES)291       : ES(ES), BaseLayer(BaseLayer),
292         GetSymbolResolver(std::move(GetSymbolResolver)),
293         SetSymbolResolver(std::move(SetSymbolResolver)),
294         Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr),
295         CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
296         CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
297 
~LegacyCompileOnDemandLayer()298   ~LegacyCompileOnDemandLayer() {
299     // FIXME: Report error on log.
300     while (!LogicalDylibs.empty())
301       consumeError(removeModule(LogicalDylibs.begin()->first));
302   }
303 
304   /// Add a module to the compile-on-demand layer.
addModule(VModuleKey K,std::unique_ptr<Module> M)305   Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
306 
307     assert(!LogicalDylibs.count(K) && "VModuleKey K already in use");
308     auto I = LogicalDylibs.insert(
309         LogicalDylibs.end(),
310         std::make_pair(K, LogicalDylib(K, GetSymbolResolver(K),
311                                        CreateIndirectStubsManager())));
312 
313     return addLogicalModule(I->second, std::move(M));
314   }
315 
316   /// Add extra modules to an existing logical module.
addExtraModule(VModuleKey K,std::unique_ptr<Module> M)317   Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) {
318     return addLogicalModule(LogicalDylibs[K], std::move(M));
319   }
320 
321   /// Remove the module represented by the given key.
322   ///
323   ///   This will remove all modules in the layers below that were derived from
324   /// the module represented by K.
removeModule(VModuleKey K)325   Error removeModule(VModuleKey K) {
326     auto I = LogicalDylibs.find(K);
327     assert(I != LogicalDylibs.end() && "VModuleKey K not valid here");
328     auto Err = I->second.removeModulesFromBaseLayer(BaseLayer);
329     LogicalDylibs.erase(I);
330     return Err;
331   }
332 
333   /// Search for the given named symbol.
334   /// @param Name The name of the symbol to search for.
335   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
336   /// @return A handle for the given named symbol, if it exists.
findSymbol(StringRef Name,bool ExportedSymbolsOnly)337   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
338     for (auto &KV : LogicalDylibs) {
339       if (auto Sym = KV.second.StubsMgr->findStub(Name, ExportedSymbolsOnly))
340         return Sym;
341       if (auto Sym = findSymbolIn(KV.first, Name, ExportedSymbolsOnly))
342         return Sym;
343       else if (auto Err = Sym.takeError())
344         return std::move(Err);
345     }
346     return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
347   }
348 
349   /// Get the address of a symbol provided by this layer, or some layer
350   ///        below this one.
findSymbolIn(VModuleKey K,const std::string & Name,bool ExportedSymbolsOnly)351   JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
352                          bool ExportedSymbolsOnly) {
353     assert(LogicalDylibs.count(K) && "VModuleKey K is not valid here");
354     return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly);
355   }
356 
357   /// Update the stub for the given function to point at FnBodyAddr.
358   /// This can be used to support re-optimization.
359   /// @return true if the function exists and the stub is updated, false
360   ///         otherwise.
361   //
362   // FIXME: We should track and free associated resources (unused compile
363   //        callbacks, uncompiled IR, and no-longer-needed/reachable function
364   //        implementations).
updatePointer(std::string FuncName,JITTargetAddress FnBodyAddr)365   Error updatePointer(std::string FuncName, JITTargetAddress FnBodyAddr) {
366     //Find out which logical dylib contains our symbol
367     auto LDI = LogicalDylibs.begin();
368     for (auto LDE = LogicalDylibs.end(); LDI != LDE; ++LDI) {
369       if (auto LMResources =
370             LDI->getLogicalModuleResourcesForSymbol(FuncName, false)) {
371         Module &SrcM = LMResources->SourceModule->getResource();
372         std::string CalledFnName = mangle(FuncName, SrcM.getDataLayout());
373         if (auto Err = LMResources->StubsMgr->updatePointer(CalledFnName,
374                                                             FnBodyAddr))
375           return Err;
376         return Error::success();
377       }
378     }
379     return make_error<JITSymbolNotFound>(FuncName);
380   }
381 
382 private:
addLogicalModule(LogicalDylib & LD,std::unique_ptr<Module> SrcMPtr)383   Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) {
384 
385     // Rename anonymous globals and promote linkage to ensure that everything
386     // will resolve properly after we partition SrcM.
387     LD.PromoteSymbols(*SrcMPtr);
388 
389     // Create a logical module handle for SrcM within the logical dylib.
390     Module &SrcM = *SrcMPtr;
391     auto LMId = LD.addSourceModule(std::move(SrcMPtr));
392 
393     // Create stub functions.
394     const DataLayout &DL = SrcM.getDataLayout();
395     {
396       typename IndirectStubsMgrT::StubInitsMap StubInits;
397       for (auto &F : SrcM) {
398         // Skip declarations.
399         if (F.isDeclaration())
400           continue;
401 
402         // Skip weak functions for which we already have definitions.
403         auto MangledName = mangle(F.getName(), DL);
404         if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) {
405           if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false))
406             continue;
407           else if (auto Err = Sym.takeError())
408             return std::move(Err);
409         }
410 
411         // Record all functions defined by this module.
412         if (CloneStubsIntoPartitions)
413           LD.getStubsToClone(LMId).insert(&F);
414 
415         // Create a callback, associate it with the stub for the function,
416         // and set the compile action to compile the partition containing the
417         // function.
418         auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress {
419           if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
420             return *FnImplAddrOrErr;
421           else {
422             // FIXME: Report error, return to 'abort' or something similar.
423             consumeError(FnImplAddrOrErr.takeError());
424             return 0;
425           }
426         };
427         if (auto CCAddr =
428                 CompileCallbackMgr.getCompileCallback(std::move(CompileAction)))
429           StubInits[MangledName] =
430               std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F));
431         else
432           return CCAddr.takeError();
433       }
434 
435       if (auto Err = LD.StubsMgr->createStubs(StubInits))
436         return Err;
437     }
438 
439     // If this module doesn't contain any globals, aliases, or module flags then
440     // we can bail out early and avoid the overhead of creating and managing an
441     // empty globals module.
442     if (SrcM.global_empty() && SrcM.alias_empty() &&
443         !SrcM.getModuleFlagsMetadata())
444       return Error::success();
445 
446     // Create the GlobalValues module.
447     auto GVsM = std::make_unique<Module>((SrcM.getName() + ".globals").str(),
448                                           SrcM.getContext());
449     GVsM->setDataLayout(DL);
450 
451     ValueToValueMapTy VMap;
452 
453     // Clone global variable decls.
454     for (auto &GV : SrcM.globals())
455       if (!GV.isDeclaration() && !VMap.count(&GV))
456         cloneGlobalVariableDecl(*GVsM, GV, &VMap);
457 
458     // And the aliases.
459     for (auto &A : SrcM.aliases())
460       if (!VMap.count(&A))
461         cloneGlobalAliasDecl(*GVsM, A, VMap);
462 
463     // Clone the module flags.
464     cloneModuleFlagsMetadata(*GVsM, SrcM, VMap);
465 
466     // Now we need to clone the GV and alias initializers.
467 
468     // Initializers may refer to functions declared (but not defined) in this
469     // module. Build a materializer to clone decls on demand.
470     auto Materializer = createLambdaMaterializer(
471       [&LD, &GVsM](Value *V) -> Value* {
472         if (auto *F = dyn_cast<Function>(V)) {
473           // Decls in the original module just get cloned.
474           if (F->isDeclaration())
475             return cloneFunctionDecl(*GVsM, *F);
476 
477           // Definitions in the original module (which we have emitted stubs
478           // for at this point) get turned into a constant alias to the stub
479           // instead.
480           const DataLayout &DL = GVsM->getDataLayout();
481           std::string FName = mangle(F->getName(), DL);
482           unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
483           JITTargetAddress StubAddr =
484             LD.StubsMgr->findStub(FName, false).getAddress();
485 
486           ConstantInt *StubAddrCI =
487             ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr));
488           Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
489                                                  StubAddrCI, F->getType());
490           return GlobalAlias::create(F->getFunctionType(),
491                                      F->getType()->getAddressSpace(),
492                                      F->getLinkage(), F->getName(),
493                                      Init, GVsM.get());
494         }
495         // else....
496         return nullptr;
497       });
498 
499     // Clone the global variable initializers.
500     for (auto &GV : SrcM.globals())
501       if (!GV.isDeclaration())
502         moveGlobalVariableInitializer(GV, VMap, &Materializer);
503 
504     // Clone the global alias initializers.
505     for (auto &A : SrcM.aliases()) {
506       auto *NewA = cast<GlobalAlias>(VMap[&A]);
507       assert(NewA && "Alias not cloned?");
508       Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr,
509                              &Materializer);
510       NewA->setAliasee(cast<Constant>(Init));
511     }
512 
513     // Build a resolver for the globals module and add it to the base layer.
514     auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol {
515       if (auto Sym = LD.StubsMgr->findStub(Name, false))
516         return Sym;
517 
518       if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
519         return Sym;
520       else if (auto Err = Sym.takeError())
521         return std::move(Err);
522 
523       return nullptr;
524     };
525 
526     auto GVsResolver = createSymbolResolver(
527         [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
528           auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup);
529 
530           if (!RS) {
531             logAllUnhandledErrors(
532                 RS.takeError(), errs(),
533                 "CODLayer/GVsResolver responsibility set lookup failed: ");
534             return SymbolNameSet();
535           }
536 
537           if (RS->size() == Symbols.size())
538             return *RS;
539 
540           SymbolNameSet NotFoundViaLegacyLookup;
541           for (auto &S : Symbols)
542             if (!RS->count(S))
543               NotFoundViaLegacyLookup.insert(S);
544           auto RS2 =
545               LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup);
546 
547           for (auto &S : RS2)
548             (*RS).insert(S);
549 
550           return *RS;
551         },
552         [this, &LD,
553          LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query,
554                        SymbolNameSet Symbols) {
555           auto NotFoundViaLegacyLookup =
556               lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
557           return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup);
558         });
559 
560     SetSymbolResolver(LD.K, std::move(GVsResolver));
561 
562     if (auto Err = BaseLayer.addModule(LD.K, std::move(GVsM)))
563       return Err;
564 
565     LD.BaseLayerVModuleKeys.push_back(LD.K);
566 
567     return Error::success();
568   }
569 
mangle(StringRef Name,const DataLayout & DL)570   static std::string mangle(StringRef Name, const DataLayout &DL) {
571     std::string MangledName;
572     {
573       raw_string_ostream MangledNameStream(MangledName);
574       Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
575     }
576     return MangledName;
577   }
578 
579   Expected<JITTargetAddress>
extractAndCompile(LogicalDylib & LD,typename LogicalDylib::SourceModuleHandle LMId,Function & F)580   extractAndCompile(LogicalDylib &LD,
581                     typename LogicalDylib::SourceModuleHandle LMId,
582                     Function &F) {
583     Module &SrcM = LD.getSourceModule(LMId);
584 
585     // If F is a declaration we must already have compiled it.
586     if (F.isDeclaration())
587       return 0;
588 
589     // Grab the name of the function being called here.
590     std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
591 
592     JITTargetAddress CalledAddr = 0;
593     auto Part = Partition(F);
594     if (auto PartKeyOrErr = emitPartition(LD, LMId, Part)) {
595       auto &PartKey = *PartKeyOrErr;
596       for (auto *SubF : Part) {
597         std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
598         if (auto FnBodySym = BaseLayer.findSymbolIn(PartKey, FnName, false)) {
599           if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) {
600             JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr;
601 
602             // If this is the function we're calling record the address so we can
603             // return it from this function.
604             if (SubF == &F)
605               CalledAddr = FnBodyAddr;
606 
607             // Update the function body pointer for the stub.
608             if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr))
609               return 0;
610 
611           } else
612             return FnBodyAddrOrErr.takeError();
613         } else if (auto Err = FnBodySym.takeError())
614           return std::move(Err);
615         else
616           llvm_unreachable("Function not emitted for partition");
617       }
618 
619       LD.BaseLayerVModuleKeys.push_back(PartKey);
620     } else
621       return PartKeyOrErr.takeError();
622 
623     return CalledAddr;
624   }
625 
626   template <typename PartitionT>
627   Expected<VModuleKey>
emitPartition(LogicalDylib & LD,typename LogicalDylib::SourceModuleHandle LMId,const PartitionT & Part)628   emitPartition(LogicalDylib &LD,
629                 typename LogicalDylib::SourceModuleHandle LMId,
630                 const PartitionT &Part) {
631     Module &SrcM = LD.getSourceModule(LMId);
632 
633     // Create the module.
634     std::string NewName = SrcM.getName();
635     for (auto *F : Part) {
636       NewName += ".";
637       NewName += F->getName();
638     }
639 
640     auto M = std::make_unique<Module>(NewName, SrcM.getContext());
641     M->setDataLayout(SrcM.getDataLayout());
642     ValueToValueMapTy VMap;
643 
644     auto Materializer = createLambdaMaterializer([&LD, &LMId,
645                                                   &M](Value *V) -> Value * {
646       if (auto *GV = dyn_cast<GlobalVariable>(V))
647         return cloneGlobalVariableDecl(*M, *GV);
648 
649       if (auto *F = dyn_cast<Function>(V)) {
650         // Check whether we want to clone an available_externally definition.
651         if (!LD.getStubsToClone(LMId).count(F))
652           return cloneFunctionDecl(*M, *F);
653 
654         // Ok - we want an inlinable stub. For that to work we need a decl
655         // for the stub pointer.
656         auto *StubPtr = createImplPointer(*F->getType(), *M,
657                                           F->getName() + "$stub_ptr", nullptr);
658         auto *ClonedF = cloneFunctionDecl(*M, *F);
659         makeStub(*ClonedF, *StubPtr);
660         ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
661         ClonedF->addFnAttr(Attribute::AlwaysInline);
662         return ClonedF;
663       }
664 
665       if (auto *A = dyn_cast<GlobalAlias>(V)) {
666         auto *Ty = A->getValueType();
667         if (Ty->isFunctionTy())
668           return Function::Create(cast<FunctionType>(Ty),
669                                   GlobalValue::ExternalLinkage, A->getName(),
670                                   M.get());
671 
672         return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage,
673                                   nullptr, A->getName(), nullptr,
674                                   GlobalValue::NotThreadLocal,
675                                   A->getType()->getAddressSpace());
676       }
677 
678       return nullptr;
679     });
680 
681     // Create decls in the new module.
682     for (auto *F : Part)
683       cloneFunctionDecl(*M, *F, &VMap);
684 
685     // Move the function bodies.
686     for (auto *F : Part)
687       moveFunctionBody(*F, VMap, &Materializer);
688 
689     auto K = ES.allocateVModule();
690 
691     auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol {
692       return LD.findSymbol(BaseLayer, Name, false);
693     };
694 
695     // Create memory manager and symbol resolver.
696     auto Resolver = createSymbolResolver(
697         [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
698           auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup);
699           if (!RS) {
700             logAllUnhandledErrors(
701                 RS.takeError(), errs(),
702                 "CODLayer/SubResolver responsibility set lookup failed: ");
703             return SymbolNameSet();
704           }
705 
706           if (RS->size() == Symbols.size())
707             return *RS;
708 
709           SymbolNameSet NotFoundViaLegacyLookup;
710           for (auto &S : Symbols)
711             if (!RS->count(S))
712               NotFoundViaLegacyLookup.insert(S);
713 
714           auto RS2 =
715               LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup);
716 
717           for (auto &S : RS2)
718             (*RS).insert(S);
719 
720           return *RS;
721         },
722         [this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q,
723                                   SymbolNameSet Symbols) {
724           auto NotFoundViaLegacyLookup =
725               lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup);
726           return LD.BackingResolver->lookup(Q,
727                                             std::move(NotFoundViaLegacyLookup));
728         });
729     SetSymbolResolver(K, std::move(Resolver));
730 
731     if (auto Err = BaseLayer.addModule(std::move(K), std::move(M)))
732       return std::move(Err);
733 
734     return K;
735   }
736 
737   ExecutionSession &ES;
738   BaseLayerT &BaseLayer;
739   SymbolResolverGetter GetSymbolResolver;
740   SymbolResolverSetter SetSymbolResolver;
741   PartitioningFtor Partition;
742   CompileCallbackMgrT &CompileCallbackMgr;
743   IndirectStubsManagerBuilderT CreateIndirectStubsManager;
744 
745   std::map<VModuleKey, LogicalDylib> LogicalDylibs;
746   bool CloneStubsIntoPartitions;
747 };
748 
749 template <typename BaseLayerT, typename CompileCallbackMgrT,
750           typename IndirectStubsMgrT>
751 LegacyCompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT, IndirectStubsMgrT>::
LegacyCompileOnDemandLayer(ExecutionSession & ES,BaseLayerT & BaseLayer,SymbolResolverGetter GetSymbolResolver,SymbolResolverSetter SetSymbolResolver,PartitioningFtor Partition,CompileCallbackMgrT & CallbackMgr,IndirectStubsManagerBuilderT CreateIndirectStubsManager,bool CloneStubsIntoPartitions)752     LegacyCompileOnDemandLayer(
753         ExecutionSession &ES, BaseLayerT &BaseLayer,
754         SymbolResolverGetter GetSymbolResolver,
755         SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition,
756         CompileCallbackMgrT &CallbackMgr,
757         IndirectStubsManagerBuilderT CreateIndirectStubsManager,
758         bool CloneStubsIntoPartitions)
759     : ES(ES), BaseLayer(BaseLayer),
760       GetSymbolResolver(std::move(GetSymbolResolver)),
761       SetSymbolResolver(std::move(SetSymbolResolver)),
762       Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr),
763       CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
764       CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
765 
766 } // end namespace orc
767 } // end namespace llvm
768 
769 #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
770