mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 04:09:45 +00:00
[ORC] Revert r286620 while I investigate a bot failure.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286621 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d8314f03b1
commit
b35b701639
@ -14,7 +14,7 @@
|
|||||||
#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H
|
#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H
|
||||||
#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H
|
#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H
|
||||||
|
|
||||||
#include "llvm/ExecutionEngine/Orc/RawByteChannel.h"
|
#include "llvm/ExecutionEngine/Orc/RPCByteChannel.h"
|
||||||
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
@ -25,7 +25,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// RPC channel that reads from and writes from file descriptors.
|
/// RPC channel that reads from and writes from file descriptors.
|
||||||
class FDRPCChannel final : public llvm::orc::rpc::RawByteChannel {
|
class FDRPCChannel final : public llvm::orc::remote::RPCByteChannel {
|
||||||
public:
|
public:
|
||||||
FDRPCChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {}
|
FDRPCChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {}
|
||||||
|
|
||||||
|
@ -1265,8 +1265,8 @@ int main(int argc, char *argv[]) {
|
|||||||
BinopPrecedence['*'] = 40; // highest.
|
BinopPrecedence['*'] = 40; // highest.
|
||||||
|
|
||||||
auto TCPChannel = connect();
|
auto TCPChannel = connect();
|
||||||
auto Remote = ExitOnErr(MyRemote::Create(*TCPChannel));
|
MyRemote Remote = ExitOnErr(MyRemote::Create(*TCPChannel));
|
||||||
TheJIT = llvm::make_unique<KaleidoscopeJIT>(*Remote);
|
TheJIT = llvm::make_unique<KaleidoscopeJIT>(Remote);
|
||||||
|
|
||||||
// Automatically inject a definition for 'printExprResult'.
|
// Automatically inject a definition for 'printExprResult'.
|
||||||
FunctionProtos["printExprResult"] =
|
FunctionProtos["printExprResult"] =
|
||||||
@ -1288,7 +1288,7 @@ int main(int argc, char *argv[]) {
|
|||||||
TheJIT = nullptr;
|
TheJIT = nullptr;
|
||||||
|
|
||||||
// Send a terminate message to the remote to tell it to exit cleanly.
|
// Send a terminate message to the remote to tell it to exit cleanly.
|
||||||
ExitOnErr(Remote->terminateSession());
|
ExitOnErr(Remote.terminateSession());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ enum class OrcErrorCode : int {
|
|||||||
RemoteIndirectStubsOwnerIdAlreadyInUse,
|
RemoteIndirectStubsOwnerIdAlreadyInUse,
|
||||||
UnexpectedRPCCall,
|
UnexpectedRPCCall,
|
||||||
UnexpectedRPCResponse,
|
UnexpectedRPCResponse,
|
||||||
UnknownRPCFunction
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Error orcError(OrcErrorCode ErrCode);
|
Error orcError(OrcErrorCode ErrCode);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// This file defines the OrcRemoteTargetClient class and helpers. This class
|
// This file defines the OrcRemoteTargetClient class and helpers. This class
|
||||||
// can be used to communicate over an RawByteChannel with an
|
// can be used to communicate over an RPCByteChannel with an
|
||||||
// OrcRemoteTargetServer instance to support remote-JITing.
|
// OrcRemoteTargetServer instance to support remote-JITing.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -36,6 +36,23 @@ namespace remote {
|
|||||||
template <typename ChannelT>
|
template <typename ChannelT>
|
||||||
class OrcRemoteTargetClient : public OrcRemoteTargetRPCAPI {
|
class OrcRemoteTargetClient : public OrcRemoteTargetRPCAPI {
|
||||||
public:
|
public:
|
||||||
|
// FIXME: Remove move/copy ops once MSVC supports synthesizing move ops.
|
||||||
|
|
||||||
|
OrcRemoteTargetClient(const OrcRemoteTargetClient &) = delete;
|
||||||
|
OrcRemoteTargetClient &operator=(const OrcRemoteTargetClient &) = delete;
|
||||||
|
|
||||||
|
OrcRemoteTargetClient(OrcRemoteTargetClient &&Other)
|
||||||
|
: Channel(Other.Channel), ExistingError(std::move(Other.ExistingError)),
|
||||||
|
RemoteTargetTriple(std::move(Other.RemoteTargetTriple)),
|
||||||
|
RemotePointerSize(std::move(Other.RemotePointerSize)),
|
||||||
|
RemotePageSize(std::move(Other.RemotePageSize)),
|
||||||
|
RemoteTrampolineSize(std::move(Other.RemoteTrampolineSize)),
|
||||||
|
RemoteIndirectStubSize(std::move(Other.RemoteIndirectStubSize)),
|
||||||
|
AllocatorIds(std::move(Other.AllocatorIds)),
|
||||||
|
IndirectStubOwnerIds(std::move(Other.IndirectStubOwnerIds)),
|
||||||
|
CallbackManager(std::move(Other.CallbackManager)) {}
|
||||||
|
|
||||||
|
OrcRemoteTargetClient &operator=(OrcRemoteTargetClient &&) = delete;
|
||||||
|
|
||||||
/// Remote memory manager.
|
/// Remote memory manager.
|
||||||
class RCMemoryManager : public RuntimeDyld::MemoryManager {
|
class RCMemoryManager : public RuntimeDyld::MemoryManager {
|
||||||
@ -45,10 +62,18 @@ public:
|
|||||||
DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
|
DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
RCMemoryManager(const RCMemoryManager&) = delete;
|
RCMemoryManager(RCMemoryManager &&Other)
|
||||||
RCMemoryManager& operator=(const RCMemoryManager&) = delete;
|
: Client(std::move(Other.Client)), Id(std::move(Other.Id)),
|
||||||
RCMemoryManager(RCMemoryManager&&) = default;
|
Unmapped(std::move(Other.Unmapped)),
|
||||||
RCMemoryManager& operator=(RCMemoryManager&&) = default;
|
Unfinalized(std::move(Other.Unfinalized)) {}
|
||||||
|
|
||||||
|
RCMemoryManager operator=(RCMemoryManager &&Other) {
|
||||||
|
Client = std::move(Other.Client);
|
||||||
|
Id = std::move(Other.Id);
|
||||||
|
Unmapped = std::move(Other.Unmapped);
|
||||||
|
Unfinalized = std::move(Other.Unfinalized);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
~RCMemoryManager() override {
|
~RCMemoryManager() override {
|
||||||
Client.destroyRemoteAllocator(Id);
|
Client.destroyRemoteAllocator(Id);
|
||||||
@ -342,10 +367,18 @@ public:
|
|||||||
Alloc(uint64_t Size, unsigned Align)
|
Alloc(uint64_t Size, unsigned Align)
|
||||||
: Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {}
|
: Size(Size), Align(Align), Contents(new char[Size + Align - 1]) {}
|
||||||
|
|
||||||
Alloc(const Alloc&) = delete;
|
Alloc(Alloc &&Other)
|
||||||
Alloc& operator=(const Alloc&) = delete;
|
: Size(std::move(Other.Size)), Align(std::move(Other.Align)),
|
||||||
Alloc(Alloc&&) = default;
|
Contents(std::move(Other.Contents)),
|
||||||
Alloc& operator=(Alloc&&) = default;
|
RemoteAddr(std::move(Other.RemoteAddr)) {}
|
||||||
|
|
||||||
|
Alloc &operator=(Alloc &&Other) {
|
||||||
|
Size = std::move(Other.Size);
|
||||||
|
Align = std::move(Other.Align);
|
||||||
|
Contents = std::move(Other.Contents);
|
||||||
|
RemoteAddr = std::move(Other.RemoteAddr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t getSize() const { return Size; }
|
uint64_t getSize() const { return Size; }
|
||||||
|
|
||||||
@ -372,10 +405,24 @@ public:
|
|||||||
|
|
||||||
struct ObjectAllocs {
|
struct ObjectAllocs {
|
||||||
ObjectAllocs() = default;
|
ObjectAllocs() = default;
|
||||||
ObjectAllocs(const ObjectAllocs &) = delete;
|
|
||||||
ObjectAllocs& operator=(const ObjectAllocs &) = delete;
|
ObjectAllocs(ObjectAllocs &&Other)
|
||||||
ObjectAllocs(ObjectAllocs&&) = default;
|
: RemoteCodeAddr(std::move(Other.RemoteCodeAddr)),
|
||||||
ObjectAllocs& operator=(ObjectAllocs&&) = default;
|
RemoteRODataAddr(std::move(Other.RemoteRODataAddr)),
|
||||||
|
RemoteRWDataAddr(std::move(Other.RemoteRWDataAddr)),
|
||||||
|
CodeAllocs(std::move(Other.CodeAllocs)),
|
||||||
|
RODataAllocs(std::move(Other.RODataAllocs)),
|
||||||
|
RWDataAllocs(std::move(Other.RWDataAllocs)) {}
|
||||||
|
|
||||||
|
ObjectAllocs &operator=(ObjectAllocs &&Other) {
|
||||||
|
RemoteCodeAddr = std::move(Other.RemoteCodeAddr);
|
||||||
|
RemoteRODataAddr = std::move(Other.RemoteRODataAddr);
|
||||||
|
RemoteRWDataAddr = std::move(Other.RemoteRWDataAddr);
|
||||||
|
CodeAllocs = std::move(Other.CodeAllocs);
|
||||||
|
RODataAllocs = std::move(Other.RODataAllocs);
|
||||||
|
RWDataAllocs = std::move(Other.RWDataAllocs);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
JITTargetAddress RemoteCodeAddr = 0;
|
JITTargetAddress RemoteCodeAddr = 0;
|
||||||
JITTargetAddress RemoteRODataAddr = 0;
|
JITTargetAddress RemoteRODataAddr = 0;
|
||||||
@ -541,21 +588,23 @@ public:
|
|||||||
/// Create an OrcRemoteTargetClient.
|
/// Create an OrcRemoteTargetClient.
|
||||||
/// Channel is the ChannelT instance to communicate on. It is assumed that
|
/// Channel is the ChannelT instance to communicate on. It is assumed that
|
||||||
/// the channel is ready to be read from and written to.
|
/// the channel is ready to be read from and written to.
|
||||||
static Expected<std::unique_ptr<OrcRemoteTargetClient>>
|
static Expected<OrcRemoteTargetClient> Create(ChannelT &Channel) {
|
||||||
Create(ChannelT &Channel) {
|
|
||||||
Error Err = Error::success();
|
Error Err = Error::success();
|
||||||
std::unique_ptr<OrcRemoteTargetClient>
|
OrcRemoteTargetClient H(Channel, Err);
|
||||||
Client(new OrcRemoteTargetClient(Channel, Err));
|
|
||||||
if (Err)
|
if (Err)
|
||||||
return std::move(Err);
|
return std::move(Err);
|
||||||
return std::move(Client);
|
return Expected<OrcRemoteTargetClient>(std::move(H));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call the int(void) function at the given address in the target and return
|
/// Call the int(void) function at the given address in the target and return
|
||||||
/// its result.
|
/// its result.
|
||||||
Expected<int> callIntVoid(JITTargetAddress Addr) {
|
Expected<int> callIntVoid(JITTargetAddress Addr) {
|
||||||
DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
|
DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
|
||||||
return callB<CallIntVoid>(Addr);
|
|
||||||
|
auto Listen = [&](RPCByteChannel &C, uint32_t Id) {
|
||||||
|
return listenForCompileRequests(C, Id);
|
||||||
|
};
|
||||||
|
return callSTHandling<CallIntVoid>(Channel, Listen, Addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call the int(int, char*[]) function at the given address in the target and
|
/// Call the int(int, char*[]) function at the given address in the target and
|
||||||
@ -564,7 +613,11 @@ public:
|
|||||||
const std::vector<std::string> &Args) {
|
const std::vector<std::string> &Args) {
|
||||||
DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
|
DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
|
||||||
<< "\n");
|
<< "\n");
|
||||||
return callB<CallMain>(Addr, Args);
|
|
||||||
|
auto Listen = [&](RPCByteChannel &C, uint32_t Id) {
|
||||||
|
return listenForCompileRequests(C, Id);
|
||||||
|
};
|
||||||
|
return callSTHandling<CallMain>(Channel, Listen, Addr, Args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call the void() function at the given address in the target and wait for
|
/// Call the void() function at the given address in the target and wait for
|
||||||
@ -572,7 +625,11 @@ public:
|
|||||||
Error callVoidVoid(JITTargetAddress Addr) {
|
Error callVoidVoid(JITTargetAddress Addr) {
|
||||||
DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
|
DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
|
||||||
<< "\n");
|
<< "\n");
|
||||||
return callB<CallVoidVoid>(Addr);
|
|
||||||
|
auto Listen = [&](RPCByteChannel &C, uint32_t Id) {
|
||||||
|
return listenForCompileRequests(C, Id);
|
||||||
|
};
|
||||||
|
return callSTHandling<CallVoidVoid>(Channel, Listen, Addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an RCMemoryManager which will allocate its memory on the remote
|
/// Create an RCMemoryManager which will allocate its memory on the remote
|
||||||
@ -581,7 +638,7 @@ public:
|
|||||||
assert(!MM && "MemoryManager should be null before creation.");
|
assert(!MM && "MemoryManager should be null before creation.");
|
||||||
|
|
||||||
auto Id = AllocatorIds.getNext();
|
auto Id = AllocatorIds.getNext();
|
||||||
if (auto Err = callB<CreateRemoteAllocator>(Id))
|
if (auto Err = callST<CreateRemoteAllocator>(Channel, Id))
|
||||||
return Err;
|
return Err;
|
||||||
MM = llvm::make_unique<RCMemoryManager>(*this, Id);
|
MM = llvm::make_unique<RCMemoryManager>(*this, Id);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
@ -592,7 +649,7 @@ public:
|
|||||||
Error createIndirectStubsManager(std::unique_ptr<RCIndirectStubsManager> &I) {
|
Error createIndirectStubsManager(std::unique_ptr<RCIndirectStubsManager> &I) {
|
||||||
assert(!I && "Indirect stubs manager should be null before creation.");
|
assert(!I && "Indirect stubs manager should be null before creation.");
|
||||||
auto Id = IndirectStubOwnerIds.getNext();
|
auto Id = IndirectStubOwnerIds.getNext();
|
||||||
if (auto Err = callB<CreateIndirectStubsOwner>(Id))
|
if (auto Err = callST<CreateIndirectStubsOwner>(Channel, Id))
|
||||||
return Err;
|
return Err;
|
||||||
I = llvm::make_unique<RCIndirectStubsManager>(*this, Id);
|
I = llvm::make_unique<RCIndirectStubsManager>(*this, Id);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
@ -605,7 +662,7 @@ public:
|
|||||||
return std::move(ExistingError);
|
return std::move(ExistingError);
|
||||||
|
|
||||||
// Emit the resolver block on the JIT server.
|
// Emit the resolver block on the JIT server.
|
||||||
if (auto Err = callB<EmitResolverBlock>())
|
if (auto Err = callST<EmitResolverBlock>(Channel))
|
||||||
return std::move(Err);
|
return std::move(Err);
|
||||||
|
|
||||||
// Create the callback manager.
|
// Create the callback manager.
|
||||||
@ -622,28 +679,18 @@ public:
|
|||||||
if (ExistingError)
|
if (ExistingError)
|
||||||
return std::move(ExistingError);
|
return std::move(ExistingError);
|
||||||
|
|
||||||
return callB<GetSymbolAddress>(Name);
|
return callST<GetSymbolAddress>(Channel, Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the triple for the remote target.
|
/// Get the triple for the remote target.
|
||||||
const std::string &getTargetTriple() const { return RemoteTargetTriple; }
|
const std::string &getTargetTriple() const { return RemoteTargetTriple; }
|
||||||
|
|
||||||
Error terminateSession() { return callB<TerminateSession>(); }
|
Error terminateSession() { return callST<TerminateSession>(Channel); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
OrcRemoteTargetClient(ChannelT &Channel, Error &Err) : Channel(Channel) {
|
||||||
OrcRemoteTargetClient(ChannelT &Channel, Error &Err)
|
|
||||||
: OrcRemoteTargetRPCAPI(Channel) {
|
|
||||||
ErrorAsOutParameter EAO(&Err);
|
ErrorAsOutParameter EAO(&Err);
|
||||||
|
if (auto RIOrErr = callST<GetRemoteInfo>(Channel)) {
|
||||||
addHandler<RequestCompile>(
|
|
||||||
[this](JITTargetAddress Addr) -> JITTargetAddress {
|
|
||||||
if (CallbackManager)
|
|
||||||
return CallbackManager->executeCompileCallback(Addr);
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (auto RIOrErr = callB<GetRemoteInfo>()) {
|
|
||||||
std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
|
std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
|
||||||
RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
|
RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
|
||||||
Err = Error::success();
|
Err = Error::success();
|
||||||
@ -653,11 +700,11 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Error deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
|
Error deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
|
||||||
return callB<RegisterEHFrames>(Addr, Size);
|
return callST<RegisterEHFrames>(Channel, Addr, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
|
void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
|
||||||
if (auto Err = callB<DestroyRemoteAllocator>(Id)) {
|
if (auto Err = callST<DestroyRemoteAllocator>(Channel, Id)) {
|
||||||
// FIXME: This will be triggered by a removeModuleSet call: Propagate
|
// FIXME: This will be triggered by a removeModuleSet call: Propagate
|
||||||
// error return up through that.
|
// error return up through that.
|
||||||
llvm_unreachable("Failed to destroy remote allocator.");
|
llvm_unreachable("Failed to destroy remote allocator.");
|
||||||
@ -667,12 +714,12 @@ private:
|
|||||||
|
|
||||||
Error destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
|
Error destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
|
||||||
IndirectStubOwnerIds.release(Id);
|
IndirectStubOwnerIds.release(Id);
|
||||||
return callB<DestroyIndirectStubsOwner>(Id);
|
return callST<DestroyIndirectStubsOwner>(Channel, Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
|
Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
|
||||||
emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
|
emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
|
||||||
return callB<EmitIndirectStubs>(Id, NumStubsRequired);
|
return callST<EmitIndirectStubs>(Channel, Id, NumStubsRequired);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() {
|
Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() {
|
||||||
@ -680,7 +727,7 @@ private:
|
|||||||
if (ExistingError)
|
if (ExistingError)
|
||||||
return std::move(ExistingError);
|
return std::move(ExistingError);
|
||||||
|
|
||||||
return callB<EmitTrampolineBlock>();
|
return callST<EmitTrampolineBlock>(Channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
|
uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
|
||||||
@ -689,17 +736,42 @@ private:
|
|||||||
|
|
||||||
uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
|
uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
|
||||||
|
|
||||||
|
Error listenForCompileRequests(RPCByteChannel &C, uint32_t &Id) {
|
||||||
|
assert(CallbackManager &&
|
||||||
|
"No calback manager. enableCompileCallbacks must be called first");
|
||||||
|
|
||||||
|
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
||||||
|
if (ExistingError)
|
||||||
|
return std::move(ExistingError);
|
||||||
|
|
||||||
|
// FIXME: CompileCallback could be an anonymous lambda defined at the use
|
||||||
|
// site below, but that triggers a GCC 4.7 ICE. When we move off
|
||||||
|
// GCC 4.7, tidy this up.
|
||||||
|
auto CompileCallback =
|
||||||
|
[this](JITTargetAddress Addr) -> Expected<JITTargetAddress> {
|
||||||
|
return this->CallbackManager->executeCompileCallback(Addr);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Id == RequestCompileId) {
|
||||||
|
if (auto Err = handle<RequestCompile>(C, CompileCallback))
|
||||||
|
return Err;
|
||||||
|
return Error::success();
|
||||||
|
}
|
||||||
|
// else
|
||||||
|
return orcError(OrcErrorCode::UnexpectedRPCCall);
|
||||||
|
}
|
||||||
|
|
||||||
Expected<std::vector<char>> readMem(char *Dst, JITTargetAddress Src,
|
Expected<std::vector<char>> readMem(char *Dst, JITTargetAddress Src,
|
||||||
uint64_t Size) {
|
uint64_t Size) {
|
||||||
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
||||||
if (ExistingError)
|
if (ExistingError)
|
||||||
return std::move(ExistingError);
|
return std::move(ExistingError);
|
||||||
|
|
||||||
return callB<ReadMem>(Src, Size);
|
return callST<ReadMem>(Channel, Src, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) {
|
Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) {
|
||||||
return callB<RegisterEHFrames>(RAddr, Size);
|
return callST<RegisterEHFrames>(Channel, RAddr, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<JITTargetAddress> reserveMem(ResourceIdMgr::ResourceId Id,
|
Expected<JITTargetAddress> reserveMem(ResourceIdMgr::ResourceId Id,
|
||||||
@ -709,12 +781,12 @@ private:
|
|||||||
if (ExistingError)
|
if (ExistingError)
|
||||||
return std::move(ExistingError);
|
return std::move(ExistingError);
|
||||||
|
|
||||||
return callB<ReserveMem>(Id, Size, Align);
|
return callST<ReserveMem>(Channel, Id, Size, Align);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error setProtections(ResourceIdMgr::ResourceId Id,
|
Error setProtections(ResourceIdMgr::ResourceId Id,
|
||||||
JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
|
JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
|
||||||
return callB<SetProtections>(Id, RemoteSegAddr, ProtFlags);
|
return callST<SetProtections>(Channel, Id, RemoteSegAddr, ProtFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
|
Error writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
|
||||||
@ -722,7 +794,7 @@ private:
|
|||||||
if (ExistingError)
|
if (ExistingError)
|
||||||
return std::move(ExistingError);
|
return std::move(ExistingError);
|
||||||
|
|
||||||
return callB<WriteMem>(DirectBufferWriter(Src, Addr, Size));
|
return callST<WriteMem>(Channel, DirectBufferWriter(Src, Addr, Size));
|
||||||
}
|
}
|
||||||
|
|
||||||
Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) {
|
Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) {
|
||||||
@ -730,11 +802,12 @@ private:
|
|||||||
if (ExistingError)
|
if (ExistingError)
|
||||||
return std::move(ExistingError);
|
return std::move(ExistingError);
|
||||||
|
|
||||||
return callB<WritePtr>(Addr, PtrVal);
|
return callST<WritePtr>(Channel, Addr, PtrVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Error doNothing() { return Error::success(); }
|
static Error doNothing() { return Error::success(); }
|
||||||
|
|
||||||
|
ChannelT &Channel;
|
||||||
Error ExistingError = Error::success();
|
Error ExistingError = Error::success();
|
||||||
std::string RemoteTargetTriple;
|
std::string RemoteTargetTriple;
|
||||||
uint32_t RemotePointerSize = 0;
|
uint32_t RemotePointerSize = 0;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H
|
#ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H
|
||||||
#define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H
|
#define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETRPCAPI_H
|
||||||
|
|
||||||
#include "RawByteChannel.h"
|
#include "RPCByteChannel.h"
|
||||||
#include "RPCUtils.h"
|
#include "RPCUtils.h"
|
||||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||||
|
|
||||||
@ -40,24 +40,13 @@ private:
|
|||||||
uint64_t Size;
|
uint64_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace remote
|
|
||||||
|
|
||||||
namespace rpc {
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class RPCTypeName<remote::DirectBufferWriter> {
|
class SerializationTraits<RPCByteChannel, DirectBufferWriter> {
|
||||||
public:
|
|
||||||
static const char *getName() { return "DirectBufferWriter"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ChannelT>
|
|
||||||
class SerializationTraits<ChannelT, remote::DirectBufferWriter, remote::DirectBufferWriter,
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_base_of<RawByteChannel, ChannelT>::
|
|
||||||
value>::type> {
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static Error serialize(ChannelT &C, const remote::DirectBufferWriter &DBW) {
|
static const char* getName() { return "DirectBufferWriter"; }
|
||||||
|
|
||||||
|
static Error serialize(RPCByteChannel &C, const DirectBufferWriter &DBW) {
|
||||||
if (auto EC = serializeSeq(C, DBW.getDst()))
|
if (auto EC = serializeSeq(C, DBW.getDst()))
|
||||||
return EC;
|
return EC;
|
||||||
if (auto EC = serializeSeq(C, DBW.getSize()))
|
if (auto EC = serializeSeq(C, DBW.getSize()))
|
||||||
@ -65,7 +54,7 @@ public:
|
|||||||
return C.appendBytes(DBW.getSrc(), DBW.getSize());
|
return C.appendBytes(DBW.getSrc(), DBW.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Error deserialize(ChannelT &C, remote::DirectBufferWriter &DBW) {
|
static Error deserialize(RPCByteChannel &C, DirectBufferWriter &DBW) {
|
||||||
JITTargetAddress Dst;
|
JITTargetAddress Dst;
|
||||||
if (auto EC = deserializeSeq(C, Dst))
|
if (auto EC = deserializeSeq(C, Dst))
|
||||||
return EC;
|
return EC;
|
||||||
@ -74,18 +63,13 @@ public:
|
|||||||
return EC;
|
return EC;
|
||||||
char *Addr = reinterpret_cast<char *>(static_cast<uintptr_t>(Dst));
|
char *Addr = reinterpret_cast<char *>(static_cast<uintptr_t>(Dst));
|
||||||
|
|
||||||
DBW = remote::DirectBufferWriter(0, Dst, Size);
|
DBW = DirectBufferWriter(0, Dst, Size);
|
||||||
|
|
||||||
return C.readBytes(Addr, Size);
|
return C.readBytes(Addr, Size);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace rpc
|
class OrcRemoteTargetRPCAPI : public RPC<RPCByteChannel> {
|
||||||
|
|
||||||
namespace remote {
|
|
||||||
|
|
||||||
class OrcRemoteTargetRPCAPI
|
|
||||||
: public rpc::SingleThreadedRPC<rpc::RawByteChannel> {
|
|
||||||
protected:
|
protected:
|
||||||
class ResourceIdMgr {
|
class ResourceIdMgr {
|
||||||
public:
|
public:
|
||||||
@ -109,162 +93,119 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// FIXME: Remove constructors once MSVC supports synthesizing move-ops.
|
// FIXME: Remove constructors once MSVC supports synthesizing move-ops.
|
||||||
OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C)
|
OrcRemoteTargetRPCAPI() = default;
|
||||||
: rpc::SingleThreadedRPC<rpc::RawByteChannel>(C, true) {}
|
OrcRemoteTargetRPCAPI(const OrcRemoteTargetRPCAPI &) = delete;
|
||||||
|
OrcRemoteTargetRPCAPI &operator=(const OrcRemoteTargetRPCAPI &) = delete;
|
||||||
|
|
||||||
class CallIntVoid : public rpc::Function<CallIntVoid,
|
OrcRemoteTargetRPCAPI(OrcRemoteTargetRPCAPI &&) {}
|
||||||
int32_t(JITTargetAddress Addr)> {
|
OrcRemoteTargetRPCAPI &operator=(OrcRemoteTargetRPCAPI &&) { return *this; }
|
||||||
public:
|
|
||||||
static const char* getName() { return "CallIntVoid"; }
|
enum JITFuncId : uint32_t {
|
||||||
|
InvalidId = RPCFunctionIdTraits<JITFuncId>::InvalidId,
|
||||||
|
CallIntVoidId = RPCFunctionIdTraits<JITFuncId>::FirstValidId,
|
||||||
|
CallMainId,
|
||||||
|
CallVoidVoidId,
|
||||||
|
CreateRemoteAllocatorId,
|
||||||
|
CreateIndirectStubsOwnerId,
|
||||||
|
DeregisterEHFramesId,
|
||||||
|
DestroyRemoteAllocatorId,
|
||||||
|
DestroyIndirectStubsOwnerId,
|
||||||
|
EmitIndirectStubsId,
|
||||||
|
EmitResolverBlockId,
|
||||||
|
EmitTrampolineBlockId,
|
||||||
|
GetSymbolAddressId,
|
||||||
|
GetRemoteInfoId,
|
||||||
|
ReadMemId,
|
||||||
|
RegisterEHFramesId,
|
||||||
|
ReserveMemId,
|
||||||
|
RequestCompileId,
|
||||||
|
SetProtectionsId,
|
||||||
|
TerminateSessionId,
|
||||||
|
WriteMemId,
|
||||||
|
WritePtrId
|
||||||
};
|
};
|
||||||
|
|
||||||
class CallMain
|
static const char *getJITFuncIdName(JITFuncId Id);
|
||||||
: public rpc::Function<CallMain,
|
|
||||||
int32_t(JITTargetAddress Addr,
|
|
||||||
std::vector<std::string> Args)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "CallMain"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class CallVoidVoid : public rpc::Function<CallVoidVoid,
|
typedef Function<CallIntVoidId, int32_t(JITTargetAddress Addr)> CallIntVoid;
|
||||||
void(JITTargetAddress FnAddr)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "CallVoidVoid"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class CreateRemoteAllocator
|
typedef Function<CallMainId,
|
||||||
: public rpc::Function<CreateRemoteAllocator,
|
int32_t(JITTargetAddress Addr,
|
||||||
void(ResourceIdMgr::ResourceId AllocatorID)> {
|
std::vector<std::string> Args)>
|
||||||
public:
|
CallMain;
|
||||||
static const char* getName() { return "CreateRemoteAllocator"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class CreateIndirectStubsOwner
|
typedef Function<CallVoidVoidId, void(JITTargetAddress FnAddr)> CallVoidVoid;
|
||||||
: public rpc::Function<CreateIndirectStubsOwner,
|
|
||||||
void(ResourceIdMgr::ResourceId StubOwnerID)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "CreateIndirectStubsOwner"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class DeregisterEHFrames
|
typedef Function<CreateRemoteAllocatorId,
|
||||||
: public rpc::Function<DeregisterEHFrames,
|
void(ResourceIdMgr::ResourceId AllocatorID)>
|
||||||
void(JITTargetAddress Addr, uint32_t Size)> {
|
CreateRemoteAllocator;
|
||||||
public:
|
|
||||||
static const char* getName() { return "DeregisterEHFrames"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class DestroyRemoteAllocator
|
typedef Function<CreateIndirectStubsOwnerId,
|
||||||
: public rpc::Function<DestroyRemoteAllocator,
|
void(ResourceIdMgr::ResourceId StubOwnerID)>
|
||||||
void(ResourceIdMgr::ResourceId AllocatorID)> {
|
CreateIndirectStubsOwner;
|
||||||
public:
|
|
||||||
static const char* getName() { return "DestroyRemoteAllocator"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class DestroyIndirectStubsOwner
|
typedef Function<DeregisterEHFramesId,
|
||||||
: public rpc::Function<DestroyIndirectStubsOwner,
|
void(JITTargetAddress Addr, uint32_t Size)>
|
||||||
void(ResourceIdMgr::ResourceId StubsOwnerID)> {
|
DeregisterEHFrames;
|
||||||
public:
|
|
||||||
static const char* getName() { return "DestroyIndirectStubsOwner"; }
|
typedef Function<DestroyRemoteAllocatorId,
|
||||||
};
|
void(ResourceIdMgr::ResourceId AllocatorID)>
|
||||||
|
DestroyRemoteAllocator;
|
||||||
|
|
||||||
|
typedef Function<DestroyIndirectStubsOwnerId,
|
||||||
|
void(ResourceIdMgr::ResourceId StubsOwnerID)>
|
||||||
|
DestroyIndirectStubsOwner;
|
||||||
|
|
||||||
/// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted).
|
/// EmitIndirectStubs result is (StubsBase, PtrsBase, NumStubsEmitted).
|
||||||
class EmitIndirectStubs
|
typedef Function<EmitIndirectStubsId,
|
||||||
: public rpc::Function<EmitIndirectStubs,
|
std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>(
|
||||||
std::tuple<JITTargetAddress, JITTargetAddress,
|
ResourceIdMgr::ResourceId StubsOwnerID,
|
||||||
uint32_t>(
|
uint32_t NumStubsRequired)>
|
||||||
ResourceIdMgr::ResourceId StubsOwnerID,
|
EmitIndirectStubs;
|
||||||
uint32_t NumStubsRequired)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "EmitIndirectStubs"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class EmitResolverBlock : public rpc::Function<EmitResolverBlock, void()> {
|
typedef Function<EmitResolverBlockId, void()> EmitResolverBlock;
|
||||||
public:
|
|
||||||
static const char* getName() { return "EmitResolverBlock"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/// EmitTrampolineBlock result is (BlockAddr, NumTrampolines).
|
/// EmitTrampolineBlock result is (BlockAddr, NumTrampolines).
|
||||||
class EmitTrampolineBlock
|
typedef Function<EmitTrampolineBlockId,
|
||||||
: public rpc::Function<EmitTrampolineBlock,
|
std::tuple<JITTargetAddress, uint32_t>()>
|
||||||
std::tuple<JITTargetAddress, uint32_t>()> {
|
EmitTrampolineBlock;
|
||||||
public:
|
|
||||||
static const char* getName() { return "EmitTrampolineBlock"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class GetSymbolAddress
|
typedef Function<GetSymbolAddressId, JITTargetAddress(std::string SymbolName)>
|
||||||
: public rpc::Function<GetSymbolAddress,
|
GetSymbolAddress;
|
||||||
JITTargetAddress(std::string SymbolName)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "GetSymbolAddress"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize,
|
/// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize,
|
||||||
/// IndirectStubsSize).
|
/// IndirectStubsSize).
|
||||||
class GetRemoteInfo
|
typedef Function<GetRemoteInfoId, std::tuple<std::string, uint32_t, uint32_t,
|
||||||
: public rpc::Function<GetRemoteInfo,
|
uint32_t, uint32_t>()>
|
||||||
std::tuple<std::string, uint32_t, uint32_t,
|
GetRemoteInfo;
|
||||||
uint32_t, uint32_t>()> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "GetRemoteInfo"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class ReadMem
|
typedef Function<ReadMemId,
|
||||||
: public rpc::Function<ReadMem,
|
std::vector<char>(JITTargetAddress Src, uint64_t Size)>
|
||||||
std::vector<uint8_t>(JITTargetAddress Src,
|
ReadMem;
|
||||||
uint64_t Size)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "ReadMem"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class RegisterEHFrames
|
typedef Function<RegisterEHFramesId, void(JITTargetAddress Addr, uint32_t Size)>
|
||||||
: public rpc::Function<RegisterEHFrames,
|
RegisterEHFrames;
|
||||||
void(JITTargetAddress Addr, uint32_t Size)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "RegisterEHFrames"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class ReserveMem
|
typedef Function<ReserveMemId,
|
||||||
: public rpc::Function<ReserveMem,
|
JITTargetAddress(ResourceIdMgr::ResourceId AllocID,
|
||||||
JITTargetAddress(ResourceIdMgr::ResourceId AllocID,
|
uint64_t Size, uint32_t Align)>
|
||||||
uint64_t Size, uint32_t Align)> {
|
ReserveMem;
|
||||||
public:
|
|
||||||
static const char* getName() { return "ReserveMem"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class RequestCompile
|
typedef Function<RequestCompileId,
|
||||||
: public rpc::Function<RequestCompile,
|
JITTargetAddress(JITTargetAddress TrampolineAddr)>
|
||||||
JITTargetAddress(JITTargetAddress TrampolineAddr)> {
|
RequestCompile;
|
||||||
public:
|
|
||||||
static const char* getName() { return "RequestCompile"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class SetProtections
|
typedef Function<SetProtectionsId,
|
||||||
: public rpc::Function<SetProtections,
|
void(ResourceIdMgr::ResourceId AllocID, JITTargetAddress Dst,
|
||||||
void(ResourceIdMgr::ResourceId AllocID,
|
uint32_t ProtFlags)>
|
||||||
JITTargetAddress Dst,
|
SetProtections;
|
||||||
uint32_t ProtFlags)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "SetProtections"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class TerminateSession : public rpc::Function<TerminateSession, void()> {
|
typedef Function<TerminateSessionId, void()> TerminateSession;
|
||||||
public:
|
|
||||||
static const char* getName() { return "TerminateSession"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class WriteMem : public rpc::Function<WriteMem,
|
typedef Function<WriteMemId, void(DirectBufferWriter DB)> WriteMem;
|
||||||
void(remote::DirectBufferWriter DB)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "WriteMem"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class WritePtr
|
|
||||||
: public rpc::Function<WritePtr,
|
|
||||||
void(JITTargetAddress Dst, JITTargetAddress Val)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "WritePtr"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
typedef Function<WritePtrId, void(JITTargetAddress Dst, JITTargetAddress Val)>
|
||||||
|
WritePtr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace remote
|
} // end namespace remote
|
||||||
|
@ -41,51 +41,94 @@ public:
|
|||||||
OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup,
|
OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup,
|
||||||
EHFrameRegistrationFtor EHFramesRegister,
|
EHFrameRegistrationFtor EHFramesRegister,
|
||||||
EHFrameRegistrationFtor EHFramesDeregister)
|
EHFrameRegistrationFtor EHFramesDeregister)
|
||||||
: OrcRemoteTargetRPCAPI(Channel), SymbolLookup(std::move(SymbolLookup)),
|
: Channel(Channel), SymbolLookup(std::move(SymbolLookup)),
|
||||||
EHFramesRegister(std::move(EHFramesRegister)),
|
EHFramesRegister(std::move(EHFramesRegister)),
|
||||||
EHFramesDeregister(std::move(EHFramesDeregister)),
|
EHFramesDeregister(std::move(EHFramesDeregister)) {}
|
||||||
TerminateFlag(false) {
|
|
||||||
|
|
||||||
using ThisT = typename std::remove_reference<decltype(*this)>::type;
|
|
||||||
addHandler<CallIntVoid>(*this, &ThisT::handleCallIntVoid);
|
|
||||||
addHandler<CallMain>(*this, &ThisT::handleCallMain);
|
|
||||||
addHandler<CallVoidVoid>(*this, &ThisT::handleCallVoidVoid);
|
|
||||||
addHandler<CreateRemoteAllocator>(*this,
|
|
||||||
&ThisT::handleCreateRemoteAllocator);
|
|
||||||
addHandler<CreateIndirectStubsOwner>(*this,
|
|
||||||
&ThisT::handleCreateIndirectStubsOwner);
|
|
||||||
addHandler<DeregisterEHFrames>(*this, &ThisT::handleDeregisterEHFrames);
|
|
||||||
addHandler<DestroyRemoteAllocator>(*this,
|
|
||||||
&ThisT::handleDestroyRemoteAllocator);
|
|
||||||
addHandler<DestroyIndirectStubsOwner>(*this,
|
|
||||||
&ThisT::handleDestroyIndirectStubsOwner);
|
|
||||||
addHandler<EmitIndirectStubs>(*this, &ThisT::handleEmitIndirectStubs);
|
|
||||||
addHandler<EmitResolverBlock>(*this, &ThisT::handleEmitResolverBlock);
|
|
||||||
addHandler<EmitTrampolineBlock>(*this, &ThisT::handleEmitTrampolineBlock);
|
|
||||||
addHandler<GetSymbolAddress>(*this, &ThisT::handleGetSymbolAddress);
|
|
||||||
addHandler<GetRemoteInfo>(*this, &ThisT::handleGetRemoteInfo);
|
|
||||||
addHandler<ReadMem>(*this, &ThisT::handleReadMem);
|
|
||||||
addHandler<RegisterEHFrames>(*this, &ThisT::handleRegisterEHFrames);
|
|
||||||
addHandler<ReserveMem>(*this, &ThisT::handleReserveMem);
|
|
||||||
addHandler<SetProtections>(*this, &ThisT::handleSetProtections);
|
|
||||||
addHandler<TerminateSession>(*this, &ThisT::handleTerminateSession);
|
|
||||||
addHandler<WriteMem>(*this, &ThisT::handleWriteMem);
|
|
||||||
addHandler<WritePtr>(*this, &ThisT::handleWritePtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Remove move/copy ops once MSVC supports synthesizing move ops.
|
// FIXME: Remove move/copy ops once MSVC supports synthesizing move ops.
|
||||||
OrcRemoteTargetServer(const OrcRemoteTargetServer &) = delete;
|
OrcRemoteTargetServer(const OrcRemoteTargetServer &) = delete;
|
||||||
OrcRemoteTargetServer &operator=(const OrcRemoteTargetServer &) = delete;
|
OrcRemoteTargetServer &operator=(const OrcRemoteTargetServer &) = delete;
|
||||||
|
|
||||||
OrcRemoteTargetServer(OrcRemoteTargetServer &&Other) = default;
|
OrcRemoteTargetServer(OrcRemoteTargetServer &&Other)
|
||||||
|
: Channel(Other.Channel), SymbolLookup(std::move(Other.SymbolLookup)),
|
||||||
|
EHFramesRegister(std::move(Other.EHFramesRegister)),
|
||||||
|
EHFramesDeregister(std::move(Other.EHFramesDeregister)) {}
|
||||||
|
|
||||||
OrcRemoteTargetServer &operator=(OrcRemoteTargetServer &&) = delete;
|
OrcRemoteTargetServer &operator=(OrcRemoteTargetServer &&) = delete;
|
||||||
|
|
||||||
|
Error handleKnownFunction(JITFuncId Id) {
|
||||||
|
typedef OrcRemoteTargetServer ThisT;
|
||||||
|
|
||||||
Expected<JITTargetAddress> requestCompile(JITTargetAddress TrampolineAddr) {
|
DEBUG(dbgs() << "Handling known proc: " << getJITFuncIdName(Id) << "\n");
|
||||||
return callB<RequestCompile>(TrampolineAddr);
|
|
||||||
|
switch (Id) {
|
||||||
|
case CallIntVoidId:
|
||||||
|
return handle<CallIntVoid>(Channel, *this, &ThisT::handleCallIntVoid);
|
||||||
|
case CallMainId:
|
||||||
|
return handle<CallMain>(Channel, *this, &ThisT::handleCallMain);
|
||||||
|
case CallVoidVoidId:
|
||||||
|
return handle<CallVoidVoid>(Channel, *this, &ThisT::handleCallVoidVoid);
|
||||||
|
case CreateRemoteAllocatorId:
|
||||||
|
return handle<CreateRemoteAllocator>(Channel, *this,
|
||||||
|
&ThisT::handleCreateRemoteAllocator);
|
||||||
|
case CreateIndirectStubsOwnerId:
|
||||||
|
return handle<CreateIndirectStubsOwner>(
|
||||||
|
Channel, *this, &ThisT::handleCreateIndirectStubsOwner);
|
||||||
|
case DeregisterEHFramesId:
|
||||||
|
return handle<DeregisterEHFrames>(Channel, *this,
|
||||||
|
&ThisT::handleDeregisterEHFrames);
|
||||||
|
case DestroyRemoteAllocatorId:
|
||||||
|
return handle<DestroyRemoteAllocator>(
|
||||||
|
Channel, *this, &ThisT::handleDestroyRemoteAllocator);
|
||||||
|
case DestroyIndirectStubsOwnerId:
|
||||||
|
return handle<DestroyIndirectStubsOwner>(
|
||||||
|
Channel, *this, &ThisT::handleDestroyIndirectStubsOwner);
|
||||||
|
case EmitIndirectStubsId:
|
||||||
|
return handle<EmitIndirectStubs>(Channel, *this,
|
||||||
|
&ThisT::handleEmitIndirectStubs);
|
||||||
|
case EmitResolverBlockId:
|
||||||
|
return handle<EmitResolverBlock>(Channel, *this,
|
||||||
|
&ThisT::handleEmitResolverBlock);
|
||||||
|
case EmitTrampolineBlockId:
|
||||||
|
return handle<EmitTrampolineBlock>(Channel, *this,
|
||||||
|
&ThisT::handleEmitTrampolineBlock);
|
||||||
|
case GetSymbolAddressId:
|
||||||
|
return handle<GetSymbolAddress>(Channel, *this,
|
||||||
|
&ThisT::handleGetSymbolAddress);
|
||||||
|
case GetRemoteInfoId:
|
||||||
|
return handle<GetRemoteInfo>(Channel, *this, &ThisT::handleGetRemoteInfo);
|
||||||
|
case ReadMemId:
|
||||||
|
return handle<ReadMem>(Channel, *this, &ThisT::handleReadMem);
|
||||||
|
case RegisterEHFramesId:
|
||||||
|
return handle<RegisterEHFrames>(Channel, *this,
|
||||||
|
&ThisT::handleRegisterEHFrames);
|
||||||
|
case ReserveMemId:
|
||||||
|
return handle<ReserveMem>(Channel, *this, &ThisT::handleReserveMem);
|
||||||
|
case SetProtectionsId:
|
||||||
|
return handle<SetProtections>(Channel, *this,
|
||||||
|
&ThisT::handleSetProtections);
|
||||||
|
case WriteMemId:
|
||||||
|
return handle<WriteMem>(Channel, *this, &ThisT::handleWriteMem);
|
||||||
|
case WritePtrId:
|
||||||
|
return handle<WritePtr>(Channel, *this, &ThisT::handleWritePtr);
|
||||||
|
default:
|
||||||
|
return orcError(OrcErrorCode::UnexpectedRPCCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm_unreachable("Unhandled JIT RPC procedure Id.");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool receivedTerminate() const { return TerminateFlag; }
|
Expected<JITTargetAddress> requestCompile(JITTargetAddress TrampolineAddr) {
|
||||||
|
auto Listen = [&](RPCByteChannel &C, uint32_t Id) {
|
||||||
|
return handleKnownFunction(static_cast<JITFuncId>(Id));
|
||||||
|
};
|
||||||
|
|
||||||
|
return callSTHandling<RequestCompile>(Channel, Listen, TrampolineAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error handleTerminateSession() {
|
||||||
|
return handle<TerminateSession>(Channel, []() { return Error::success(); });
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Allocator {
|
struct Allocator {
|
||||||
@ -322,16 +365,15 @@ private:
|
|||||||
IndirectStubSize);
|
IndirectStubSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::vector<uint8_t>> handleReadMem(JITTargetAddress RSrc,
|
Expected<std::vector<char>> handleReadMem(JITTargetAddress RSrc, uint64_t Size) {
|
||||||
uint64_t Size) {
|
char *Src = reinterpret_cast<char *>(static_cast<uintptr_t>(RSrc));
|
||||||
uint8_t *Src = reinterpret_cast<uint8_t*>(static_cast<uintptr_t>(RSrc));
|
|
||||||
|
|
||||||
DEBUG(dbgs() << " Reading " << Size << " bytes from "
|
DEBUG(dbgs() << " Reading " << Size << " bytes from "
|
||||||
<< format("0x%016x", RSrc) << "\n");
|
<< format("0x%016x", RSrc) << "\n");
|
||||||
|
|
||||||
std::vector<uint8_t> Buffer;
|
std::vector<char> Buffer;
|
||||||
Buffer.resize(Size);
|
Buffer.resize(Size);
|
||||||
for (uint8_t *P = Src; Size != 0; --Size)
|
for (char *P = Src; Size != 0; --Size)
|
||||||
Buffer.push_back(*P++);
|
Buffer.push_back(*P++);
|
||||||
|
|
||||||
return Buffer;
|
return Buffer;
|
||||||
@ -379,11 +421,6 @@ private:
|
|||||||
return Allocator.setProtections(LocalAddr, Flags);
|
return Allocator.setProtections(LocalAddr, Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error handleTerminateSession() {
|
|
||||||
TerminateFlag = true;
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error handleWriteMem(DirectBufferWriter DBW) {
|
Error handleWriteMem(DirectBufferWriter DBW) {
|
||||||
DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to "
|
DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to "
|
||||||
<< format("0x%016x", DBW.getDst()) << "\n");
|
<< format("0x%016x", DBW.getDst()) << "\n");
|
||||||
@ -399,6 +436,7 @@ private:
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChannelT &Channel;
|
||||||
SymbolLookupFtor SymbolLookup;
|
SymbolLookupFtor SymbolLookup;
|
||||||
EHFrameRegistrationFtor EHFramesRegister, EHFramesDeregister;
|
EHFrameRegistrationFtor EHFramesRegister, EHFramesDeregister;
|
||||||
std::map<ResourceIdMgr::ResourceId, Allocator> Allocators;
|
std::map<ResourceIdMgr::ResourceId, Allocator> Allocators;
|
||||||
@ -406,7 +444,6 @@ private:
|
|||||||
std::map<ResourceIdMgr::ResourceId, ISBlockOwnerList> IndirectStubsOwners;
|
std::map<ResourceIdMgr::ResourceId, ISBlockOwnerList> IndirectStubsOwners;
|
||||||
sys::OwningMemoryBlock ResolverBlock;
|
sys::OwningMemoryBlock ResolverBlock;
|
||||||
std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
|
std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
|
||||||
bool TerminateFlag;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace remote
|
} // end namespace remote
|
||||||
|
231
include/llvm/ExecutionEngine/Orc/RPCByteChannel.h
Normal file
231
include/llvm/ExecutionEngine/Orc/RPCByteChannel.h
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
//===- llvm/ExecutionEngine/Orc/RPCByteChannel.h ----------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_EXECUTIONENGINE_ORC_RPCBYTECHANNEL_H
|
||||||
|
#define LLVM_EXECUTIONENGINE_ORC_RPCBYTECHANNEL_H
|
||||||
|
|
||||||
|
#include "OrcError.h"
|
||||||
|
#include "RPCSerialization.h"
|
||||||
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/Support/Endian.h"
|
||||||
|
#include "llvm/Support/Error.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace orc {
|
||||||
|
namespace remote {
|
||||||
|
|
||||||
|
/// Interface for byte-streams to be used with RPC.
|
||||||
|
class RPCByteChannel {
|
||||||
|
public:
|
||||||
|
virtual ~RPCByteChannel() {}
|
||||||
|
|
||||||
|
/// Read Size bytes from the stream into *Dst.
|
||||||
|
virtual Error readBytes(char *Dst, unsigned Size) = 0;
|
||||||
|
|
||||||
|
/// Read size bytes from *Src and append them to the stream.
|
||||||
|
virtual Error appendBytes(const char *Src, unsigned Size) = 0;
|
||||||
|
|
||||||
|
/// Flush the stream if possible.
|
||||||
|
virtual Error send() = 0;
|
||||||
|
|
||||||
|
/// Get the lock for stream reading.
|
||||||
|
std::mutex &getReadLock() { return readLock; }
|
||||||
|
|
||||||
|
/// Get the lock for stream writing.
|
||||||
|
std::mutex &getWriteLock() { return writeLock; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex readLock, writeLock;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Notify the channel that we're starting a message send.
|
||||||
|
/// Locks the channel for writing.
|
||||||
|
inline Error startSendMessage(RPCByteChannel &C) {
|
||||||
|
C.getWriteLock().lock();
|
||||||
|
return Error::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Notify the channel that we're ending a message send.
|
||||||
|
/// Unlocks the channel for writing.
|
||||||
|
inline Error endSendMessage(RPCByteChannel &C) {
|
||||||
|
C.getWriteLock().unlock();
|
||||||
|
return Error::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Notify the channel that we're starting a message receive.
|
||||||
|
/// Locks the channel for reading.
|
||||||
|
inline Error startReceiveMessage(RPCByteChannel &C) {
|
||||||
|
C.getReadLock().lock();
|
||||||
|
return Error::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Notify the channel that we're ending a message receive.
|
||||||
|
/// Unlocks the channel for reading.
|
||||||
|
inline Error endReceiveMessage(RPCByteChannel &C) {
|
||||||
|
C.getReadLock().unlock();
|
||||||
|
return Error::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ChannelT, typename T,
|
||||||
|
typename =
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_base_of<RPCByteChannel, ChannelT>::value>::
|
||||||
|
type>
|
||||||
|
class RPCByteChannelPrimitiveSerialization {
|
||||||
|
public:
|
||||||
|
static Error serialize(ChannelT &C, T V) {
|
||||||
|
support::endian::byte_swap<T, support::big>(V);
|
||||||
|
return C.appendBytes(reinterpret_cast<const char *>(&V), sizeof(T));
|
||||||
|
};
|
||||||
|
|
||||||
|
static Error deserialize(ChannelT &C, T &V) {
|
||||||
|
if (auto Err = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T)))
|
||||||
|
return Err;
|
||||||
|
support::endian::byte_swap<T, support::big>(V);
|
||||||
|
return Error::success();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, uint64_t>
|
||||||
|
: public RPCByteChannelPrimitiveSerialization<ChannelT, uint64_t> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "uint64_t"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, int64_t>
|
||||||
|
: public RPCByteChannelPrimitiveSerialization<ChannelT, int64_t> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "int64_t"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, uint32_t>
|
||||||
|
: public RPCByteChannelPrimitiveSerialization<ChannelT, uint32_t> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "uint32_t"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, int32_t>
|
||||||
|
: public RPCByteChannelPrimitiveSerialization<ChannelT, int32_t> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "int32_t"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, uint16_t>
|
||||||
|
: public RPCByteChannelPrimitiveSerialization<ChannelT, uint16_t> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "uint16_t"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, int16_t>
|
||||||
|
: public RPCByteChannelPrimitiveSerialization<ChannelT, int16_t> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "int16_t"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, uint8_t>
|
||||||
|
: public RPCByteChannelPrimitiveSerialization<ChannelT, uint8_t> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "uint8_t"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, int8_t>
|
||||||
|
: public RPCByteChannelPrimitiveSerialization<ChannelT, int8_t> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "int8_t"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, char>
|
||||||
|
: public RPCByteChannelPrimitiveSerialization<ChannelT, uint8_t> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "char"; }
|
||||||
|
|
||||||
|
static Error serialize(RPCByteChannel &C, char V) {
|
||||||
|
return serializeSeq(C, static_cast<uint8_t>(V));
|
||||||
|
};
|
||||||
|
|
||||||
|
static Error deserialize(RPCByteChannel &C, char &V) {
|
||||||
|
uint8_t VV;
|
||||||
|
if (auto Err = deserializeSeq(C, VV))
|
||||||
|
return Err;
|
||||||
|
V = static_cast<char>(V);
|
||||||
|
return Error::success();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, bool,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_base_of<RPCByteChannel, ChannelT>::value>::
|
||||||
|
type> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "bool"; }
|
||||||
|
|
||||||
|
static Error serialize(ChannelT &C, bool V) {
|
||||||
|
return C.appendBytes(reinterpret_cast<const char *>(&V), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Error deserialize(ChannelT &C, bool &V) {
|
||||||
|
return C.readBytes(reinterpret_cast<char *>(&V), 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT>
|
||||||
|
class SerializationTraits<ChannelT, std::string,
|
||||||
|
typename std::enable_if<
|
||||||
|
std::is_base_of<RPCByteChannel, ChannelT>::value>::
|
||||||
|
type> {
|
||||||
|
public:
|
||||||
|
static const char* getName() { return "std::string"; }
|
||||||
|
|
||||||
|
static Error serialize(RPCByteChannel &C, StringRef S) {
|
||||||
|
if (auto Err = SerializationTraits<RPCByteChannel, uint64_t>::
|
||||||
|
serialize(C, static_cast<uint64_t>(S.size())))
|
||||||
|
return Err;
|
||||||
|
return C.appendBytes((const char *)S.bytes_begin(), S.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RPC channel serialization for std::strings.
|
||||||
|
static Error serialize(RPCByteChannel &C, const std::string &S) {
|
||||||
|
return serialize(C, StringRef(S));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RPC channel deserialization for std::strings.
|
||||||
|
static Error deserialize(RPCByteChannel &C, std::string &S) {
|
||||||
|
uint64_t Count = 0;
|
||||||
|
if (auto Err = SerializationTraits<RPCByteChannel, uint64_t>::
|
||||||
|
deserialize(C, Count))
|
||||||
|
return Err;
|
||||||
|
S.resize(Count);
|
||||||
|
return C.readBytes(&S[0], Count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace remote
|
||||||
|
} // end namespace orc
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
|
#endif // LLVM_EXECUTIONENGINE_ORC_RPCBYTECHANNEL_H
|
@ -17,164 +17,7 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace orc {
|
namespace orc {
|
||||||
namespace rpc {
|
namespace remote {
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class RPCTypeName;
|
|
||||||
|
|
||||||
/// TypeNameSequence is a utility for rendering sequences of types to a string
|
|
||||||
/// by rendering each type, separated by ", ".
|
|
||||||
template <typename... ArgTs> class RPCTypeNameSequence {};
|
|
||||||
|
|
||||||
/// Render an empty TypeNameSequence to an ostream.
|
|
||||||
template <typename OStream>
|
|
||||||
OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) {
|
|
||||||
return OS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render a TypeNameSequence of a single type to an ostream.
|
|
||||||
template <typename OStream, typename ArgT>
|
|
||||||
OStream &operator<<(OStream &OS, const RPCTypeNameSequence<ArgT> &V) {
|
|
||||||
OS << RPCTypeName<ArgT>::getName();
|
|
||||||
return OS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render a TypeNameSequence of more than one type to an ostream.
|
|
||||||
template <typename OStream, typename ArgT1, typename ArgT2, typename... ArgTs>
|
|
||||||
OStream&
|
|
||||||
operator<<(OStream &OS, const RPCTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) {
|
|
||||||
OS << RPCTypeName<ArgT1>::getName() << ", "
|
|
||||||
<< RPCTypeNameSequence<ArgT2, ArgTs...>();
|
|
||||||
return OS;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<void> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "void"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<int8_t> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "int8_t"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<uint8_t> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "uint8_t"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<int16_t> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "int16_t"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<uint16_t> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "uint16_t"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<int32_t> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "int32_t"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<uint32_t> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "uint32_t"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<int64_t> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "int64_t"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<uint64_t> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "uint64_t"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<bool> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "bool"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
class RPCTypeName<std::string> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "std::string"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
|
||||||
class RPCTypeName<std::pair<T1, T2>> {
|
|
||||||
public:
|
|
||||||
static const char* getName() {
|
|
||||||
std::lock_guard<std::mutex> Lock(NameMutex);
|
|
||||||
if (Name.empty())
|
|
||||||
raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>()
|
|
||||||
<< ">";
|
|
||||||
return Name.data();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
static std::mutex NameMutex;
|
|
||||||
static std::string Name;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
|
||||||
std::mutex RPCTypeName<std::pair<T1, T2>>::NameMutex;
|
|
||||||
template <typename T1, typename T2>
|
|
||||||
std::string RPCTypeName<std::pair<T1, T2>>::Name;
|
|
||||||
|
|
||||||
template <typename... ArgTs>
|
|
||||||
class RPCTypeName<std::tuple<ArgTs...>> {
|
|
||||||
public:
|
|
||||||
static const char* getName() {
|
|
||||||
std::lock_guard<std::mutex> Lock(NameMutex);
|
|
||||||
if (Name.empty())
|
|
||||||
raw_string_ostream(Name) << "std::tuple<"
|
|
||||||
<< RPCTypeNameSequence<ArgTs...>() << ">";
|
|
||||||
return Name.data();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
static std::mutex NameMutex;
|
|
||||||
static std::string Name;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... ArgTs>
|
|
||||||
std::mutex RPCTypeName<std::tuple<ArgTs...>>::NameMutex;
|
|
||||||
template <typename... ArgTs>
|
|
||||||
std::string RPCTypeName<std::tuple<ArgTs...>>::Name;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class RPCTypeName<std::vector<T>> {
|
|
||||||
public:
|
|
||||||
static const char*getName() {
|
|
||||||
std::lock_guard<std::mutex> Lock(NameMutex);
|
|
||||||
if (Name.empty())
|
|
||||||
raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName()
|
|
||||||
<< ">";
|
|
||||||
return Name.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::mutex NameMutex;
|
|
||||||
static std::string Name;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::mutex RPCTypeName<std::vector<T>>::NameMutex;
|
|
||||||
template <typename T>
|
|
||||||
std::string RPCTypeName<std::vector<T>>::Name;
|
|
||||||
|
|
||||||
|
|
||||||
/// The SerializationTraits<ChannelT, T> class describes how to serialize and
|
/// The SerializationTraits<ChannelT, T> class describes how to serialize and
|
||||||
/// deserialize an instance of type T to/from an abstract channel of type
|
/// deserialize an instance of type T to/from an abstract channel of type
|
||||||
@ -208,92 +51,71 @@ std::string RPCTypeName<std::vector<T>>::Name;
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// @endcode
|
/// @endcode
|
||||||
template <typename ChannelT, typename WireType, typename From = WireType,
|
template <typename ChannelT, typename T, typename = void>
|
||||||
typename = void>
|
|
||||||
class SerializationTraits {};
|
class SerializationTraits {};
|
||||||
|
|
||||||
template <typename ChannelT>
|
/// TypeNameSequence is a utility for rendering sequences of types to a string
|
||||||
class SequenceTraits {
|
/// by rendering each type, separated by ", ".
|
||||||
public:
|
template <typename ChannelT, typename... ArgTs> class TypeNameSequence {};
|
||||||
static Error emitSeparator(ChannelT &C) { return Error::success(); }
|
|
||||||
static Error consumeSeparator(ChannelT &C) { return Error::success(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Utility class for serializing sequences of values of varying types.
|
/// Render a TypeNameSequence of a single type to an ostream.
|
||||||
/// Specializations of this class contain 'serialize' and 'deserialize' methods
|
template <typename OStream, typename ChannelT, typename ArgT>
|
||||||
/// for the given channel. The ArgTs... list will determine the "over-the-wire"
|
OStream &operator<<(OStream &OS, const TypeNameSequence<ChannelT, ArgT> &V) {
|
||||||
/// types to be serialized. The serialize and deserialize methods take a list
|
OS << SerializationTraits<ChannelT, ArgT>::getName();
|
||||||
/// CArgTs... ("caller arg types") which must be the same length as ArgTs...,
|
return OS;
|
||||||
/// but may be different types from ArgTs, provided that for each CArgT there
|
|
||||||
/// is a SerializationTraits specialization
|
|
||||||
/// SerializeTraits<ChannelT, ArgT, CArgT> with methods that can serialize the
|
|
||||||
/// caller argument to over-the-wire value.
|
|
||||||
template <typename ChannelT, typename... ArgTs>
|
|
||||||
class SequenceSerialization;
|
|
||||||
|
|
||||||
template <typename ChannelT>
|
|
||||||
class SequenceSerialization<ChannelT> {
|
|
||||||
public:
|
|
||||||
static Error serialize(ChannelT &C) { return Error::success(); }
|
|
||||||
static Error deserialize(ChannelT &C) { return Error::success(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ChannelT, typename ArgT>
|
|
||||||
class SequenceSerialization<ChannelT, ArgT> {
|
|
||||||
public:
|
|
||||||
|
|
||||||
template <typename CArgT>
|
|
||||||
static Error serialize(ChannelT &C, const CArgT &CArg) {
|
|
||||||
return SerializationTraits<ChannelT, ArgT, CArgT>::serialize(C, CArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename CArgT>
|
|
||||||
static Error deserialize(ChannelT &C, CArgT &CArg) {
|
|
||||||
return SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ChannelT, typename ArgT, typename... ArgTs>
|
|
||||||
class SequenceSerialization<ChannelT, ArgT, ArgTs...> {
|
|
||||||
public:
|
|
||||||
|
|
||||||
template <typename CArgT, typename... CArgTs>
|
|
||||||
static Error serialize(ChannelT &C, const CArgT &CArg,
|
|
||||||
const CArgTs&... CArgs) {
|
|
||||||
if (auto Err =
|
|
||||||
SerializationTraits<ChannelT, ArgT, CArgT>::serialize(C, CArg))
|
|
||||||
return Err;
|
|
||||||
if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C))
|
|
||||||
return Err;
|
|
||||||
return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, CArgs...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename CArgT, typename... CArgTs>
|
|
||||||
static Error deserialize(ChannelT &C, CArgT &CArg,
|
|
||||||
CArgTs&... CArgs) {
|
|
||||||
if (auto Err =
|
|
||||||
SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg))
|
|
||||||
return Err;
|
|
||||||
if (auto Err = SequenceTraits<ChannelT>::consumeSeparator(C))
|
|
||||||
return Err;
|
|
||||||
return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, CArgs...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ChannelT, typename... ArgTs>
|
|
||||||
Error serializeSeq(ChannelT &C, const ArgTs &... Args) {
|
|
||||||
return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, Args...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ChannelT, typename... ArgTs>
|
/// Render a TypeNameSequence of more than one type to an ostream.
|
||||||
Error deserializeSeq(ChannelT &C, ArgTs &... Args) {
|
template <typename OStream, typename ChannelT, typename ArgT1, typename ArgT2,
|
||||||
return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...);
|
typename... ArgTs>
|
||||||
|
OStream &
|
||||||
|
operator<<(OStream &OS,
|
||||||
|
const TypeNameSequence<ChannelT, ArgT1, ArgT2, ArgTs...> &V) {
|
||||||
|
OS << SerializationTraits<ChannelT, ArgT1>::getName() << ", "
|
||||||
|
<< TypeNameSequence<ChannelT, ArgT2, ArgTs...>();
|
||||||
|
return OS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RPC channel serialization for a variadic list of arguments.
|
||||||
|
template <typename ChannelT, typename T, typename... Ts>
|
||||||
|
Error serializeSeq(ChannelT &C, const T &Arg, const Ts &... Args) {
|
||||||
|
if (auto Err = SerializationTraits<ChannelT, T>::serialize(C, Arg))
|
||||||
|
return Err;
|
||||||
|
return serializeSeq(C, Args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RPC channel serialization for an (empty) variadic list of arguments.
|
||||||
|
template <typename ChannelT> Error serializeSeq(ChannelT &C) {
|
||||||
|
return Error::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RPC channel deserialization for a variadic list of arguments.
|
||||||
|
template <typename ChannelT, typename T, typename... Ts>
|
||||||
|
Error deserializeSeq(ChannelT &C, T &Arg, Ts &... Args) {
|
||||||
|
if (auto Err = SerializationTraits<ChannelT, T>::deserialize(C, Arg))
|
||||||
|
return Err;
|
||||||
|
return deserializeSeq(C, Args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RPC channel serialization for an (empty) variadic list of arguments.
|
||||||
|
template <typename ChannelT> Error deserializeSeq(ChannelT &C) {
|
||||||
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SerializationTraits default specialization for std::pair.
|
/// SerializationTraits default specialization for std::pair.
|
||||||
template <typename ChannelT, typename T1, typename T2>
|
template <typename ChannelT, typename T1, typename T2>
|
||||||
class SerializationTraits<ChannelT, std::pair<T1, T2>> {
|
class SerializationTraits<ChannelT, std::pair<T1, T2>> {
|
||||||
public:
|
public:
|
||||||
|
static const char *getName() {
|
||||||
|
std::lock_guard<std::mutex> Lock(NameMutex);
|
||||||
|
if (Name.empty())
|
||||||
|
Name = (std::ostringstream()
|
||||||
|
<< "std::pair<" << TypeNameSequence<ChannelT, T1, T2>() << ">")
|
||||||
|
.str();
|
||||||
|
|
||||||
|
return Name.data();
|
||||||
|
}
|
||||||
|
|
||||||
static Error serialize(ChannelT &C, const std::pair<T1, T2> &V) {
|
static Error serialize(ChannelT &C, const std::pair<T1, T2> &V) {
|
||||||
return serializeSeq(C, V.first, V.second);
|
return serializeSeq(C, V.first, V.second);
|
||||||
}
|
}
|
||||||
@ -301,12 +123,31 @@ public:
|
|||||||
static Error deserialize(ChannelT &C, std::pair<T1, T2> &V) {
|
static Error deserialize(ChannelT &C, std::pair<T1, T2> &V) {
|
||||||
return deserializeSeq(C, V.first, V.second);
|
return deserializeSeq(C, V.first, V.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::mutex NameMutex;
|
||||||
|
static std::string Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT, typename T1, typename T2>
|
||||||
|
std::mutex SerializationTraits<ChannelT, std::pair<T1, T2>>::NameMutex;
|
||||||
|
|
||||||
|
template <typename ChannelT, typename T1, typename T2>
|
||||||
|
std::string SerializationTraits<ChannelT, std::pair<T1, T2>>::Name;
|
||||||
|
|
||||||
/// SerializationTraits default specialization for std::tuple.
|
/// SerializationTraits default specialization for std::tuple.
|
||||||
template <typename ChannelT, typename... ArgTs>
|
template <typename ChannelT, typename... ArgTs>
|
||||||
class SerializationTraits<ChannelT, std::tuple<ArgTs...>> {
|
class SerializationTraits<ChannelT, std::tuple<ArgTs...>> {
|
||||||
public:
|
public:
|
||||||
|
static const char *getName() {
|
||||||
|
std::lock_guard<std::mutex> Lock(NameMutex);
|
||||||
|
if (Name.empty())
|
||||||
|
Name = (std::ostringstream()
|
||||||
|
<< "std::tuple<" << TypeNameSequence<ChannelT, ArgTs...>() << ">")
|
||||||
|
.str();
|
||||||
|
|
||||||
|
return Name.data();
|
||||||
|
}
|
||||||
|
|
||||||
/// RPC channel serialization for std::tuple.
|
/// RPC channel serialization for std::tuple.
|
||||||
static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) {
|
static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) {
|
||||||
@ -332,41 +173,68 @@ private:
|
|||||||
llvm::index_sequence<Is...> _) {
|
llvm::index_sequence<Is...> _) {
|
||||||
return deserializeSeq(C, std::get<Is>(V)...);
|
return deserializeSeq(C, std::get<Is>(V)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::mutex NameMutex;
|
||||||
|
static std::string Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename ChannelT, typename... ArgTs>
|
||||||
|
std::mutex SerializationTraits<ChannelT, std::tuple<ArgTs...>>::NameMutex;
|
||||||
|
|
||||||
|
template <typename ChannelT, typename... ArgTs>
|
||||||
|
std::string SerializationTraits<ChannelT, std::tuple<ArgTs...>>::Name;
|
||||||
|
|
||||||
/// SerializationTraits default specialization for std::vector.
|
/// SerializationTraits default specialization for std::vector.
|
||||||
template <typename ChannelT, typename T>
|
template <typename ChannelT, typename T>
|
||||||
class SerializationTraits<ChannelT, std::vector<T>> {
|
class SerializationTraits<ChannelT, std::vector<T>> {
|
||||||
public:
|
public:
|
||||||
|
static const char *getName() {
|
||||||
|
std::lock_guard<std::mutex> Lock(NameMutex);
|
||||||
|
if (Name.empty())
|
||||||
|
Name = (std::ostringstream() << "std::vector<"
|
||||||
|
<< TypeNameSequence<ChannelT, T>() << ">")
|
||||||
|
.str();
|
||||||
|
return Name.data();
|
||||||
|
}
|
||||||
|
|
||||||
/// Serialize a std::vector<T> from std::vector<T>.
|
|
||||||
static Error serialize(ChannelT &C, const std::vector<T> &V) {
|
static Error serialize(ChannelT &C, const std::vector<T> &V) {
|
||||||
if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size())))
|
if (auto Err = SerializationTraits<ChannelT, uint64_t>::serialize(
|
||||||
|
C, static_cast<uint64_t>(V.size())))
|
||||||
return Err;
|
return Err;
|
||||||
|
|
||||||
for (const auto &E : V)
|
for (const auto &E : V)
|
||||||
if (auto Err = serializeSeq(C, E))
|
if (auto Err = SerializationTraits<ChannelT, T>::serialize(C, E))
|
||||||
return Err;
|
return Err;
|
||||||
|
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserialize a std::vector<T> to a std::vector<T>.
|
|
||||||
static Error deserialize(ChannelT &C, std::vector<T> &V) {
|
static Error deserialize(ChannelT &C, std::vector<T> &V) {
|
||||||
uint64_t Count = 0;
|
uint64_t Count = 0;
|
||||||
if (auto Err = deserializeSeq(C, Count))
|
if (auto Err =
|
||||||
|
SerializationTraits<ChannelT, uint64_t>::deserialize(C, Count))
|
||||||
return Err;
|
return Err;
|
||||||
|
|
||||||
V.resize(Count);
|
V.resize(Count);
|
||||||
for (auto &E : V)
|
for (auto &E : V)
|
||||||
if (auto Err = deserializeSeq(C, E))
|
if (auto Err = SerializationTraits<ChannelT, T>::deserialize(C, E))
|
||||||
return Err;
|
return Err;
|
||||||
|
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::mutex NameMutex;
|
||||||
|
static std::string Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace rpc
|
template <typename ChannelT, typename T>
|
||||||
|
std::mutex SerializationTraits<ChannelT, std::vector<T>>::NameMutex;
|
||||||
|
|
||||||
|
template <typename ChannelT, typename T>
|
||||||
|
std::string SerializationTraits<ChannelT, std::vector<T>>::Name;
|
||||||
|
|
||||||
|
} // end namespace remote
|
||||||
} // end namespace orc
|
} // end namespace orc
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,182 +0,0 @@
|
|||||||
//===- llvm/ExecutionEngine/Orc/RawByteChannel.h ----------------*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H
|
|
||||||
#define LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H
|
|
||||||
|
|
||||||
#include "OrcError.h"
|
|
||||||
#include "RPCSerialization.h"
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
|
||||||
#include "llvm/ADT/STLExtras.h"
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
|
||||||
#include "llvm/Support/Endian.h"
|
|
||||||
#include "llvm/Support/Error.h"
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
#include <tuple>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
namespace orc {
|
|
||||||
namespace rpc {
|
|
||||||
|
|
||||||
/// Interface for byte-streams to be used with RPC.
|
|
||||||
class RawByteChannel {
|
|
||||||
public:
|
|
||||||
virtual ~RawByteChannel() {}
|
|
||||||
|
|
||||||
/// Read Size bytes from the stream into *Dst.
|
|
||||||
virtual Error readBytes(char *Dst, unsigned Size) = 0;
|
|
||||||
|
|
||||||
/// Read size bytes from *Src and append them to the stream.
|
|
||||||
virtual Error appendBytes(const char *Src, unsigned Size) = 0;
|
|
||||||
|
|
||||||
/// Flush the stream if possible.
|
|
||||||
virtual Error send() = 0;
|
|
||||||
|
|
||||||
/// Notify the channel that we're starting a message send.
|
|
||||||
/// Locks the channel for writing.
|
|
||||||
template <typename FunctionIdT, typename SequenceIdT>
|
|
||||||
Error startSendMessage(const FunctionIdT &FnId, const SequenceIdT &SeqNo) {
|
|
||||||
if (auto Err = serializeSeq(*this, FnId, SeqNo))
|
|
||||||
return Err;
|
|
||||||
writeLock.lock();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Notify the channel that we're ending a message send.
|
|
||||||
/// Unlocks the channel for writing.
|
|
||||||
Error endSendMessage() {
|
|
||||||
writeLock.unlock();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Notify the channel that we're starting a message receive.
|
|
||||||
/// Locks the channel for reading.
|
|
||||||
template <typename FunctionIdT, typename SequenceNumberT>
|
|
||||||
Error startReceiveMessage(FunctionIdT &FnId, SequenceNumberT &SeqNo) {
|
|
||||||
readLock.lock();
|
|
||||||
return deserializeSeq(*this, FnId, SeqNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Notify the channel that we're ending a message receive.
|
|
||||||
/// Unlocks the channel for reading.
|
|
||||||
Error endReceiveMessage() {
|
|
||||||
readLock.unlock();
|
|
||||||
return Error::success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the lock for stream reading.
|
|
||||||
std::mutex &getReadLock() { return readLock; }
|
|
||||||
|
|
||||||
/// Get the lock for stream writing.
|
|
||||||
std::mutex &getWriteLock() { return writeLock; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::mutex readLock, writeLock;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ChannelT, typename T>
|
|
||||||
class SerializationTraits<ChannelT, T, T,
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_base_of<RawByteChannel, ChannelT>::value &&
|
|
||||||
(std::is_same<T, uint8_t>::value ||
|
|
||||||
std::is_same<T, int8_t>::value ||
|
|
||||||
std::is_same<T, uint16_t>::value ||
|
|
||||||
std::is_same<T, int16_t>::value ||
|
|
||||||
std::is_same<T, uint32_t>::value ||
|
|
||||||
std::is_same<T, int32_t>::value ||
|
|
||||||
std::is_same<T, uint64_t>::value ||
|
|
||||||
std::is_same<T, int64_t>::value ||
|
|
||||||
std::is_same<T, char>::value)>::type> {
|
|
||||||
public:
|
|
||||||
static Error serialize(ChannelT &C, T V) {
|
|
||||||
support::endian::byte_swap<T, support::big>(V);
|
|
||||||
return C.appendBytes(reinterpret_cast<const char *>(&V), sizeof(T));
|
|
||||||
};
|
|
||||||
|
|
||||||
static Error deserialize(ChannelT &C, T &V) {
|
|
||||||
if (auto Err = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T)))
|
|
||||||
return Err;
|
|
||||||
support::endian::byte_swap<T, support::big>(V);
|
|
||||||
return Error::success();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ChannelT>
|
|
||||||
class SerializationTraits<ChannelT, bool, bool,
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_base_of<RawByteChannel, ChannelT>::value>::
|
|
||||||
type> {
|
|
||||||
public:
|
|
||||||
static Error serialize(ChannelT &C, bool V) {
|
|
||||||
return C.appendBytes(reinterpret_cast<const char *>(&V), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Error deserialize(ChannelT &C, bool &V) {
|
|
||||||
return C.readBytes(reinterpret_cast<char *>(&V), 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ChannelT>
|
|
||||||
class SerializationTraits<ChannelT, std::string, StringRef,
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_base_of<RawByteChannel, ChannelT>::value>::
|
|
||||||
type> {
|
|
||||||
public:
|
|
||||||
/// RPC channel serialization for std::strings.
|
|
||||||
static Error serialize(RawByteChannel &C, StringRef S) {
|
|
||||||
if (auto Err = serializeSeq(C, static_cast<uint64_t>(S.size())))
|
|
||||||
return Err;
|
|
||||||
return C.appendBytes((const char *)S.data(), S.size());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ChannelT>
|
|
||||||
class SerializationTraits<ChannelT, std::string, const char*,
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_base_of<RawByteChannel, ChannelT>::value>::
|
|
||||||
type> {
|
|
||||||
public:
|
|
||||||
static Error serialize(RawByteChannel &C, const char *S) {
|
|
||||||
return SerializationTraits<ChannelT, std::string, StringRef>::
|
|
||||||
serialize(C, S);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ChannelT>
|
|
||||||
class SerializationTraits<ChannelT, std::string, std::string,
|
|
||||||
typename std::enable_if<
|
|
||||||
std::is_base_of<RawByteChannel, ChannelT>::value>::
|
|
||||||
type> {
|
|
||||||
public:
|
|
||||||
/// RPC channel serialization for std::strings.
|
|
||||||
static Error serialize(RawByteChannel &C, const std::string &S) {
|
|
||||||
return SerializationTraits<ChannelT, std::string, StringRef>::
|
|
||||||
serialize(C, S);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// RPC channel deserialization for std::strings.
|
|
||||||
static Error deserialize(RawByteChannel &C, std::string &S) {
|
|
||||||
uint64_t Count = 0;
|
|
||||||
if (auto Err = deserializeSeq(C, Count))
|
|
||||||
return Err;
|
|
||||||
S.resize(Count);
|
|
||||||
return C.readBytes(&S[0], Count);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace rpc
|
|
||||||
} // end namespace orc
|
|
||||||
} // end namespace llvm
|
|
||||||
|
|
||||||
#endif // LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H
|
|
@ -6,6 +6,7 @@ add_llvm_library(LLVMOrcJIT
|
|||||||
OrcCBindings.cpp
|
OrcCBindings.cpp
|
||||||
OrcError.cpp
|
OrcError.cpp
|
||||||
OrcMCJITReplacement.cpp
|
OrcMCJITReplacement.cpp
|
||||||
|
OrcRemoteTargetRPCAPI.cpp
|
||||||
|
|
||||||
ADDITIONAL_HEADER_DIRS
|
ADDITIONAL_HEADER_DIRS
|
||||||
${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc
|
${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc
|
||||||
|
@ -43,8 +43,6 @@ public:
|
|||||||
return "Unexpected RPC call";
|
return "Unexpected RPC call";
|
||||||
case OrcErrorCode::UnexpectedRPCResponse:
|
case OrcErrorCode::UnexpectedRPCResponse:
|
||||||
return "Unexpected RPC response";
|
return "Unexpected RPC response";
|
||||||
case OrcErrorCode::UnknownRPCFunction:
|
|
||||||
return "Unknown RPC function";
|
|
||||||
}
|
}
|
||||||
llvm_unreachable("Unhandled error code");
|
llvm_unreachable("Unhandled error code");
|
||||||
}
|
}
|
||||||
|
53
lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp
Normal file
53
lib/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//===------- OrcRemoteTargetRPCAPI.cpp - ORC Remote API utilities ---------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace orc {
|
||||||
|
namespace remote {
|
||||||
|
|
||||||
|
#define FUNCNAME(X) \
|
||||||
|
case X ## Id: \
|
||||||
|
return #X
|
||||||
|
|
||||||
|
const char *OrcRemoteTargetRPCAPI::getJITFuncIdName(JITFuncId Id) {
|
||||||
|
switch (Id) {
|
||||||
|
case InvalidId:
|
||||||
|
return "*** Invalid JITFuncId ***";
|
||||||
|
FUNCNAME(CallIntVoid);
|
||||||
|
FUNCNAME(CallMain);
|
||||||
|
FUNCNAME(CallVoidVoid);
|
||||||
|
FUNCNAME(CreateRemoteAllocator);
|
||||||
|
FUNCNAME(CreateIndirectStubsOwner);
|
||||||
|
FUNCNAME(DeregisterEHFrames);
|
||||||
|
FUNCNAME(DestroyRemoteAllocator);
|
||||||
|
FUNCNAME(DestroyIndirectStubsOwner);
|
||||||
|
FUNCNAME(EmitIndirectStubs);
|
||||||
|
FUNCNAME(EmitResolverBlock);
|
||||||
|
FUNCNAME(EmitTrampolineBlock);
|
||||||
|
FUNCNAME(GetSymbolAddress);
|
||||||
|
FUNCNAME(GetRemoteInfo);
|
||||||
|
FUNCNAME(ReadMem);
|
||||||
|
FUNCNAME(RegisterEHFrames);
|
||||||
|
FUNCNAME(ReserveMem);
|
||||||
|
FUNCNAME(RequestCompile);
|
||||||
|
FUNCNAME(SetProtections);
|
||||||
|
FUNCNAME(TerminateSession);
|
||||||
|
FUNCNAME(WriteMem);
|
||||||
|
FUNCNAME(WritePtr);
|
||||||
|
};
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef FUNCNAME
|
||||||
|
|
||||||
|
} // end namespace remote
|
||||||
|
} // end namespace orc
|
||||||
|
} // end namespace llvm
|
@ -53,12 +53,23 @@ int main(int argc, char *argv[]) {
|
|||||||
RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size);
|
RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size);
|
||||||
};
|
};
|
||||||
|
|
||||||
FDRawChannel Channel(InFD, OutFD);
|
FDRPCChannel Channel(InFD, OutFD);
|
||||||
typedef remote::OrcRemoteTargetServer<FDRawChannel, HostOrcArch> JITServer;
|
typedef remote::OrcRemoteTargetServer<FDRPCChannel, HostOrcArch> JITServer;
|
||||||
JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames);
|
JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames);
|
||||||
|
|
||||||
while (!Server.receivedTerminate())
|
while (1) {
|
||||||
ExitOnErr(Server.handleOne());
|
uint32_t RawId;
|
||||||
|
ExitOnErr(Server.startReceivingFunction(Channel, RawId));
|
||||||
|
auto Id = static_cast<JITServer::JITFuncId>(RawId);
|
||||||
|
switch (Id) {
|
||||||
|
case JITServer::TerminateSessionId:
|
||||||
|
ExitOnErr(Server.handleTerminateSession());
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
ExitOnErr(Server.handleKnownFunction(Id));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
close(InFD);
|
close(InFD);
|
||||||
close(OutFD);
|
close(OutFD);
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H
|
#ifndef LLVM_TOOLS_LLI_REMOTEJITUTILS_H
|
||||||
#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H
|
#define LLVM_TOOLS_LLI_REMOTEJITUTILS_H
|
||||||
|
|
||||||
#include "llvm/ExecutionEngine/Orc/RawByteChannel.h"
|
#include "llvm/ExecutionEngine/Orc/RPCByteChannel.h"
|
||||||
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
@ -25,9 +25,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// RPC channel that reads from and writes from file descriptors.
|
/// RPC channel that reads from and writes from file descriptors.
|
||||||
class FDRawChannel final : public llvm::orc::rpc::RawByteChannel {
|
class FDRPCChannel final : public llvm::orc::remote::RPCByteChannel {
|
||||||
public:
|
public:
|
||||||
FDRawChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {}
|
FDRPCChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {}
|
||||||
|
|
||||||
llvm::Error readBytes(char *Dst, unsigned Size) override {
|
llvm::Error readBytes(char *Dst, unsigned Size) override {
|
||||||
assert(Dst && "Attempt to read into null.");
|
assert(Dst && "Attempt to read into null.");
|
||||||
@ -72,12 +72,11 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// launch the remote process (see lli.cpp) and return a channel to it.
|
// launch the remote process (see lli.cpp) and return a channel to it.
|
||||||
std::unique_ptr<FDRawChannel> launchRemote();
|
std::unique_ptr<FDRPCChannel> launchRemote();
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
// ForwardingMM - Adapter to connect MCJIT to Orc's Remote8
|
// ForwardingMM - Adapter to connect MCJIT to Orc's Remote memory manager.
|
||||||
// memory manager.
|
|
||||||
class ForwardingMemoryManager : public llvm::RTDyldMemoryManager {
|
class ForwardingMemoryManager : public llvm::RTDyldMemoryManager {
|
||||||
public:
|
public:
|
||||||
void setMemMgr(std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr) {
|
void setMemMgr(std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr) {
|
||||||
|
@ -654,20 +654,20 @@ int main(int argc, char **argv, char * const *envp) {
|
|||||||
// MCJIT itself. FIXME.
|
// MCJIT itself. FIXME.
|
||||||
|
|
||||||
// Lanch the remote process and get a channel to it.
|
// Lanch the remote process and get a channel to it.
|
||||||
std::unique_ptr<FDRawChannel> C = launchRemote();
|
std::unique_ptr<FDRPCChannel> C = launchRemote();
|
||||||
if (!C) {
|
if (!C) {
|
||||||
errs() << "Failed to launch remote JIT.\n";
|
errs() << "Failed to launch remote JIT.\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a remote target client running over the channel.
|
// Create a remote target client running over the channel.
|
||||||
typedef orc::remote::OrcRemoteTargetClient<orc::rpc::RawByteChannel>
|
typedef orc::remote::OrcRemoteTargetClient<orc::remote::RPCByteChannel>
|
||||||
MyRemote;
|
MyRemote;
|
||||||
auto R = ExitOnErr(MyRemote::Create(*C));
|
MyRemote R = ExitOnErr(MyRemote::Create(*C));
|
||||||
|
|
||||||
// Create a remote memory manager.
|
// Create a remote memory manager.
|
||||||
std::unique_ptr<MyRemote::RCMemoryManager> RemoteMM;
|
std::unique_ptr<MyRemote::RCMemoryManager> RemoteMM;
|
||||||
ExitOnErr(R->createRemoteMemoryManager(RemoteMM));
|
ExitOnErr(R.createRemoteMemoryManager(RemoteMM));
|
||||||
|
|
||||||
// Forward MCJIT's memory manager calls to the remote memory manager.
|
// Forward MCJIT's memory manager calls to the remote memory manager.
|
||||||
static_cast<ForwardingMemoryManager*>(RTDyldMM)->setMemMgr(
|
static_cast<ForwardingMemoryManager*>(RTDyldMM)->setMemMgr(
|
||||||
@ -678,7 +678,7 @@ int main(int argc, char **argv, char * const *envp) {
|
|||||||
orc::createLambdaResolver(
|
orc::createLambdaResolver(
|
||||||
[](const std::string &Name) { return nullptr; },
|
[](const std::string &Name) { return nullptr; },
|
||||||
[&](const std::string &Name) {
|
[&](const std::string &Name) {
|
||||||
if (auto Addr = ExitOnErr(R->getSymbolAddress(Name)))
|
if (auto Addr = ExitOnErr(R.getSymbolAddress(Name)))
|
||||||
return JITSymbol(Addr, JITSymbolFlags::Exported);
|
return JITSymbol(Addr, JITSymbolFlags::Exported);
|
||||||
return JITSymbol(nullptr);
|
return JITSymbol(nullptr);
|
||||||
}
|
}
|
||||||
@ -691,7 +691,7 @@ int main(int argc, char **argv, char * const *envp) {
|
|||||||
EE->finalizeObject();
|
EE->finalizeObject();
|
||||||
DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
|
DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
|
||||||
<< format("%llx", Entry) << "\n");
|
<< format("%llx", Entry) << "\n");
|
||||||
Result = ExitOnErr(R->callIntVoid(Entry));
|
Result = ExitOnErr(R.callIntVoid(Entry));
|
||||||
|
|
||||||
// Like static constructors, the remote target MCJIT support doesn't handle
|
// Like static constructors, the remote target MCJIT support doesn't handle
|
||||||
// this yet. It could. FIXME.
|
// this yet. It could. FIXME.
|
||||||
@ -702,13 +702,13 @@ int main(int argc, char **argv, char * const *envp) {
|
|||||||
EE.reset();
|
EE.reset();
|
||||||
|
|
||||||
// Signal the remote target that we're done JITing.
|
// Signal the remote target that we're done JITing.
|
||||||
ExitOnErr(R->terminateSession());
|
ExitOnErr(R.terminateSession());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<FDRawChannel> launchRemote() {
|
std::unique_ptr<FDRPCChannel> launchRemote() {
|
||||||
#ifndef LLVM_ON_UNIX
|
#ifndef LLVM_ON_UNIX
|
||||||
llvm_unreachable("launchRemote not supported on non-Unix platforms");
|
llvm_unreachable("launchRemote not supported on non-Unix platforms");
|
||||||
#else
|
#else
|
||||||
@ -758,6 +758,6 @@ std::unique_ptr<FDRawChannel> launchRemote() {
|
|||||||
close(PipeFD[1][1]);
|
close(PipeFD[1][1]);
|
||||||
|
|
||||||
// Return an RPC channel connected to our end of the pipes.
|
// Return an RPC channel connected to our end of the pipes.
|
||||||
return llvm::make_unique<FDRawChannel>(PipeFD[1][0], PipeFD[0][1]);
|
return llvm::make_unique<FDRPCChannel>(PipeFD[1][0], PipeFD[0][1]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/ExecutionEngine/Orc/RawByteChannel.h"
|
#include "llvm/ExecutionEngine/Orc/RPCByteChannel.h"
|
||||||
#include "llvm/ExecutionEngine/Orc/RPCUtils.h"
|
#include "llvm/ExecutionEngine/Orc/RPCUtils.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::orc;
|
using namespace llvm::orc;
|
||||||
using namespace llvm::orc::rpc;
|
using namespace llvm::orc::remote;
|
||||||
|
|
||||||
class Queue : public std::queue<char> {
|
class Queue : public std::queue<char> {
|
||||||
public:
|
public:
|
||||||
@ -25,7 +25,7 @@ private:
|
|||||||
std::mutex Lock;
|
std::mutex Lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QueueChannel : public RawByteChannel {
|
class QueueChannel : public RPCByteChannel {
|
||||||
public:
|
public:
|
||||||
QueueChannel(Queue &InQueue, Queue &OutQueue)
|
QueueChannel(Queue &InQueue, Queue &OutQueue)
|
||||||
: InQueue(InQueue), OutQueue(OutQueue) {}
|
: InQueue(InQueue), OutQueue(OutQueue) {}
|
||||||
@ -61,190 +61,126 @@ private:
|
|||||||
Queue &OutQueue;
|
Queue &OutQueue;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DummyRPCAPI {
|
class DummyRPC : public testing::Test, public RPC<QueueChannel> {
|
||||||
public:
|
public:
|
||||||
|
enum FuncId : uint32_t {
|
||||||
class VoidBool : public Function<VoidBool, void(bool)> {
|
VoidBoolId = RPCFunctionIdTraits<FuncId>::FirstValidId,
|
||||||
public:
|
IntIntId,
|
||||||
static const char* getName() { return "VoidBool"; }
|
AllTheTypesId
|
||||||
};
|
};
|
||||||
|
|
||||||
class IntInt : public Function<IntInt, int32_t(int32_t)> {
|
typedef Function<VoidBoolId, void(bool)> VoidBool;
|
||||||
public:
|
typedef Function<IntIntId, int32_t(int32_t)> IntInt;
|
||||||
static const char* getName() { return "IntInt"; }
|
typedef Function<AllTheTypesId,
|
||||||
};
|
void(int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||||
|
int64_t, uint64_t, bool, std::string, std::vector<int>)>
|
||||||
class AllTheTypes
|
AllTheTypes;
|
||||||
: public Function<AllTheTypes,
|
|
||||||
void(int8_t, uint8_t, int16_t, uint16_t, int32_t,
|
|
||||||
uint32_t, int64_t, uint64_t, bool, std::string,
|
|
||||||
std::vector<int>)> {
|
|
||||||
public:
|
|
||||||
static const char* getName() { return "AllTheTypes"; }
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DummyRPCEndpoint : public DummyRPCAPI,
|
TEST_F(DummyRPC, TestAsyncVoidBool) {
|
||||||
public SingleThreadedRPC<QueueChannel> {
|
|
||||||
public:
|
|
||||||
DummyRPCEndpoint(Queue &Q1, Queue &Q2)
|
|
||||||
: SingleThreadedRPC(C, true), C(Q1, Q2) {}
|
|
||||||
private:
|
|
||||||
QueueChannel C;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST(DummyRPC, TestAsyncVoidBool) {
|
|
||||||
Queue Q1, Q2;
|
Queue Q1, Q2;
|
||||||
DummyRPCEndpoint Client(Q1, Q2);
|
QueueChannel C1(Q1, Q2);
|
||||||
DummyRPCEndpoint Server(Q2, Q1);
|
QueueChannel C2(Q2, Q1);
|
||||||
|
|
||||||
std::thread ServerThread([&]() {
|
// Make an async call.
|
||||||
Server.addHandler<DummyRPCAPI::VoidBool>(
|
auto ResOrErr = callNBWithSeq<VoidBool>(C1, true);
|
||||||
[](bool B) {
|
EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
|
||||||
EXPECT_EQ(B, true)
|
|
||||||
<< "Server void(bool) received unexpected result";
|
|
||||||
});
|
|
||||||
|
|
||||||
{
|
|
||||||
// Poke the server to handle the negotiate call.
|
|
||||||
auto Err = Server.handleOne();
|
|
||||||
EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Poke the server to handle the VoidBool call.
|
|
||||||
auto Err = Server.handleOne();
|
|
||||||
EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// Make an async call.
|
// Expect a call to Proc1.
|
||||||
auto Err = Client.callAsync<DummyRPCAPI::VoidBool>(
|
auto EC = expect<VoidBool>(C2, [&](bool &B) {
|
||||||
[](Error Err) {
|
EXPECT_EQ(B, true) << "Bool serialization broken";
|
||||||
EXPECT_FALSE(!!Err) << "Async void(bool) response handler failed";
|
return Error::success();
|
||||||
return Error::success();
|
|
||||||
}, true);
|
|
||||||
EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)";
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Poke the client to process the result of the void(bool) call.
|
|
||||||
auto Err = Client.handleOne();
|
|
||||||
EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerThread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(DummyRPC, TestAsyncIntInt) {
|
|
||||||
Queue Q1, Q2;
|
|
||||||
DummyRPCEndpoint Client(Q1, Q2);
|
|
||||||
DummyRPCEndpoint Server(Q2, Q1);
|
|
||||||
|
|
||||||
std::thread ServerThread([&]() {
|
|
||||||
Server.addHandler<DummyRPCAPI::IntInt>(
|
|
||||||
[](int X) -> int {
|
|
||||||
EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
|
|
||||||
return 2 * X;
|
|
||||||
});
|
|
||||||
|
|
||||||
{
|
|
||||||
// Poke the server to handle the negotiate call.
|
|
||||||
auto Err = Server.handleOne();
|
|
||||||
EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Poke the server to handle the int(int) call.
|
|
||||||
auto Err = Server.handleOne();
|
|
||||||
EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)";
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
EXPECT_FALSE(EC) << "Simple expect over queue failed";
|
||||||
{
|
|
||||||
auto Err = Client.callAsync<DummyRPCAPI::IntInt>(
|
|
||||||
[](Expected<int> Result) {
|
|
||||||
EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
|
|
||||||
EXPECT_EQ(*Result, 42)
|
|
||||||
<< "Async int(int) response handler received incorrect result";
|
|
||||||
return Error::success();
|
|
||||||
}, 21);
|
|
||||||
EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// Poke the client to process the result.
|
// Wait for the result.
|
||||||
auto Err = Client.handleOne();
|
auto EC = waitForResult(C1, ResOrErr->second, handleNone);
|
||||||
EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
|
EXPECT_FALSE(EC) << "Could not read result.";
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerThread.join();
|
// Verify that the function returned ok.
|
||||||
|
auto Err = ResOrErr->first.get();
|
||||||
|
EXPECT_FALSE(!!Err) << "Remote void function failed to execute.";
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(DummyRPC, TestSerialization) {
|
TEST_F(DummyRPC, TestAsyncIntInt) {
|
||||||
Queue Q1, Q2;
|
Queue Q1, Q2;
|
||||||
DummyRPCEndpoint Client(Q1, Q2);
|
QueueChannel C1(Q1, Q2);
|
||||||
DummyRPCEndpoint Server(Q2, Q1);
|
QueueChannel C2(Q2, Q1);
|
||||||
|
|
||||||
std::thread ServerThread([&]() {
|
// Make an async call.
|
||||||
Server.addHandler<DummyRPCAPI::AllTheTypes>(
|
auto ResOrErr = callNBWithSeq<IntInt>(C1, 21);
|
||||||
[&](int8_t S8, uint8_t U8, int16_t S16, uint16_t U16,
|
EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
|
||||||
int32_t S32, uint32_t U32, int64_t S64, uint64_t U64,
|
|
||||||
bool B, std::string S, std::vector<int> V) {
|
|
||||||
|
|
||||||
EXPECT_EQ(S8, -101) << "int8_t serialization broken";
|
{
|
||||||
EXPECT_EQ(U8, 250) << "uint8_t serialization broken";
|
// Expect a call to Proc1.
|
||||||
EXPECT_EQ(S16, -10000) << "int16_t serialization broken";
|
auto EC = expect<IntInt>(C2, [&](int32_t I) -> Expected<int32_t> {
|
||||||
EXPECT_EQ(U16, 10000) << "uint16_t serialization broken";
|
EXPECT_EQ(I, 21) << "Bool serialization broken";
|
||||||
EXPECT_EQ(S32, -1000000000) << "int32_t serialization broken";
|
return 2 * I;
|
||||||
EXPECT_EQ(U32, 1000000000ULL) << "uint32_t serialization broken";
|
});
|
||||||
EXPECT_EQ(S64, -10000000000) << "int64_t serialization broken";
|
EXPECT_FALSE(EC) << "Simple expect over queue failed";
|
||||||
EXPECT_EQ(U64, 10000000000ULL) << "uint64_t serialization broken";
|
}
|
||||||
EXPECT_EQ(B, true) << "bool serialization broken";
|
|
||||||
EXPECT_EQ(S, "foo") << "std::string serialization broken";
|
{
|
||||||
EXPECT_EQ(V, std::vector<int>({42, 7}))
|
// Wait for the result.
|
||||||
|
auto EC = waitForResult(C1, ResOrErr->second, handleNone);
|
||||||
|
EXPECT_FALSE(EC) << "Could not read result.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the function returned ok.
|
||||||
|
auto Val = ResOrErr->first.get();
|
||||||
|
EXPECT_TRUE(!!Val) << "Remote int function failed to execute.";
|
||||||
|
EXPECT_EQ(*Val, 42) << "Remote int function return wrong value.";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DummyRPC, TestSerialization) {
|
||||||
|
Queue Q1, Q2;
|
||||||
|
QueueChannel C1(Q1, Q2);
|
||||||
|
QueueChannel C2(Q2, Q1);
|
||||||
|
|
||||||
|
// Make a call to Proc1.
|
||||||
|
std::vector<int> v({42, 7});
|
||||||
|
auto ResOrErr = callNBWithSeq<AllTheTypes>(
|
||||||
|
C1, -101, 250, -10000, 10000, -1000000000, 1000000000, -10000000000,
|
||||||
|
10000000000, true, "foo", v);
|
||||||
|
EXPECT_TRUE(!!ResOrErr) << "Big (serialization test) call over queue failed";
|
||||||
|
|
||||||
|
{
|
||||||
|
// Expect a call to Proc1.
|
||||||
|
auto EC = expect<AllTheTypes>(
|
||||||
|
C2, [&](int8_t &s8, uint8_t &u8, int16_t &s16, uint16_t &u16,
|
||||||
|
int32_t &s32, uint32_t &u32, int64_t &s64, uint64_t &u64,
|
||||||
|
bool &b, std::string &s, std::vector<int> &v) {
|
||||||
|
|
||||||
|
EXPECT_EQ(s8, -101) << "int8_t serialization broken";
|
||||||
|
EXPECT_EQ(u8, 250) << "uint8_t serialization broken";
|
||||||
|
EXPECT_EQ(s16, -10000) << "int16_t serialization broken";
|
||||||
|
EXPECT_EQ(u16, 10000) << "uint16_t serialization broken";
|
||||||
|
EXPECT_EQ(s32, -1000000000) << "int32_t serialization broken";
|
||||||
|
EXPECT_EQ(u32, 1000000000ULL) << "uint32_t serialization broken";
|
||||||
|
EXPECT_EQ(s64, -10000000000) << "int64_t serialization broken";
|
||||||
|
EXPECT_EQ(u64, 10000000000ULL) << "uint64_t serialization broken";
|
||||||
|
EXPECT_EQ(b, true) << "bool serialization broken";
|
||||||
|
EXPECT_EQ(s, "foo") << "std::string serialization broken";
|
||||||
|
EXPECT_EQ(v, std::vector<int>({42, 7}))
|
||||||
<< "std::vector serialization broken";
|
<< "std::vector serialization broken";
|
||||||
return Error::success();
|
|
||||||
});
|
|
||||||
|
|
||||||
{
|
|
||||||
// Poke the server to handle the negotiate call.
|
|
||||||
auto Err = Server.handleOne();
|
|
||||||
EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Poke the server to handle the AllTheTypes call.
|
|
||||||
auto Err = Server.handleOne();
|
|
||||||
EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
// Make an async call.
|
|
||||||
std::vector<int> v({42, 7});
|
|
||||||
auto Err = Client.callAsync<DummyRPCAPI::AllTheTypes>(
|
|
||||||
[](Error Err) {
|
|
||||||
EXPECT_FALSE(!!Err) << "Async AllTheTypes response handler failed";
|
|
||||||
return Error::success();
|
return Error::success();
|
||||||
},
|
});
|
||||||
static_cast<int8_t>(-101), static_cast<uint8_t>(250),
|
EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
|
||||||
static_cast<int16_t>(-10000), static_cast<uint16_t>(10000),
|
|
||||||
static_cast<int32_t>(-1000000000), static_cast<uint32_t>(1000000000),
|
|
||||||
static_cast<int64_t>(-10000000000), static_cast<uint64_t>(10000000000),
|
|
||||||
true, std::string("foo"), v);
|
|
||||||
EXPECT_FALSE(!!Err) << "Client.callAsync failed for AllTheTypes";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// Poke the client to process the result of the AllTheTypes call.
|
// Wait for the result.
|
||||||
auto Err = Client.handleOne();
|
auto EC = waitForResult(C1, ResOrErr->second, handleNone);
|
||||||
EXPECT_FALSE(!!Err) << "Client failed to handle response from AllTheTypes";
|
EXPECT_FALSE(EC) << "Could not read result.";
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerThread.join();
|
// Verify that the function returned ok.
|
||||||
|
auto Err = ResOrErr->first.get();
|
||||||
|
EXPECT_FALSE(!!Err) << "Remote void function failed to execute.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the synchronous call API.
|
// Test the synchronous call API.
|
||||||
|
Loading…
Reference in New Issue
Block a user