150
|
1 //===-------------------- Layer.cpp - Layer interfaces --------------------===//
|
|
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/Layer.h"
|
173
|
10
|
|
11 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
|
|
12 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
|
150
|
13 #include "llvm/IR/Constants.h"
|
173
|
14 #include "llvm/Object/MachO.h"
|
150
|
15 #include "llvm/Object/ObjectFile.h"
|
|
16 #include "llvm/Support/Debug.h"
|
|
17
|
|
18 #define DEBUG_TYPE "orc"
|
|
19
|
|
20 namespace llvm {
|
|
21 namespace orc {
|
|
22
|
|
23 IRLayer::~IRLayer() {}
|
|
24
|
|
25 Error IRLayer::add(JITDylib &JD, ThreadSafeModule TSM, VModuleKey K) {
|
|
26 return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
|
|
27 *this, *getManglingOptions(), std::move(TSM), std::move(K)));
|
|
28 }
|
|
29
|
173
|
30 IRMaterializationUnit::IRMaterializationUnit(
|
|
31 ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,
|
|
32 ThreadSafeModule TSM, VModuleKey K)
|
|
33 : MaterializationUnit(SymbolFlagsMap(), nullptr, std::move(K)),
|
|
34 TSM(std::move(TSM)) {
|
150
|
35
|
|
36 assert(this->TSM && "Module must not be null");
|
|
37
|
|
38 MangleAndInterner Mangle(ES, this->TSM.getModuleUnlocked()->getDataLayout());
|
|
39 this->TSM.withModuleDo([&](Module &M) {
|
|
40 for (auto &G : M.global_values()) {
|
|
41 // Skip globals that don't generate symbols.
|
173
|
42
|
150
|
43 if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() ||
|
|
44 G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage())
|
|
45 continue;
|
|
46
|
|
47 // thread locals generate different symbols depending on whether or not
|
|
48 // emulated TLS is enabled.
|
|
49 if (G.isThreadLocal() && MO.EmulatedTLS) {
|
|
50 auto &GV = cast<GlobalVariable>(G);
|
|
51
|
|
52 auto Flags = JITSymbolFlags::fromGlobalValue(GV);
|
|
53
|
|
54 auto EmuTLSV = Mangle(("__emutls_v." + GV.getName()).str());
|
|
55 SymbolFlags[EmuTLSV] = Flags;
|
|
56 SymbolToDefinition[EmuTLSV] = &GV;
|
|
57
|
|
58 // If this GV has a non-zero initializer we'll need to emit an
|
|
59 // __emutls.t symbol too.
|
|
60 if (GV.hasInitializer()) {
|
|
61 const auto *InitVal = GV.getInitializer();
|
|
62
|
|
63 // Skip zero-initializers.
|
|
64 if (isa<ConstantAggregateZero>(InitVal))
|
|
65 continue;
|
|
66 const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
|
|
67 if (InitIntValue && InitIntValue->isZero())
|
|
68 continue;
|
|
69
|
|
70 auto EmuTLST = Mangle(("__emutls_t." + GV.getName()).str());
|
|
71 SymbolFlags[EmuTLST] = Flags;
|
|
72 }
|
|
73 continue;
|
|
74 }
|
|
75
|
|
76 // Otherwise we just need a normal linker mangling.
|
|
77 auto MangledName = Mangle(G.getName());
|
|
78 SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
|
|
79 SymbolToDefinition[MangledName] = &G;
|
|
80 }
|
173
|
81
|
|
82 // If we need an init symbol for this module then create one.
|
|
83 if (!llvm::empty(getStaticInitGVs(M))) {
|
|
84 size_t Counter = 0;
|
|
85
|
|
86 while (true) {
|
|
87 std::string InitSymbolName;
|
|
88 raw_string_ostream(InitSymbolName)
|
|
89 << "$." << M.getModuleIdentifier() << ".__inits." << Counter++;
|
|
90 InitSymbol = ES.intern(InitSymbolName);
|
|
91 if (SymbolFlags.count(InitSymbol))
|
|
92 continue;
|
|
93 SymbolFlags[InitSymbol] =
|
|
94 JITSymbolFlags::MaterializationSideEffectsOnly;
|
|
95 break;
|
|
96 }
|
|
97 }
|
150
|
98 });
|
|
99 }
|
|
100
|
|
101 IRMaterializationUnit::IRMaterializationUnit(
|
|
102 ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags,
|
173
|
103 SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition)
|
|
104 : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol),
|
|
105 std::move(K)),
|
150
|
106 TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {}
|
|
107
|
|
108 StringRef IRMaterializationUnit::getName() const {
|
|
109 if (TSM)
|
|
110 return TSM.withModuleDo(
|
|
111 [](const Module &M) -> StringRef { return M.getModuleIdentifier(); });
|
|
112 return "<null module>";
|
|
113 }
|
|
114
|
|
115 void IRMaterializationUnit::discard(const JITDylib &JD,
|
|
116 const SymbolStringPtr &Name) {
|
|
117 LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {
|
|
118 dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@"
|
|
119 << this << " (" << getName() << ")\n";
|
|
120 }););
|
|
121
|
|
122 auto I = SymbolToDefinition.find(Name);
|
|
123 assert(I != SymbolToDefinition.end() &&
|
|
124 "Symbol not provided by this MU, or previously discarded");
|
|
125 assert(!I->second->isDeclaration() &&
|
|
126 "Discard should only apply to definitions");
|
|
127 I->second->setLinkage(GlobalValue::AvailableExternallyLinkage);
|
|
128 SymbolToDefinition.erase(I);
|
|
129 }
|
|
130
|
|
131 BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
|
173
|
132 IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM,
|
|
133 VModuleKey K)
|
150
|
134 : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM),
|
|
135 std::move(K)),
|
|
136 L(L), K(std::move(K)) {}
|
|
137
|
|
138 void BasicIRLayerMaterializationUnit::materialize(
|
|
139 MaterializationResponsibility R) {
|
|
140
|
|
141 // Throw away the SymbolToDefinition map: it's not usable after we hand
|
|
142 // off the module.
|
|
143 SymbolToDefinition.clear();
|
|
144
|
|
145 // If cloneToNewContextOnEmit is set, clone the module now.
|
|
146 if (L.getCloneToNewContextOnEmit())
|
|
147 TSM = cloneToNewContext(TSM);
|
|
148
|
|
149 #ifndef NDEBUG
|
|
150 auto &ES = R.getTargetJITDylib().getExecutionSession();
|
|
151 auto &N = R.getTargetJITDylib().getName();
|
|
152 #endif // NDEBUG
|
|
153
|
|
154 LLVM_DEBUG(ES.runSessionLocked(
|
|
155 [&]() { dbgs() << "Emitting, for " << N << ", " << *this << "\n"; }););
|
|
156 L.emit(std::move(R), std::move(TSM));
|
|
157 LLVM_DEBUG(ES.runSessionLocked([&]() {
|
|
158 dbgs() << "Finished emitting, for " << N << ", " << *this << "\n";
|
|
159 }););
|
|
160 }
|
|
161
|
|
162 ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
|
|
163
|
|
164 ObjectLayer::~ObjectLayer() {}
|
|
165
|
|
166 Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O,
|
|
167 VModuleKey K) {
|
|
168 auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(K),
|
|
169 std::move(O));
|
|
170 if (!ObjMU)
|
|
171 return ObjMU.takeError();
|
|
172 return JD.define(std::move(*ObjMU));
|
|
173 }
|
|
174
|
|
175 Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
|
|
176 BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K,
|
|
177 std::unique_ptr<MemoryBuffer> O) {
|
173
|
178 auto ObjSymInfo =
|
|
179 getObjectSymbolInfo(L.getExecutionSession(), O->getMemBufferRef());
|
150
|
180
|
173
|
181 if (!ObjSymInfo)
|
|
182 return ObjSymInfo.takeError();
|
|
183
|
|
184 auto &SymbolFlags = ObjSymInfo->first;
|
|
185 auto &InitSymbol = ObjSymInfo->second;
|
150
|
186
|
|
187 return std::unique_ptr<BasicObjectLayerMaterializationUnit>(
|
173
|
188 new BasicObjectLayerMaterializationUnit(
|
|
189 L, K, std::move(O), std::move(SymbolFlags), std::move(InitSymbol)));
|
150
|
190 }
|
|
191
|
|
192 BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(
|
|
193 ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O,
|
173
|
194 SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol)
|
|
195 : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol),
|
|
196 std::move(K)),
|
|
197 L(L), O(std::move(O)) {}
|
150
|
198
|
|
199 StringRef BasicObjectLayerMaterializationUnit::getName() const {
|
|
200 if (O)
|
|
201 return O->getBufferIdentifier();
|
|
202 return "<null object>";
|
|
203 }
|
|
204
|
|
205 void BasicObjectLayerMaterializationUnit::materialize(
|
|
206 MaterializationResponsibility R) {
|
|
207 L.emit(std::move(R), std::move(O));
|
|
208 }
|
|
209
|
|
210 void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD,
|
|
211 const SymbolStringPtr &Name) {
|
173
|
212 // This is a no-op for object files: Having removed 'Name' from SymbolFlags
|
|
213 // the symbol will be dead-stripped by the JIT linker.
|
150
|
214 }
|
|
215
|
|
216 } // End namespace orc.
|
|
217 } // End namespace llvm.
|