[Orc] Add overloads of RPC::handle and RPC::expect that take member functions as

handlers.

It is expected that RPC handlers will usually be member functions. Accepting them
directly in handle and expect allows for the remove of a lot of lambdas an
explicit error variables.

This patch also uses this new feature to substantially tidy up the
OrcRemoteTargetServer class.

llvm-svn: 257452
This commit is contained in:
Lang Hames 2016-01-12 06:48:52 +00:00
parent 8620d4c55b
commit 85215942ef
2 changed files with 139 additions and 167 deletions

View File

@ -43,41 +43,54 @@ public:
}
std::error_code handleKnownProcedure(JITProcId Id) {
typedef OrcRemoteTargetServer ThisT;
DEBUG(dbgs() << "Handling known proc: " << getJITProcIdName(Id) << "\n");
switch (Id) {
case CallIntVoidId:
return handleCallIntVoid();
return handle<CallIntVoid>(Channel, *this, &ThisT::handleCallIntVoid);
case CallMainId:
return handleCallMain();
return handle<CallMain>(Channel, *this, &ThisT::handleCallMain);
case CallVoidVoidId:
return handleCallVoidVoid();
return handle<CallVoidVoid>(Channel, *this, &ThisT::handleCallVoidVoid);
case CreateRemoteAllocatorId:
return handleCreateRemoteAllocator();
return handle<CreateRemoteAllocator>(Channel, *this,
&ThisT::handleCreateRemoteAllocator);
case CreateIndirectStubsOwnerId:
return handleCreateIndirectStubsOwner();
return handle<CreateIndirectStubsOwner>(
Channel, *this, &ThisT::handleCreateIndirectStubsOwner);
case DestroyRemoteAllocatorId:
return handleDestroyRemoteAllocator();
return handle<DestroyRemoteAllocator>(
Channel, *this, &ThisT::handleDestroyRemoteAllocator);
case DestroyIndirectStubsOwnerId:
return handle<DestroyIndirectStubsOwner>(
Channel, *this, &ThisT::handleDestroyIndirectStubsOwner);
case EmitIndirectStubsId:
return handleEmitIndirectStubs();
return handle<EmitIndirectStubs>(Channel, *this,
&ThisT::handleEmitIndirectStubs);
case EmitResolverBlockId:
return handleEmitResolverBlock();
return handle<EmitResolverBlock>(Channel, *this,
&ThisT::handleEmitResolverBlock);
case EmitTrampolineBlockId:
return handleEmitTrampolineBlock();
return handle<EmitTrampolineBlock>(Channel, *this,
&ThisT::handleEmitTrampolineBlock);
case GetSymbolAddressId:
return handleGetSymbolAddress();
return handle<GetSymbolAddress>(Channel, *this,
&ThisT::handleGetSymbolAddress);
case GetRemoteInfoId:
return handleGetRemoteInfo();
return handle<GetRemoteInfo>(Channel, *this, &ThisT::handleGetRemoteInfo);
case ReadMemId:
return handleReadMem();
return handle<ReadMem>(Channel, *this, &ThisT::handleReadMem);
case ReserveMemId:
return handleReserveMem();
return handle<ReserveMem>(Channel, *this, &ThisT::handleReserveMem);
case SetProtectionsId:
return handleSetProtections();
return handle<SetProtections>(Channel, *this,
&ThisT::handleSetProtections);
case WriteMemId:
return handleWriteMem();
return handle<WriteMem>(Channel, *this, &ThisT::handleWriteMem);
case WritePtrId:
return handleWritePtr();
return handle<WritePtr>(Channel, *this, &ThisT::handleWritePtr);
default:
return orcError(OrcErrorCode::UnexpectedRPCCall);
}
@ -160,16 +173,10 @@ private:
return CompiledFnAddr;
}
std::error_code handleCallIntVoid() {
std::error_code handleCallIntVoid(TargetAddress Addr) {
typedef int (*IntVoidFnTy)();
IntVoidFnTy Fn = nullptr;
if (std::error_code EC =
handle<CallIntVoid>(Channel, [&](TargetAddress Addr) {
Fn = reinterpret_cast<IntVoidFnTy>(static_cast<uintptr_t>(Addr));
return std::error_code();
}))
return EC;
IntVoidFnTy Fn =
reinterpret_cast<IntVoidFnTy>(static_cast<uintptr_t>(Addr));
DEBUG(dbgs() << " Calling "
<< reinterpret_cast<void *>(reinterpret_cast<intptr_t>(Fn))
@ -180,19 +187,11 @@ private:
return call<CallIntVoidResponse>(Channel, Result);
}
std::error_code handleCallMain() {
std::error_code handleCallMain(TargetAddress Addr,
std::vector<std::string> Args) {
typedef int (*MainFnTy)(int, const char *[]);
MainFnTy Fn = nullptr;
std::vector<std::string> Args;
if (std::error_code EC = handle<CallMain>(
Channel, [&](TargetAddress Addr, std::vector<std::string> &A) {
Fn = reinterpret_cast<MainFnTy>(static_cast<uintptr_t>(Addr));
Args = std::move(A);
return std::error_code();
}))
return EC;
MainFnTy Fn = reinterpret_cast<MainFnTy>(static_cast<uintptr_t>(Addr));
int ArgC = Args.size() + 1;
int Idx = 1;
std::unique_ptr<const char *[]> ArgV(new const char *[ArgC + 1]);
@ -207,16 +206,10 @@ private:
return call<CallMainResponse>(Channel, Result);
}
std::error_code handleCallVoidVoid() {
std::error_code handleCallVoidVoid(TargetAddress Addr) {
typedef void (*VoidVoidFnTy)();
VoidVoidFnTy Fn = nullptr;
if (std::error_code EC =
handle<CallIntVoid>(Channel, [&](TargetAddress Addr) {
Fn = reinterpret_cast<VoidVoidFnTy>(static_cast<uintptr_t>(Addr));
return std::error_code();
}))
return EC;
VoidVoidFnTy Fn =
reinterpret_cast<VoidVoidFnTy>(static_cast<uintptr_t>(Addr));
DEBUG(dbgs() << " Calling " << reinterpret_cast<void *>(Fn) << "\n");
Fn();
@ -225,66 +218,48 @@ private:
return call<CallVoidVoidResponse>(Channel);
}
std::error_code handleCreateRemoteAllocator() {
return handle<CreateRemoteAllocator>(
Channel, [&](ResourceIdMgr::ResourceId Id) {
auto I = Allocators.find(Id);
if (I != Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse);
DEBUG(dbgs() << " Created allocator " << Id << "\n");
Allocators[Id] = Allocator();
return std::error_code();
});
std::error_code handleCreateRemoteAllocator(ResourceIdMgr::ResourceId Id) {
auto I = Allocators.find(Id);
if (I != Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse);
DEBUG(dbgs() << " Created allocator " << Id << "\n");
Allocators[Id] = Allocator();
return std::error_code();
}
std::error_code handleCreateIndirectStubsOwner() {
return handle<CreateIndirectStubsOwner>(
Channel, [&](ResourceIdMgr::ResourceId Id) {
auto I = IndirectStubsOwners.find(Id);
if (I != IndirectStubsOwners.end())
return orcError(
OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse);
DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");
IndirectStubsOwners[Id] = ISBlockOwnerList();
return std::error_code();
});
std::error_code handleCreateIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
auto I = IndirectStubsOwners.find(Id);
if (I != IndirectStubsOwners.end())
return orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse);
DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n");
IndirectStubsOwners[Id] = ISBlockOwnerList();
return std::error_code();
}
std::error_code handleDestroyRemoteAllocator() {
return handle<DestroyRemoteAllocator>(
Channel, [&](ResourceIdMgr::ResourceId Id) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
Allocators.erase(I);
DEBUG(dbgs() << " Destroyed allocator " << Id << "\n");
return std::error_code();
});
std::error_code handleDestroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
Allocators.erase(I);
DEBUG(dbgs() << " Destroyed allocator " << Id << "\n");
return std::error_code();
}
std::error_code handleDestroyIndirectStubsOwner() {
return handle<DestroyIndirectStubsOwner>(
Channel, [&](ResourceIdMgr::ResourceId Id) {
auto I = IndirectStubsOwners.find(Id);
if (I == IndirectStubsOwners.end())
return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);
IndirectStubsOwners.erase(I);
return std::error_code();
});
std::error_code
handleDestroyIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
auto I = IndirectStubsOwners.find(Id);
if (I == IndirectStubsOwners.end())
return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);
IndirectStubsOwners.erase(I);
return std::error_code();
}
std::error_code handleEmitIndirectStubs() {
ResourceIdMgr::ResourceId ISOwnerId = ~0U;
uint32_t NumStubsRequired = 0;
if (auto EC = handle<EmitIndirectStubs>(
Channel, readArgs(ISOwnerId, NumStubsRequired)))
return EC;
DEBUG(dbgs() << " ISMgr " << ISOwnerId << " request " << NumStubsRequired
std::error_code handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
uint32_t NumStubsRequired) {
DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired
<< " stubs.\n");
auto StubOwnerItr = IndirectStubsOwners.find(ISOwnerId);
auto StubOwnerItr = IndirectStubsOwners.find(Id);
if (StubOwnerItr == IndirectStubsOwners.end())
return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);
@ -307,9 +282,6 @@ private:
}
std::error_code handleEmitResolverBlock() {
if (auto EC = handle<EmitResolverBlock>(Channel, doNothing))
return EC;
std::error_code EC;
ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
TargetT::ResolverCodeSize, nullptr,
@ -326,11 +298,7 @@ private:
}
std::error_code handleEmitTrampolineBlock() {
if (auto EC = handle<EmitTrampolineBlock>(Channel, doNothing))
return EC;
std::error_code EC;
auto TrampolineBlock =
sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
sys::Process::getPageSize(), nullptr,
@ -358,21 +326,14 @@ private:
NumTrampolines);
}
std::error_code handleGetSymbolAddress() {
std::string SymbolName;
if (auto EC = handle<GetSymbolAddress>(Channel, readArgs(SymbolName)))
return EC;
TargetAddress SymbolAddr = SymbolLookup(SymbolName);
DEBUG(dbgs() << " Symbol '" << SymbolName
<< "' = " << format("0x%016x", SymbolAddr) << "\n");
return call<GetSymbolAddressResponse>(Channel, SymbolAddr);
std::error_code handleGetSymbolAddress(const std::string &Name) {
TargetAddress Addr = SymbolLookup(Name);
DEBUG(dbgs() << " Symbol '" << Name << "' = " << format("0x%016x", Addr)
<< "\n");
return call<GetSymbolAddressResponse>(Channel, Addr);
}
std::error_code handleGetRemoteInfo() {
if (auto EC = handle<GetRemoteInfo>(Channel, doNothing))
return EC;
std::string ProcessTriple = sys::getProcessTriple();
uint32_t PointerSize = TargetT::PointerSize;
uint32_t PageSize = sys::Process::getPageSize();
@ -389,16 +350,8 @@ private:
IndirectStubSize);
}
std::error_code handleReadMem() {
char *Src = nullptr;
uint64_t Size = 0;
if (std::error_code EC =
handle<ReadMem>(Channel, [&](TargetAddress RSrc, uint64_t RSize) {
Src = reinterpret_cast<char *>(static_cast<uintptr_t>(RSrc));
Size = RSize;
return std::error_code();
}))
return EC;
std::error_code handleReadMem(TargetAddress RSrc, uint64_t Size) {
char *Src = reinterpret_cast<char *>(static_cast<uintptr_t>(RSrc));
DEBUG(dbgs() << " Reading " << Size << " bytes from "
<< static_cast<void *>(Src) << "\n");
@ -412,62 +365,49 @@ private:
return Channel.send();
}
std::error_code handleReserveMem() {
std::error_code handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
uint32_t Align) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
auto &Allocator = I->second;
void *LocalAllocAddr = nullptr;
if (std::error_code EC =
handle<ReserveMem>(Channel, [&](ResourceIdMgr::ResourceId Id,
uint64_t Size, uint32_t Align) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
auto &Allocator = I->second;
auto EC2 = Allocator.allocate(LocalAllocAddr, Size, Align);
DEBUG(dbgs() << " Allocator " << Id << " reserved "
<< LocalAllocAddr << " (" << Size
<< " bytes, alignment " << Align << ")\n");
return EC2;
}))
if (auto EC = Allocator.allocate(LocalAllocAddr, Size, Align))
return EC;
DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr
<< " (" << Size << " bytes, alignment " << Align << ")\n");
TargetAddress AllocAddr =
static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(LocalAllocAddr));
return call<ReserveMemResponse>(Channel, AllocAddr);
}
std::error_code handleSetProtections() {
return handle<ReserveMem>(Channel, [&](ResourceIdMgr::ResourceId Id,
TargetAddress Addr, uint32_t Flags) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
auto &Allocator = I->second;
void *LocalAddr = reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
DEBUG(dbgs() << " Allocator " << Id << " set permissions on "
<< LocalAddr << " to "
<< (Flags & sys::Memory::MF_READ ? 'R' : '-')
<< (Flags & sys::Memory::MF_WRITE ? 'W' : '-')
<< (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n");
return Allocator.setProtections(LocalAddr, Flags);
});
std::error_code handleSetProtections(ResourceIdMgr::ResourceId Id,
TargetAddress Addr, uint32_t Flags) {
auto I = Allocators.find(Id);
if (I == Allocators.end())
return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
auto &Allocator = I->second;
void *LocalAddr = reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
DEBUG(dbgs() << " Allocator " << Id << " set permissions on " << LocalAddr
<< " to " << (Flags & sys::Memory::MF_READ ? 'R' : '-')
<< (Flags & sys::Memory::MF_WRITE ? 'W' : '-')
<< (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n");
return Allocator.setProtections(LocalAddr, Flags);
}
std::error_code handleWriteMem() {
return handle<WriteMem>(Channel, [&](TargetAddress RDst, uint64_t Size) {
char *Dst = reinterpret_cast<char *>(static_cast<uintptr_t>(RDst));
return Channel.readBytes(Dst, Size);
});
std::error_code handleWriteMem(TargetAddress RDst, uint64_t Size) {
char *Dst = reinterpret_cast<char *>(static_cast<uintptr_t>(RDst));
return Channel.readBytes(Dst, Size);
}
std::error_code handleWritePtr() {
return handle<WritePtr>(
Channel, [&](TargetAddress Addr, TargetAddress PtrVal) {
uintptr_t *Ptr =
reinterpret_cast<uintptr_t *>(static_cast<uintptr_t>(Addr));
*Ptr = static_cast<uintptr_t>(PtrVal);
return std::error_code();
});
std::error_code handleWritePtr(TargetAddress Addr, TargetAddress PtrVal) {
uintptr_t *Ptr =
reinterpret_cast<uintptr_t *>(static_cast<uintptr_t>(Addr));
*Ptr = static_cast<uintptr_t>(PtrVal);
return std::error_code();
}
ChannelT &Channel;

View File

@ -69,6 +69,20 @@ protected:
}
};
template <typename ClassT, typename... ArgTs> class MemberFnWrapper {
public:
typedef std::error_code (ClassT::*MethodT)(ArgTs...);
MemberFnWrapper(ClassT &Instance, MethodT Method)
: Instance(Instance), Method(Method) {}
std::error_code operator()(ArgTs &... Args) {
return (Instance.*Method)(Args...);
}
private:
ClassT &Instance;
MethodT Method;
};
template <typename... ArgTs> class ReadArgs {
public:
std::error_code operator()() { return std::error_code(); }
@ -193,6 +207,15 @@ public:
return HandlerHelper<ChannelT, Proc>::handle(C, Handler);
}
/// Helper version of 'handle' for calling member functions.
template <typename Proc, typename ClassT, typename... ArgTs>
static std::error_code
handle(ChannelT &C, ClassT &Instance,
std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {
return handle<Proc>(
C, MemberFnWrapper<ClassT, ArgTs...>(Instance, HandlerMethod));
}
/// Deserialize a ProcedureIdT from C and verify it matches the id for Proc.
/// If the id does match, deserialize the arguments and call the handler
/// (similarly to handle).
@ -208,6 +231,15 @@ public:
return handle<Proc>(C, Handler);
}
/// Helper version of expect for calling member functions.
template <typename Proc, typename ClassT, typename... ArgTs>
static std::error_code
expect(ChannelT &C, ClassT &Instance,
std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {
return expect<Proc>(
C, MemberFnWrapper<ClassT, ArgTs...>(Instance, HandlerMethod));
}
/// Helper for handling setter procedures - this method returns a functor that
/// sets the variables referred to by Args... to values deserialized from the
/// channel.