File: | lib/ExecutionEngine/Orc/Layer.cpp |
Warning: | line 98, column 3 Method called on moved-from object 'R' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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" | |||
10 | #include "llvm/Object/ObjectFile.h" | |||
11 | #include "llvm/Support/Debug.h" | |||
12 | ||||
13 | #define DEBUG_TYPE"orc" "orc" | |||
14 | ||||
15 | namespace llvm { | |||
16 | namespace orc { | |||
17 | ||||
18 | IRLayer::IRLayer(ExecutionSession &ES) : ES(ES) {} | |||
19 | IRLayer::~IRLayer() {} | |||
20 | ||||
21 | Error IRLayer::add(JITDylib &JD, ThreadSafeModule TSM, VModuleKey K) { | |||
22 | return JD.define(llvm::make_unique<BasicIRLayerMaterializationUnit>( | |||
23 | *this, std::move(K), std::move(TSM))); | |||
24 | } | |||
25 | ||||
26 | IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES, | |||
27 | ThreadSafeModule TSM, VModuleKey K) | |||
28 | : MaterializationUnit(SymbolFlagsMap(), std::move(K)), TSM(std::move(TSM)) { | |||
29 | ||||
30 | assert(this->TSM && "Module must not be null")((this->TSM && "Module must not be null") ? static_cast <void> (0) : __assert_fail ("this->TSM && \"Module must not be null\"" , "/build/llvm-toolchain-snapshot-9~svn361194/lib/ExecutionEngine/Orc/Layer.cpp" , 30, __PRETTY_FUNCTION__)); | |||
31 | ||||
32 | MangleAndInterner Mangle(ES, this->TSM.getModule()->getDataLayout()); | |||
33 | for (auto &G : this->TSM.getModule()->global_values()) { | |||
34 | if (G.hasName() && !G.isDeclaration() && !G.hasLocalLinkage() && | |||
35 | !G.hasAvailableExternallyLinkage() && !G.hasAppendingLinkage()) { | |||
36 | auto MangledName = Mangle(G.getName()); | |||
37 | SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G); | |||
38 | SymbolToDefinition[MangledName] = &G; | |||
39 | } | |||
40 | } | |||
41 | } | |||
42 | ||||
43 | IRMaterializationUnit::IRMaterializationUnit( | |||
44 | ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags, | |||
45 | SymbolNameToDefinitionMap SymbolToDefinition) | |||
46 | : MaterializationUnit(std::move(SymbolFlags), std::move(K)), | |||
47 | TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {} | |||
48 | ||||
49 | StringRef IRMaterializationUnit::getName() const { | |||
50 | if (TSM.getModule()) | |||
51 | return TSM.getModule()->getModuleIdentifier(); | |||
52 | return "<null module>"; | |||
53 | } | |||
54 | ||||
55 | void IRMaterializationUnit::discard(const JITDylib &JD, | |||
56 | const SymbolStringPtr &Name) { | |||
57 | LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { JD.getExecutionSession().runSessionLocked([&]( ) { dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@" << this << " (" << getName() << ")\n"; });; } } while (false) | |||
58 | dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { JD.getExecutionSession().runSessionLocked([&]( ) { dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@" << this << " (" << getName() << ")\n"; });; } } while (false) | |||
59 | << this << " (" << getName() << ")\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { JD.getExecutionSession().runSessionLocked([&]( ) { dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@" << this << " (" << getName() << ")\n"; });; } } while (false) | |||
60 | });)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { JD.getExecutionSession().runSessionLocked([&]( ) { dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@" << this << " (" << getName() << ")\n"; });; } } while (false); | |||
61 | ||||
62 | auto I = SymbolToDefinition.find(Name); | |||
63 | assert(I != SymbolToDefinition.end() &&((I != SymbolToDefinition.end() && "Symbol not provided by this MU, or previously discarded" ) ? static_cast<void> (0) : __assert_fail ("I != SymbolToDefinition.end() && \"Symbol not provided by this MU, or previously discarded\"" , "/build/llvm-toolchain-snapshot-9~svn361194/lib/ExecutionEngine/Orc/Layer.cpp" , 64, __PRETTY_FUNCTION__)) | |||
64 | "Symbol not provided by this MU, or previously discarded")((I != SymbolToDefinition.end() && "Symbol not provided by this MU, or previously discarded" ) ? static_cast<void> (0) : __assert_fail ("I != SymbolToDefinition.end() && \"Symbol not provided by this MU, or previously discarded\"" , "/build/llvm-toolchain-snapshot-9~svn361194/lib/ExecutionEngine/Orc/Layer.cpp" , 64, __PRETTY_FUNCTION__)); | |||
65 | assert(!I->second->isDeclaration() &&((!I->second->isDeclaration() && "Discard should only apply to definitions" ) ? static_cast<void> (0) : __assert_fail ("!I->second->isDeclaration() && \"Discard should only apply to definitions\"" , "/build/llvm-toolchain-snapshot-9~svn361194/lib/ExecutionEngine/Orc/Layer.cpp" , 66, __PRETTY_FUNCTION__)) | |||
66 | "Discard should only apply to definitions")((!I->second->isDeclaration() && "Discard should only apply to definitions" ) ? static_cast<void> (0) : __assert_fail ("!I->second->isDeclaration() && \"Discard should only apply to definitions\"" , "/build/llvm-toolchain-snapshot-9~svn361194/lib/ExecutionEngine/Orc/Layer.cpp" , 66, __PRETTY_FUNCTION__)); | |||
67 | I->second->setLinkage(GlobalValue::AvailableExternallyLinkage); | |||
68 | SymbolToDefinition.erase(I); | |||
69 | } | |||
70 | ||||
71 | BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit( | |||
72 | IRLayer &L, VModuleKey K, ThreadSafeModule TSM) | |||
73 | : IRMaterializationUnit(L.getExecutionSession(), std::move(TSM), | |||
74 | std::move(K)), | |||
75 | L(L), K(std::move(K)) {} | |||
76 | ||||
77 | void BasicIRLayerMaterializationUnit::materialize( | |||
78 | MaterializationResponsibility R) { | |||
79 | ||||
80 | // Throw away the SymbolToDefinition map: it's not usable after we hand | |||
81 | // off the module. | |||
82 | SymbolToDefinition.clear(); | |||
83 | ||||
84 | // If cloneToNewContextOnEmit is set, clone the module now. | |||
85 | if (L.getCloneToNewContextOnEmit()) | |||
| ||||
86 | TSM = cloneToNewContext(TSM); | |||
87 | ||||
88 | #ifndef NDEBUG | |||
89 | auto &ES = R.getTargetJITDylib().getExecutionSession(); | |||
90 | #endif // NDEBUG | |||
91 | ||||
92 | auto Lock = TSM.getContextLock(); | |||
93 | LLVM_DEBUG(ES.runSessionLocked([&]() {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { ES.runSessionLocked([&]() { dbgs() << "Emitting, for " << R.getTargetJITDylib().getName() << ", " << *this << "\n"; });; } } while (false) | |||
94 | dbgs() << "Emitting, for " << R.getTargetJITDylib().getName() << ", "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { ES.runSessionLocked([&]() { dbgs() << "Emitting, for " << R.getTargetJITDylib().getName() << ", " << *this << "\n"; });; } } while (false) | |||
95 | << *this << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { ES.runSessionLocked([&]() { dbgs() << "Emitting, for " << R.getTargetJITDylib().getName() << ", " << *this << "\n"; });; } } while (false) | |||
96 | });)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { ES.runSessionLocked([&]() { dbgs() << "Emitting, for " << R.getTargetJITDylib().getName() << ", " << *this << "\n"; });; } } while (false); | |||
97 | L.emit(std::move(R), std::move(TSM)); | |||
98 | LLVM_DEBUG(ES.runSessionLocked([&]() {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { ES.runSessionLocked([&]() { dbgs() << "Finished emitting, for " << R.getTargetJITDylib().getName() << ", " << *this << "\n"; });; } } while (false) | |||
| ||||
99 | dbgs() << "Finished emitting, for " << R.getTargetJITDylib().getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { ES.runSessionLocked([&]() { dbgs() << "Finished emitting, for " << R.getTargetJITDylib().getName() << ", " << *this << "\n"; });; } } while (false) | |||
100 | << ", " << *this << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { ES.runSessionLocked([&]() { dbgs() << "Finished emitting, for " << R.getTargetJITDylib().getName() << ", " << *this << "\n"; });; } } while (false) | |||
101 | });)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { ES.runSessionLocked([&]() { dbgs() << "Finished emitting, for " << R.getTargetJITDylib().getName() << ", " << *this << "\n"; });; } } while (false); | |||
102 | } | |||
103 | ||||
104 | ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {} | |||
105 | ||||
106 | ObjectLayer::~ObjectLayer() {} | |||
107 | ||||
108 | Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O, | |||
109 | VModuleKey K) { | |||
110 | auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(K), | |||
111 | std::move(O)); | |||
112 | if (!ObjMU) | |||
113 | return ObjMU.takeError(); | |||
114 | return JD.define(std::move(*ObjMU)); | |||
115 | } | |||
116 | ||||
117 | Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>> | |||
118 | BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K, | |||
119 | std::unique_ptr<MemoryBuffer> O) { | |||
120 | auto SymbolFlags = | |||
121 | getObjectSymbolFlags(L.getExecutionSession(), O->getMemBufferRef()); | |||
122 | ||||
123 | if (!SymbolFlags) | |||
124 | return SymbolFlags.takeError(); | |||
125 | ||||
126 | return std::unique_ptr<BasicObjectLayerMaterializationUnit>( | |||
127 | new BasicObjectLayerMaterializationUnit(L, K, std::move(O), | |||
128 | std::move(*SymbolFlags))); | |||
129 | } | |||
130 | ||||
131 | BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit( | |||
132 | ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O, | |||
133 | SymbolFlagsMap SymbolFlags) | |||
134 | : MaterializationUnit(std::move(SymbolFlags), std::move(K)), L(L), | |||
135 | O(std::move(O)) {} | |||
136 | ||||
137 | StringRef BasicObjectLayerMaterializationUnit::getName() const { | |||
138 | if (O) | |||
139 | return O->getBufferIdentifier(); | |||
140 | return "<null object>"; | |||
141 | } | |||
142 | ||||
143 | void BasicObjectLayerMaterializationUnit::materialize( | |||
144 | MaterializationResponsibility R) { | |||
145 | L.emit(std::move(R), std::move(O)); | |||
146 | } | |||
147 | ||||
148 | void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD, | |||
149 | const SymbolStringPtr &Name) { | |||
150 | // FIXME: Support object file level discard. This could be done by building a | |||
151 | // filter to pass to the object layer along with the object itself. | |||
152 | } | |||
153 | ||||
154 | Expected<SymbolFlagsMap> getObjectSymbolFlags(ExecutionSession &ES, | |||
155 | MemoryBufferRef ObjBuffer) { | |||
156 | auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); | |||
157 | ||||
158 | if (!Obj) | |||
159 | return Obj.takeError(); | |||
160 | ||||
161 | SymbolFlagsMap SymbolFlags; | |||
162 | for (auto &Sym : (*Obj)->symbols()) { | |||
163 | // Skip symbols not defined in this object file. | |||
164 | if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) | |||
165 | continue; | |||
166 | ||||
167 | // Skip symbols that are not global. | |||
168 | if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) | |||
169 | continue; | |||
170 | ||||
171 | auto Name = Sym.getName(); | |||
172 | if (!Name) | |||
173 | return Name.takeError(); | |||
174 | auto InternedName = ES.intern(*Name); | |||
175 | auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); | |||
176 | if (!SymFlags) | |||
177 | return SymFlags.takeError(); | |||
178 | SymbolFlags[InternedName] = std::move(*SymFlags); | |||
179 | } | |||
180 | ||||
181 | return SymbolFlags; | |||
182 | } | |||
183 | ||||
184 | } // End namespace orc. | |||
185 | } // End namespace llvm. |
1 | //===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===// |
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 | // Contains core ORC APIs. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H |
14 | #define LLVM_EXECUTIONENGINE_ORC_CORE_H |
15 | |
16 | #include "llvm/ADT/BitmaskEnum.h" |
17 | #include "llvm/ExecutionEngine/JITSymbol.h" |
18 | #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" |
19 | #include "llvm/IR/Module.h" |
20 | #include "llvm/Support/Debug.h" |
21 | |
22 | #include <memory> |
23 | #include <vector> |
24 | |
25 | #define DEBUG_TYPE"orc" "orc" |
26 | |
27 | namespace llvm { |
28 | namespace orc { |
29 | |
30 | // Forward declare some classes. |
31 | class AsynchronousSymbolQuery; |
32 | class ExecutionSession; |
33 | class MaterializationUnit; |
34 | class MaterializationResponsibility; |
35 | class JITDylib; |
36 | |
37 | /// VModuleKey provides a unique identifier (allocated and managed by |
38 | /// ExecutionSessions) for a module added to the JIT. |
39 | using VModuleKey = uint64_t; |
40 | |
41 | /// A set of symbol names (represented by SymbolStringPtrs for |
42 | // efficiency). |
43 | using SymbolNameSet = DenseSet<SymbolStringPtr>; |
44 | |
45 | /// A map from symbol names (as SymbolStringPtrs) to JITSymbols |
46 | /// (address/flags pairs). |
47 | using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>; |
48 | |
49 | /// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags. |
50 | using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>; |
51 | |
52 | /// A base class for materialization failures that allows the failing |
53 | /// symbols to be obtained for logging. |
54 | using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>; |
55 | |
56 | /// A list of (JITDylib*, bool) pairs. |
57 | using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>; |
58 | |
59 | /// Render a SymbolStringPtr. |
60 | raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym); |
61 | |
62 | /// Render a SymbolNameSet. |
63 | raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols); |
64 | |
65 | /// Render a SymbolFlagsMap entry. |
66 | raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV); |
67 | |
68 | /// Render a SymbolMap entry. |
69 | raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV); |
70 | |
71 | /// Render a SymbolFlagsMap. |
72 | raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags); |
73 | |
74 | /// Render a SymbolMap. |
75 | raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols); |
76 | |
77 | /// Render a SymbolDependenceMap entry. |
78 | raw_ostream &operator<<(raw_ostream &OS, |
79 | const SymbolDependenceMap::value_type &KV); |
80 | |
81 | /// Render a SymbolDependendeMap. |
82 | raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps); |
83 | |
84 | /// Render a MaterializationUnit. |
85 | raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU); |
86 | |
87 | /// Render a JITDylibSearchList. |
88 | raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs); |
89 | |
90 | /// Callback to notify client that symbols have been resolved. |
91 | using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>; |
92 | |
93 | /// Callback to notify client that symbols are ready for execution. |
94 | using SymbolsReadyCallback = std::function<void(Error)>; |
95 | |
96 | /// Callback to register the dependencies for a given query. |
97 | using RegisterDependenciesFunction = |
98 | std::function<void(const SymbolDependenceMap &)>; |
99 | |
100 | /// This can be used as the value for a RegisterDependenciesFunction if there |
101 | /// are no dependants to register with. |
102 | extern RegisterDependenciesFunction NoDependenciesToRegister; |
103 | |
104 | /// Used to notify a JITDylib that the given set of symbols failed to |
105 | /// materialize. |
106 | class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> { |
107 | public: |
108 | static char ID; |
109 | |
110 | FailedToMaterialize(SymbolNameSet Symbols); |
111 | std::error_code convertToErrorCode() const override; |
112 | void log(raw_ostream &OS) const override; |
113 | const SymbolNameSet &getSymbols() const { return Symbols; } |
114 | |
115 | private: |
116 | SymbolNameSet Symbols; |
117 | }; |
118 | |
119 | /// Used to notify clients when symbols can not be found during a lookup. |
120 | class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> { |
121 | public: |
122 | static char ID; |
123 | |
124 | SymbolsNotFound(SymbolNameSet Symbols); |
125 | std::error_code convertToErrorCode() const override; |
126 | void log(raw_ostream &OS) const override; |
127 | const SymbolNameSet &getSymbols() const { return Symbols; } |
128 | |
129 | private: |
130 | SymbolNameSet Symbols; |
131 | }; |
132 | |
133 | /// Used to notify clients that a set of symbols could not be removed. |
134 | class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> { |
135 | public: |
136 | static char ID; |
137 | |
138 | SymbolsCouldNotBeRemoved(SymbolNameSet Symbols); |
139 | std::error_code convertToErrorCode() const override; |
140 | void log(raw_ostream &OS) const override; |
141 | const SymbolNameSet &getSymbols() const { return Symbols; } |
142 | |
143 | private: |
144 | SymbolNameSet Symbols; |
145 | }; |
146 | |
147 | /// Tracks responsibility for materialization, and mediates interactions between |
148 | /// MaterializationUnits and JDs. |
149 | /// |
150 | /// An instance of this class is passed to MaterializationUnits when their |
151 | /// materialize method is called. It allows MaterializationUnits to resolve and |
152 | /// emit symbols, or abandon materialization by notifying any unmaterialized |
153 | /// symbols of an error. |
154 | class MaterializationResponsibility { |
155 | friend class MaterializationUnit; |
156 | public: |
157 | MaterializationResponsibility(MaterializationResponsibility &&) = default; |
158 | MaterializationResponsibility & |
159 | operator=(MaterializationResponsibility &&) = delete; |
160 | |
161 | /// Destruct a MaterializationResponsibility instance. In debug mode |
162 | /// this asserts that all symbols being tracked have been either |
163 | /// emitted or notified of an error. |
164 | ~MaterializationResponsibility(); |
165 | |
166 | /// Returns the target JITDylib that these symbols are being materialized |
167 | /// into. |
168 | JITDylib &getTargetJITDylib() const { return JD; } |
169 | |
170 | /// Returns the VModuleKey for this instance. |
171 | VModuleKey getVModuleKey() const { return K; } |
172 | |
173 | /// Returns the symbol flags map for this responsibility instance. |
174 | /// Note: The returned flags may have transient flags (Lazy, Materializing) |
175 | /// set. These should be stripped with JITSymbolFlags::stripTransientFlags |
176 | /// before using. |
177 | const SymbolFlagsMap &getSymbols() const { return SymbolFlags; } |
178 | |
179 | /// Returns the names of any symbols covered by this |
180 | /// MaterializationResponsibility object that have queries pending. This |
181 | /// information can be used to return responsibility for unrequested symbols |
182 | /// back to the JITDylib via the delegate method. |
183 | SymbolNameSet getRequestedSymbols() const; |
184 | |
185 | /// Notifies the target JITDylib that the given symbols have been resolved. |
186 | /// This will update the given symbols' addresses in the JITDylib, and notify |
187 | /// any pending queries on the given symbols of their resolution. The given |
188 | /// symbols must be ones covered by this MaterializationResponsibility |
189 | /// instance. Individual calls to this method may resolve a subset of the |
190 | /// symbols, but all symbols must have been resolved prior to calling emit. |
191 | void resolve(const SymbolMap &Symbols); |
192 | |
193 | /// Notifies the target JITDylib (and any pending queries on that JITDylib) |
194 | /// that all symbols covered by this MaterializationResponsibility instance |
195 | /// have been emitted. |
196 | void emit(); |
197 | |
198 | /// Adds new symbols to the JITDylib and this responsibility instance. |
199 | /// JITDylib entries start out in the materializing state. |
200 | /// |
201 | /// This method can be used by materialization units that want to add |
202 | /// additional symbols at materialization time (e.g. stubs, compile |
203 | /// callbacks, metadata). |
204 | Error defineMaterializing(const SymbolFlagsMap &SymbolFlags); |
205 | |
206 | /// Notify all not-yet-emitted covered by this MaterializationResponsibility |
207 | /// instance that an error has occurred. |
208 | /// This will remove all symbols covered by this MaterializationResponsibilty |
209 | /// from the target JITDylib, and send an error to any queries waiting on |
210 | /// these symbols. |
211 | void failMaterialization(); |
212 | |
213 | /// Transfers responsibility to the given MaterializationUnit for all |
214 | /// symbols defined by that MaterializationUnit. This allows |
215 | /// materializers to break up work based on run-time information (e.g. |
216 | /// by introspecting which symbols have actually been looked up and |
217 | /// materializing only those). |
218 | void replace(std::unique_ptr<MaterializationUnit> MU); |
219 | |
220 | /// Delegates responsibility for the given symbols to the returned |
221 | /// materialization responsibility. Useful for breaking up work between |
222 | /// threads, or different kinds of materialization processes. |
223 | MaterializationResponsibility delegate(const SymbolNameSet &Symbols, |
224 | VModuleKey NewKey = VModuleKey()); |
225 | |
226 | void addDependencies(const SymbolStringPtr &Name, |
227 | const SymbolDependenceMap &Dependencies); |
228 | |
229 | /// Add dependencies that apply to all symbols covered by this instance. |
230 | void addDependenciesForAll(const SymbolDependenceMap &Dependencies); |
231 | |
232 | private: |
233 | /// Create a MaterializationResponsibility for the given JITDylib and |
234 | /// initial symbols. |
235 | MaterializationResponsibility(JITDylib &JD, SymbolFlagsMap SymbolFlags, |
236 | VModuleKey K); |
237 | |
238 | JITDylib &JD; |
239 | SymbolFlagsMap SymbolFlags; |
240 | VModuleKey K; |
241 | }; |
242 | |
243 | /// A MaterializationUnit represents a set of symbol definitions that can |
244 | /// be materialized as a group, or individually discarded (when |
245 | /// overriding definitions are encountered). |
246 | /// |
247 | /// MaterializationUnits are used when providing lazy definitions of symbols to |
248 | /// JITDylibs. The JITDylib will call materialize when the address of a symbol |
249 | /// is requested via the lookup method. The JITDylib will call discard if a |
250 | /// stronger definition is added or already present. |
251 | class MaterializationUnit { |
252 | public: |
253 | MaterializationUnit(SymbolFlagsMap InitalSymbolFlags, VModuleKey K) |
254 | : SymbolFlags(std::move(InitalSymbolFlags)), K(std::move(K)) {} |
255 | |
256 | virtual ~MaterializationUnit() {} |
257 | |
258 | /// Return the name of this materialization unit. Useful for debugging |
259 | /// output. |
260 | virtual StringRef getName() const = 0; |
261 | |
262 | /// Return the set of symbols that this source provides. |
263 | const SymbolFlagsMap &getSymbols() const { return SymbolFlags; } |
264 | |
265 | /// Called by materialization dispatchers (see |
266 | /// ExecutionSession::DispatchMaterializationFunction) to trigger |
267 | /// materialization of this MaterializationUnit. |
268 | void doMaterialize(JITDylib &JD) { |
269 | materialize(MaterializationResponsibility(JD, std::move(SymbolFlags), |
270 | std::move(K))); |
271 | } |
272 | |
273 | /// Called by JITDylibs to notify MaterializationUnits that the given symbol |
274 | /// has been overridden. |
275 | void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name) { |
276 | SymbolFlags.erase(Name); |
277 | discard(JD, std::move(Name)); |
278 | } |
279 | |
280 | protected: |
281 | SymbolFlagsMap SymbolFlags; |
282 | VModuleKey K; |
283 | |
284 | private: |
285 | virtual void anchor(); |
286 | |
287 | /// Implementations of this method should materialize all symbols |
288 | /// in the materialzation unit, except for those that have been |
289 | /// previously discarded. |
290 | virtual void materialize(MaterializationResponsibility R) = 0; |
291 | |
292 | /// Implementations of this method should discard the given symbol |
293 | /// from the source (e.g. if the source is an LLVM IR Module and the |
294 | /// symbol is a function, delete the function body or mark it available |
295 | /// externally). |
296 | virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0; |
297 | }; |
298 | |
299 | using MaterializationUnitList = |
300 | std::vector<std::unique_ptr<MaterializationUnit>>; |
301 | |
302 | /// A MaterializationUnit implementation for pre-existing absolute symbols. |
303 | /// |
304 | /// All symbols will be resolved and marked ready as soon as the unit is |
305 | /// materialized. |
306 | class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit { |
307 | public: |
308 | AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols, VModuleKey K); |
309 | |
310 | StringRef getName() const override; |
311 | |
312 | private: |
313 | void materialize(MaterializationResponsibility R) override; |
314 | void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; |
315 | static SymbolFlagsMap extractFlags(const SymbolMap &Symbols); |
316 | |
317 | SymbolMap Symbols; |
318 | }; |
319 | |
320 | /// Create an AbsoluteSymbolsMaterializationUnit with the given symbols. |
321 | /// Useful for inserting absolute symbols into a JITDylib. E.g.: |
322 | /// \code{.cpp} |
323 | /// JITDylib &JD = ...; |
324 | /// SymbolStringPtr Foo = ...; |
325 | /// JITEvaluatedSymbol FooSym = ...; |
326 | /// if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}}))) |
327 | /// return Err; |
328 | /// \endcode |
329 | /// |
330 | inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit> |
331 | absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) { |
332 | return llvm::make_unique<AbsoluteSymbolsMaterializationUnit>( |
333 | std::move(Symbols), std::move(K)); |
334 | } |
335 | |
336 | struct SymbolAliasMapEntry { |
337 | SymbolAliasMapEntry() = default; |
338 | SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags) |
339 | : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {} |
340 | |
341 | SymbolStringPtr Aliasee; |
342 | JITSymbolFlags AliasFlags; |
343 | }; |
344 | |
345 | /// A map of Symbols to (Symbol, Flags) pairs. |
346 | using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>; |
347 | |
348 | /// A materialization unit for symbol aliases. Allows existing symbols to be |
349 | /// aliased with alternate flags. |
350 | class ReExportsMaterializationUnit : public MaterializationUnit { |
351 | public: |
352 | /// SourceJD is allowed to be nullptr, in which case the source JITDylib is |
353 | /// taken to be whatever JITDylib these definitions are materialized in (and |
354 | /// MatchNonExported has no effect). This is useful for defining aliases |
355 | /// within a JITDylib. |
356 | /// |
357 | /// Note: Care must be taken that no sets of aliases form a cycle, as such |
358 | /// a cycle will result in a deadlock when any symbol in the cycle is |
359 | /// resolved. |
360 | ReExportsMaterializationUnit(JITDylib *SourceJD, bool MatchNonExported, |
361 | SymbolAliasMap Aliases, VModuleKey K); |
362 | |
363 | StringRef getName() const override; |
364 | |
365 | private: |
366 | void materialize(MaterializationResponsibility R) override; |
367 | void discard(const JITDylib &JD, const SymbolStringPtr &Name) override; |
368 | static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases); |
369 | |
370 | JITDylib *SourceJD = nullptr; |
371 | bool MatchNonExported = false; |
372 | SymbolAliasMap Aliases; |
373 | }; |
374 | |
375 | /// Create a ReExportsMaterializationUnit with the given aliases. |
376 | /// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing |
377 | /// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux" |
378 | /// (for "bar") with: \code{.cpp} |
379 | /// SymbolStringPtr Baz = ...; |
380 | /// SymbolStringPtr Qux = ...; |
381 | /// if (auto Err = JD.define(symbolAliases({ |
382 | /// {Baz, { Foo, JITSymbolFlags::Exported }}, |
383 | /// {Qux, { Bar, JITSymbolFlags::Weak }}})) |
384 | /// return Err; |
385 | /// \endcode |
386 | inline std::unique_ptr<ReExportsMaterializationUnit> |
387 | symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) { |
388 | return llvm::make_unique<ReExportsMaterializationUnit>( |
389 | nullptr, true, std::move(Aliases), std::move(K)); |
390 | } |
391 | |
392 | /// Create a materialization unit for re-exporting symbols from another JITDylib |
393 | /// with alternative names/flags. |
394 | /// If MatchNonExported is true then non-exported symbols from SourceJD can be |
395 | /// re-exported. If it is false, attempts to re-export a non-exported symbol |
396 | /// will result in a "symbol not found" error. |
397 | inline std::unique_ptr<ReExportsMaterializationUnit> |
398 | reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, |
399 | bool MatchNonExported = false, VModuleKey K = VModuleKey()) { |
400 | return llvm::make_unique<ReExportsMaterializationUnit>( |
401 | &SourceJD, MatchNonExported, std::move(Aliases), std::move(K)); |
402 | } |
403 | |
404 | /// Build a SymbolAliasMap for the common case where you want to re-export |
405 | /// symbols from another JITDylib with the same linkage/flags. |
406 | Expected<SymbolAliasMap> |
407 | buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols); |
408 | |
409 | /// ReexportsGenerator can be used with JITDylib::setGenerator to automatically |
410 | /// re-export a subset of the source JITDylib's symbols in the target. |
411 | class ReexportsGenerator { |
412 | public: |
413 | using SymbolPredicate = std::function<bool(SymbolStringPtr)>; |
414 | |
415 | /// Create a reexports generator. If an Allow predicate is passed, only |
416 | /// symbols for which the predicate returns true will be reexported. If no |
417 | /// Allow predicate is passed, all symbols will be exported. |
418 | ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false, |
419 | SymbolPredicate Allow = SymbolPredicate()); |
420 | |
421 | Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names); |
422 | |
423 | private: |
424 | JITDylib &SourceJD; |
425 | bool MatchNonExported = false; |
426 | SymbolPredicate Allow; |
427 | }; |
428 | |
429 | /// A symbol query that returns results via a callback when results are |
430 | /// ready. |
431 | /// |
432 | /// makes a callback when all symbols are available. |
433 | class AsynchronousSymbolQuery { |
434 | friend class ExecutionSession; |
435 | friend class JITDylib; |
436 | friend class JITSymbolResolverAdapter; |
437 | |
438 | public: |
439 | |
440 | /// Create a query for the given symbols, notify-resolved and |
441 | /// notify-ready callbacks. |
442 | AsynchronousSymbolQuery(const SymbolNameSet &Symbols, |
443 | SymbolsResolvedCallback NotifySymbolsResolved, |
444 | SymbolsReadyCallback NotifySymbolsReady); |
445 | |
446 | /// Set the resolved symbol information for the given symbol name. |
447 | void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym); |
448 | |
449 | /// Returns true if all symbols covered by this query have been |
450 | /// resolved. |
451 | bool isFullyResolved() const { return NotYetResolvedCount == 0; } |
452 | |
453 | /// Call the NotifySymbolsResolved callback. |
454 | /// |
455 | /// This should only be called if all symbols covered by the query have been |
456 | /// resolved. |
457 | void handleFullyResolved(); |
458 | |
459 | /// Notify the query that a requested symbol is ready for execution. |
460 | void notifySymbolReady(); |
461 | |
462 | /// Returns true if all symbols covered by this query are ready. |
463 | bool isFullyReady() const { return NotYetReadyCount == 0; } |
464 | |
465 | /// Calls the NotifySymbolsReady callback. |
466 | /// |
467 | /// This should only be called if all symbols covered by this query are ready. |
468 | void handleFullyReady(); |
469 | |
470 | private: |
471 | void addQueryDependence(JITDylib &JD, SymbolStringPtr Name); |
472 | |
473 | void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name); |
474 | |
475 | bool canStillFail(); |
476 | |
477 | void handleFailed(Error Err); |
478 | |
479 | void detach(); |
480 | |
481 | SymbolsResolvedCallback NotifySymbolsResolved; |
482 | SymbolsReadyCallback NotifySymbolsReady; |
483 | SymbolDependenceMap QueryRegistrations; |
484 | SymbolMap ResolvedSymbols; |
485 | size_t NotYetResolvedCount; |
486 | size_t NotYetReadyCount; |
487 | }; |
488 | |
489 | /// A symbol table that supports asynchoronous symbol queries. |
490 | /// |
491 | /// Represents a virtual shared object. Instances can not be copied or moved, so |
492 | /// their addresses may be used as keys for resource management. |
493 | /// JITDylib state changes must be made via an ExecutionSession to guarantee |
494 | /// that they are synchronized with respect to other JITDylib operations. |
495 | class JITDylib { |
496 | friend class AsynchronousSymbolQuery; |
497 | friend class ExecutionSession; |
498 | friend class MaterializationResponsibility; |
499 | public: |
500 | using GeneratorFunction = std::function<Expected<SymbolNameSet>( |
501 | JITDylib &Parent, const SymbolNameSet &Names)>; |
502 | |
503 | using AsynchronousSymbolQuerySet = |
504 | std::set<std::shared_ptr<AsynchronousSymbolQuery>>; |
505 | |
506 | JITDylib(const JITDylib &) = delete; |
507 | JITDylib &operator=(const JITDylib &) = delete; |
508 | JITDylib(JITDylib &&) = delete; |
509 | JITDylib &operator=(JITDylib &&) = delete; |
510 | |
511 | /// Get the name for this JITDylib. |
512 | const std::string &getName() const { return JITDylibName; } |
513 | |
514 | /// Get a reference to the ExecutionSession for this JITDylib. |
515 | ExecutionSession &getExecutionSession() const { return ES; } |
516 | |
517 | /// Set a definition generator. If set, whenever a symbol fails to resolve |
518 | /// within this JITDylib, lookup and lookupFlags will pass the unresolved |
519 | /// symbols set to the definition generator. The generator can optionally |
520 | /// add a definition for the unresolved symbols to the dylib. |
521 | void setGenerator(GeneratorFunction DefGenerator) { |
522 | this->DefGenerator = std::move(DefGenerator); |
523 | } |
524 | |
525 | /// Set the search order to be used when fixing up definitions in JITDylib. |
526 | /// This will replace the previous search order, and apply to any symbol |
527 | /// resolutions made for definitions in this JITDylib after the call to |
528 | /// setSearchOrder (even if the definition itself was added before the |
529 | /// call). |
530 | /// |
531 | /// If SearchThisJITDylibFirst is set, which by default it is, then this |
532 | /// JITDylib will add itself to the beginning of the SearchOrder (Clients |
533 | /// should *not* put this JITDylib in the list in this case, to avoid |
534 | /// redundant lookups). |
535 | /// |
536 | /// If SearchThisJITDylibFirst is false then the search order will be used as |
537 | /// given. The main motivation for this feature is to support deliberate |
538 | /// shadowing of symbols in this JITDylib by a facade JITDylib. For example, |
539 | /// the facade may resolve function names to stubs, and the stubs may compile |
540 | /// lazily by looking up symbols in this dylib. Adding the facade dylib |
541 | /// as the first in the search order (instead of this dylib) ensures that |
542 | /// definitions within this dylib resolve to the lazy-compiling stubs, |
543 | /// rather than immediately materializing the definitions in this dylib. |
544 | void setSearchOrder(JITDylibSearchList NewSearchOrder, |
545 | bool SearchThisJITDylibFirst = true, |
546 | bool MatchNonExportedInThisDylib = true); |
547 | |
548 | /// Add the given JITDylib to the search order for definitions in this |
549 | /// JITDylib. |
550 | void addToSearchOrder(JITDylib &JD, bool MatcNonExported = false); |
551 | |
552 | /// Replace OldJD with NewJD in the search order if OldJD is present. |
553 | /// Otherwise this operation is a no-op. |
554 | void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD, |
555 | bool MatchNonExported = false); |
556 | |
557 | /// Remove the given JITDylib from the search order for this JITDylib if it is |
558 | /// present. Otherwise this operation is a no-op. |
559 | void removeFromSearchOrder(JITDylib &JD); |
560 | |
561 | /// Do something with the search order (run under the session lock). |
562 | template <typename Func> |
563 | auto withSearchOrderDo(Func &&F) |
564 | -> decltype(F(std::declval<const JITDylibSearchList &>())); |
565 | |
566 | /// Define all symbols provided by the materialization unit to be part of this |
567 | /// JITDylib. |
568 | /// |
569 | /// This overload always takes ownership of the MaterializationUnit. If any |
570 | /// errors occur, the MaterializationUnit consumed. |
571 | template <typename MaterializationUnitType> |
572 | Error define(std::unique_ptr<MaterializationUnitType> &&MU); |
573 | |
574 | /// Define all symbols provided by the materialization unit to be part of this |
575 | /// JITDylib. |
576 | /// |
577 | /// This overload only takes ownership of the MaterializationUnit no error is |
578 | /// generated. If an error occurs, ownership remains with the caller. This |
579 | /// may allow the caller to modify the MaterializationUnit to correct the |
580 | /// issue, then re-call define. |
581 | template <typename MaterializationUnitType> |
582 | Error define(std::unique_ptr<MaterializationUnitType> &MU); |
583 | |
584 | /// Tries to remove the given symbols. |
585 | /// |
586 | /// If any symbols are not defined in this JITDylib this method will return |
587 | /// a SymbolsNotFound error covering the missing symbols. |
588 | /// |
589 | /// If all symbols are found but some symbols are in the process of being |
590 | /// materialized this method will return a SymbolsCouldNotBeRemoved error. |
591 | /// |
592 | /// On success, all symbols are removed. On failure, the JITDylib state is |
593 | /// left unmodified (no symbols are removed). |
594 | Error remove(const SymbolNameSet &Names); |
595 | |
596 | /// Search the given JITDylib for the symbols in Symbols. If found, store |
597 | /// the flags for each symbol in Flags. Returns any unresolved symbols. |
598 | Expected<SymbolFlagsMap> lookupFlags(const SymbolNameSet &Names); |
599 | |
600 | /// Dump current JITDylib state to OS. |
601 | void dump(raw_ostream &OS); |
602 | |
603 | /// FIXME: Remove this when we remove the old ORC layers. |
604 | /// Search the given JITDylibs in order for the symbols in Symbols. Results |
605 | /// (once they become available) will be returned via the given Query. |
606 | /// |
607 | /// If any symbol is not found then the unresolved symbols will be returned, |
608 | /// and the query will not be applied. The Query is not failed and can be |
609 | /// re-used in a subsequent lookup once the symbols have been added, or |
610 | /// manually failed. |
611 | Expected<SymbolNameSet> |
612 | legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names); |
613 | |
614 | private: |
615 | using AsynchronousSymbolQueryList = |
616 | std::vector<std::shared_ptr<AsynchronousSymbolQuery>>; |
617 | |
618 | struct UnmaterializedInfo { |
619 | UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU) |
620 | : MU(std::move(MU)) {} |
621 | |
622 | std::unique_ptr<MaterializationUnit> MU; |
623 | }; |
624 | |
625 | using UnmaterializedInfosMap = |
626 | DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>; |
627 | |
628 | struct MaterializingInfo { |
629 | AsynchronousSymbolQueryList PendingQueries; |
630 | SymbolDependenceMap Dependants; |
631 | SymbolDependenceMap UnemittedDependencies; |
632 | bool IsEmitted = false; |
633 | }; |
634 | |
635 | using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>; |
636 | |
637 | using LookupImplActionFlags = enum { |
638 | None = 0, |
639 | NotifyFullyResolved = 1 << 0U, |
640 | NotifyFullyReady = 1 << 1U, |
641 | LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)LLVM_BITMASK_LARGEST_ENUMERATOR = NotifyFullyReady |
642 | }; |
643 | |
644 | JITDylib(ExecutionSession &ES, std::string Name); |
645 | |
646 | Error defineImpl(MaterializationUnit &MU); |
647 | |
648 | Expected<SymbolNameSet> lookupFlagsImpl(SymbolFlagsMap &Flags, |
649 | const SymbolNameSet &Names); |
650 | |
651 | Error lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q, |
652 | SymbolNameSet &Unresolved, bool MatchNonExported, |
653 | MaterializationUnitList &MUs); |
654 | |
655 | void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, |
656 | SymbolNameSet &Unresolved, bool MatchNonExported, |
657 | MaterializationUnitList &MUs); |
658 | |
659 | LookupImplActionFlags |
660 | lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, |
661 | std::vector<std::unique_ptr<MaterializationUnit>> &MUs, |
662 | SymbolNameSet &Unresolved); |
663 | |
664 | void detachQueryHelper(AsynchronousSymbolQuery &Q, |
665 | const SymbolNameSet &QuerySymbols); |
666 | |
667 | void transferEmittedNodeDependencies(MaterializingInfo &DependantMI, |
668 | const SymbolStringPtr &DependantName, |
669 | MaterializingInfo &EmittedMI); |
670 | |
671 | Error defineMaterializing(const SymbolFlagsMap &SymbolFlags); |
672 | |
673 | void replace(std::unique_ptr<MaterializationUnit> MU); |
674 | |
675 | SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const; |
676 | |
677 | void addDependencies(const SymbolStringPtr &Name, |
678 | const SymbolDependenceMap &Dependants); |
679 | |
680 | void resolve(const SymbolMap &Resolved); |
681 | |
682 | void emit(const SymbolFlagsMap &Emitted); |
683 | |
684 | void notifyFailed(const SymbolNameSet &FailedSymbols); |
685 | |
686 | ExecutionSession &ES; |
687 | std::string JITDylibName; |
688 | SymbolMap Symbols; |
689 | UnmaterializedInfosMap UnmaterializedInfos; |
690 | MaterializingInfosMap MaterializingInfos; |
691 | GeneratorFunction DefGenerator; |
692 | JITDylibSearchList SearchOrder; |
693 | }; |
694 | |
695 | /// An ExecutionSession represents a running JIT program. |
696 | class ExecutionSession { |
697 | // FIXME: Remove this when we remove the old ORC layers. |
698 | friend class JITDylib; |
699 | |
700 | public: |
701 | /// For reporting errors. |
702 | using ErrorReporter = std::function<void(Error)>; |
703 | |
704 | /// For dispatching MaterializationUnit::materialize calls. |
705 | using DispatchMaterializationFunction = std::function<void( |
706 | JITDylib &JD, std::unique_ptr<MaterializationUnit> MU)>; |
707 | |
708 | /// Construct an ExecutionSession. |
709 | /// |
710 | /// SymbolStringPools may be shared between ExecutionSessions. |
711 | ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr); |
712 | |
713 | /// Add a symbol name to the SymbolStringPool and return a pointer to it. |
714 | SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); } |
715 | |
716 | /// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession. |
717 | std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; } |
718 | |
719 | /// Run the given lambda with the session mutex locked. |
720 | template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) { |
721 | std::lock_guard<std::recursive_mutex> Lock(SessionMutex); |
722 | return F(); |
723 | } |
724 | |
725 | /// Get the "main" JITDylib, which is created automatically on construction of |
726 | /// the ExecutionSession. |
727 | JITDylib &getMainJITDylib(); |
728 | |
729 | /// Add a new JITDylib to this ExecutionSession. |
730 | JITDylib &createJITDylib(std::string Name, |
731 | bool AddToMainDylibSearchOrder = true); |
732 | |
733 | /// Allocate a module key for a new module to add to the JIT. |
734 | VModuleKey allocateVModule() { |
735 | return runSessionLocked([this]() { return ++LastKey; }); |
736 | } |
737 | |
738 | /// Return a module key to the ExecutionSession so that it can be |
739 | /// re-used. This should only be done once all resources associated |
740 | /// with the original key have been released. |
741 | void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */ |
742 | } |
743 | |
744 | /// Set the error reporter function. |
745 | ExecutionSession &setErrorReporter(ErrorReporter ReportError) { |
746 | this->ReportError = std::move(ReportError); |
747 | return *this; |
748 | } |
749 | |
750 | /// Report a error for this execution session. |
751 | /// |
752 | /// Unhandled errors can be sent here to log them. |
753 | void reportError(Error Err) { ReportError(std::move(Err)); } |
754 | |
755 | /// Set the materialization dispatch function. |
756 | ExecutionSession &setDispatchMaterialization( |
757 | DispatchMaterializationFunction DispatchMaterialization) { |
758 | this->DispatchMaterialization = std::move(DispatchMaterialization); |
759 | return *this; |
760 | } |
761 | |
762 | void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err); |
763 | |
764 | using LegacyAsyncLookupFunction = std::function<SymbolNameSet( |
765 | std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>; |
766 | |
767 | /// A legacy lookup function for JITSymbolResolverAdapter. |
768 | /// Do not use -- this will be removed soon. |
769 | Expected<SymbolMap> |
770 | legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names, |
771 | bool WaiUntilReady, |
772 | RegisterDependenciesFunction RegisterDependencies); |
773 | |
774 | /// Search the given JITDylib list for the given symbols. |
775 | /// |
776 | /// SearchOrder lists the JITDylibs to search. For each dylib, the associated |
777 | /// boolean indicates whether the search should match against non-exported |
778 | /// (hidden visibility) symbols in that dylib (true means match against |
779 | /// non-exported symbols, false means do not match). |
780 | /// |
781 | /// The OnResolve callback will be called once all requested symbols are |
782 | /// resolved, or if an error occurs prior to resolution. |
783 | /// |
784 | /// The OnReady callback will be called once all requested symbols are ready, |
785 | /// or if an error occurs after resolution but before all symbols are ready. |
786 | /// |
787 | /// If all symbols are found, the RegisterDependencies function will be called |
788 | /// while the session lock is held. This gives clients a chance to register |
789 | /// dependencies for on the queried symbols for any symbols they are |
790 | /// materializing (if a MaterializationResponsibility instance is present, |
791 | /// this can be implemented by calling |
792 | /// MaterializationResponsibility::addDependencies). If there are no |
793 | /// dependenant symbols for this query (e.g. it is being made by a top level |
794 | /// client to get an address to call) then the value NoDependenciesToRegister |
795 | /// can be used. |
796 | void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols, |
797 | SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady, |
798 | RegisterDependenciesFunction RegisterDependencies); |
799 | |
800 | /// Blocking version of lookup above. Returns the resolved symbol map. |
801 | /// If WaitUntilReady is true (the default), will not return until all |
802 | /// requested symbols are ready (or an error occurs). If WaitUntilReady is |
803 | /// false, will return as soon as all requested symbols are resolved, |
804 | /// or an error occurs. If WaitUntilReady is false and an error occurs |
805 | /// after resolution, the function will return a success value, but the |
806 | /// error will be reported via reportErrors. |
807 | Expected<SymbolMap> lookup(const JITDylibSearchList &SearchOrder, |
808 | const SymbolNameSet &Symbols, |
809 | RegisterDependenciesFunction RegisterDependencies = |
810 | NoDependenciesToRegister, |
811 | bool WaitUntilReady = true); |
812 | |
813 | /// Convenience version of blocking lookup. |
814 | /// Searches each of the JITDylibs in the search order in turn for the given |
815 | /// symbol. |
816 | Expected<JITEvaluatedSymbol> lookup(const JITDylibSearchList &SearchOrder, |
817 | SymbolStringPtr Symbol); |
818 | |
819 | /// Convenience version of blocking lookup. |
820 | /// Searches each of the JITDylibs in the search order in turn for the given |
821 | /// symbol. The search will not find non-exported symbols. |
822 | Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder, |
823 | SymbolStringPtr Symbol); |
824 | |
825 | /// Convenience version of blocking lookup. |
826 | /// Searches each of the JITDylibs in the search order in turn for the given |
827 | /// symbol. The search will not find non-exported symbols. |
828 | Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder, |
829 | StringRef Symbol); |
830 | |
831 | /// Materialize the given unit. |
832 | void dispatchMaterialization(JITDylib &JD, |
833 | std::unique_ptr<MaterializationUnit> MU) { |
834 | LLVM_DEBUG(runSessionLocked([&]() {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { runSessionLocked([&]() { dbgs() << "Compiling, for " << JD.getName() << ", " << *MU << "\n" ; });; } } while (false) |
835 | dbgs() << "Compiling, for " << JD.getName() << ", " << *MUdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { runSessionLocked([&]() { dbgs() << "Compiling, for " << JD.getName() << ", " << *MU << "\n" ; });; } } while (false) |
836 | << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { runSessionLocked([&]() { dbgs() << "Compiling, for " << JD.getName() << ", " << *MU << "\n" ; });; } } while (false) |
837 | });)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("orc")) { runSessionLocked([&]() { dbgs() << "Compiling, for " << JD.getName() << ", " << *MU << "\n" ; });; } } while (false); |
838 | DispatchMaterialization(JD, std::move(MU)); |
839 | } |
840 | |
841 | /// Dump the state of all the JITDylibs in this session. |
842 | void dump(raw_ostream &OS); |
843 | |
844 | private: |
845 | static void logErrorsToStdErr(Error Err) { |
846 | logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: "); |
847 | } |
848 | |
849 | static void |
850 | materializeOnCurrentThread(JITDylib &JD, |
851 | std::unique_ptr<MaterializationUnit> MU) { |
852 | MU->doMaterialize(JD); |
853 | } |
854 | |
855 | void runOutstandingMUs(); |
856 | |
857 | mutable std::recursive_mutex SessionMutex; |
858 | std::shared_ptr<SymbolStringPool> SSP; |
859 | VModuleKey LastKey = 0; |
860 | ErrorReporter ReportError = logErrorsToStdErr; |
861 | DispatchMaterializationFunction DispatchMaterialization = |
862 | materializeOnCurrentThread; |
863 | |
864 | std::vector<std::unique_ptr<JITDylib>> JDs; |
865 | |
866 | // FIXME: Remove this (and runOutstandingMUs) once the linking layer works |
867 | // with callbacks from asynchronous queries. |
868 | mutable std::recursive_mutex OutstandingMUsMutex; |
869 | std::vector<std::pair<JITDylib *, std::unique_ptr<MaterializationUnit>>> |
870 | OutstandingMUs; |
871 | }; |
872 | |
873 | template <typename Func> |
874 | auto JITDylib::withSearchOrderDo(Func &&F) |
875 | -> decltype(F(std::declval<const JITDylibSearchList &>())) { |
876 | return ES.runSessionLocked([&]() { return F(SearchOrder); }); |
877 | } |
878 | |
879 | template <typename MaterializationUnitType> |
880 | Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) { |
881 | assert(MU && "Can not define with a null MU")((MU && "Can not define with a null MU") ? static_cast <void> (0) : __assert_fail ("MU && \"Can not define with a null MU\"" , "/build/llvm-toolchain-snapshot-9~svn361194/include/llvm/ExecutionEngine/Orc/Core.h" , 881, __PRETTY_FUNCTION__)); |
882 | return ES.runSessionLocked([&, this]() -> Error { |
883 | if (auto Err = defineImpl(*MU)) |
884 | return Err; |
885 | |
886 | /// defineImpl succeeded. |
887 | auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU)); |
888 | for (auto &KV : UMI->MU->getSymbols()) |
889 | UnmaterializedInfos[KV.first] = UMI; |
890 | |
891 | return Error::success(); |
892 | }); |
893 | } |
894 | |
895 | template <typename MaterializationUnitType> |
896 | Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) { |
897 | assert(MU && "Can not define with a null MU")((MU && "Can not define with a null MU") ? static_cast <void> (0) : __assert_fail ("MU && \"Can not define with a null MU\"" , "/build/llvm-toolchain-snapshot-9~svn361194/include/llvm/ExecutionEngine/Orc/Core.h" , 897, __PRETTY_FUNCTION__)); |
898 | |
899 | return ES.runSessionLocked([&, this]() -> Error { |
900 | if (auto Err = defineImpl(*MU)) |
901 | return Err; |
902 | |
903 | /// defineImpl succeeded. |
904 | auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU)); |
905 | for (auto &KV : UMI->MU->getSymbols()) |
906 | UnmaterializedInfos[KV.first] = UMI; |
907 | |
908 | return Error::success(); |
909 | }); |
910 | } |
911 | |
912 | /// Mangles symbol names then uniques them in the context of an |
913 | /// ExecutionSession. |
914 | class MangleAndInterner { |
915 | public: |
916 | MangleAndInterner(ExecutionSession &ES, const DataLayout &DL); |
917 | SymbolStringPtr operator()(StringRef Name); |
918 | |
919 | private: |
920 | ExecutionSession &ES; |
921 | const DataLayout &DL; |
922 | }; |
923 | |
924 | } // End namespace orc |
925 | } // End namespace llvm |
926 | |
927 | #undef DEBUG_TYPE"orc" // "orc" |
928 | |
929 | #endif // LLVM_EXECUTIONENGINE_ORC_CORE_H |