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