Mercurial > hg > CbC > CbC_llvm
comparison llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 0572611fdcc8 |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 //===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld backed ORC ObjectLayer -===// | |
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/RTDyldObjectLinkingLayer.h" | |
10 #include "llvm/Object/COFF.h" | |
11 | |
12 namespace { | |
13 | |
14 using namespace llvm; | |
15 using namespace llvm::orc; | |
16 | |
17 class JITDylibSearchOrderResolver : public JITSymbolResolver { | |
18 public: | |
19 JITDylibSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {} | |
20 | |
21 void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) { | |
22 auto &ES = MR.getTargetJITDylib().getExecutionSession(); | |
23 SymbolLookupSet InternedSymbols; | |
24 | |
25 // Intern the requested symbols: lookup takes interned strings. | |
26 for (auto &S : Symbols) | |
27 InternedSymbols.add(ES.intern(S)); | |
28 | |
29 // Build an OnResolve callback to unwrap the interned strings and pass them | |
30 // to the OnResolved callback. | |
31 auto OnResolvedWithUnwrap = | |
32 [OnResolved = std::move(OnResolved)]( | |
33 Expected<SymbolMap> InternedResult) mutable { | |
34 if (!InternedResult) { | |
35 OnResolved(InternedResult.takeError()); | |
36 return; | |
37 } | |
38 | |
39 LookupResult Result; | |
40 for (auto &KV : *InternedResult) | |
41 Result[*KV.first] = std::move(KV.second); | |
42 OnResolved(Result); | |
43 }; | |
44 | |
45 // Register dependencies for all symbols contained in this set. | |
46 auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) { | |
47 MR.addDependenciesForAll(Deps); | |
48 }; | |
49 | |
50 JITDylibSearchOrder SearchOrder; | |
51 MR.getTargetJITDylib().withSearchOrderDo( | |
52 [&](const JITDylibSearchOrder &JDs) { SearchOrder = JDs; }); | |
53 ES.lookup(LookupKind::Static, SearchOrder, InternedSymbols, | |
54 SymbolState::Resolved, std::move(OnResolvedWithUnwrap), | |
55 RegisterDependencies); | |
56 } | |
57 | |
58 Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) { | |
59 LookupSet Result; | |
60 | |
61 for (auto &KV : MR.getSymbols()) { | |
62 if (Symbols.count(*KV.first)) | |
63 Result.insert(*KV.first); | |
64 } | |
65 | |
66 return Result; | |
67 } | |
68 | |
69 private: | |
70 MaterializationResponsibility &MR; | |
71 }; | |
72 | |
73 } // end anonymous namespace | |
74 | |
75 namespace llvm { | |
76 namespace orc { | |
77 | |
78 RTDyldObjectLinkingLayer::RTDyldObjectLinkingLayer( | |
79 ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager) | |
80 : ObjectLayer(ES), GetMemoryManager(GetMemoryManager) {} | |
81 | |
82 RTDyldObjectLinkingLayer::~RTDyldObjectLinkingLayer() { | |
83 std::lock_guard<std::mutex> Lock(RTDyldLayerMutex); | |
84 for (auto &MemMgr : MemMgrs) | |
85 MemMgr->deregisterEHFrames(); | |
86 } | |
87 | |
88 void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R, | |
89 std::unique_ptr<MemoryBuffer> O) { | |
90 assert(O && "Object must not be null"); | |
91 | |
92 // This method launches an asynchronous link step that will fulfill our | |
93 // materialization responsibility. We need to switch R to be heap | |
94 // allocated before that happens so it can live as long as the asynchronous | |
95 // link needs it to (i.e. it must be able to outlive this method). | |
96 auto SharedR = std::make_shared<MaterializationResponsibility>(std::move(R)); | |
97 | |
98 auto &ES = getExecutionSession(); | |
99 | |
100 // Create a MemoryBufferRef backed MemoryBuffer (i.e. shallow) copy of the | |
101 // the underlying buffer to pass into RuntimeDyld. This allows us to hold | |
102 // ownership of the real underlying buffer and return it to the user once | |
103 // the object has been emitted. | |
104 auto ObjBuffer = MemoryBuffer::getMemBuffer(O->getMemBufferRef(), false); | |
105 | |
106 auto Obj = object::ObjectFile::createObjectFile(*ObjBuffer); | |
107 | |
108 if (!Obj) { | |
109 getExecutionSession().reportError(Obj.takeError()); | |
110 SharedR->failMaterialization(); | |
111 return; | |
112 } | |
113 | |
114 // Collect the internal symbols from the object file: We will need to | |
115 // filter these later. | |
116 auto InternalSymbols = std::make_shared<std::set<StringRef>>(); | |
117 { | |
118 for (auto &Sym : (*Obj)->symbols()) { | |
119 if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) { | |
120 if (auto SymName = Sym.getName()) | |
121 InternalSymbols->insert(*SymName); | |
122 else { | |
123 ES.reportError(SymName.takeError()); | |
124 R.failMaterialization(); | |
125 return; | |
126 } | |
127 } | |
128 } | |
129 } | |
130 | |
131 auto K = R.getVModuleKey(); | |
132 RuntimeDyld::MemoryManager *MemMgr = nullptr; | |
133 | |
134 // Create a record a memory manager for this object. | |
135 { | |
136 auto Tmp = GetMemoryManager(); | |
137 std::lock_guard<std::mutex> Lock(RTDyldLayerMutex); | |
138 MemMgrs.push_back(std::move(Tmp)); | |
139 MemMgr = MemMgrs.back().get(); | |
140 } | |
141 | |
142 JITDylibSearchOrderResolver Resolver(*SharedR); | |
143 | |
144 jitLinkForORC( | |
145 **Obj, std::move(O), *MemMgr, Resolver, ProcessAllSections, | |
146 [this, K, SharedR, &Obj, InternalSymbols]( | |
147 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo, | |
148 std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) { | |
149 return onObjLoad(K, *SharedR, **Obj, std::move(LoadedObjInfo), | |
150 ResolvedSymbols, *InternalSymbols); | |
151 }, | |
152 [this, K, SharedR, O = std::move(O)](Error Err) mutable { | |
153 onObjEmit(K, std::move(O), *SharedR, std::move(Err)); | |
154 }); | |
155 } | |
156 | |
157 Error RTDyldObjectLinkingLayer::onObjLoad( | |
158 VModuleKey K, MaterializationResponsibility &R, object::ObjectFile &Obj, | |
159 std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo, | |
160 std::map<StringRef, JITEvaluatedSymbol> Resolved, | |
161 std::set<StringRef> &InternalSymbols) { | |
162 SymbolFlagsMap ExtraSymbolsToClaim; | |
163 SymbolMap Symbols; | |
164 | |
165 // Hack to support COFF constant pool comdats introduced during compilation: | |
166 // (See http://llvm.org/PR40074) | |
167 if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(&Obj)) { | |
168 auto &ES = getExecutionSession(); | |
169 | |
170 // For all resolved symbols that are not already in the responsibilty set: | |
171 // check whether the symbol is in a comdat section and if so mark it as | |
172 // weak. | |
173 for (auto &Sym : COFFObj->symbols()) { | |
174 if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) | |
175 continue; | |
176 auto Name = Sym.getName(); | |
177 if (!Name) | |
178 return Name.takeError(); | |
179 auto I = Resolved.find(*Name); | |
180 | |
181 // Skip unresolved symbols, internal symbols, and symbols that are | |
182 // already in the responsibility set. | |
183 if (I == Resolved.end() || InternalSymbols.count(*Name) || | |
184 R.getSymbols().count(ES.intern(*Name))) | |
185 continue; | |
186 auto Sec = Sym.getSection(); | |
187 if (!Sec) | |
188 return Sec.takeError(); | |
189 if (*Sec == COFFObj->section_end()) | |
190 continue; | |
191 auto &COFFSec = *COFFObj->getCOFFSection(**Sec); | |
192 if (COFFSec.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) | |
193 I->second.setFlags(I->second.getFlags() | JITSymbolFlags::Weak); | |
194 } | |
195 } | |
196 | |
197 for (auto &KV : Resolved) { | |
198 // Scan the symbols and add them to the Symbols map for resolution. | |
199 | |
200 // We never claim internal symbols. | |
201 if (InternalSymbols.count(KV.first)) | |
202 continue; | |
203 | |
204 auto InternedName = getExecutionSession().intern(KV.first); | |
205 auto Flags = KV.second.getFlags(); | |
206 | |
207 // Override object flags and claim responsibility for symbols if | |
208 // requested. | |
209 if (OverrideObjectFlags || AutoClaimObjectSymbols) { | |
210 auto I = R.getSymbols().find(InternedName); | |
211 | |
212 if (OverrideObjectFlags && I != R.getSymbols().end()) | |
213 Flags = I->second; | |
214 else if (AutoClaimObjectSymbols && I == R.getSymbols().end()) | |
215 ExtraSymbolsToClaim[InternedName] = Flags; | |
216 } | |
217 | |
218 Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags); | |
219 } | |
220 | |
221 if (!ExtraSymbolsToClaim.empty()) { | |
222 if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim)) | |
223 return Err; | |
224 | |
225 // If we claimed responsibility for any weak symbols but were rejected then | |
226 // we need to remove them from the resolved set. | |
227 for (auto &KV : ExtraSymbolsToClaim) | |
228 if (KV.second.isWeak() && !R.getSymbols().count(KV.first)) | |
229 Symbols.erase(KV.first); | |
230 } | |
231 | |
232 if (auto Err = R.notifyResolved(Symbols)) { | |
233 R.failMaterialization(); | |
234 return Err; | |
235 } | |
236 | |
237 if (NotifyLoaded) | |
238 NotifyLoaded(K, Obj, *LoadedObjInfo); | |
239 | |
240 return Error::success(); | |
241 } | |
242 | |
243 void RTDyldObjectLinkingLayer::onObjEmit( | |
244 VModuleKey K, std::unique_ptr<MemoryBuffer> ObjBuffer, | |
245 MaterializationResponsibility &R, Error Err) { | |
246 if (Err) { | |
247 getExecutionSession().reportError(std::move(Err)); | |
248 R.failMaterialization(); | |
249 return; | |
250 } | |
251 | |
252 if (auto Err = R.notifyEmitted()) { | |
253 getExecutionSession().reportError(std::move(Err)); | |
254 R.failMaterialization(); | |
255 return; | |
256 } | |
257 | |
258 if (NotifyEmitted) | |
259 NotifyEmitted(K, std::move(ObjBuffer)); | |
260 } | |
261 | |
262 LegacyRTDyldObjectLinkingLayer::LegacyRTDyldObjectLinkingLayer( | |
263 ExecutionSession &ES, ResourcesGetter GetResources, | |
264 NotifyLoadedFtor NotifyLoaded, NotifyFinalizedFtor NotifyFinalized, | |
265 NotifyFreedFtor NotifyFreed) | |
266 : ES(ES), GetResources(std::move(GetResources)), | |
267 NotifyLoaded(std::move(NotifyLoaded)), | |
268 NotifyFinalized(std::move(NotifyFinalized)), | |
269 NotifyFreed(std::move(NotifyFreed)), ProcessAllSections(false) {} | |
270 | |
271 } // End namespace orc. | |
272 } // End namespace llvm. |