1 | //===----- CompileOnDemandLayer.cpp - Lazily emit IR on first call --------===// |
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 | #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" |
10 | #include "llvm/ExecutionEngine/Orc/Layer.h" |
11 | #include "llvm/IR/Module.h" |
12 | |
13 | using namespace llvm; |
14 | using namespace llvm::orc; |
15 | |
16 | CompileOnDemandLayer::CompileOnDemandLayer( |
17 | ExecutionSession &ES, IRLayer &BaseLayer, LazyCallThroughManager &LCTMgr, |
18 | IndirectStubsManagerBuilder BuildIndirectStubsManager) |
19 | : IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer), |
20 | LCTMgr(LCTMgr), |
21 | BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)) {} |
22 | |
23 | void CompileOnDemandLayer::setImplMap(ImplSymbolMap *Imp) { |
24 | this->AliaseeImpls = Imp; |
25 | } |
26 | |
27 | void CompileOnDemandLayer::emit( |
28 | std::unique_ptr<MaterializationResponsibility> R, ThreadSafeModule TSM) { |
29 | assert(TSM && "Null module" ); |
30 | |
31 | auto &ES = getExecutionSession(); |
32 | |
33 | // Sort the callables and non-callables, build re-exports and lodge the |
34 | // actual module with the implementation dylib. |
35 | auto &PDR = getPerDylibResources(TargetD&: R->getTargetJITDylib()); |
36 | |
37 | SymbolAliasMap NonCallables; |
38 | SymbolAliasMap Callables; |
39 | |
40 | for (auto &KV : R->getSymbols()) { |
41 | auto &Name = KV.first; |
42 | auto &Flags = KV.second; |
43 | if (Flags.isCallable()) |
44 | Callables[Name] = SymbolAliasMapEntry(Name, Flags); |
45 | else |
46 | NonCallables[Name] = SymbolAliasMapEntry(Name, Flags); |
47 | } |
48 | |
49 | // Lodge symbols with the implementation dylib. |
50 | if (auto Err = PDR.getImplDylib().define( |
51 | MU: std::make_unique<BasicIRLayerMaterializationUnit>( |
52 | args&: BaseLayer, args: *getManglingOptions(), args: std::move(TSM)))) { |
53 | ES.reportError(Err: std::move(Err)); |
54 | R->failMaterialization(); |
55 | return; |
56 | } |
57 | |
58 | if (!NonCallables.empty()) |
59 | if (auto Err = |
60 | R->replace(MU: reexports(SourceJD&: PDR.getImplDylib(), Aliases: std::move(NonCallables), |
61 | SourceJDLookupFlags: JITDylibLookupFlags::MatchAllSymbols))) { |
62 | getExecutionSession().reportError(Err: std::move(Err)); |
63 | R->failMaterialization(); |
64 | return; |
65 | } |
66 | if (!Callables.empty()) { |
67 | if (auto Err = R->replace( |
68 | MU: lazyReexports(LCTManager&: LCTMgr, RSManager&: PDR.getISManager(), SourceJD&: PDR.getImplDylib(), |
69 | CallableAliases: std::move(Callables), SrcJDLoc: AliaseeImpls))) { |
70 | getExecutionSession().reportError(Err: std::move(Err)); |
71 | R->failMaterialization(); |
72 | return; |
73 | } |
74 | } |
75 | } |
76 | |
77 | CompileOnDemandLayer::PerDylibResources & |
78 | CompileOnDemandLayer::getPerDylibResources(JITDylib &TargetD) { |
79 | std::lock_guard<std::mutex> Lock(CODLayerMutex); |
80 | |
81 | auto I = DylibResources.find(x: &TargetD); |
82 | if (I == DylibResources.end()) { |
83 | auto &ImplD = |
84 | getExecutionSession().createBareJITDylib(Name: TargetD.getName() + ".impl" ); |
85 | JITDylibSearchOrder NewLinkOrder; |
86 | TargetD.withLinkOrderDo(F: [&](const JITDylibSearchOrder &TargetLinkOrder) { |
87 | NewLinkOrder = TargetLinkOrder; |
88 | }); |
89 | |
90 | assert(!NewLinkOrder.empty() && NewLinkOrder.front().first == &TargetD && |
91 | NewLinkOrder.front().second == |
92 | JITDylibLookupFlags::MatchAllSymbols && |
93 | "TargetD must be at the front of its own search order and match " |
94 | "non-exported symbol" ); |
95 | NewLinkOrder.insert(position: std::next(x: NewLinkOrder.begin()), |
96 | x: {&ImplD, JITDylibLookupFlags::MatchAllSymbols}); |
97 | ImplD.setLinkOrder(NewSearchOrder: NewLinkOrder, LinkAgainstThisJITDylibFirst: false); |
98 | TargetD.setLinkOrder(NewSearchOrder: std::move(NewLinkOrder), LinkAgainstThisJITDylibFirst: false); |
99 | |
100 | PerDylibResources PDR(ImplD, BuildIndirectStubsManager()); |
101 | I = DylibResources.insert(x: std::make_pair(x: &TargetD, y: std::move(PDR))).first; |
102 | } |
103 | |
104 | return I->second; |
105 | } |
106 | |