[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:
Lang Hames 2016-11-11 19:46:46 +00:00
parent d8314f03b1
commit b35b701639
17 changed files with 1398 additions and 1792 deletions

View File

@ -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) {}

View File

@ -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;
} }

View File

@ -29,7 +29,6 @@ enum class OrcErrorCode : int {
RemoteIndirectStubsOwnerIdAlreadyInUse, RemoteIndirectStubsOwnerIdAlreadyInUse,
UnexpectedRPCCall, UnexpectedRPCCall,
UnexpectedRPCResponse, UnexpectedRPCResponse,
UnknownRPCFunction
}; };
Error orcError(OrcErrorCode ErrCode); Error orcError(OrcErrorCode ErrCode);

View File

@ -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;

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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");
} }

View 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

View File

@ -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);

View File

@ -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) {

View File

@ -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
} }

View File

@ -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.