Bug Summary

File:lib/ExecutionEngine/Orc/Layer.cpp
Warning:line 98, column 3
Method called on moved-from object 'R'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name Layer.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-9/lib/clang/9.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-9~svn361194/build-llvm/lib/ExecutionEngine/Orc -I /build/llvm-toolchain-snapshot-9~svn361194/lib/ExecutionEngine/Orc -I /build/llvm-toolchain-snapshot-9~svn361194/build-llvm/include -I /build/llvm-toolchain-snapshot-9~svn361194/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/9.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-9/lib/clang/9.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-9~svn361194/build-llvm/lib/ExecutionEngine/Orc -fdebug-prefix-map=/build/llvm-toolchain-snapshot-9~svn361194=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2019-05-21-060711-3714-1 -x c++ /build/llvm-toolchain-snapshot-9~svn361194/lib/ExecutionEngine/Orc/Layer.cpp -faddrsig

/build/llvm-toolchain-snapshot-9~svn361194/lib/ExecutionEngine/Orc/Layer.cpp

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
15namespace llvm {
16namespace orc {
17
18IRLayer::IRLayer(ExecutionSession &ES) : ES(ES) {}
19IRLayer::~IRLayer() {}
20
21Error 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
26IRMaterializationUnit::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
43IRMaterializationUnit::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
49StringRef IRMaterializationUnit::getName() const {
50 if (TSM.getModule())
51 return TSM.getModule()->getModuleIdentifier();
52 return "<null module>";
53}
54
55void 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
71BasicIRLayerMaterializationUnit::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
77void 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())
1
Assuming the condition is false
2
Taking false branch
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)
3
Assuming 'DebugFlag' is 0
4
Loop condition is false. Exiting loop
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));
5
Object 'R' is moved
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)
6
Assuming 'DebugFlag' is not equal to 0
7
Assuming the condition is true
8
Taking true branch
9
Calling 'ExecutionSession::runSessionLocked'
11
Method called on moved-from object 'R'
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
104ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
105
106ObjectLayer::~ObjectLayer() {}
107
108Error 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
117Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
118BasicObjectLayerMaterializationUnit::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
131BasicObjectLayerMaterializationUnit::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
137StringRef BasicObjectLayerMaterializationUnit::getName() const {
138 if (O)
139 return O->getBufferIdentifier();
140 return "<null object>";
141}
142
143void BasicObjectLayerMaterializationUnit::materialize(
144 MaterializationResponsibility R) {
145 L.emit(std::move(R), std::move(O));
146}
147
148void 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
154Expected<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.

/build/llvm-toolchain-snapshot-9~svn361194/include/llvm/ExecutionEngine/Orc/Core.h

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
27namespace llvm {
28namespace orc {
29
30// Forward declare some classes.
31class AsynchronousSymbolQuery;
32class ExecutionSession;
33class MaterializationUnit;
34class MaterializationResponsibility;
35class JITDylib;
36
37/// VModuleKey provides a unique identifier (allocated and managed by
38/// ExecutionSessions) for a module added to the JIT.
39using VModuleKey = uint64_t;
40
41/// A set of symbol names (represented by SymbolStringPtrs for
42// efficiency).
43using SymbolNameSet = DenseSet<SymbolStringPtr>;
44
45/// A map from symbol names (as SymbolStringPtrs) to JITSymbols
46/// (address/flags pairs).
47using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>;
48
49/// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
50using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>;
51
52/// A base class for materialization failures that allows the failing
53/// symbols to be obtained for logging.
54using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
55
56/// A list of (JITDylib*, bool) pairs.
57using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>;
58
59/// Render a SymbolStringPtr.
60raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
61
62/// Render a SymbolNameSet.
63raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
64
65/// Render a SymbolFlagsMap entry.
66raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap::value_type &KV);
67
68/// Render a SymbolMap entry.
69raw_ostream &operator<<(raw_ostream &OS, const SymbolMap::value_type &KV);
70
71/// Render a SymbolFlagsMap.
72raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &SymbolFlags);
73
74/// Render a SymbolMap.
75raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
76
77/// Render a SymbolDependenceMap entry.
78raw_ostream &operator<<(raw_ostream &OS,
79 const SymbolDependenceMap::value_type &KV);
80
81/// Render a SymbolDependendeMap.
82raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
83
84/// Render a MaterializationUnit.
85raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU);
86
87/// Render a JITDylibSearchList.
88raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs);
89
90/// Callback to notify client that symbols have been resolved.
91using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
92
93/// Callback to notify client that symbols are ready for execution.
94using SymbolsReadyCallback = std::function<void(Error)>;
95
96/// Callback to register the dependencies for a given query.
97using 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.
102extern RegisterDependenciesFunction NoDependenciesToRegister;
103
104/// Used to notify a JITDylib that the given set of symbols failed to
105/// materialize.
106class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
107public:
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
115private:
116 SymbolNameSet Symbols;
117};
118
119/// Used to notify clients when symbols can not be found during a lookup.
120class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
121public:
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
129private:
130 SymbolNameSet Symbols;
131};
132
133/// Used to notify clients that a set of symbols could not be removed.
134class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> {
135public:
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
143private:
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.
154class MaterializationResponsibility {
155 friend class MaterializationUnit;
156public:
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
232private:
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.
251class MaterializationUnit {
252public:
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
280protected:
281 SymbolFlagsMap SymbolFlags;
282 VModuleKey K;
283
284private:
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
299using 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.
306class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
307public:
308 AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols, VModuleKey K);
309
310 StringRef getName() const override;
311
312private:
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///
330inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
331absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) {
332 return llvm::make_unique<AbsoluteSymbolsMaterializationUnit>(
333 std::move(Symbols), std::move(K));
334}
335
336struct 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.
346using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
347
348/// A materialization unit for symbol aliases. Allows existing symbols to be
349/// aliased with alternate flags.
350class ReExportsMaterializationUnit : public MaterializationUnit {
351public:
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
365private:
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
386inline std::unique_ptr<ReExportsMaterializationUnit>
387symbolAliases(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.
397inline std::unique_ptr<ReExportsMaterializationUnit>
398reexports(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.
406Expected<SymbolAliasMap>
407buildSimpleReexportsAliasMap(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.
411class ReexportsGenerator {
412public:
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
423private:
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.
433class AsynchronousSymbolQuery {
434 friend class ExecutionSession;
435 friend class JITDylib;
436 friend class JITSymbolResolverAdapter;
437
438public:
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
470private:
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.
495class JITDylib {
496 friend class AsynchronousSymbolQuery;
497 friend class ExecutionSession;
498 friend class MaterializationResponsibility;
499public:
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
614private:
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.
696class ExecutionSession {
697 // FIXME: Remove this when we remove the old ORC layers.
698 friend class JITDylib;
699
700public:
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();
10
Calling 'operator()'
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
844private:
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
873template <typename Func>
874auto JITDylib::withSearchOrderDo(Func &&F)
875 -> decltype(F(std::declval<const JITDylibSearchList &>())) {
876 return ES.runSessionLocked([&]() { return F(SearchOrder); });
877}
878
879template <typename MaterializationUnitType>
880Error 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
895template <typename MaterializationUnitType>
896Error 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.
914class MangleAndInterner {
915public:
916 MangleAndInterner(ExecutionSession &ES, const DataLayout &DL);
917 SymbolStringPtr operator()(StringRef Name);
918
919private:
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