llvm.org GIT mirror llvm / 543cda4
[ORC] Update JITCompileCallbackManager to support multi-threaded code. Previously JITCompileCallbackManager only supported single threaded code. This patch embeds a VSO (see include/llvm/ExecutionEngine/Orc/Core.h) in the callback manager. The VSO ensures that the compile callback is only executed once and that the resulting address cached for use by subsequent re-entries. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@333490 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 1 year, 1 month ago
17 changed file(s) with 251 addition(s) and 232 deletion(s). Raw diff Collapse all Expand all
7575 [this](std::unique_ptr M) {
7676 return optimizeModule(std::move(M));
7777 }),
78 CompileCallbackManager(
79 orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)),
78 CompileCallbackManager(orc::createLocalCompileCallbackManager(
79 TM->getTargetTriple(), ES, 0)),
8080 CODLayer(ES, OptimizeLayer,
8181 [&](orc::VModuleKey K) { return Resolvers[K]; },
8282 [&](orc::VModuleKey K, std::shared_ptr R) {
115115 [this](std::unique_ptr M) {
116116 return optimizeModule(std::move(M));
117117 }),
118 CompileCallbackMgr(
119 orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)) {
118 CompileCallbackMgr(orc::createLocalCompileCallbackManager(
119 TM->getTargetTriple(), ES, 0)) {
120120 auto IndirectStubsMgrBuilder =
121121 orc::createLocalIndirectStubsManagerBuilder(TM->getTargetTriple());
122122 IndirectStubsMgr = IndirectStubsMgrBuilder();
133133 }
134134
135135 Error addFunctionAST(std::unique_ptr FnAST) {
136 // Create a CompileCallback - this is the re-entry point into the compiler
137 // for functions that haven't been compiled yet.
138 auto CCInfo = cantFail(CompileCallbackMgr->getCompileCallback());
139
140 // Create an indirect stub. This serves as the functions "canonical
141 // definition" - an unchanging (constant address) entry point to the
142 // function implementation.
143 // Initially we point the stub's function-pointer at the compile callback
144 // that we just created. In the compile action for the callback (see below)
145 // we will update the stub's function pointer to point at the function
146 // implementation that we just implemented.
147 if (auto Err = IndirectStubsMgr->createStub(mangle(FnAST->getName()),
148 CCInfo.getAddress(),
149 JITSymbolFlags::Exported))
150 return Err;
151
152136 // Move ownership of FnAST to a shared pointer - C++11 lambdas don't support
153137 // capture-by-move, which is be required for unique_ptr.
154138 auto SharedFnAST = std::shared_ptr(std::move(FnAST));
169153 // The JIT runtime (the resolver block) will use the return address of
170154 // this function as the address to continue at once it has reset the
171155 // CPU state to what it was immediately before the call.
172 CCInfo.setCompileAction(
173 [this, SharedFnAST]() {
174 auto M = irgenAndTakeOwnership(*SharedFnAST, "$impl");
175 addModule(std::move(M));
176 auto Sym = findSymbol(SharedFnAST->getName() + "$impl");
177 assert(Sym && "Couldn't find compiled function?");
178 JITTargetAddress SymAddr = cantFail(Sym.getAddress());
179 if (auto Err =
180 IndirectStubsMgr->updatePointer(mangle(SharedFnAST->getName()),
181 SymAddr)) {
182 logAllUnhandledErrors(std::move(Err), errs(),
183 "Error updating function pointer: ");
184 exit(1);
185 }
186
187 return SymAddr;
188 });
156 auto CompileAction = [this, SharedFnAST]() {
157 auto M = irgenAndTakeOwnership(*SharedFnAST, "$impl");
158 addModule(std::move(M));
159 auto Sym = findSymbol(SharedFnAST->getName() + "$impl");
160 assert(Sym && "Couldn't find compiled function?");
161 JITTargetAddress SymAddr = cantFail(Sym.getAddress());
162 if (auto Err = IndirectStubsMgr->updatePointer(
163 mangle(SharedFnAST->getName()), SymAddr)) {
164 logAllUnhandledErrors(std::move(Err), errs(),
165 "Error updating function pointer: ");
166 exit(1);
167 }
168
169 return SymAddr;
170 };
171
172 // Create a CompileCallback using the CompileAction - this is the re-entry
173 // point into the compiler for functions that haven't been compiled yet.
174 auto CCAddr = cantFail(
175 CompileCallbackMgr->getCompileCallback(std::move(CompileAction)));
176
177 // Create an indirect stub. This serves as the functions "canonical
178 // definition" - an unchanging (constant address) entry point to the
179 // function implementation.
180 // Initially we point the stub's function-pointer at the compile callback
181 // that we just created. When the compile action for the callback is run we
182 // will update the stub's function pointer to point at the function
183 // implementation that we just implemented.
184 if (auto Err = IndirectStubsMgr->createStub(
185 mangle(SharedFnAST->getName()), CCAddr, JITSymbolFlags::Exported))
186 return Err;
189187
190188 return Error::success();
191189 }
7777
7878 class KaleidoscopeJIT {
7979 private:
80 ExecutionSession ES;
80 ExecutionSession &ES;
8181 std::shared_ptr Resolver;
8282 std::unique_ptr TM;
8383 const DataLayout DL;
9494 MyRemote &Remote;
9595
9696 public:
97 KaleidoscopeJIT(MyRemote &Remote)
98 : Resolver(createLegacyLookupResolver(
97 KaleidoscopeJIT(ExecutionSession &ES, MyRemote &Remote)
98 : ES(ES),
99 Resolver(createLegacyLookupResolver(
99100 ES,
100101 [this](const std::string &Name) -> JITSymbol {
101102 if (auto Sym = IndirectStubsMgr->findStub(Name, false))
145146 }
146147
147148 Error addFunctionAST(std::unique_ptr FnAST) {
148 // Create a CompileCallback - this is the re-entry point into the compiler
149 // for functions that haven't been compiled yet.
150 auto CCInfo = cantFail(CompileCallbackMgr->getCompileCallback());
151
152 // Create an indirect stub. This serves as the functions "canonical
153 // definition" - an unchanging (constant address) entry point to the
154 // function implementation.
155 // Initially we point the stub's function-pointer at the compile callback
156 // that we just created. In the compile action for the callback (see below)
157 // we will update the stub's function pointer to point at the function
158 // implementation that we just implemented.
159 if (auto Err = IndirectStubsMgr->createStub(mangle(FnAST->getName()),
160 CCInfo.getAddress(),
161 JITSymbolFlags::Exported))
162 return Err;
163
164149 // Move ownership of FnAST to a shared pointer - C++11 lambdas don't support
165150 // capture-by-move, which is be required for unique_ptr.
166151 auto SharedFnAST = std::shared_ptr(std::move(FnAST));
181166 // The JIT runtime (the resolver block) will use the return address of
182167 // this function as the address to continue at once it has reset the
183168 // CPU state to what it was immediately before the call.
184 CCInfo.setCompileAction(
185 [this, SharedFnAST]() {
186 auto M = irgenAndTakeOwnership(*SharedFnAST, "$impl");
187 addModule(std::move(M));
188 auto Sym = findSymbol(SharedFnAST->getName() + "$impl");
189 assert(Sym && "Couldn't find compiled function?");
190 JITTargetAddress SymAddr = cantFail(Sym.getAddress());
191 if (auto Err =
192 IndirectStubsMgr->updatePointer(mangle(SharedFnAST->getName()),
193 SymAddr)) {
194 logAllUnhandledErrors(std::move(Err), errs(),
195 "Error updating function pointer: ");
196 exit(1);
197 }
198
199 return SymAddr;
200 });
169 auto CompileAction = [this, SharedFnAST]() {
170 auto M = irgenAndTakeOwnership(*SharedFnAST, "$impl");
171 addModule(std::move(M));
172 auto Sym = findSymbol(SharedFnAST->getName() + "$impl");
173 assert(Sym && "Couldn't find compiled function?");
174 JITTargetAddress SymAddr = cantFail(Sym.getAddress());
175 if (auto Err = IndirectStubsMgr->updatePointer(
176 mangle(SharedFnAST->getName()), SymAddr)) {
177 logAllUnhandledErrors(std::move(Err), errs(),
178 "Error updating function pointer: ");
179 exit(1);
180 }
181
182 return SymAddr;
183 };
184
185 // Create a CompileCallback suing the CompileAction - this is the re-entry
186 // point into the compiler for functions that haven't been compiled yet.
187 auto CCAddr = cantFail(
188 CompileCallbackMgr->getCompileCallback(std::move(CompileAction)));
189
190 // Create an indirect stub. This serves as the functions "canonical
191 // definition" - an unchanging (constant address) entry point to the
192 // function implementation.
193 // Initially we point the stub's function-pointer at the compile callback
194 // that we just created. In the compile action for the callback we will
195 // update the stub's function pointer to point at the function
196 // implementation that we just implemented.
197 if (auto Err = IndirectStubsMgr->createStub(
198 mangle(SharedFnAST->getName()), CCAddr, JITSymbolFlags::Exported))
199 return Err;
201200
202201 return Error::success();
203202 }
12421242 sockaddr_in servAddr;
12431243 memset(&servAddr, 0, sizeof(servAddr));
12441244 servAddr.sin_family = PF_INET;
1245 memcpy(&servAddr.sin_addr.s_addr, server->h_addr, server->h_length);
1245 char *src;
1246 memcpy(&src, &server->h_addr, sizeof(char *));
1247 memcpy(&servAddr.sin_addr.s_addr, src, server->h_length);
12461248 servAddr.sin_port = htons(Port);
12471249 if (connect(sockfd, reinterpret_cast(&servAddr),
12481250 sizeof(servAddr)) < 0) {
12751277 BinopPrecedence['-'] = 20;
12761278 BinopPrecedence['*'] = 40; // highest.
12771279
1280 ExecutionSession ES;
12781281 auto TCPChannel = connect();
1279 auto Remote = ExitOnErr(MyRemote::Create(*TCPChannel, ExitOnErr));
1280 TheJIT = llvm::make_unique(*Remote);
1282 auto Remote = ExitOnErr(MyRemote::Create(*TCPChannel, ES));
1283 TheJIT = llvm::make_unique(ES, *Remote);
12811284
12821285 // Automatically inject a definition for 'printExprResult'.
12831286 FunctionProtos["printExprResult"] =
348348 // Create a callback, associate it with the stub for the function,
349349 // and set the compile action to compile the partition containing the
350350 // function.
351 if (auto CCInfoOrErr = CompileCallbackMgr.getCompileCallback()) {
352 auto &CCInfo = *CCInfoOrErr;
351 auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress {
352 if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
353 return *FnImplAddrOrErr;
354 else {
355 // FIXME: Report error, return to 'abort' or something similar.
356 consumeError(FnImplAddrOrErr.takeError());
357 return 0;
358 }
359 };
360 if (auto CCAddr =
361 CompileCallbackMgr.getCompileCallback(std::move(CompileAction)))
353362 StubInits[MangledName] =
354 std::make_pair(CCInfo.getAddress(),
355 JITSymbolFlags::fromGlobalValue(F));
356 CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress {
357 if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
358 return *FnImplAddrOrErr;
359 else {
360 // FIXME: Report error, return to 'abort' or something similar.
361 consumeError(FnImplAddrOrErr.takeError());
362 return 0;
363 }
364 });
365 } else
366 return CCInfoOrErr.takeError();
363 std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F));
364 else
365 return CCAddr.takeError();
367366 }
368367
369368 if (auto Err = LD.StubsMgr->createStubs(StubInits))
609609 /// VSOs will be searched in order and no VSO pointer may be null.
610610 /// All symbols must be found within the given VSOs or an error
611611 /// will be returned.
612 Expected lookup(const std::vector &VSOs, SymbolNameSet Names);
612 Expected lookup(const VSO::VSOList &VSOs, SymbolNameSet Names);
613613
614614 /// Look up a symbol by searching a list of VSOs.
615 Expected lookup(const std::vector VSOs,
615 Expected lookup(const VSO::VSOList &VSOs,
616616 SymbolStringPtr Name);
617617
618618 } // End namespace orc
1717 #include "llvm/ADT/StringRef.h"
1818 #include "llvm/ADT/Twine.h"
1919 #include "llvm/ExecutionEngine/JITSymbol.h"
20 #include "llvm/ExecutionEngine/Orc/Core.h"
2021 #include "llvm/Support/Error.h"
2122 #include "llvm/Support/Memory.h"
2223 #include "llvm/Support/Process.h"
4849 /// Target-independent base class for compile callback management.
4950 class JITCompileCallbackManager {
5051 public:
51 using CompileFtor = std::function;
52
53 /// Handle to a newly created compile callback. Can be used to get an
54 /// IR constant representing the address of the trampoline, and to set
55 /// the compile action for the callback.
56 class CompileCallbackInfo {
57 public:
58 CompileCallbackInfo(JITTargetAddress Addr, CompileFtor &Compile)
59 : Addr(Addr), Compile(Compile) {}
60
61 JITTargetAddress getAddress() const { return Addr; }
62 void setCompileAction(CompileFtor Compile) {
63 this->Compile = std::move(Compile);
64 }
65
66 private:
67 JITTargetAddress Addr;
68 CompileFtor &Compile;
69 };
52 using CompileFunction = std::function;
7053
7154 /// Construct a JITCompileCallbackManager.
7255 /// @param ErrorHandlerAddress The address of an error handler in the target
7356 /// process to be used if a compile callback fails.
74 JITCompileCallbackManager(JITTargetAddress ErrorHandlerAddress)
75 : ErrorHandlerAddress(ErrorHandlerAddress) {}
57 JITCompileCallbackManager(ExecutionSession &ES,
58 JITTargetAddress ErrorHandlerAddress)
59 : ES(ES), CallbacksVSO(ES.createVSO("")),
60 ErrorHandlerAddress(ErrorHandlerAddress) {}
7661
7762 virtual ~JITCompileCallbackManager() = default;
63
64 /// Reserve a compile callback.
65 Expected getCompileCallback(CompileFunction Compile);
7866
7967 /// Execute the callback for the given trampoline id. Called by the JIT
8068 /// to compile functions on demand.
81 JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr) {
82 auto I = ActiveTrampolines.find(TrampolineAddr);
83 // FIXME: Also raise an error in the Orc error-handler when we finally have
84 // one.
85 if (I == ActiveTrampolines.end())
86 return ErrorHandlerAddress;
87
88 // Found a callback handler. Yank this trampoline out of the active list and
89 // put it back in the available trampolines list, then try to run the
90 // handler's compile and update actions.
91 // Moving the trampoline ID back to the available list first means there's
92 // at
93 // least one available trampoline if the compile action triggers a request
94 // for
95 // a new one.
96 auto Compile = std::move(I->second);
97 ActiveTrampolines.erase(I);
98 AvailableTrampolines.push_back(TrampolineAddr);
99
100 if (auto Addr = Compile())
101 return Addr;
102
103 return ErrorHandlerAddress;
104 }
105
106 /// Reserve a compile callback.
107 Expected getCompileCallback() {
108 if (auto TrampolineAddrOrErr = getAvailableTrampolineAddr()) {
109 const auto &TrampolineAddr = *TrampolineAddrOrErr;
110 auto &Compile = this->ActiveTrampolines[TrampolineAddr];
111 return CompileCallbackInfo(TrampolineAddr, Compile);
112 } else
113 return TrampolineAddrOrErr.takeError();
114 }
115
116 /// Get a CompileCallbackInfo for an existing callback.
117 CompileCallbackInfo getCompileCallbackInfo(JITTargetAddress TrampolineAddr) {
118 auto I = ActiveTrampolines.find(TrampolineAddr);
119 assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
120 return CompileCallbackInfo(I->first, I->second);
121 }
122
123 /// Release a compile callback.
124 ///
125 /// Note: Callbacks are auto-released after they execute. This method should
126 /// only be called to manually release a callback that is not going to
127 /// execute.
128 void releaseCompileCallback(JITTargetAddress TrampolineAddr) {
129 auto I = ActiveTrampolines.find(TrampolineAddr);
130 assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
131 ActiveTrampolines.erase(I);
132 AvailableTrampolines.push_back(TrampolineAddr);
133 }
69 JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
13470
13571 protected:
136 JITTargetAddress ErrorHandlerAddress;
137
138 using TrampolineMapT = std::map;
139 TrampolineMapT ActiveTrampolines;
14072 std::vector AvailableTrampolines;
14173
14274 private:
15587 virtual Error grow() = 0;
15688
15789 virtual void anchor();
90
91 std::mutex CCMgrMutex;
92 ExecutionSession &ES;
93 VSO &CallbacksVSO;
94 JITTargetAddress ErrorHandlerAddress;
95 std::map AddrToSymbol;
96 size_t NextCallbackId = 0;
15897 };
15998
16099 /// Manage compile callbacks for in-process JITs.
164103 /// Construct a InProcessJITCompileCallbackManager.
165104 /// @param ErrorHandlerAddress The address of an error handler in the target
166105 /// process to be used if a compile callback fails.
167 LocalJITCompileCallbackManager(JITTargetAddress ErrorHandlerAddress)
168 : JITCompileCallbackManager(ErrorHandlerAddress) {
106 LocalJITCompileCallbackManager(ExecutionSession &ES,
107 JITTargetAddress ErrorHandlerAddress)
108 : JITCompileCallbackManager(ES, ErrorHandlerAddress) {
169109 /// Set up the resolver block.
170110 std::error_code EC;
171111 ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
359299 /// ErrorHandlerAddress will be used by the resulting compile callback
360300 /// manager if a compile callback fails.
361301 std::unique_ptr
362 createLocalCompileCallbackManager(const Triple &T,
302 createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
363303 JITTargetAddress ErrorHandlerAddress);
364304
365305 /// Create a local indriect stubs manager builder.
450450 class RemoteCompileCallbackManager : public JITCompileCallbackManager {
451451 public:
452452 RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
453 ExecutionSession &ES,
453454 JITTargetAddress ErrorHandlerAddress)
454 : JITCompileCallbackManager(ErrorHandlerAddress), Client(Client) {}
455 : JITCompileCallbackManager(ES, ErrorHandlerAddress), Client(Client) {}
455456
456457 private:
457458 Error grow() override {
476477 /// Channel is the ChannelT instance to communicate on. It is assumed that
477478 /// the channel is ready to be read from and written to.
478479 static Expected>
479 Create(rpc::RawByteChannel &Channel, std::function ReportError) {
480 Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) {
480481 Error Err = Error::success();
481482 auto Client = std::unique_ptr(
482 new OrcRemoteTargetClient(Channel, std::move(ReportError), Err));
483 new OrcRemoteTargetClient(Channel, ES, Err));
483484 if (Err)
484485 return std::move(Err);
485486 return std::move(Client);
533534
534535 Expected
535536 enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) {
537 assert(!CallbackManager && "CallbackManager already obtained");
538
536539 // Emit the resolver block on the JIT server.
537540 if (auto Err = callB())
538541 return std::move(Err);
539542
540543 // Create the callback manager.
541 CallbackManager.emplace(*this, ErrorHandlerAddress);
544 CallbackManager.emplace(*this, ES, ErrorHandlerAddress);
542545 RemoteCompileCallbackManager &Mgr = *CallbackManager;
543546 return Mgr;
544547 }
556559 Error terminateSession() { return callB(); }
557560
558561 private:
559 OrcRemoteTargetClient(rpc::RawByteChannel &Channel,
560 std::function ReportError, Error &Err)
562 OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES,
563 Error &Err)
561564 : rpc::SingleThreadedRPCEndpoint(Channel, true),
562 ReportError(std::move(ReportError)) {
565 ES(ES) {
563566 ErrorAsOutParameter EAO(&Err);
564567
565568 addHandler(
579582
580583 void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
581584 if (auto Err = callB(Addr, Size))
582 ReportError(std::move(Err));
585 ES.reportError(std::move(Err));
583586 }
584587
585588 void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
594597 void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
595598 IndirectStubOwnerIds.release(Id);
596599 if (auto Err = callB(Id))
597 ReportError(std::move(Err));
600 ES.reportError(std::move(Err));
598601 }
599602
600603 Expected>
627630 if (auto AddrOrErr = callB(Id, Size, Align))
628631 return *AddrOrErr;
629632 else {
630 ReportError(AddrOrErr.takeError());
633 ES.reportError(AddrOrErr.takeError());
631634 return 0;
632635 }
633636 }
635638 bool setProtections(ResourceIdMgr::ResourceId Id,
636639 JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
637640 if (auto Err = callB(Id, RemoteSegAddr, ProtFlags)) {
638 ReportError(std::move(Err));
641 ES.reportError(std::move(Err));
639642 return true;
640643 } else
641644 return false;
643646
644647 bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
645648 if (auto Err = callB(DirectBufferWriter(Src, Addr, Size))) {
646 ReportError(std::move(Err));
649 ES.reportError(std::move(Err));
647650 return true;
648651 } else
649652 return false;
655658
656659 static Error doNothing() { return Error::success(); }
657660
661 ExecutionSession &ES;
658662 std::function ReportError;
659663 std::string RemoteTargetTriple;
660664 uint32_t RemotePointerSize = 0;
868868 });
869869 }
870870
871 Expected lookup(const std::vector &VSOs, SymbolNameSet Names) {
871 Expected lookup(const VSO::VSOList &VSOs, SymbolNameSet Names) {
872872 #if LLVM_ENABLE_THREADS
873873 // In the threaded case we use promises to return the results.
874874 std::promise PromisedResult;
974974 }
975975
976976 /// Look up a symbol by searching a list of VSOs.
977 Expected lookup(const std::vector VSOs,
977 Expected lookup(const VSO::VSOList &VSOs,
978978 SymbolStringPtr Name) {
979979 SymbolNameSet Names({Name});
980980 if (auto ResultMap = lookup(VSOs, std::move(Names))) {
1212 #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
1313 #include "llvm/IR/CallSite.h"
1414 #include "llvm/IR/IRBuilder.h"
15 #include "llvm/Support/Format.h"
1516 #include "llvm/Transforms/Utils/Cloning.h"
1617 #include
1718
19 using namespace llvm;
20 using namespace llvm::orc;
21
22 namespace {
23
24 class CompileCallbackMaterializationUnit : public orc::MaterializationUnit {
25 public:
26 using CompileFunction = JITCompileCallbackManager::CompileFunction;
27
28 CompileCallbackMaterializationUnit(SymbolStringPtr Name,
29 CompileFunction Compile)
30 : MaterializationUnit(SymbolFlagsMap({{Name, JITSymbolFlags::Exported}})),
31 Name(std::move(Name)), Compile(std::move(Compile)) {}
32
33 private:
34 void materialize(MaterializationResponsibility R) {
35 SymbolMap Result;
36 Result[Name] = JITEvaluatedSymbol(Compile(), JITSymbolFlags::Exported);
37 R.resolve(Result);
38 R.finalize();
39 }
40
41 void discard(const VSO &V, SymbolStringPtr Name) {
42 llvm_unreachable("Discard should never occur on a LMU?");
43 }
44
45 SymbolStringPtr Name;
46 CompileFunction Compile;
47 };
48
49 } // namespace
50
1851 namespace llvm {
1952 namespace orc {
2053
2154 void JITCompileCallbackManager::anchor() {}
2255 void IndirectStubsManager::anchor() {}
2356
57 Expected
58 JITCompileCallbackManager::getCompileCallback(CompileFunction Compile) {
59 if (auto TrampolineAddr = getAvailableTrampolineAddr()) {
60 auto CallbackName = ES.getSymbolStringPool().intern(
61 std::string("cc") + std::to_string(++NextCallbackId));
62
63 std::lock_guard Lock(CCMgrMutex);
64 AddrToSymbol[*TrampolineAddr] = CallbackName;
65 cantFail(
66 CallbacksVSO.define(make_unique(
67 std::move(CallbackName), std::move(Compile))));
68 return *TrampolineAddr;
69 } else
70 return TrampolineAddr.takeError();
71 }
72
73 JITTargetAddress JITCompileCallbackManager::executeCompileCallback(
74 JITTargetAddress TrampolineAddr) {
75 SymbolStringPtr Name;
76
77 {
78 std::unique_lock Lock(CCMgrMutex);
79 auto I = AddrToSymbol.find(TrampolineAddr);
80
81 // If this address is not associated with a compile callback then report an
82 // error to the execution session and return ErrorHandlerAddress to the
83 // callee.
84 if (I == AddrToSymbol.end()) {
85 Lock.unlock();
86 std::string ErrMsg;
87 {
88 raw_string_ostream ErrMsgStream(ErrMsg);
89 ErrMsgStream << "No compile callback for trampoline at "
90 << format("0x%016x", TrampolineAddr);
91 }
92 ES.reportError(
93 make_error(std::move(ErrMsg), inconvertibleErrorCode()));
94 return ErrorHandlerAddress;
95 } else
96 Name = I->second;
97 }
98
99 if (auto Sym = lookup({&CallbacksVSO}, Name))
100 return Sym->getAddress();
101 else {
102 // If anything goes wrong materializing Sym then report it to the session
103 // and return the ErrorHandlerAddress;
104 ES.reportError(Sym.takeError());
105 return ErrorHandlerAddress;
106 }
107 }
108
24109 std::unique_ptr
25 createLocalCompileCallbackManager(const Triple &T,
110 createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
26111 JITTargetAddress ErrorHandlerAddress) {
27112 switch (T.getArch()) {
28113 default: return nullptr;
29114
30115 case Triple::aarch64: {
31116 typedef orc::LocalJITCompileCallbackManager CCMgrT;
32 return llvm::make_unique(ErrorHandlerAddress);
117 return llvm::make_unique(ES, ErrorHandlerAddress);
33118 }
34119
35120 case Triple::x86: {
36121 typedef orc::LocalJITCompileCallbackManager CCMgrT;
37 return llvm::make_unique(ErrorHandlerAddress);
122 return llvm::make_unique(ES, ErrorHandlerAddress);
38123 }
39124
40125 case Triple::x86_64: {
41126 if ( T.getOS() == Triple::OSType::Win32 ) {
42127 typedef orc::LocalJITCompileCallbackManager CCMgrT;
43 return llvm::make_unique(ErrorHandlerAddress);
128 return llvm::make_unique(ES, ErrorHandlerAddress);
44129 } else {
45130 typedef orc::LocalJITCompileCallbackManager CCMgrT;
46 return llvm::make_unique(ErrorHandlerAddress);
131 return llvm::make_unique(ES, ErrorHandlerAddress);
47132 }
48133 }
49134
1717
1818 Triple T(TM2->getTargetTriple());
1919
20 auto CompileCallbackMgr = orc::createLocalCompileCallbackManager(T, 0);
2120 auto IndirectStubsMgrBuilder =
2221 orc::createLocalIndirectStubsManagerBuilder(T);
2322
24 OrcCBindingsStack *JITStack = new OrcCBindingsStack(
25 *TM2, std::move(CompileCallbackMgr), IndirectStubsMgrBuilder);
23 OrcCBindingsStack *JITStack =
24 new OrcCBindingsStack(*TM2, std::move(IndirectStubsMgrBuilder));
2625
2726 return wrap(JITStack);
2827 }
199199 };
200200
201201 public:
202
203202 OrcCBindingsStack(TargetMachine &TM,
204 std::unique_ptr CCMgr,
205203 IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
206 : DL(TM.createDataLayout()),
207 IndirectStubsMgr(IndirectStubsMgrBuilder()), CCMgr(std::move(CCMgr)),
204 : CCMgr(createLocalCompileCallbackManager(TM.getTargetTriple(), ES, 0)),
205 DL(TM.createDataLayout()), IndirectStubsMgr(IndirectStubsMgrBuilder()),
208206 ObjectLayer(ES,
209207 [this](orc::VModuleKey K) {
210208 auto ResolverI = Resolvers.find(K);
215213 return ObjLayerT::Resources{
216214 std::make_shared(), Resolver};
217215 },
218 nullptr,
219 [this](orc::VModuleKey K, const object::ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
216 nullptr,
217 [this](orc::VModuleKey K, const object::ObjectFile &Obj,
218 const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
220219 this->notifyFinalized(K, Obj, LoadedObjInfo);
221 },
222 [this](orc::VModuleKey K, const object::ObjectFile &Obj) {
220 },
221 [this](orc::VModuleKey K, const object::ObjectFile &Obj) {
223222 this->notifyFreed(K, Obj);
224 }),
223 }),
225224 CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)),
226225 CODLayer(ES, CompileLayer,
227226 [this](orc::VModuleKey K) {
269268 createLazyCompileCallback(JITTargetAddress &RetAddr,
270269 LLVMOrcLazyCompileCallbackFn Callback,
271270 void *CallbackCtx) {
272 if (auto CCInfoOrErr = CCMgr->getCompileCallback()) {
273 auto &CCInfo = *CCInfoOrErr;
274 CCInfo.setCompileAction([=]() -> JITTargetAddress {
275 return Callback(wrap(this), CallbackCtx);
276 });
277 RetAddr = CCInfo.getAddress();
271 auto WrappedCallback = [=]() -> JITTargetAddress {
272 return Callback(wrap(this), CallbackCtx);
273 };
274
275 if (auto CCAddr = CCMgr->getCompileCallback(std::move(WrappedCallback))) {
276 RetAddr = *CCAddr;
278277 return LLVMOrcErrSuccess;
279278 } else
280 return mapError(CCInfoOrErr.takeError());
279 return mapError(CCAddr.takeError());
281280 }
282281
283282 LLVMOrcErrorCode createIndirectStub(StringRef StubName,
483482 }
484483
485484 orc::ExecutionSession ES;
485 std::unique_ptr CCMgr;
486486
487487 std::vector EventListeners;
488488
491491
492492 std::unique_ptr IndirectStubsMgr;
493493
494 std::unique_ptr CCMgr;
495494 ObjLayerT ObjectLayer;
496495 CompileLayerT CompileLayer;
497496 CODLayerT CODLayer;
120120 EB.setOptLevel(getOptLevel());
121121 auto TM = std::unique_ptr(EB.selectTarget());
122122 Triple T(TM->getTargetTriple());
123 auto CompileCallbackMgr = orc::createLocalCompileCallbackManager(T, 0);
124
125 // If we couldn't build the factory function then there must not be a callback
126 // manager for this target. Bail out.
127 if (!CompileCallbackMgr) {
128 errs() << "No callback manager available for target '"
129 << TM->getTargetTriple().str() << "'.\n";
130 return 1;
131 }
132123
133124 auto IndirectStubsMgrBuilder = orc::createLocalIndirectStubsManagerBuilder(T);
134125
140131 }
141132
142133 // Everything looks good. Build the JIT.
143 OrcLazyJIT J(std::move(TM), std::move(CompileCallbackMgr),
144 std::move(IndirectStubsMgrBuilder),
134 OrcLazyJIT J(std::move(TM), std::move(IndirectStubsMgrBuilder),
145135 OrcInlineStubs);
146136
147137 // Add the module, look up main and run it.
5656 using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
5757
5858 OrcLazyJIT(std::unique_ptr TM,
59 std::unique_ptr CCMgr,
6059 IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
6160 bool InlineStubs)
62 : TM(std::move(TM)),
63 DL(this->TM->createDataLayout()),
64 CCMgr(std::move(CCMgr)),
61 : TM(std::move(TM)), DL(this->TM->createDataLayout()),
62 CCMgr(orc::createLocalCompileCallbackManager(
63 this->TM->getTargetTriple(), ES, 0)),
6564 ObjectLayer(ES,
6665 [this](orc::VModuleKey K) {
6766 auto ResolverI = Resolvers.find(K);
611611 }
612612
613613 // Create a remote target client running over the channel.
614 llvm::orc::ExecutionSession ES;
615 ES.setErrorReporter([&](Error Err) { ExitOnErr(std::move(Err)); });
614616 typedef orc::remote::OrcRemoteTargetClient MyRemote;
615 auto R = ExitOnErr(MyRemote::Create(*C, ExitOnErr));
617 auto R = ExitOnErr(MyRemote::Create(*C, ES));
616618
617619 // Create a remote memory manager.
618620 auto RemoteMM = ExitOnErr(R->createRemoteMemoryManager());
1717
1818 class DummyCallbackManager : public orc::JITCompileCallbackManager {
1919 public:
20 DummyCallbackManager() : JITCompileCallbackManager(0) {}
20 DummyCallbackManager(ExecutionSession &ES)
21 : JITCompileCallbackManager(ES, 0) {}
2122
2223 public:
2324 Error grow() override { llvm_unreachable("not implemented"); }
5657 return JITSymbol(nullptr);
5758 };
5859
59 DummyCallbackManager CallbackMgr;
6060
6161 ExecutionSession ES(std::make_shared());
62 DummyCallbackManager CallbackMgr(ES);
6263
6364 auto GetResolver =
6465 [](orc::VModuleKey) -> std::shared_ptr {
7070 // Use ability to create callback manager to detect whether Orc
7171 // has indirection support on this platform. This way the test
7272 // and Orc code do not get out of sync.
73 SupportsIndirection = !!orc::createLocalCompileCallbackManager(TT, 0);
73 SupportsIndirection = !!orc::createLocalCompileCallbackManager(TT, ES, 0);
7474 }
7575 };
7676
7777 protected:
78 orc::ExecutionSession ES;
7879 LLVMContext Context;
7980 std::unique_ptr TM;
8081 bool SupportsJIT = false;