Skip to content

Commit 05052ba

Browse files
committed
use TaskDispatch-safe concurrency primitives
1 parent b00c91a commit 05052ba

28 files changed

+519
-59
lines changed

llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
2323
#include "llvm/Support/Compiler.h"
2424

25-
#include <future>
25+
#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
2626
#include <list>
2727
#include <memory>
2828
#include <thread>

llvm/include/llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
2121
#include "llvm/Support/Compiler.h"
2222

23-
#include <future>
23+
#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
2424
#include <memory>
2525
#include <thread>
2626
#include <vector>

llvm/include/llvm/ExecutionEngine/Orc/Core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
#include <atomic>
3535
#include <deque>
36-
#include <future>
36+
#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
3737
#include <memory>
3838
#include <vector>
3939

llvm/include/llvm/ExecutionEngine/Orc/DylibManager.h

Lines changed: 109 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,25 @@
1313
#ifndef LLVM_EXECUTIONENGINE_ORC_DYLIBMANAGER_H
1414
#define LLVM_EXECUTIONENGINE_ORC_DYLIBMANAGER_H
1515

16+
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
1617
#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
18+
#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
1719
#include "llvm/Support/Compiler.h"
1820
#include "llvm/Support/Error.h"
1921
#include "llvm/Support/MSVCErrorWorkarounds.h"
20-
21-
#include <future>
2222
#include <mutex>
2323
#include <vector>
2424

2525
namespace llvm::orc {
2626

2727
class SymbolLookupSet;
2828

29-
class LLVM_ABI DylibManager {
29+
class LLVM_ABI DylibManager : public ExecutorProcessControl {
3030
public:
31+
DylibManager(std::shared_ptr<SymbolStringPool> SSP,
32+
std::unique_ptr<TaskDispatcher> D)
33+
: ExecutorProcessControl(std::move(SSP), std::move(D)) {}
34+
3135
/// A pair of a dylib and a set of symbols to be looked up.
3236
struct LookupRequest {
3337
LookupRequest(tpctypes::DylibHandle Handle, const SymbolLookupSet &Symbols)
@@ -51,11 +55,11 @@ class LLVM_ABI DylibManager {
5155
/// symbol is not found then it be assigned a '0' value.
5256
Expected<std::vector<tpctypes::LookupResult>>
5357
lookupSymbols(ArrayRef<LookupRequest> Request) {
54-
std::promise<MSVCPExpected<std::vector<tpctypes::LookupResult>>> RP;
58+
orc::promise<MSVCPExpected<std::vector<tpctypes::LookupResult>>> RP;
5559
auto RF = RP.get_future();
5660
lookupSymbolsAsync(Request,
5761
[&RP](auto Result) { RP.set_value(std::move(Result)); });
58-
return RF.get();
62+
return RF.get(getDispatcher());
5963
}
6064

6165
using SymbolLookupCompleteFn =
@@ -71,6 +75,106 @@ class LLVM_ABI DylibManager {
7175
SymbolLookupCompleteFn F) = 0;
7276
};
7377

78+
/// A ExecutorProcessControl instance that asserts if any of its methods are
79+
/// used. Suitable for use is unit tests, and by ORC clients who haven't moved
80+
/// to ExecutorProcessControl-based APIs yet.
81+
class UnsupportedExecutorProcessControl : public DylibManager,
82+
private InProcessMemoryAccess {
83+
public:
84+
UnsupportedExecutorProcessControl(
85+
std::shared_ptr<SymbolStringPool> SSP = nullptr,
86+
std::unique_ptr<TaskDispatcher> D = nullptr, const std::string &TT = "",
87+
unsigned PageSize = 0)
88+
: DylibManager(
89+
SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>(),
90+
D ? std::move(D) : std::make_unique<InPlaceTaskDispatcher>()),
91+
InProcessMemoryAccess(*this, Triple(TT).isArch64Bit()) {
92+
this->TargetTriple = Triple(TT);
93+
this->PageSize = PageSize;
94+
this->MemAccess = this;
95+
}
96+
97+
Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
98+
ArrayRef<std::string> Args) override {
99+
llvm_unreachable("Unsupported");
100+
}
101+
102+
Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override {
103+
llvm_unreachable("Unsupported");
104+
}
105+
106+
Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override {
107+
llvm_unreachable("Unsupported");
108+
}
109+
110+
void callWrapperAsync(ExecutorAddr WrapperFnAddr,
111+
IncomingWFRHandler OnComplete,
112+
ArrayRef<char> ArgBuffer) override {
113+
llvm_unreachable("Unsupported");
114+
}
115+
116+
Error disconnect() override { return Error::success(); }
117+
118+
Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override {
119+
return make_error<StringError>("Unsupported", inconvertibleErrorCode());
120+
}
121+
122+
void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
123+
SymbolLookupCompleteFn F) override {
124+
F(make_error<StringError>("Unsupported", inconvertibleErrorCode()));
125+
}
126+
};
127+
128+
129+
/// A ExecutorProcessControl implementation targeting the current process.
130+
class LLVM_ABI SelfExecutorProcessControl : public DylibManager,
131+
private InProcessMemoryAccess {
132+
public:
133+
SelfExecutorProcessControl(
134+
std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher> D,
135+
Triple TargetTriple, unsigned PageSize,
136+
std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
137+
138+
/// Create a SelfExecutorProcessControl with the given symbol string pool and
139+
/// memory manager.
140+
/// If no symbol string pool is given then one will be created.
141+
/// If no memory manager is given a jitlink::InProcessMemoryManager will
142+
/// be created and used by default.
143+
static Expected<std::unique_ptr<SelfExecutorProcessControl>>
144+
Create(std::shared_ptr<SymbolStringPool> SSP = nullptr,
145+
std::unique_ptr<TaskDispatcher> D = nullptr,
146+
std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr = nullptr);
147+
148+
Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
149+
ArrayRef<std::string> Args) override;
150+
151+
Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override;
152+
153+
Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override;
154+
155+
void callWrapperAsync(ExecutorAddr WrapperFnAddr,
156+
IncomingWFRHandler OnComplete,
157+
ArrayRef<char> ArgBuffer) override;
158+
159+
Error disconnect() override;
160+
161+
private:
162+
static shared::CWrapperFunctionResult
163+
jitDispatchViaWrapperFunctionManager(void *Ctx, const void *FnTag,
164+
const char *Data, size_t Size);
165+
166+
Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override;
167+
168+
void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
169+
SymbolLookupCompleteFn F) override;
170+
171+
std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
172+
#ifdef __APPLE__
173+
std::unique_ptr<UnwindInfoManager> UnwindInfoMgr;
174+
#endif // __APPLE__
175+
char GlobalManglingPrefix = 0;
176+
};
177+
74178
} // end namespace llvm::orc
75179

76180
#endif // LLVM_EXECUTIONENGINE_ORC_DYLIBMANAGER_H

llvm/include/llvm/ExecutionEngine/Orc/ELFNixPlatform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
2121
#include "llvm/Support/Compiler.h"
2222

23-
#include <future>
23+
#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
2424
#include <thread>
2525
#include <unordered_map>
2626
#include <vector>

llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
2222
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
2323
#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
24+
#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
2425
#include "llvm/Support/Compiler.h"
2526

2627
namespace llvm {
@@ -53,19 +54,19 @@ class EPCGenericDylibManager {
5354
/// Looks up symbols within the given dylib.
5455
Expected<tpctypes::LookupResult> lookup(tpctypes::DylibHandle H,
5556
const SymbolLookupSet &Lookup) {
56-
std::promise<MSVCPExpected<tpctypes::LookupResult>> RP;
57+
orc::promise<MSVCPExpected<tpctypes::LookupResult>> RP;
5758
auto RF = RP.get_future();
5859
lookupAsync(H, Lookup, [&RP](auto R) { RP.set_value(std::move(R)); });
59-
return RF.get();
60+
return RF.get(EPC.getDispatcher());
6061
}
6162

6263
/// Looks up symbols within the given dylib.
6364
Expected<tpctypes::LookupResult> lookup(tpctypes::DylibHandle H,
6465
const RemoteSymbolLookupSet &Lookup) {
65-
std::promise<MSVCPExpected<tpctypes::LookupResult>> RP;
66+
orc::promise<MSVCPExpected<tpctypes::LookupResult>> RP;
6667
auto RF = RP.get_future();
6768
lookupAsync(H, Lookup, [&RP](auto R) { RP.set_value(std::move(R)); });
68-
return RF.get();
69+
return RF.get(EPC.getDispatcher());
6970
}
7071

7172
using SymbolLookupCompleteFn =

llvm/include/llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class EPCGenericMemoryAccess : public MemoryAccess {
4545
/// Create an EPCGenericMemoryAccess instance from a given set of
4646
/// function addrs.
4747
EPCGenericMemoryAccess(ExecutorProcessControl &EPC, FuncAddrs FAs)
48-
: EPC(EPC), FAs(FAs) {}
48+
: MemoryAccess(EPC), FAs(FAs) {}
4949

5050
void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
5151
WriteResultFn OnWriteComplete) override {
@@ -202,7 +202,6 @@ class EPCGenericMemoryAccess : public MemoryAccess {
202202
}
203203

204204
private:
205-
ExecutorProcessControl &EPC;
206205
FuncAddrs FAs;
207206
};
208207

llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@
2626
#include "llvm/Support/Compiler.h"
2727
#include "llvm/TargetParser/Triple.h"
2828

29-
#include <future>
3029
#include <mutex>
3130
#include <vector>
3231

3332
namespace llvm::orc {
3433

3534
class ExecutionSession;
35+
class DylibManager;
3636

3737
/// ExecutorProcessControl supports interaction with a JIT target process.
3838
class LLVM_ABI ExecutorProcessControl {
@@ -97,6 +97,85 @@ class LLVM_ABI ExecutorProcessControl {
9797
TaskDispatcher &D;
9898
};
9999

100+
/// APIs for manipulating memory in the target process.
101+
class LLVM_ABI MemoryAccess {
102+
public:
103+
/// Callback function for asynchronous writes.
104+
using WriteResultFn = unique_function<void(Error)>;
105+
106+
MemoryAccess(ExecutorProcessControl &EPC) : EPC(EPC) {}
107+
virtual ~MemoryAccess();
108+
109+
virtual void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
110+
WriteResultFn OnWriteComplete) = 0;
111+
112+
virtual void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws,
113+
WriteResultFn OnWriteComplete) = 0;
114+
115+
virtual void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws,
116+
WriteResultFn OnWriteComplete) = 0;
117+
118+
virtual void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws,
119+
WriteResultFn OnWriteComplete) = 0;
120+
121+
virtual void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
122+
WriteResultFn OnWriteComplete) = 0;
123+
124+
virtual void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,
125+
WriteResultFn OnWriteComplete) = 0;
126+
127+
Error writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws) {
128+
orc::promise<MSVCPError> ResultP;
129+
auto ResultF = ResultP.get_future();
130+
writeUInt8sAsync(Ws,
131+
[&](Error Err) { ResultP.set_value(std::move(Err)); });
132+
return ResultF.get(EPC.getDispatcher());
133+
}
134+
135+
Error writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws) {
136+
orc::promise<MSVCPError> ResultP;
137+
auto ResultF = ResultP.get_future();
138+
writeUInt16sAsync(Ws,
139+
[&](Error Err) { ResultP.set_value(std::move(Err)); });
140+
return ResultF.get(EPC.getDispatcher());
141+
}
142+
143+
Error writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws) {
144+
orc::promise<MSVCPError> ResultP;
145+
auto ResultF = ResultP.get_future();
146+
writeUInt32sAsync(Ws,
147+
[&](Error Err) { ResultP.set_value(std::move(Err)); });
148+
return ResultF.get(EPC.getDispatcher());
149+
}
150+
151+
Error writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws) {
152+
orc::promise<MSVCPError> ResultP;
153+
auto ResultF = ResultP.get_future();
154+
writeUInt64sAsync(Ws,
155+
[&](Error Err) { ResultP.set_value(std::move(Err)); });
156+
return ResultF.get(EPC.getDispatcher());
157+
}
158+
159+
Error writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws) {
160+
orc::promise<MSVCPError> ResultP;
161+
auto ResultF = ResultP.get_future();
162+
writeBuffersAsync(Ws,
163+
[&](Error Err) { ResultP.set_value(std::move(Err)); });
164+
return ResultF.get(EPC.getDispatcher());
165+
}
166+
167+
Error writePointers(ArrayRef<tpctypes::PointerWrite> Ws) {
168+
orc::promise<MSVCPError> ResultP;
169+
auto ResultF = ResultP.get_future();
170+
writePointersAsync(Ws,
171+
[&](Error Err) { ResultP.set_value(std::move(Err)); });
172+
return ResultF.get(EPC.getDispatcher());
173+
}
174+
175+
protected:
176+
ExecutorProcessControl &EPC;
177+
};
178+
100179
/// Contains the address of the dispatch function and context that the ORC
101180
/// runtime can use to call functions in the JIT.
102181
struct JITDispatchInfo {
@@ -251,14 +330,14 @@ class LLVM_ABI ExecutorProcessControl {
251330
/// \endcode{.cpp}
252331
shared::WrapperFunctionResult callWrapper(ExecutorAddr WrapperFnAddr,
253332
ArrayRef<char> ArgBuffer) {
254-
std::promise<shared::WrapperFunctionResult> RP;
333+
orc::promise<shared::WrapperFunctionResult> RP;
255334
auto RF = RP.get_future();
256335
callWrapperAsync(
257336
RunInPlace(), WrapperFnAddr,
258337
[&](shared::WrapperFunctionResult R) {
259338
RP.set_value(std::move(R));
260339
}, ArgBuffer);
261-
return RF.get();
340+
return RF.get(*D);
262341
}
263342

264343
/// Run a wrapper function using SPS to serialize the arguments and
@@ -322,6 +401,34 @@ class LLVM_ABI ExecutorProcessControl {
322401
StringMap<ExecutorAddr> BootstrapSymbols;
323402
};
324403

325-
} // namespace llvm::orc
404+
class LLVM_ABI InProcessMemoryAccess
405+
: public ExecutorProcessControl::MemoryAccess {
406+
public:
407+
InProcessMemoryAccess(ExecutorProcessControl &EPC, bool IsArch64Bit)
408+
: MemoryAccess(EPC), IsArch64Bit(IsArch64Bit) {}
409+
void writeUInt8sAsync(ArrayRef<tpctypes::UInt8Write> Ws,
410+
WriteResultFn OnWriteComplete) override;
411+
412+
void writeUInt16sAsync(ArrayRef<tpctypes::UInt16Write> Ws,
413+
WriteResultFn OnWriteComplete) override;
414+
415+
void writeUInt32sAsync(ArrayRef<tpctypes::UInt32Write> Ws,
416+
WriteResultFn OnWriteComplete) override;
417+
418+
void writeUInt64sAsync(ArrayRef<tpctypes::UInt64Write> Ws,
419+
WriteResultFn OnWriteComplete) override;
420+
421+
void writeBuffersAsync(ArrayRef<tpctypes::BufferWrite> Ws,
422+
WriteResultFn OnWriteComplete) override;
423+
424+
void writePointersAsync(ArrayRef<tpctypes::PointerWrite> Ws,
425+
WriteResultFn OnWriteComplete) override;
426+
427+
private:
428+
bool IsArch64Bit;
429+
};
430+
431+
} // end namespace orc
432+
} // end namespace llvm
326433

327434
#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTORPROCESSCONTROL_H

0 commit comments

Comments
 (0)