1 //===----- CompileOnDemandLayer.cpp - Lazily emit IR on first call --------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
10 #include "llvm/ExecutionEngine/Orc/Layer.h"
11 #include "llvm/IR/Module.h"
14 using namespace llvm::orc
;
16 CompileOnDemandLayer::CompileOnDemandLayer(
17 ExecutionSession
&ES
, IRLayer
&BaseLayer
, LazyCallThroughManager
&LCTMgr
,
18 IndirectStubsManagerBuilder BuildIndirectStubsManager
)
19 : IRLayer(ES
, BaseLayer
.getManglingOptions()), BaseLayer(BaseLayer
),
21 BuildIndirectStubsManager(std::move(BuildIndirectStubsManager
)) {}
23 void CompileOnDemandLayer::setImplMap(ImplSymbolMap
*Imp
) {
24 this->AliaseeImpls
= Imp
;
27 void CompileOnDemandLayer::emit(
28 std::unique_ptr
<MaterializationResponsibility
> R
, ThreadSafeModule TSM
) {
29 assert(TSM
&& "Null module");
31 auto &ES
= getExecutionSession();
33 // Sort the callables and non-callables, build re-exports and lodge the
34 // actual module with the implementation dylib.
35 auto &PDR
= getPerDylibResources(R
->getTargetJITDylib());
37 SymbolAliasMap NonCallables
;
38 SymbolAliasMap Callables
;
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
);
46 NonCallables
[Name
] = SymbolAliasMapEntry(Name
, Flags
);
49 // Lodge symbols with the implementation dylib.
50 if (auto Err
= PDR
.getImplDylib().define(
51 std::make_unique
<BasicIRLayerMaterializationUnit
>(
52 BaseLayer
, *getManglingOptions(), std::move(TSM
)))) {
53 ES
.reportError(std::move(Err
));
54 R
->failMaterialization();
58 if (!NonCallables
.empty())
60 R
->replace(reexports(PDR
.getImplDylib(), std::move(NonCallables
),
61 JITDylibLookupFlags::MatchAllSymbols
))) {
62 getExecutionSession().reportError(std::move(Err
));
63 R
->failMaterialization();
66 if (!Callables
.empty()) {
67 if (auto Err
= R
->replace(
68 lazyReexports(LCTMgr
, PDR
.getISManager(), PDR
.getImplDylib(),
69 std::move(Callables
), AliaseeImpls
))) {
70 getExecutionSession().reportError(std::move(Err
));
71 R
->failMaterialization();
77 CompileOnDemandLayer::PerDylibResources
&
78 CompileOnDemandLayer::getPerDylibResources(JITDylib
&TargetD
) {
79 std::lock_guard
<std::mutex
> Lock(CODLayerMutex
);
81 auto I
= DylibResources
.find(&TargetD
);
82 if (I
== DylibResources
.end()) {
84 getExecutionSession().createBareJITDylib(TargetD
.getName() + ".impl");
85 JITDylibSearchOrder NewLinkOrder
;
86 TargetD
.withLinkOrderDo([&](const JITDylibSearchOrder
&TargetLinkOrder
) {
87 NewLinkOrder
= TargetLinkOrder
;
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(std::next(NewLinkOrder
.begin()),
96 {&ImplD
, JITDylibLookupFlags::MatchAllSymbols
});
97 ImplD
.setLinkOrder(NewLinkOrder
, false);
98 TargetD
.setLinkOrder(std::move(NewLinkOrder
), false);
100 PerDylibResources
PDR(ImplD
, BuildIndirectStubsManager());
101 I
= DylibResources
.insert(std::make_pair(&TargetD
, std::move(PDR
))).first
;