forked from OSchip/llvm-project
[ORC] Thread Error/Expected through the RPC library.
This replaces use of std::error_code and ErrorOr in the ORC RPC support library with Error and Expected. This required updating the OrcRemoteTarget API, Client, and server code, as well as updating the Orc C API. This patch also fixes several instances where Errors were dropped. llvm-svn: 267457
This commit is contained in:
parent
074ea2851c
commit
ef5a0ee2c3
|
@ -37,6 +37,11 @@ typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name,
|
|||
typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
|
||||
void *CallbackCtx);
|
||||
|
||||
typedef enum {
|
||||
LLVMOrcErrSuccess = 0,
|
||||
LLVMOrcErrGeneric
|
||||
} LLVMOrcErrorCode;
|
||||
|
||||
/**
|
||||
* Create an ORC JIT stack.
|
||||
*
|
||||
|
@ -48,6 +53,14 @@ typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
|
|||
*/
|
||||
LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM);
|
||||
|
||||
/**
|
||||
* Get the error message for the most recent error (if any).
|
||||
*
|
||||
* This message is owned by the ORC JIT Stack and will be freed when the stack
|
||||
* is disposed of by LLVMOrcDisposeInstance.
|
||||
*/
|
||||
const char *LLVMOrcGetErrorMsg(LLVMOrcJITStackRef JITStack);
|
||||
|
||||
/**
|
||||
* Mangle the given symbol.
|
||||
* Memory will be allocated for MangledSymbol to hold the result. The client
|
||||
|
@ -58,7 +71,6 @@ void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledSymbol,
|
|||
/**
|
||||
* Dispose of a mangled symbol.
|
||||
*/
|
||||
|
||||
void LLVMOrcDisposeMangledSymbol(char *MangledSymbol);
|
||||
|
||||
/**
|
||||
|
@ -72,16 +84,16 @@ LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack,
|
|||
/**
|
||||
* Create a named indirect call stub.
|
||||
*/
|
||||
void LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
|
||||
const char *StubName,
|
||||
LLVMOrcTargetAddress InitAddr);
|
||||
LLVMOrcErrorCode LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
|
||||
const char *StubName,
|
||||
LLVMOrcTargetAddress InitAddr);
|
||||
|
||||
/**
|
||||
* Set the pointer for the given indirect stub.
|
||||
*/
|
||||
void LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
|
||||
const char *StubName,
|
||||
LLVMOrcTargetAddress NewAddr);
|
||||
LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
|
||||
const char *StubName,
|
||||
LLVMOrcTargetAddress NewAddr);
|
||||
|
||||
/**
|
||||
* Add module to be eagerly compiled.
|
||||
|
|
|
@ -219,12 +219,12 @@ public:
|
|||
virtual ~IndirectStubsManager() {}
|
||||
|
||||
/// @brief Create a single stub with the given name, target address and flags.
|
||||
virtual std::error_code createStub(StringRef StubName, TargetAddress StubAddr,
|
||||
JITSymbolFlags StubFlags) = 0;
|
||||
virtual Error createStub(StringRef StubName, TargetAddress StubAddr,
|
||||
JITSymbolFlags StubFlags) = 0;
|
||||
|
||||
/// @brief Create StubInits.size() stubs with the given names, target
|
||||
/// addresses, and flags.
|
||||
virtual std::error_code createStubs(const StubInitsMap &StubInits) = 0;
|
||||
virtual Error createStubs(const StubInitsMap &StubInits) = 0;
|
||||
|
||||
/// @brief Find the stub with the given name. If ExportedStubsOnly is true,
|
||||
/// this will only return a result if the stub's flags indicate that it
|
||||
|
@ -235,7 +235,7 @@ public:
|
|||
virtual JITSymbol findPointer(StringRef Name) = 0;
|
||||
|
||||
/// @brief Change the value of the implementation pointer for the stub.
|
||||
virtual std::error_code updatePointer(StringRef Name, TargetAddress NewAddr) = 0;
|
||||
virtual Error updatePointer(StringRef Name, TargetAddress NewAddr) = 0;
|
||||
private:
|
||||
virtual void anchor();
|
||||
};
|
||||
|
@ -246,25 +246,25 @@ template <typename TargetT>
|
|||
class LocalIndirectStubsManager : public IndirectStubsManager {
|
||||
public:
|
||||
|
||||
std::error_code createStub(StringRef StubName, TargetAddress StubAddr,
|
||||
Error createStub(StringRef StubName, TargetAddress StubAddr,
|
||||
JITSymbolFlags StubFlags) override {
|
||||
if (auto EC = reserveStubs(1))
|
||||
return EC;
|
||||
if (auto Err = reserveStubs(1))
|
||||
return Err;
|
||||
|
||||
createStubInternal(StubName, StubAddr, StubFlags);
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code createStubs(const StubInitsMap &StubInits) override {
|
||||
if (auto EC = reserveStubs(StubInits.size()))
|
||||
return EC;
|
||||
Error createStubs(const StubInitsMap &StubInits) override {
|
||||
if (auto Err = reserveStubs(StubInits.size()))
|
||||
return Err;
|
||||
|
||||
for (auto &Entry : StubInits)
|
||||
createStubInternal(Entry.first(), Entry.second.first,
|
||||
Entry.second.second);
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
|
||||
|
@ -294,31 +294,31 @@ public:
|
|||
return JITSymbol(PtrTargetAddr, I->second.second);
|
||||
}
|
||||
|
||||
std::error_code updatePointer(StringRef Name, TargetAddress NewAddr) override {
|
||||
Error updatePointer(StringRef Name, TargetAddress NewAddr) override {
|
||||
auto I = StubIndexes.find(Name);
|
||||
assert(I != StubIndexes.end() && "No stub pointer for symbol");
|
||||
auto Key = I->second.first;
|
||||
*IndirectStubsInfos[Key.first].getPtr(Key.second) =
|
||||
reinterpret_cast<void*>(static_cast<uintptr_t>(NewAddr));
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::error_code reserveStubs(unsigned NumStubs) {
|
||||
Error reserveStubs(unsigned NumStubs) {
|
||||
if (NumStubs <= FreeStubs.size())
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
|
||||
unsigned NewStubsRequired = NumStubs - FreeStubs.size();
|
||||
unsigned NewBlockId = IndirectStubsInfos.size();
|
||||
typename TargetT::IndirectStubsInfo ISI;
|
||||
if (auto EC = TargetT::emitIndirectStubsBlock(ISI, NewStubsRequired,
|
||||
if (auto Err = TargetT::emitIndirectStubsBlock(ISI, NewStubsRequired,
|
||||
nullptr))
|
||||
return EC;
|
||||
return Err;
|
||||
for (unsigned I = 0; I < ISI.getNumStubs(); ++I)
|
||||
FreeStubs.push_back(std::make_pair(NewBlockId, I));
|
||||
IndirectStubsInfos.push_back(std::move(ISI));
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void createStubInternal(StringRef StubName, TargetAddress InitAddr,
|
||||
|
|
|
@ -59,9 +59,8 @@ public:
|
|||
void **getPtr(unsigned Idx) const { llvm_unreachable("Not supported"); }
|
||||
};
|
||||
|
||||
static std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
||||
unsigned MinStubs,
|
||||
void *InitialPtrVal) {
|
||||
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
||||
unsigned MinStubs, void *InitialPtrVal) {
|
||||
llvm_unreachable("emitIndirectStubsBlock is not supported by the generic "
|
||||
"host support class");
|
||||
}
|
||||
|
@ -69,8 +68,7 @@ public:
|
|||
|
||||
/// @brief Provide information about stub blocks generated by the
|
||||
/// makeIndirectStubsBlock function.
|
||||
template <unsigned StubSizeVal>
|
||||
class GenericIndirectStubsInfo {
|
||||
template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
|
||||
public:
|
||||
const static unsigned StubSize = StubSizeVal;
|
||||
|
||||
|
@ -100,8 +98,7 @@ public:
|
|||
/// @brief Get a pointer to the implementation-pointer at the given index,
|
||||
/// which must be in the range 0 .. getNumStubs() - 1.
|
||||
void **getPtr(unsigned Idx) const {
|
||||
char *PtrsBase =
|
||||
static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
|
||||
char *PtrsBase = static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
|
||||
return reinterpret_cast<void **>(PtrsBase) + Idx;
|
||||
}
|
||||
|
||||
|
@ -140,9 +137,8 @@ public:
|
|||
/// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
|
||||
/// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
|
||||
/// will return a block of 1024 (2-pages worth).
|
||||
static std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
||||
unsigned MinStubs,
|
||||
void *InitialPtrVal);
|
||||
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
||||
unsigned MinStubs, void *InitialPtrVal);
|
||||
};
|
||||
|
||||
/// @brief I386 support.
|
||||
|
@ -175,12 +171,10 @@ public:
|
|||
/// E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k
|
||||
/// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
|
||||
/// will return a block of 1024 (2-pages worth).
|
||||
static std::error_code emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
||||
unsigned MinStubs,
|
||||
void *InitialPtrVal);
|
||||
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
||||
unsigned MinStubs, void *InitialPtrVal);
|
||||
};
|
||||
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#ifndef LLVM_EXECUTIONENGINE_ORC_ORCERROR_H
|
||||
#define LLVM_EXECUTIONENGINE_ORC_ORCERROR_H
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <system_error>
|
||||
|
||||
namespace llvm {
|
||||
|
@ -30,7 +31,7 @@ enum class OrcErrorCode : int {
|
|||
UnexpectedRPCResponse,
|
||||
};
|
||||
|
||||
std::error_code orcError(OrcErrorCode ErrCode);
|
||||
Error orcError(OrcErrorCode ErrCode);
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
|
|
|
@ -36,25 +36,22 @@ namespace remote {
|
|||
template <typename ChannelT>
|
||||
class OrcRemoteTargetClient : public OrcRemoteTargetRPCAPI {
|
||||
public:
|
||||
|
||||
// FIXME: Remove move/copy ops once MSVC supports synthesizing move ops.
|
||||
|
||||
OrcRemoteTargetClient(const OrcRemoteTargetClient&) = delete;
|
||||
OrcRemoteTargetClient& operator=(const OrcRemoteTargetClient&) = delete;
|
||||
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)),
|
||||
CompileCallback(std::move(Other.CompileCallback)) {}
|
||||
: 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)) {}
|
||||
|
||||
OrcRemoteTargetClient& operator=(OrcRemoteTargetClient&&) = delete;
|
||||
OrcRemoteTargetClient &operator=(OrcRemoteTargetClient &&) = delete;
|
||||
|
||||
/// Remote memory manager.
|
||||
class RCMemoryManager : public RuntimeDyld::MemoryManager {
|
||||
|
@ -125,12 +122,12 @@ public:
|
|||
DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
|
||||
|
||||
if (CodeSize != 0) {
|
||||
if (auto AddrOrErr = Client.reserveMem(Id, CodeSize, CodeAlign))
|
||||
Unmapped.back().RemoteCodeAddr = *AddrOrErr;
|
||||
else {
|
||||
// FIXME; Add error to poll.
|
||||
assert(!AddrOrErr.getError() && "Failed reserving remote memory.");
|
||||
}
|
||||
if (auto AddrOrErr = Client.reserveMem(Id, CodeSize, CodeAlign))
|
||||
Unmapped.back().RemoteCodeAddr = *AddrOrErr;
|
||||
else {
|
||||
// FIXME; Add error to poll.
|
||||
assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << " code: "
|
||||
<< format("0x%016x", Unmapped.back().RemoteCodeAddr)
|
||||
|
@ -140,12 +137,12 @@ public:
|
|||
|
||||
if (RODataSize != 0) {
|
||||
if (auto AddrOrErr = Client.reserveMem(Id, RODataSize, RODataAlign))
|
||||
Unmapped.back().RemoteRODataAddr = *AddrOrErr;
|
||||
else {
|
||||
// FIXME; Add error to poll.
|
||||
assert(!AddrOrErr.getError() && "Failed reserving remote memory.");
|
||||
}
|
||||
|
||||
Unmapped.back().RemoteRODataAddr = *AddrOrErr;
|
||||
else {
|
||||
// FIXME; Add error to poll.
|
||||
assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << " ro-data: "
|
||||
<< format("0x%016x", Unmapped.back().RemoteRODataAddr)
|
||||
<< " (" << RODataSize << " bytes, alignment "
|
||||
|
@ -154,10 +151,10 @@ public:
|
|||
|
||||
if (RWDataSize != 0) {
|
||||
if (auto AddrOrErr = Client.reserveMem(Id, RWDataSize, RWDataAlign))
|
||||
Unmapped.back().RemoteRWDataAddr = *AddrOrErr;
|
||||
else {
|
||||
// FIXME; Add error to poll.
|
||||
assert(!AddrOrErr.getError() && "Failed reserving remote memory.");
|
||||
Unmapped.back().RemoteRWDataAddr = *AddrOrErr;
|
||||
else {
|
||||
// FIXME; Add error to poll.
|
||||
assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << " rw-data: "
|
||||
|
@ -177,10 +174,10 @@ public:
|
|||
|
||||
void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
|
||||
size_t Size) override {
|
||||
auto EC = Client.deregisterEHFrames(LoadAddr, Size);
|
||||
auto Err = Client.deregisterEHFrames(LoadAddr, Size);
|
||||
// FIXME: Add error poll.
|
||||
assert(!EC && "Failed to register remote EH frames.");
|
||||
(void)EC;
|
||||
assert(!Err && "Failed to register remote EH frames.");
|
||||
(void)Err;
|
||||
}
|
||||
|
||||
void notifyObjectLoaded(RuntimeDyld &Dyld,
|
||||
|
@ -240,15 +237,35 @@ public:
|
|||
<< static_cast<void *>(Alloc.getLocalAddress()) << " -> "
|
||||
<< format("0x%016x", Alloc.getRemoteAddress()) << " ("
|
||||
<< Alloc.getSize() << " bytes)\n");
|
||||
Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
|
||||
Alloc.getSize());
|
||||
if (auto Err =
|
||||
Client.writeMem(Alloc.getRemoteAddress(),
|
||||
Alloc.getLocalAddress(), Alloc.getSize())) {
|
||||
// FIXME: Replace this once finalizeMemory can return an Error.
|
||||
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
|
||||
if (ErrMsg) {
|
||||
raw_string_ostream ErrOut(*ErrMsg);
|
||||
EIB.log(ErrOut);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ObjAllocs.RemoteCodeAddr) {
|
||||
DEBUG(dbgs() << " setting R-X permissions on code block: "
|
||||
<< format("0x%016x", ObjAllocs.RemoteCodeAddr) << "\n");
|
||||
Client.setProtections(Id, ObjAllocs.RemoteCodeAddr,
|
||||
sys::Memory::MF_READ | sys::Memory::MF_EXEC);
|
||||
if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteCodeAddr,
|
||||
sys::Memory::MF_READ |
|
||||
sys::Memory::MF_EXEC)) {
|
||||
// FIXME: Replace this once finalizeMemory can return an Error.
|
||||
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
|
||||
if (ErrMsg) {
|
||||
raw_string_ostream ErrOut(*ErrMsg);
|
||||
EIB.log(ErrOut);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &Alloc : ObjAllocs.RODataAllocs) {
|
||||
|
@ -256,16 +273,35 @@ public:
|
|||
<< static_cast<void *>(Alloc.getLocalAddress()) << " -> "
|
||||
<< format("0x%016x", Alloc.getRemoteAddress()) << " ("
|
||||
<< Alloc.getSize() << " bytes)\n");
|
||||
Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
|
||||
Alloc.getSize());
|
||||
if (auto Err =
|
||||
Client.writeMem(Alloc.getRemoteAddress(),
|
||||
Alloc.getLocalAddress(), Alloc.getSize())) {
|
||||
// FIXME: Replace this once finalizeMemory can return an Error.
|
||||
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
|
||||
if (ErrMsg) {
|
||||
raw_string_ostream ErrOut(*ErrMsg);
|
||||
EIB.log(ErrOut);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ObjAllocs.RemoteRODataAddr) {
|
||||
DEBUG(dbgs() << " setting R-- permissions on ro-data block: "
|
||||
<< format("0x%016x", ObjAllocs.RemoteRODataAddr)
|
||||
<< "\n");
|
||||
Client.setProtections(Id, ObjAllocs.RemoteRODataAddr,
|
||||
sys::Memory::MF_READ);
|
||||
if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteRODataAddr,
|
||||
sys::Memory::MF_READ)) {
|
||||
// FIXME: Replace this once finalizeMemory can return an Error.
|
||||
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
|
||||
if (ErrMsg) {
|
||||
raw_string_ostream ErrOut(*ErrMsg);
|
||||
EIB.log(ErrOut);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &Alloc : ObjAllocs.RWDataAllocs) {
|
||||
|
@ -273,25 +309,51 @@ public:
|
|||
<< static_cast<void *>(Alloc.getLocalAddress()) << " -> "
|
||||
<< format("0x%016x", Alloc.getRemoteAddress()) << " ("
|
||||
<< Alloc.getSize() << " bytes)\n");
|
||||
Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
|
||||
Alloc.getSize());
|
||||
if (auto Err =
|
||||
Client.writeMem(Alloc.getRemoteAddress(),
|
||||
Alloc.getLocalAddress(), Alloc.getSize())) {
|
||||
// FIXME: Replace this once finalizeMemory can return an Error.
|
||||
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
|
||||
if (ErrMsg) {
|
||||
raw_string_ostream ErrOut(*ErrMsg);
|
||||
EIB.log(ErrOut);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ObjAllocs.RemoteRWDataAddr) {
|
||||
DEBUG(dbgs() << " setting RW- permissions on rw-data block: "
|
||||
<< format("0x%016x", ObjAllocs.RemoteRWDataAddr)
|
||||
<< "\n");
|
||||
Client.setProtections(Id, ObjAllocs.RemoteRWDataAddr,
|
||||
sys::Memory::MF_READ | sys::Memory::MF_WRITE);
|
||||
if (auto Err = Client.setProtections(Id, ObjAllocs.RemoteRWDataAddr,
|
||||
sys::Memory::MF_READ |
|
||||
sys::Memory::MF_WRITE)) {
|
||||
// FIXME: Replace this once finalizeMemory can return an Error.
|
||||
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
|
||||
if (ErrMsg) {
|
||||
raw_string_ostream ErrOut(*ErrMsg);
|
||||
EIB.log(ErrOut);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Unfinalized.clear();
|
||||
|
||||
for (auto &EHFrame : UnfinalizedEHFrames) {
|
||||
auto EC = Client.registerEHFrames(EHFrame.first, EHFrame.second);
|
||||
// FIXME: Add error poll.
|
||||
assert(!EC && "Failed to register remote EH frames.");
|
||||
(void)EC;
|
||||
if (auto Err = Client.registerEHFrames(EHFrame.first, EHFrame.second)) {
|
||||
// FIXME: Replace this once finalizeMemory can return an Error.
|
||||
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
|
||||
if (ErrMsg) {
|
||||
raw_string_ostream ErrOut(*ErrMsg);
|
||||
EIB.log(ErrOut);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
UnfinalizedEHFrames.clear();
|
||||
|
||||
|
@ -382,27 +444,30 @@ public:
|
|||
: Remote(Remote), Id(Id) {}
|
||||
|
||||
~RCIndirectStubsManager() override {
|
||||
Remote.destroyIndirectStubsManager(Id);
|
||||
if (auto Err = Remote.destroyIndirectStubsManager(Id)) {
|
||||
// FIXME: Thread this error back to clients.
|
||||
consumeError(std::move(Err));
|
||||
}
|
||||
}
|
||||
|
||||
std::error_code createStub(StringRef StubName, TargetAddress StubAddr,
|
||||
JITSymbolFlags StubFlags) override {
|
||||
if (auto EC = reserveStubs(1))
|
||||
return EC;
|
||||
Error createStub(StringRef StubName, TargetAddress StubAddr,
|
||||
JITSymbolFlags StubFlags) override {
|
||||
if (auto Err = reserveStubs(1))
|
||||
return Err;
|
||||
|
||||
return createStubInternal(StubName, StubAddr, StubFlags);
|
||||
}
|
||||
|
||||
std::error_code createStubs(const StubInitsMap &StubInits) override {
|
||||
if (auto EC = reserveStubs(StubInits.size()))
|
||||
return EC;
|
||||
Error createStubs(const StubInitsMap &StubInits) override {
|
||||
if (auto Err = reserveStubs(StubInits.size()))
|
||||
return Err;
|
||||
|
||||
for (auto &Entry : StubInits)
|
||||
if (auto EC = createStubInternal(Entry.first(), Entry.second.first,
|
||||
Entry.second.second))
|
||||
return EC;
|
||||
if (auto Err = createStubInternal(Entry.first(), Entry.second.first,
|
||||
Entry.second.second))
|
||||
return Err;
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
|
||||
|
@ -426,8 +491,7 @@ public:
|
|||
return JITSymbol(getPtrAddr(Key), Flags);
|
||||
}
|
||||
|
||||
std::error_code updatePointer(StringRef Name,
|
||||
TargetAddress NewAddr) override {
|
||||
Error updatePointer(StringRef Name, TargetAddress NewAddr) override {
|
||||
auto I = StubIndexes.find(Name);
|
||||
assert(I != StubIndexes.end() && "No stub pointer for symbol");
|
||||
auto Key = I->second.first;
|
||||
|
@ -448,9 +512,9 @@ public:
|
|||
std::vector<StubKey> FreeStubs;
|
||||
StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
|
||||
|
||||
std::error_code reserveStubs(unsigned NumStubs) {
|
||||
Error reserveStubs(unsigned NumStubs) {
|
||||
if (NumStubs <= FreeStubs.size())
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
|
||||
unsigned NewStubsRequired = NumStubs - FreeStubs.size();
|
||||
TargetAddress StubBase;
|
||||
|
@ -458,9 +522,9 @@ public:
|
|||
unsigned NumStubsEmitted;
|
||||
|
||||
if (auto StubInfoOrErr = Remote.emitIndirectStubs(Id, NewStubsRequired))
|
||||
std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
|
||||
std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
|
||||
else
|
||||
return StubInfoOrErr.getError();
|
||||
return StubInfoOrErr.takeError();
|
||||
|
||||
unsigned NewBlockId = RemoteIndirectStubsInfos.size();
|
||||
RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
|
||||
|
@ -468,12 +532,11 @@ public:
|
|||
for (unsigned I = 0; I < NumStubsEmitted; ++I)
|
||||
FreeStubs.push_back(std::make_pair(NewBlockId, I));
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code createStubInternal(StringRef StubName,
|
||||
TargetAddress InitAddr,
|
||||
JITSymbolFlags StubFlags) {
|
||||
Error createStubInternal(StringRef StubName, TargetAddress InitAddr,
|
||||
JITSymbolFlags StubFlags) {
|
||||
auto Key = FreeStubs.back();
|
||||
FreeStubs.pop_back();
|
||||
StubIndexes[StubName] = std::make_pair(Key, StubFlags);
|
||||
|
@ -500,23 +563,17 @@ public:
|
|||
public:
|
||||
RCCompileCallbackManager(TargetAddress ErrorHandlerAddress,
|
||||
OrcRemoteTargetClient &Remote)
|
||||
: JITCompileCallbackManager(ErrorHandlerAddress), Remote(Remote) {
|
||||
assert(!Remote.CompileCallback && "Compile callback already set");
|
||||
Remote.CompileCallback = [this](TargetAddress TrampolineAddr) {
|
||||
return executeCompileCallback(TrampolineAddr);
|
||||
};
|
||||
Remote.emitResolverBlock();
|
||||
}
|
||||
: JITCompileCallbackManager(ErrorHandlerAddress), Remote(Remote) {}
|
||||
|
||||
private:
|
||||
void grow() override {
|
||||
TargetAddress BlockAddr = 0;
|
||||
uint32_t NumTrampolines = 0;
|
||||
if (auto TrampolineInfoOrErr = Remote.emitTrampolineBlock())
|
||||
std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
|
||||
std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
|
||||
else {
|
||||
// FIXME: Return error.
|
||||
llvm_unreachable("Failed to create trampolines");
|
||||
// FIXME: Return error.
|
||||
llvm_unreachable("Failed to create trampolines");
|
||||
}
|
||||
|
||||
uint32_t TrampolineSize = Remote.getTrampolineSize();
|
||||
|
@ -530,85 +587,96 @@ public:
|
|||
/// Create an OrcRemoteTargetClient.
|
||||
/// Channel is the ChannelT instance to communicate on. It is assumed that
|
||||
/// the channel is ready to be read from and written to.
|
||||
static ErrorOr<OrcRemoteTargetClient> Create(ChannelT &Channel) {
|
||||
std::error_code EC;
|
||||
OrcRemoteTargetClient H(Channel, EC);
|
||||
if (EC)
|
||||
return EC;
|
||||
return ErrorOr<OrcRemoteTargetClient>(std::move(H));
|
||||
static Expected<OrcRemoteTargetClient> Create(ChannelT &Channel) {
|
||||
Error Err;
|
||||
OrcRemoteTargetClient H(Channel, Err);
|
||||
if (Err)
|
||||
return std::move(Err);
|
||||
return Expected<OrcRemoteTargetClient>(std::move(H));
|
||||
}
|
||||
|
||||
/// Call the int(void) function at the given address in the target and return
|
||||
/// its result.
|
||||
ErrorOr<int> callIntVoid(TargetAddress Addr) {
|
||||
Expected<int> callIntVoid(TargetAddress Addr) {
|
||||
DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
|
||||
|
||||
auto Listen =
|
||||
[&](RPCChannel &C, uint32_t Id) {
|
||||
return listenForCompileRequests(C, Id);
|
||||
};
|
||||
auto Listen = [&](RPCChannel &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
|
||||
/// return its result.
|
||||
ErrorOr<int> callMain(TargetAddress Addr,
|
||||
const std::vector<std::string> &Args) {
|
||||
Expected<int> callMain(TargetAddress Addr,
|
||||
const std::vector<std::string> &Args) {
|
||||
DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
|
||||
<< "\n");
|
||||
|
||||
auto Listen =
|
||||
[&](RPCChannel &C, uint32_t Id) {
|
||||
return listenForCompileRequests(C, Id);
|
||||
};
|
||||
auto Listen = [&](RPCChannel &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
|
||||
/// it to finish.
|
||||
std::error_code callVoidVoid(TargetAddress Addr) {
|
||||
Error callVoidVoid(TargetAddress Addr) {
|
||||
DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
|
||||
<< "\n");
|
||||
|
||||
auto Listen =
|
||||
[&](RPCChannel &C, JITFuncId Id) {
|
||||
return listenForCompileRequests(C, Id);
|
||||
};
|
||||
auto Listen = [&](RPCChannel &C, JITFuncId Id) {
|
||||
return listenForCompileRequests(C, Id);
|
||||
};
|
||||
return callSTHandling<CallVoidVoid>(Channel, Listen, Addr);
|
||||
}
|
||||
|
||||
/// Create an RCMemoryManager which will allocate its memory on the remote
|
||||
/// target.
|
||||
std::error_code
|
||||
createRemoteMemoryManager(std::unique_ptr<RCMemoryManager> &MM) {
|
||||
Error createRemoteMemoryManager(std::unique_ptr<RCMemoryManager> &MM) {
|
||||
assert(!MM && "MemoryManager should be null before creation.");
|
||||
|
||||
auto Id = AllocatorIds.getNext();
|
||||
if (auto EC = callST<CreateRemoteAllocator>(Channel, Id))
|
||||
return EC;
|
||||
if (auto Err = callST<CreateRemoteAllocator>(Channel, Id))
|
||||
return Err;
|
||||
MM = llvm::make_unique<RCMemoryManager>(*this, Id);
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// Create an RCIndirectStubsManager that will allocate stubs on the remote
|
||||
/// target.
|
||||
std::error_code
|
||||
createIndirectStubsManager(std::unique_ptr<RCIndirectStubsManager> &I) {
|
||||
Error createIndirectStubsManager(std::unique_ptr<RCIndirectStubsManager> &I) {
|
||||
assert(!I && "Indirect stubs manager should be null before creation.");
|
||||
auto Id = IndirectStubOwnerIds.getNext();
|
||||
if (auto EC = callST<CreateIndirectStubsOwner>(Channel, Id))
|
||||
return EC;
|
||||
if (auto Err = callST<CreateIndirectStubsOwner>(Channel, Id))
|
||||
return Err;
|
||||
I = llvm::make_unique<RCIndirectStubsManager>(*this, Id);
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Expected<RCCompileCallbackManager &>
|
||||
enableCompileCallbacks(TargetAddress ErrorHandlerAddress) {
|
||||
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
||||
if (ExistingError)
|
||||
return std::move(ExistingError);
|
||||
|
||||
// Emit the resolver block on the JIT server.
|
||||
if (auto Err = callST<EmitResolverBlock>(Channel))
|
||||
return std::move(Err);
|
||||
|
||||
// Create the callback manager.
|
||||
CallbackManager.emplace(ErrorHandlerAddress, *this);
|
||||
RCCompileCallbackManager &Mgr = *CallbackManager;
|
||||
return Mgr;
|
||||
}
|
||||
|
||||
/// Search for symbols in the remote process. Note: This should be used by
|
||||
/// symbol resolvers *after* they've searched the local symbol table in the
|
||||
/// JIT stack.
|
||||
ErrorOr<TargetAddress> getSymbolAddress(StringRef Name) {
|
||||
Expected<TargetAddress> getSymbolAddress(StringRef Name) {
|
||||
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
||||
if (ExistingError)
|
||||
return ExistingError;
|
||||
return std::move(ExistingError);
|
||||
|
||||
return callST<GetSymbolAddress>(Channel, Name);
|
||||
}
|
||||
|
@ -616,28 +684,25 @@ public:
|
|||
/// Get the triple for the remote target.
|
||||
const std::string &getTargetTriple() const { return RemoteTargetTriple; }
|
||||
|
||||
std::error_code terminateSession() {
|
||||
return callST<TerminateSession>(Channel);
|
||||
}
|
||||
Error terminateSession() { return callST<TerminateSession>(Channel); }
|
||||
|
||||
private:
|
||||
OrcRemoteTargetClient(ChannelT &Channel, std::error_code &EC)
|
||||
: Channel(Channel) {
|
||||
OrcRemoteTargetClient(ChannelT &Channel, Error &Err) : Channel(Channel) {
|
||||
ErrorAsOutParameter EAO(Err);
|
||||
if (auto RIOrErr = callST<GetRemoteInfo>(Channel)) {
|
||||
std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
|
||||
RemoteTrampolineSize, RemoteIndirectStubSize) =
|
||||
*RIOrErr;
|
||||
EC = std::error_code();
|
||||
RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
|
||||
Err = Error::success();
|
||||
} else
|
||||
EC = RIOrErr.getError();
|
||||
Err = RIOrErr.takeError();
|
||||
}
|
||||
|
||||
std::error_code deregisterEHFrames(TargetAddress Addr, uint32_t Size) {
|
||||
Error deregisterEHFrames(TargetAddress Addr, uint32_t Size) {
|
||||
return callST<RegisterEHFrames>(Channel, Addr, Size);
|
||||
}
|
||||
|
||||
void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
|
||||
if (auto EC = callST<DestroyRemoteAllocator>(Channel, Id)) {
|
||||
if (auto Err = callST<DestroyRemoteAllocator>(Channel, Id)) {
|
||||
// FIXME: This will be triggered by a removeModuleSet call: Propagate
|
||||
// error return up through that.
|
||||
llvm_unreachable("Failed to destroy remote allocator.");
|
||||
|
@ -645,30 +710,20 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
std::error_code destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
|
||||
Error destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
|
||||
IndirectStubOwnerIds.release(Id);
|
||||
return callST<DestroyIndirectStubsOwner>(Channel, Id);
|
||||
}
|
||||
|
||||
ErrorOr<std::tuple<TargetAddress, TargetAddress, uint32_t>>
|
||||
emitIndirectStubs(ResourceIdMgr::ResourceId Id,
|
||||
uint32_t NumStubsRequired) {
|
||||
Expected<std::tuple<TargetAddress, TargetAddress, uint32_t>>
|
||||
emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
|
||||
return callST<EmitIndirectStubs>(Channel, Id, NumStubsRequired);
|
||||
}
|
||||
|
||||
std::error_code emitResolverBlock() {
|
||||
Expected<std::tuple<TargetAddress, uint32_t>> emitTrampolineBlock() {
|
||||
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
||||
if (ExistingError)
|
||||
return ExistingError;
|
||||
|
||||
return callST<EmitResolverBlock>(Channel);
|
||||
}
|
||||
|
||||
ErrorOr<std::tuple<TargetAddress, uint32_t>>
|
||||
emitTrampolineBlock() {
|
||||
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
||||
if (ExistingError)
|
||||
return ExistingError;
|
||||
return std::move(ExistingError);
|
||||
|
||||
return callST<EmitTrampolineBlock>(Channel);
|
||||
}
|
||||
|
@ -679,75 +734,81 @@ private:
|
|||
|
||||
uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
|
||||
|
||||
std::error_code listenForCompileRequests(RPCChannel &C, uint32_t &Id) {
|
||||
Error listenForCompileRequests(RPCChannel &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 ExistingError;
|
||||
return std::move(ExistingError);
|
||||
|
||||
if (Id == RequestCompileId) {
|
||||
if (auto EC = handle<RequestCompile>(C, CompileCallback))
|
||||
return EC;
|
||||
return std::error_code();
|
||||
if (auto Err = handle<RequestCompile>(
|
||||
C, [&](TargetAddress Addr) -> Expected<TargetAddress> {
|
||||
return CallbackManager->executeCompileCallback(Addr);
|
||||
}))
|
||||
return Err;
|
||||
return Error::success();
|
||||
}
|
||||
// else
|
||||
return orcError(OrcErrorCode::UnexpectedRPCCall);
|
||||
}
|
||||
|
||||
ErrorOr<std::vector<char>> readMem(char *Dst, TargetAddress Src, uint64_t Size) {
|
||||
Expected<std::vector<char>> readMem(char *Dst, TargetAddress Src,
|
||||
uint64_t Size) {
|
||||
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
||||
if (ExistingError)
|
||||
return ExistingError;
|
||||
return std::move(ExistingError);
|
||||
|
||||
return callST<ReadMem>(Channel, Src, Size);
|
||||
}
|
||||
|
||||
std::error_code registerEHFrames(TargetAddress &RAddr, uint32_t Size) {
|
||||
Error registerEHFrames(TargetAddress &RAddr, uint32_t Size) {
|
||||
return callST<RegisterEHFrames>(Channel, RAddr, Size);
|
||||
}
|
||||
|
||||
ErrorOr<TargetAddress> reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
|
||||
uint32_t Align) {
|
||||
Expected<TargetAddress> reserveMem(ResourceIdMgr::ResourceId Id,
|
||||
uint64_t Size, uint32_t Align) {
|
||||
|
||||
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
||||
if (ExistingError)
|
||||
return ExistingError;
|
||||
return std::move(ExistingError);
|
||||
|
||||
return callST<ReserveMem>(Channel, Id, Size, Align);
|
||||
}
|
||||
|
||||
std::error_code setProtections(ResourceIdMgr::ResourceId Id,
|
||||
TargetAddress RemoteSegAddr,
|
||||
unsigned ProtFlags) {
|
||||
Error setProtections(ResourceIdMgr::ResourceId Id,
|
||||
TargetAddress RemoteSegAddr, unsigned ProtFlags) {
|
||||
return callST<SetProtections>(Channel, Id, RemoteSegAddr, ProtFlags);
|
||||
}
|
||||
|
||||
std::error_code writeMem(TargetAddress Addr, const char *Src, uint64_t Size) {
|
||||
Error writeMem(TargetAddress Addr, const char *Src, uint64_t Size) {
|
||||
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
||||
if (ExistingError)
|
||||
return ExistingError;
|
||||
return std::move(ExistingError);
|
||||
|
||||
return callST<WriteMem>(Channel, DirectBufferWriter(Src, Addr, Size));
|
||||
}
|
||||
|
||||
std::error_code writePointer(TargetAddress Addr, TargetAddress PtrVal) {
|
||||
Error writePointer(TargetAddress Addr, TargetAddress PtrVal) {
|
||||
// Check for an 'out-of-band' error, e.g. from an MM destructor.
|
||||
if (ExistingError)
|
||||
return ExistingError;
|
||||
return std::move(ExistingError);
|
||||
|
||||
return callST<WritePtr>(Channel, Addr, PtrVal);
|
||||
}
|
||||
|
||||
static std::error_code doNothing() { return std::error_code(); }
|
||||
static Error doNothing() { return Error::success(); }
|
||||
|
||||
ChannelT &Channel;
|
||||
std::error_code ExistingError;
|
||||
Error ExistingError;
|
||||
std::string RemoteTargetTriple;
|
||||
uint32_t RemotePointerSize = 0;
|
||||
uint32_t RemotePageSize = 0;
|
||||
uint32_t RemoteTrampolineSize = 0;
|
||||
uint32_t RemoteIndirectStubSize = 0;
|
||||
ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
|
||||
std::function<TargetAddress(TargetAddress)> CompileCallback;
|
||||
Optional<RCCompileCallbackManager> CallbackManager;
|
||||
};
|
||||
|
||||
} // end namespace remote
|
||||
|
|
|
@ -39,8 +39,8 @@ private:
|
|||
uint64_t Size;
|
||||
};
|
||||
|
||||
inline std::error_code serialize(RPCChannel &C,
|
||||
const DirectBufferWriter &DBW) {
|
||||
inline Error serialize(RPCChannel &C,
|
||||
const DirectBufferWriter &DBW) {
|
||||
if (auto EC = serialize(C, DBW.getDst()))
|
||||
return EC;
|
||||
if (auto EC = serialize(C, DBW.getSize()))
|
||||
|
@ -48,8 +48,8 @@ inline std::error_code serialize(RPCChannel &C,
|
|||
return C.appendBytes(DBW.getSrc(), DBW.getSize());
|
||||
}
|
||||
|
||||
inline std::error_code deserialize(RPCChannel &C,
|
||||
DirectBufferWriter &DBW) {
|
||||
inline Error deserialize(RPCChannel &C,
|
||||
DirectBufferWriter &DBW) {
|
||||
TargetAddress Dst;
|
||||
if (auto EC = deserialize(C, Dst))
|
||||
return EC;
|
||||
|
@ -69,6 +69,8 @@ protected:
|
|||
class ResourceIdMgr {
|
||||
public:
|
||||
typedef uint64_t ResourceId;
|
||||
static const ResourceId InvalidId = ~0U;
|
||||
|
||||
ResourceId getNext() {
|
||||
if (!FreeIds.empty()) {
|
||||
ResourceId I = FreeIds.back();
|
||||
|
|
|
@ -46,18 +46,17 @@ public:
|
|||
EHFramesDeregister(std::move(EHFramesDeregister)) {}
|
||||
|
||||
// FIXME: Remove move/copy ops once MSVC supports synthesizing move ops.
|
||||
OrcRemoteTargetServer(const OrcRemoteTargetServer&) = delete;
|
||||
OrcRemoteTargetServer& operator=(const OrcRemoteTargetServer&) = delete;
|
||||
OrcRemoteTargetServer(const OrcRemoteTargetServer &) = delete;
|
||||
OrcRemoteTargetServer &operator=(const OrcRemoteTargetServer &) = delete;
|
||||
|
||||
OrcRemoteTargetServer(OrcRemoteTargetServer &&Other)
|
||||
: Channel(Other.Channel),
|
||||
SymbolLookup(std::move(Other.SymbolLookup)),
|
||||
EHFramesRegister(std::move(Other.EHFramesRegister)),
|
||||
EHFramesDeregister(std::move(Other.EHFramesDeregister)) {}
|
||||
: 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;
|
||||
|
||||
std::error_code handleKnownFunction(JITFuncId Id) {
|
||||
Error handleKnownFunction(JITFuncId Id) {
|
||||
typedef OrcRemoteTargetServer ThisT;
|
||||
|
||||
DEBUG(dbgs() << "Handling known proc: " << getJITFuncIdName(Id) << "\n");
|
||||
|
@ -119,17 +118,16 @@ public:
|
|||
llvm_unreachable("Unhandled JIT RPC procedure Id.");
|
||||
}
|
||||
|
||||
ErrorOr<TargetAddress> requestCompile(TargetAddress TrampolineAddr) {
|
||||
auto Listen =
|
||||
[&](RPCChannel &C, uint32_t Id) {
|
||||
return handleKnownFunction(static_cast<JITFuncId>(Id));
|
||||
};
|
||||
Expected<TargetAddress> requestCompile(TargetAddress TrampolineAddr) {
|
||||
auto Listen = [&](RPCChannel &C, uint32_t Id) {
|
||||
return handleKnownFunction(static_cast<JITFuncId>(Id));
|
||||
};
|
||||
|
||||
return callSTHandling<RequestCompile>(Channel, Listen, TrampolineAddr);
|
||||
}
|
||||
|
||||
void handleTerminateSession() {
|
||||
handle<TerminateSession>(Channel, [](){ return std::error_code(); });
|
||||
Error handleTerminateSession() {
|
||||
return handle<TerminateSession>(Channel, []() { return Error::success(); });
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -146,43 +144,43 @@ private:
|
|||
sys::Memory::releaseMappedMemory(Alloc.second);
|
||||
}
|
||||
|
||||
std::error_code allocate(void *&Addr, size_t Size, uint32_t Align) {
|
||||
Error allocate(void *&Addr, size_t Size, uint32_t Align) {
|
||||
std::error_code EC;
|
||||
sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(
|
||||
Size, nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC);
|
||||
if (EC)
|
||||
return EC;
|
||||
return errorCodeToError(EC);
|
||||
|
||||
Addr = MB.base();
|
||||
assert(Allocs.find(MB.base()) == Allocs.end() && "Duplicate alloc");
|
||||
Allocs[MB.base()] = std::move(MB);
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code setProtections(void *block, unsigned Flags) {
|
||||
Error setProtections(void *block, unsigned Flags) {
|
||||
auto I = Allocs.find(block);
|
||||
if (I == Allocs.end())
|
||||
return orcError(OrcErrorCode::RemoteMProtectAddrUnrecognized);
|
||||
return sys::Memory::protectMappedMemory(I->second, Flags);
|
||||
return errorCodeToError(
|
||||
sys::Memory::protectMappedMemory(I->second, Flags));
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<void *, sys::MemoryBlock> Allocs;
|
||||
};
|
||||
|
||||
static std::error_code doNothing() { return std::error_code(); }
|
||||
static Error doNothing() { return Error::success(); }
|
||||
|
||||
static TargetAddress reenter(void *JITTargetAddr, void *TrampolineAddr) {
|
||||
auto T = static_cast<OrcRemoteTargetServer *>(JITTargetAddr);
|
||||
auto AddrOrErr = T->requestCompile(
|
||||
static_cast<TargetAddress>(
|
||||
reinterpret_cast<uintptr_t>(TrampolineAddr)));
|
||||
auto AddrOrErr = T->requestCompile(static_cast<TargetAddress>(
|
||||
reinterpret_cast<uintptr_t>(TrampolineAddr)));
|
||||
// FIXME: Allow customizable failure substitution functions.
|
||||
assert(AddrOrErr && "Compile request failed");
|
||||
return *AddrOrErr;
|
||||
}
|
||||
|
||||
ErrorOr<int32_t> handleCallIntVoid(TargetAddress Addr) {
|
||||
Expected<int32_t> handleCallIntVoid(TargetAddress Addr) {
|
||||
typedef int (*IntVoidFnTy)();
|
||||
IntVoidFnTy Fn =
|
||||
reinterpret_cast<IntVoidFnTy>(static_cast<uintptr_t>(Addr));
|
||||
|
@ -194,8 +192,8 @@ private:
|
|||
return Result;
|
||||
}
|
||||
|
||||
ErrorOr<int32_t> handleCallMain(TargetAddress Addr,
|
||||
std::vector<std::string> Args) {
|
||||
Expected<int32_t> handleCallMain(TargetAddress Addr,
|
||||
std::vector<std::string> Args) {
|
||||
typedef int (*MainFnTy)(int, const char *[]);
|
||||
|
||||
MainFnTy Fn = reinterpret_cast<MainFnTy>(static_cast<uintptr_t>(Addr));
|
||||
|
@ -213,7 +211,7 @@ private:
|
|||
return Result;
|
||||
}
|
||||
|
||||
std::error_code handleCallVoidVoid(TargetAddress Addr) {
|
||||
Error handleCallVoidVoid(TargetAddress Addr) {
|
||||
typedef void (*VoidVoidFnTy)();
|
||||
VoidVoidFnTy Fn =
|
||||
reinterpret_cast<VoidVoidFnTy>(static_cast<uintptr_t>(Addr));
|
||||
|
@ -222,56 +220,55 @@ private:
|
|||
Fn();
|
||||
DEBUG(dbgs() << " Complete.\n");
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code handleCreateRemoteAllocator(ResourceIdMgr::ResourceId Id) {
|
||||
Error 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();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code handleCreateIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
|
||||
Error 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();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code handleDeregisterEHFrames(TargetAddress TAddr, uint32_t Size) {
|
||||
Error handleDeregisterEHFrames(TargetAddress TAddr, uint32_t Size) {
|
||||
uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
|
||||
DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr)
|
||||
<< ", Size = " << Size << " bytes\n");
|
||||
EHFramesDeregister(Addr, Size);
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code handleDestroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
|
||||
Error 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();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code
|
||||
handleDestroyIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
|
||||
Error handleDestroyIndirectStubsOwner(ResourceIdMgr::ResourceId Id) {
|
||||
auto I = IndirectStubsOwners.find(Id);
|
||||
if (I == IndirectStubsOwners.end())
|
||||
return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);
|
||||
IndirectStubsOwners.erase(I);
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
ErrorOr<std::tuple<TargetAddress, TargetAddress, uint32_t>>
|
||||
Expected<std::tuple<TargetAddress, TargetAddress, uint32_t>>
|
||||
handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
|
||||
uint32_t NumStubsRequired) {
|
||||
uint32_t NumStubsRequired) {
|
||||
DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired
|
||||
<< " stubs.\n");
|
||||
|
||||
|
@ -280,9 +277,9 @@ private:
|
|||
return orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist);
|
||||
|
||||
typename TargetT::IndirectStubsInfo IS;
|
||||
if (auto EC =
|
||||
if (auto Err =
|
||||
TargetT::emitIndirectStubsBlock(IS, NumStubsRequired, nullptr))
|
||||
return EC;
|
||||
return std::move(Err);
|
||||
|
||||
TargetAddress StubsBase =
|
||||
static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(IS.getStub(0)));
|
||||
|
@ -296,31 +293,30 @@ private:
|
|||
return std::make_tuple(StubsBase, PtrsBase, NumStubsEmitted);
|
||||
}
|
||||
|
||||
std::error_code handleEmitResolverBlock() {
|
||||
Error handleEmitResolverBlock() {
|
||||
std::error_code EC;
|
||||
ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
|
||||
TargetT::ResolverCodeSize, nullptr,
|
||||
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
|
||||
if (EC)
|
||||
return EC;
|
||||
return errorCodeToError(EC);
|
||||
|
||||
TargetT::writeResolverCode(static_cast<uint8_t *>(ResolverBlock.base()),
|
||||
&reenter, this);
|
||||
|
||||
return sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(),
|
||||
sys::Memory::MF_READ |
|
||||
sys::Memory::MF_EXEC);
|
||||
return errorCodeToError(sys::Memory::protectMappedMemory(
|
||||
ResolverBlock.getMemoryBlock(),
|
||||
sys::Memory::MF_READ | sys::Memory::MF_EXEC));
|
||||
}
|
||||
|
||||
ErrorOr<std::tuple<TargetAddress, uint32_t>>
|
||||
handleEmitTrampolineBlock() {
|
||||
Expected<std::tuple<TargetAddress, uint32_t>> handleEmitTrampolineBlock() {
|
||||
std::error_code EC;
|
||||
auto TrampolineBlock =
|
||||
sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
|
||||
sys::Process::getPageSize(), nullptr,
|
||||
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
|
||||
if (EC)
|
||||
return EC;
|
||||
return errorCodeToError(EC);
|
||||
|
||||
uint32_t NumTrampolines =
|
||||
(sys::Process::getPageSize() - TargetT::PointerSize) /
|
||||
|
@ -337,19 +333,19 @@ private:
|
|||
TrampolineBlocks.push_back(std::move(TrampolineBlock));
|
||||
|
||||
auto TrampolineBaseAddr =
|
||||
static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(TrampolineMem));
|
||||
static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(TrampolineMem));
|
||||
|
||||
return std::make_tuple(TrampolineBaseAddr, NumTrampolines);
|
||||
}
|
||||
|
||||
ErrorOr<TargetAddress> handleGetSymbolAddress(const std::string &Name) {
|
||||
Expected<TargetAddress> handleGetSymbolAddress(const std::string &Name) {
|
||||
TargetAddress Addr = SymbolLookup(Name);
|
||||
DEBUG(dbgs() << " Symbol '" << Name << "' = " << format("0x%016x", Addr)
|
||||
<< "\n");
|
||||
return Addr;
|
||||
}
|
||||
|
||||
ErrorOr<std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>>
|
||||
Expected<std::tuple<std::string, uint32_t, uint32_t, uint32_t, uint32_t>>
|
||||
handleGetRemoteInfo() {
|
||||
std::string ProcessTriple = sys::getProcessTriple();
|
||||
uint32_t PointerSize = TargetT::PointerSize;
|
||||
|
@ -362,12 +358,11 @@ private:
|
|||
<< " page size = " << PageSize << "\n"
|
||||
<< " trampoline size = " << TrampolineSize << "\n"
|
||||
<< " indirect stub size = " << IndirectStubSize << "\n");
|
||||
return std::make_tuple(ProcessTriple, PointerSize, PageSize ,TrampolineSize,
|
||||
IndirectStubSize);
|
||||
return std::make_tuple(ProcessTriple, PointerSize, PageSize, TrampolineSize,
|
||||
IndirectStubSize);
|
||||
}
|
||||
|
||||
ErrorOr<std::vector<char>>
|
||||
handleReadMem(TargetAddress RSrc, uint64_t Size) {
|
||||
Expected<std::vector<char>> handleReadMem(TargetAddress RSrc, uint64_t Size) {
|
||||
char *Src = reinterpret_cast<char *>(static_cast<uintptr_t>(RSrc));
|
||||
|
||||
DEBUG(dbgs() << " Reading " << Size << " bytes from "
|
||||
|
@ -381,24 +376,23 @@ private:
|
|||
return Buffer;
|
||||
}
|
||||
|
||||
std::error_code handleRegisterEHFrames(TargetAddress TAddr, uint32_t Size) {
|
||||
Error handleRegisterEHFrames(TargetAddress TAddr, uint32_t Size) {
|
||||
uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
|
||||
DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr)
|
||||
<< ", Size = " << Size << " bytes\n");
|
||||
EHFramesRegister(Addr, Size);
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
ErrorOr<TargetAddress>
|
||||
handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
|
||||
uint32_t Align) {
|
||||
Expected<TargetAddress> 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 (auto EC = Allocator.allocate(LocalAllocAddr, Size, Align))
|
||||
return EC;
|
||||
if (auto Err = Allocator.allocate(LocalAllocAddr, Size, Align))
|
||||
return std::move(Err);
|
||||
|
||||
DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr
|
||||
<< " (" << Size << " bytes, alignment " << Align << ")\n");
|
||||
|
@ -409,8 +403,8 @@ private:
|
|||
return AllocAddr;
|
||||
}
|
||||
|
||||
std::error_code handleSetProtections(ResourceIdMgr::ResourceId Id,
|
||||
TargetAddress Addr, uint32_t Flags) {
|
||||
Error handleSetProtections(ResourceIdMgr::ResourceId Id, TargetAddress Addr,
|
||||
uint32_t Flags) {
|
||||
auto I = Allocators.find(Id);
|
||||
if (I == Allocators.end())
|
||||
return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
|
||||
|
@ -423,19 +417,19 @@ private:
|
|||
return Allocator.setProtections(LocalAddr, Flags);
|
||||
}
|
||||
|
||||
std::error_code handleWriteMem(DirectBufferWriter DBW) {
|
||||
Error handleWriteMem(DirectBufferWriter DBW) {
|
||||
DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to "
|
||||
<< format("0x%016x", DBW.getDst()) << "\n");
|
||||
return std::error_code();
|
||||
<< format("0x%016x", DBW.getDst()) << "\n");
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code handleWritePtr(TargetAddress Addr, TargetAddress PtrVal) {
|
||||
Error handleWritePtr(TargetAddress Addr, TargetAddress PtrVal) {
|
||||
DEBUG(dbgs() << " Writing pointer *" << format("0x%016x", Addr) << " = "
|
||||
<< format("0x%016x", PtrVal) << "\n");
|
||||
uintptr_t *Ptr =
|
||||
reinterpret_cast<uintptr_t *>(static_cast<uintptr_t>(Addr));
|
||||
*Ptr = static_cast<uintptr_t>(PtrVal);
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
ChannelT &Channel;
|
||||
|
|
|
@ -21,19 +21,19 @@ public:
|
|||
virtual ~RPCChannel() {}
|
||||
|
||||
/// Read Size bytes from the stream into *Dst.
|
||||
virtual std::error_code readBytes(char *Dst, unsigned Size) = 0;
|
||||
virtual Error readBytes(char *Dst, unsigned Size) = 0;
|
||||
|
||||
/// Read size bytes from *Src and append them to the stream.
|
||||
virtual std::error_code appendBytes(const char *Src, unsigned Size) = 0;
|
||||
virtual Error appendBytes(const char *Src, unsigned Size) = 0;
|
||||
|
||||
/// Flush the stream if possible.
|
||||
virtual std::error_code send() = 0;
|
||||
virtual Error send() = 0;
|
||||
|
||||
/// Get the lock for stream reading.
|
||||
std::mutex& getReadLock() { return readLock; }
|
||||
std::mutex &getReadLock() { return readLock; }
|
||||
|
||||
/// Get the lock for stream writing.
|
||||
std::mutex& getWriteLock() { return writeLock; }
|
||||
std::mutex &getWriteLock() { return writeLock; }
|
||||
|
||||
private:
|
||||
std::mutex readLock, writeLock;
|
||||
|
@ -41,57 +41,53 @@ private:
|
|||
|
||||
/// Notify the channel that we're starting a message send.
|
||||
/// Locks the channel for writing.
|
||||
inline std::error_code startSendMessage(RPCChannel &C) {
|
||||
inline Error startSendMessage(RPCChannel &C) {
|
||||
C.getWriteLock().lock();
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// Notify the channel that we're ending a message send.
|
||||
/// Unlocks the channel for writing.
|
||||
inline std::error_code endSendMessage(RPCChannel &C) {
|
||||
inline Error endSendMessage(RPCChannel &C) {
|
||||
C.getWriteLock().unlock();
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// Notify the channel that we're starting a message receive.
|
||||
/// Locks the channel for reading.
|
||||
inline std::error_code startReceiveMessage(RPCChannel &C) {
|
||||
inline Error startReceiveMessage(RPCChannel &C) {
|
||||
C.getReadLock().lock();
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// Notify the channel that we're ending a message receive.
|
||||
/// Unlocks the channel for reading.
|
||||
inline std::error_code endReceiveMessage(RPCChannel &C) {
|
||||
inline Error endReceiveMessage(RPCChannel &C) {
|
||||
C.getReadLock().unlock();
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// RPC channel serialization for a variadic list of arguments.
|
||||
template <typename T, typename... Ts>
|
||||
std::error_code serializeSeq(RPCChannel &C, const T &Arg, const Ts &... Args) {
|
||||
if (auto EC = serialize(C, Arg))
|
||||
return EC;
|
||||
Error serializeSeq(RPCChannel &C, const T &Arg, const Ts &... Args) {
|
||||
if (auto Err = serialize(C, Arg))
|
||||
return Err;
|
||||
return serializeSeq(C, Args...);
|
||||
}
|
||||
|
||||
/// RPC channel serialization for an (empty) variadic list of arguments.
|
||||
inline std::error_code serializeSeq(RPCChannel &C) {
|
||||
return std::error_code();
|
||||
}
|
||||
inline Error serializeSeq(RPCChannel &C) { return Error::success(); }
|
||||
|
||||
/// RPC channel deserialization for a variadic list of arguments.
|
||||
template <typename T, typename... Ts>
|
||||
std::error_code deserializeSeq(RPCChannel &C, T &Arg, Ts &... Args) {
|
||||
if (auto EC = deserialize(C, Arg))
|
||||
return EC;
|
||||
Error deserializeSeq(RPCChannel &C, T &Arg, Ts &... Args) {
|
||||
if (auto Err = deserialize(C, Arg))
|
||||
return Err;
|
||||
return deserializeSeq(C, Args...);
|
||||
}
|
||||
|
||||
/// RPC channel serialization for an (empty) variadic list of arguments.
|
||||
inline std::error_code deserializeSeq(RPCChannel &C) {
|
||||
return std::error_code();
|
||||
}
|
||||
inline Error deserializeSeq(RPCChannel &C) { return Error::success(); }
|
||||
|
||||
/// RPC channel serialization for integer primitives.
|
||||
template <typename T>
|
||||
|
@ -100,7 +96,7 @@ typename std::enable_if<
|
|||
std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
|
||||
std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
|
||||
std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value,
|
||||
std::error_code>::type
|
||||
Error>::type
|
||||
serialize(RPCChannel &C, T V) {
|
||||
support::endian::byte_swap<T, support::big>(V);
|
||||
return C.appendBytes(reinterpret_cast<const char *>(&V), sizeof(T));
|
||||
|
@ -113,130 +109,125 @@ typename std::enable_if<
|
|||
std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
|
||||
std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
|
||||
std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value,
|
||||
std::error_code>::type
|
||||
Error>::type
|
||||
deserialize(RPCChannel &C, T &V) {
|
||||
if (auto EC = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T)))
|
||||
return EC;
|
||||
if (auto Err = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T)))
|
||||
return Err;
|
||||
support::endian::byte_swap<T, support::big>(V);
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// RPC channel serialization for enums.
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_enum<T>::value, std::error_code>::type
|
||||
typename std::enable_if<std::is_enum<T>::value, Error>::type
|
||||
serialize(RPCChannel &C, T V) {
|
||||
return serialize(C, static_cast<typename std::underlying_type<T>::type>(V));
|
||||
}
|
||||
|
||||
/// RPC channel deserialization for enums.
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_enum<T>::value, std::error_code>::type
|
||||
typename std::enable_if<std::is_enum<T>::value, Error>::type
|
||||
deserialize(RPCChannel &C, T &V) {
|
||||
typename std::underlying_type<T>::type Tmp;
|
||||
std::error_code EC = deserialize(C, Tmp);
|
||||
Error Err = deserialize(C, Tmp);
|
||||
V = static_cast<T>(Tmp);
|
||||
return EC;
|
||||
return Err;
|
||||
}
|
||||
|
||||
/// RPC channel serialization for bools.
|
||||
inline std::error_code serialize(RPCChannel &C, bool V) {
|
||||
inline Error serialize(RPCChannel &C, bool V) {
|
||||
uint8_t VN = V ? 1 : 0;
|
||||
return C.appendBytes(reinterpret_cast<const char *>(&VN), 1);
|
||||
}
|
||||
|
||||
/// RPC channel deserialization for bools.
|
||||
inline std::error_code deserialize(RPCChannel &C, bool &V) {
|
||||
inline Error deserialize(RPCChannel &C, bool &V) {
|
||||
uint8_t VN = 0;
|
||||
if (auto EC = C.readBytes(reinterpret_cast<char *>(&VN), 1))
|
||||
return EC;
|
||||
if (auto Err = C.readBytes(reinterpret_cast<char *>(&VN), 1))
|
||||
return Err;
|
||||
|
||||
V = (VN != 0) ? true : false;
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// RPC channel serialization for StringRefs.
|
||||
/// Note: There is no corresponding deseralization for this, as StringRef
|
||||
/// doesn't own its memory and so can't hold the deserialized data.
|
||||
inline std::error_code serialize(RPCChannel &C, StringRef S) {
|
||||
if (auto EC = serialize(C, static_cast<uint64_t>(S.size())))
|
||||
return EC;
|
||||
inline Error serialize(RPCChannel &C, StringRef S) {
|
||||
if (auto Err = 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.
|
||||
inline std::error_code serialize(RPCChannel &C, const std::string &S) {
|
||||
inline Error serialize(RPCChannel &C, const std::string &S) {
|
||||
return serialize(C, StringRef(S));
|
||||
}
|
||||
|
||||
/// RPC channel deserialization for std::strings.
|
||||
inline std::error_code deserialize(RPCChannel &C, std::string &S) {
|
||||
inline Error deserialize(RPCChannel &C, std::string &S) {
|
||||
uint64_t Count;
|
||||
if (auto EC = deserialize(C, Count))
|
||||
return EC;
|
||||
if (auto Err = deserialize(C, Count))
|
||||
return Err;
|
||||
S.resize(Count);
|
||||
return C.readBytes(&S[0], Count);
|
||||
}
|
||||
|
||||
// Serialization helper for std::tuple.
|
||||
template <typename TupleT, size_t... Is>
|
||||
inline std::error_code serializeTupleHelper(RPCChannel &C,
|
||||
const TupleT &V,
|
||||
llvm::index_sequence<Is...> _) {
|
||||
inline Error serializeTupleHelper(RPCChannel &C, const TupleT &V,
|
||||
llvm::index_sequence<Is...> _) {
|
||||
return serializeSeq(C, std::get<Is>(V)...);
|
||||
}
|
||||
|
||||
/// RPC channel serialization for std::tuple.
|
||||
template <typename... ArgTs>
|
||||
inline std::error_code serialize(RPCChannel &C, const std::tuple<ArgTs...> &V) {
|
||||
inline Error serialize(RPCChannel &C, const std::tuple<ArgTs...> &V) {
|
||||
return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
|
||||
}
|
||||
|
||||
// Serialization helper for std::tuple.
|
||||
template <typename TupleT, size_t... Is>
|
||||
inline std::error_code deserializeTupleHelper(RPCChannel &C,
|
||||
TupleT &V,
|
||||
llvm::index_sequence<Is...> _) {
|
||||
inline Error deserializeTupleHelper(RPCChannel &C, TupleT &V,
|
||||
llvm::index_sequence<Is...> _) {
|
||||
return deserializeSeq(C, std::get<Is>(V)...);
|
||||
}
|
||||
|
||||
/// RPC channel deserialization for std::tuple.
|
||||
template <typename... ArgTs>
|
||||
inline std::error_code deserialize(RPCChannel &C, std::tuple<ArgTs...> &V) {
|
||||
inline Error deserialize(RPCChannel &C, std::tuple<ArgTs...> &V) {
|
||||
return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
|
||||
}
|
||||
|
||||
/// RPC channel serialization for ArrayRef<T>.
|
||||
template <typename T>
|
||||
std::error_code serialize(RPCChannel &C, const ArrayRef<T> &A) {
|
||||
if (auto EC = serialize(C, static_cast<uint64_t>(A.size())))
|
||||
return EC;
|
||||
template <typename T> Error serialize(RPCChannel &C, const ArrayRef<T> &A) {
|
||||
if (auto Err = serialize(C, static_cast<uint64_t>(A.size())))
|
||||
return Err;
|
||||
|
||||
for (const auto &E : A)
|
||||
if (auto EC = serialize(C, E))
|
||||
return EC;
|
||||
if (auto Err = serialize(C, E))
|
||||
return Err;
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// RPC channel serialization for std::array<T>.
|
||||
template <typename T>
|
||||
std::error_code serialize(RPCChannel &C, const std::vector<T> &V) {
|
||||
template <typename T> Error serialize(RPCChannel &C, const std::vector<T> &V) {
|
||||
return serialize(C, ArrayRef<T>(V));
|
||||
}
|
||||
|
||||
/// RPC channel deserialization for std::array<T>.
|
||||
template <typename T>
|
||||
std::error_code deserialize(RPCChannel &C, std::vector<T> &V) {
|
||||
template <typename T> Error deserialize(RPCChannel &C, std::vector<T> &V) {
|
||||
uint64_t Count = 0;
|
||||
if (auto EC = deserialize(C, Count))
|
||||
return EC;
|
||||
if (auto Err = deserialize(C, Count))
|
||||
return Err;
|
||||
|
||||
V.resize(Count);
|
||||
for (auto &E : V)
|
||||
if (auto EC = deserialize(C, E))
|
||||
return EC;
|
||||
if (auto Err = deserialize(C, E))
|
||||
return Err;
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
} // end namespace remote
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ExecutionEngine/Orc/OrcError.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// concrt.h depends on eh.h for __uncaught_exception declaration
|
||||
|
@ -94,7 +93,7 @@ protected:
|
|||
|
||||
typedef Optional<RetT> OptionalReturn;
|
||||
|
||||
typedef ErrorOr<RetT> ErrorReturn;
|
||||
typedef Expected<RetT> ErrorReturn;
|
||||
|
||||
static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) {
|
||||
assert(V && "Return value not available");
|
||||
|
@ -102,21 +101,18 @@ protected:
|
|||
}
|
||||
|
||||
template <typename ChannelT>
|
||||
static std::error_code readResult(ChannelT &C,
|
||||
std::promise<OptionalReturn> &P) {
|
||||
static Error readResult(ChannelT &C, std::promise<OptionalReturn> &P) {
|
||||
RetT Val;
|
||||
auto EC = deserialize(C, Val);
|
||||
// FIXME: Join error EC2 from endReceiveMessage with the deserialize
|
||||
// error once we switch to using Error.
|
||||
auto EC2 = endReceiveMessage(C);
|
||||
(void)EC2;
|
||||
auto Err = deserialize(C, Val);
|
||||
auto Err2 = endReceiveMessage(C);
|
||||
Err = joinErrors(std::move(Err), std::move(Err2));
|
||||
|
||||
if (EC) {
|
||||
if (Err) {
|
||||
P.set_value(OptionalReturn());
|
||||
return EC;
|
||||
return Err;
|
||||
}
|
||||
P.set_value(std::move(Val));
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static void abandon(std::promise<OptionalReturn> &P) {
|
||||
|
@ -124,19 +120,19 @@ protected:
|
|||
}
|
||||
|
||||
template <typename ChannelT, typename SequenceNumberT>
|
||||
static std::error_code respond(ChannelT &C, SequenceNumberT SeqNo,
|
||||
const ErrorReturn &Result) {
|
||||
static Error respond(ChannelT &C, SequenceNumberT SeqNo,
|
||||
ErrorReturn &Result) {
|
||||
FunctionIdT ResponseId = RPCFunctionIdTraits<FunctionIdT>::ResponseId;
|
||||
|
||||
// If the handler returned an error then bail out with that.
|
||||
if (!Result)
|
||||
return Result.getError();
|
||||
return Result.takeError();
|
||||
|
||||
// Otherwise open a new message on the channel and send the result.
|
||||
if (auto EC = startSendMessage(C))
|
||||
return EC;
|
||||
if (auto EC = serializeSeq(C, ResponseId, SeqNo, *Result))
|
||||
return EC;
|
||||
if (auto Err = startSendMessage(C))
|
||||
return Err;
|
||||
if (auto Err = serializeSeq(C, ResponseId, SeqNo, *Result))
|
||||
return Err;
|
||||
return endSendMessage(C);
|
||||
}
|
||||
};
|
||||
|
@ -153,16 +149,15 @@ protected:
|
|||
static const FunctionIdT Id = FuncId;
|
||||
|
||||
typedef bool OptionalReturn;
|
||||
typedef std::error_code ErrorReturn;
|
||||
typedef Error ErrorReturn;
|
||||
|
||||
static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) {
|
||||
assert(V && "Return value not available");
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
template <typename ChannelT>
|
||||
static std::error_code readResult(ChannelT &C,
|
||||
std::promise<OptionalReturn> &P) {
|
||||
static Error readResult(ChannelT &C, std::promise<OptionalReturn> &P) {
|
||||
// Void functions don't have anything to deserialize, so we're good.
|
||||
P.set_value(true);
|
||||
return endReceiveMessage(C);
|
||||
|
@ -171,20 +166,20 @@ protected:
|
|||
static void abandon(std::promise<OptionalReturn> &P) { P.set_value(false); }
|
||||
|
||||
template <typename ChannelT, typename SequenceNumberT>
|
||||
static std::error_code respond(ChannelT &C, SequenceNumberT SeqNo,
|
||||
const ErrorReturn &Result) {
|
||||
static Error respond(ChannelT &C, SequenceNumberT SeqNo,
|
||||
ErrorReturn &Result) {
|
||||
const FunctionIdT ResponseId =
|
||||
RPCFunctionIdTraits<FunctionIdT>::ResponseId;
|
||||
|
||||
// If the handler returned an error then bail out with that.
|
||||
if (Result)
|
||||
return Result;
|
||||
return std::move(Result);
|
||||
|
||||
// Otherwise open a new message on the channel and send the result.
|
||||
if (auto EC = startSendMessage(C))
|
||||
return EC;
|
||||
if (auto EC = serializeSeq(C, ResponseId, SeqNo))
|
||||
return EC;
|
||||
if (auto Err = startSendMessage(C))
|
||||
return Err;
|
||||
if (auto Err = serializeSeq(C, ResponseId, SeqNo))
|
||||
return Err;
|
||||
return endSendMessage(C);
|
||||
}
|
||||
};
|
||||
|
@ -198,12 +193,12 @@ protected:
|
|||
class CallHelper<ChannelT, SequenceNumberT,
|
||||
FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)>> {
|
||||
public:
|
||||
static std::error_code call(ChannelT &C, SequenceNumberT SeqNo,
|
||||
const ArgTs &... Args) {
|
||||
if (auto EC = startSendMessage(C))
|
||||
return EC;
|
||||
if (auto EC = serializeSeq(C, FuncId, SeqNo, Args...))
|
||||
return EC;
|
||||
static Error call(ChannelT &C, SequenceNumberT SeqNo,
|
||||
const ArgTs &... Args) {
|
||||
if (auto Err = startSendMessage(C))
|
||||
return Err;
|
||||
if (auto Err = serializeSeq(C, FuncId, SeqNo, Args...))
|
||||
return Err;
|
||||
return endSendMessage(C);
|
||||
}
|
||||
};
|
||||
|
@ -218,7 +213,7 @@ protected:
|
|||
FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)>> {
|
||||
public:
|
||||
template <typename HandlerT>
|
||||
static std::error_code handle(ChannelT &C, HandlerT Handler) {
|
||||
static Error handle(ChannelT &C, HandlerT Handler) {
|
||||
return readAndHandle(C, Handler, llvm::index_sequence_for<ArgTs...>());
|
||||
}
|
||||
|
||||
|
@ -226,24 +221,28 @@ protected:
|
|||
typedef FunctionHelper<FunctionIdT, FuncId, RetT(ArgTs...)> Func;
|
||||
|
||||
template <typename HandlerT, size_t... Is>
|
||||
static std::error_code readAndHandle(ChannelT &C, HandlerT Handler,
|
||||
llvm::index_sequence<Is...> _) {
|
||||
static Error readAndHandle(ChannelT &C, HandlerT Handler,
|
||||
llvm::index_sequence<Is...> _) {
|
||||
std::tuple<ArgTs...> RPCArgs;
|
||||
SequenceNumberT SeqNo;
|
||||
// GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning
|
||||
// for RPCArgs. Void cast RPCArgs to work around this for now.
|
||||
// FIXME: Remove this workaround once we can assume a working GCC version.
|
||||
(void)RPCArgs;
|
||||
if (auto EC = deserializeSeq(C, SeqNo, std::get<Is>(RPCArgs)...))
|
||||
return EC;
|
||||
if (auto Err = deserializeSeq(C, SeqNo, std::get<Is>(RPCArgs)...))
|
||||
return Err;
|
||||
|
||||
// We've deserialized the arguments, so unlock the channel for reading
|
||||
// before we call the handler. This allows recursive RPC calls.
|
||||
if (auto EC = endReceiveMessage(C))
|
||||
return EC;
|
||||
if (auto Err = endReceiveMessage(C))
|
||||
return Err;
|
||||
|
||||
return Func::template respond<ChannelT, SequenceNumberT>(
|
||||
C, SeqNo, Handler(std::get<Is>(RPCArgs)...));
|
||||
// Run the handler and get the result.
|
||||
auto Result = Handler(std::get<Is>(RPCArgs)...);
|
||||
|
||||
// Return the result to the client.
|
||||
return Func::template respond<ChannelT, SequenceNumberT>(C, SeqNo,
|
||||
Result);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -264,7 +263,7 @@ protected:
|
|||
// Helper that provides a Functor for deserializing arguments.
|
||||
template <typename... ArgTs> class ReadArgs {
|
||||
public:
|
||||
std::error_code operator()() { return std::error_code(); }
|
||||
Error operator()() { return Error::success(); }
|
||||
};
|
||||
|
||||
template <typename ArgT, typename... ArgTs>
|
||||
|
@ -273,7 +272,7 @@ protected:
|
|||
ReadArgs(ArgT &Arg, ArgTs &... Args)
|
||||
: ReadArgs<ArgTs...>(Args...), Arg(Arg) {}
|
||||
|
||||
std::error_code operator()(ArgT &ArgVal, ArgTs &... ArgVals) {
|
||||
Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) {
|
||||
this->Arg = std::move(ArgVal);
|
||||
return ReadArgs<ArgTs...>::operator()(ArgVals...);
|
||||
}
|
||||
|
@ -313,13 +312,13 @@ protected:
|
|||
/// arguments and sending the resulting bytes to 'Channel'.
|
||||
///
|
||||
///
|
||||
/// handle<Func>(Channel, <functor matching std::error_code(Args...)> :
|
||||
/// handle<Func>(Channel, <functor matching Error(Args...)> :
|
||||
///
|
||||
/// Handles a call to 'Func' by deserializing its arguments and calling the
|
||||
/// given functor. This assumes that the id for 'Func' has already been
|
||||
/// deserialized.
|
||||
///
|
||||
/// expect<Func>(Channel, <functor matching std::error_code(Args...)> :
|
||||
/// expect<Func>(Channel, <functor matching Error(Args...)> :
|
||||
///
|
||||
/// The same as 'handle', except that the procedure id should not have been
|
||||
/// read yet. Expect will deserialize the id and assert that it matches Func's
|
||||
|
@ -367,15 +366,15 @@ public:
|
|||
/// typedef Function<0, bool> Func1;
|
||||
/// typedef Function<1, std::string, std::vector<int>> Func2;
|
||||
///
|
||||
/// if (auto EC = call<Func1>(Channel, true))
|
||||
/// /* handle EC */;
|
||||
/// if (auto Err = call<Func1>(Channel, true))
|
||||
/// /* handle Err */;
|
||||
///
|
||||
/// if (auto EC = expect<Func2>(Channel,
|
||||
/// if (auto Err = expect<Func2>(Channel,
|
||||
/// [](std::string &S, std::vector<int> &V) {
|
||||
/// // Stuff.
|
||||
/// return std::error_code();
|
||||
/// return Error::success();
|
||||
/// })
|
||||
/// /* handle EC */;
|
||||
/// /* handle Err */;
|
||||
///
|
||||
template <FunctionIdT FuncId, typename FnT>
|
||||
using Function = FunctionHelper<FunctionIdT, FuncId, FnT>;
|
||||
|
@ -400,18 +399,18 @@ public:
|
|||
/// result. In multi-threaded mode the appendCallAsync method, which does not
|
||||
/// return the sequence numeber, should be preferred.
|
||||
template <typename Func, typename... ArgTs>
|
||||
ErrorOr<AsyncCallWithSeqResult<Func>>
|
||||
Expected<AsyncCallWithSeqResult<Func>>
|
||||
appendCallAsyncWithSeq(ChannelT &C, const ArgTs &... Args) {
|
||||
auto SeqNo = SequenceNumberMgr.getSequenceNumber();
|
||||
std::promise<typename Func::OptionalReturn> Promise;
|
||||
auto Result = Promise.get_future();
|
||||
OutstandingResults[SeqNo] =
|
||||
createOutstandingResult<Func>(std::move(Promise));
|
||||
createOutstandingResult<Func>(std::move(Promise));
|
||||
|
||||
if (auto EC = CallHelper<ChannelT, SequenceNumberT, Func>::call(C, SeqNo,
|
||||
if (auto Err = CallHelper<ChannelT, SequenceNumberT, Func>::call(C, SeqNo,
|
||||
Args...)) {
|
||||
abandonOutstandingResults();
|
||||
return EC;
|
||||
return std::move(Err);
|
||||
} else
|
||||
return AsyncCallWithSeqResult<Func>(std::move(Result), SeqNo);
|
||||
}
|
||||
|
@ -419,14 +418,14 @@ public:
|
|||
/// The same as appendCallAsyncWithSeq, except that it calls C.send() to
|
||||
/// flush the channel after serializing the call.
|
||||
template <typename Func, typename... ArgTs>
|
||||
ErrorOr<AsyncCallWithSeqResult<Func>>
|
||||
Expected<AsyncCallWithSeqResult<Func>>
|
||||
callAsyncWithSeq(ChannelT &C, const ArgTs &... Args) {
|
||||
auto Result = appendCallAsyncWithSeq<Func>(C, Args...);
|
||||
if (!Result)
|
||||
return Result;
|
||||
if (auto EC = C.send()) {
|
||||
if (auto Err = C.send()) {
|
||||
abandonOutstandingResults();
|
||||
return EC;
|
||||
return std::move(Err);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
@ -435,8 +434,8 @@ public:
|
|||
/// Returns an error if serialization fails, otherwise returns a
|
||||
/// std::future<Optional<T>> (or a future<bool> for void functions).
|
||||
template <typename Func, typename... ArgTs>
|
||||
ErrorOr<AsyncCallResult<Func>>
|
||||
appendCallAsync(ChannelT &C, const ArgTs &... Args) {
|
||||
Expected<AsyncCallResult<Func>> appendCallAsync(ChannelT &C,
|
||||
const ArgTs &... Args) {
|
||||
auto ResAndSeqOrErr = appendCallAsyncWithSeq<Func>(C, Args...);
|
||||
if (ResAndSeqOrErr)
|
||||
return std::move(ResAndSeqOrErr->first);
|
||||
|
@ -446,8 +445,7 @@ public:
|
|||
/// The same as appendCallAsync, except that it calls C.send to flush the
|
||||
/// channel after serializing the call.
|
||||
template <typename Func, typename... ArgTs>
|
||||
ErrorOr<AsyncCallResult<Func>>
|
||||
callAsync(ChannelT &C, const ArgTs &... Args) {
|
||||
Expected<AsyncCallResult<Func>> callAsync(ChannelT &C, const ArgTs &... Args) {
|
||||
auto ResAndSeqOrErr = callAsyncWithSeq<Func>(C, Args...);
|
||||
if (ResAndSeqOrErr)
|
||||
return std::move(ResAndSeqOrErr->first);
|
||||
|
@ -460,11 +458,11 @@ public:
|
|||
callSTHandling(ChannelT &C, HandleFtor &HandleOther, const ArgTs &... Args) {
|
||||
if (auto ResultAndSeqNoOrErr = callAsyncWithSeq<Func>(C, Args...)) {
|
||||
auto &ResultAndSeqNo = *ResultAndSeqNoOrErr;
|
||||
if (auto EC = waitForResult(C, ResultAndSeqNo.second, HandleOther))
|
||||
return EC;
|
||||
if (auto Err = waitForResult(C, ResultAndSeqNo.second, HandleOther))
|
||||
return std::move(Err);
|
||||
return Func::optionalToErrorReturn(ResultAndSeqNo.first.get());
|
||||
} else
|
||||
return ResultAndSeqNoOrErr.getError();
|
||||
return ResultAndSeqNoOrErr.takeError();
|
||||
}
|
||||
|
||||
// This can be used in single-threaded mode.
|
||||
|
@ -477,25 +475,25 @@ public:
|
|||
///
|
||||
/// Calls startReceiveMessage on the channel, then deserializes a FunctionId
|
||||
/// into Id.
|
||||
std::error_code startReceivingFunction(ChannelT &C, FunctionIdT &Id) {
|
||||
if (auto EC = startReceiveMessage(C))
|
||||
return EC;
|
||||
Error startReceivingFunction(ChannelT &C, FunctionIdT &Id) {
|
||||
if (auto Err = startReceiveMessage(C))
|
||||
return Err;
|
||||
|
||||
return deserialize(C, Id);
|
||||
}
|
||||
|
||||
/// Deserialize args for Func from C and call Handler. The signature of
|
||||
/// handler must conform to 'std::error_code(Args...)' where Args... matches
|
||||
/// handler must conform to 'Error(Args...)' where Args... matches
|
||||
/// the arguments used in the Func typedef.
|
||||
template <typename Func, typename HandlerT>
|
||||
static std::error_code handle(ChannelT &C, HandlerT Handler) {
|
||||
static Error handle(ChannelT &C, HandlerT Handler) {
|
||||
return HandlerHelper<ChannelT, SequenceNumberT, Func>::handle(C, Handler);
|
||||
}
|
||||
|
||||
/// Helper version of 'handle' for calling member functions.
|
||||
template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
|
||||
static std::error_code handle(ChannelT &C, ClassT &Instance,
|
||||
RetT (ClassT::*HandlerMethod)(ArgTs...)) {
|
||||
static Error handle(ChannelT &C, ClassT &Instance,
|
||||
RetT (ClassT::*HandlerMethod)(ArgTs...)) {
|
||||
return handle<Func>(
|
||||
C, MemberFnWrapper<ClassT, RetT, ArgTs...>(Instance, HandlerMethod));
|
||||
}
|
||||
|
@ -506,10 +504,10 @@ public:
|
|||
/// If the id does not match, return an unexpect RPC call error and do not
|
||||
/// deserialize any further bytes.
|
||||
template <typename Func, typename HandlerT>
|
||||
std::error_code expect(ChannelT &C, HandlerT Handler) {
|
||||
Error expect(ChannelT &C, HandlerT Handler) {
|
||||
FunctionIdT FuncId;
|
||||
if (auto EC = startReceivingFunction(C, FuncId))
|
||||
return std::move(EC);
|
||||
if (auto Err = startReceivingFunction(C, FuncId))
|
||||
return std::move(Err);
|
||||
if (FuncId != Func::Id)
|
||||
return orcError(OrcErrorCode::UnexpectedRPCCall);
|
||||
return handle<Func>(C, Handler);
|
||||
|
@ -517,9 +515,8 @@ public:
|
|||
|
||||
/// Helper version of expect for calling member functions.
|
||||
template <typename Func, typename ClassT, typename... ArgTs>
|
||||
static std::error_code
|
||||
expect(ChannelT &C, ClassT &Instance,
|
||||
std::error_code (ClassT::*HandlerMethod)(ArgTs...)) {
|
||||
static Error expect(ChannelT &C, ClassT &Instance,
|
||||
Error (ClassT::*HandlerMethod)(ArgTs...)) {
|
||||
return expect<Func>(
|
||||
C, MemberFnWrapper<ClassT, ArgTs...>(Instance, HandlerMethod));
|
||||
}
|
||||
|
@ -534,7 +531,7 @@ public:
|
|||
/// ...
|
||||
/// bool B;
|
||||
/// int I;
|
||||
/// if (auto EC = expect<Func1>(Channel, readArgs(B, I)))
|
||||
/// if (auto Err = expect<Func1>(Channel, readArgs(B, I)))
|
||||
/// /* Handle Args */ ;
|
||||
///
|
||||
template <typename... ArgTs>
|
||||
|
@ -544,12 +541,11 @@ public:
|
|||
|
||||
/// Read a response from Channel.
|
||||
/// This should be called from the receive loop to retrieve results.
|
||||
std::error_code handleResponse(ChannelT &C,
|
||||
SequenceNumberT *SeqNoRet = nullptr) {
|
||||
Error handleResponse(ChannelT &C, SequenceNumberT *SeqNoRet = nullptr) {
|
||||
SequenceNumberT SeqNo;
|
||||
if (auto EC = deserialize(C, SeqNo)) {
|
||||
if (auto Err = deserialize(C, SeqNo)) {
|
||||
abandonOutstandingResults();
|
||||
return EC;
|
||||
return Err;
|
||||
}
|
||||
|
||||
if (SeqNoRet)
|
||||
|
@ -561,44 +557,44 @@ public:
|
|||
return orcError(OrcErrorCode::UnexpectedRPCResponse);
|
||||
}
|
||||
|
||||
if (auto EC = I->second->readResult(C)) {
|
||||
if (auto Err = I->second->readResult(C)) {
|
||||
abandonOutstandingResults();
|
||||
// FIXME: Release sequence numbers?
|
||||
return EC;
|
||||
return Err;
|
||||
}
|
||||
|
||||
OutstandingResults.erase(I);
|
||||
SequenceNumberMgr.releaseSequenceNumber(SeqNo);
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// Loop waiting for a result with the given sequence number.
|
||||
// This can be used as a receive loop if the user doesn't have a default.
|
||||
template <typename HandleOtherFtor>
|
||||
std::error_code waitForResult(ChannelT &C, SequenceNumberT TgtSeqNo,
|
||||
HandleOtherFtor &HandleOther = handleNone) {
|
||||
Error waitForResult(ChannelT &C, SequenceNumberT TgtSeqNo,
|
||||
HandleOtherFtor &HandleOther = handleNone) {
|
||||
bool GotTgtResult = false;
|
||||
|
||||
while (!GotTgtResult) {
|
||||
FunctionIdT Id = RPCFunctionIdTraits<FunctionIdT>::InvalidId;
|
||||
if (auto EC = startReceivingFunction(C, Id))
|
||||
return EC;
|
||||
if (auto Err = startReceivingFunction(C, Id))
|
||||
return Err;
|
||||
if (Id == RPCFunctionIdTraits<FunctionIdT>::ResponseId) {
|
||||
SequenceNumberT SeqNo;
|
||||
if (auto EC = handleResponse(C, &SeqNo))
|
||||
return EC;
|
||||
if (auto Err = handleResponse(C, &SeqNo))
|
||||
return Err;
|
||||
GotTgtResult = (SeqNo == TgtSeqNo);
|
||||
} else if (auto EC = HandleOther(C, Id))
|
||||
return EC;
|
||||
} else if (auto Err = HandleOther(C, Id))
|
||||
return Err;
|
||||
}
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// Default handler for 'other' (non-response) functions when waiting for a
|
||||
// result from the channel.
|
||||
static std::error_code handleNone(ChannelT &, FunctionIdT) {
|
||||
static Error handleNone(ChannelT &, FunctionIdT) {
|
||||
return orcError(OrcErrorCode::UnexpectedRPCCall);
|
||||
};
|
||||
|
||||
|
@ -608,8 +604,8 @@ private:
|
|||
public:
|
||||
SequenceNumberManager() = default;
|
||||
|
||||
SequenceNumberManager(const SequenceNumberManager&) = delete;
|
||||
SequenceNumberManager& operator=(const SequenceNumberManager&) = delete;
|
||||
SequenceNumberManager(const SequenceNumberManager &) = delete;
|
||||
SequenceNumberManager &operator=(const SequenceNumberManager &) = delete;
|
||||
|
||||
SequenceNumberManager(SequenceNumberManager &&Other)
|
||||
: NextSequenceNumber(std::move(Other.NextSequenceNumber)),
|
||||
|
@ -651,7 +647,7 @@ private:
|
|||
class OutstandingResult {
|
||||
public:
|
||||
virtual ~OutstandingResult() {}
|
||||
virtual std::error_code readResult(ChannelT &C) = 0;
|
||||
virtual Error readResult(ChannelT &C) = 0;
|
||||
virtual void abandon() = 0;
|
||||
};
|
||||
|
||||
|
@ -663,9 +659,7 @@ private:
|
|||
OutstandingResultImpl(std::promise<typename Func::OptionalReturn> &&P)
|
||||
: P(std::move(P)) {}
|
||||
|
||||
std::error_code readResult(ChannelT &C) override {
|
||||
return Func::readResult(C, P);
|
||||
}
|
||||
Error readResult(ChannelT &C) override { return Func::readResult(C, P); }
|
||||
|
||||
void abandon() override { Func::abandon(P); }
|
||||
|
||||
|
|
|
@ -94,9 +94,9 @@ void OrcX86_64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
|
|||
Trampolines[I] = CallIndirPCRel | ((OffsetToPtr - 6) << 16);
|
||||
}
|
||||
|
||||
std::error_code OrcX86_64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
||||
unsigned MinStubs,
|
||||
void *InitialPtrVal) {
|
||||
Error OrcX86_64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
||||
unsigned MinStubs,
|
||||
void *InitialPtrVal) {
|
||||
// Stub format is:
|
||||
//
|
||||
// .section __orc_stubs
|
||||
|
@ -134,7 +134,7 @@ std::error_code OrcX86_64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
|||
EC));
|
||||
|
||||
if (EC)
|
||||
return EC;
|
||||
return errorCodeToError(EC);
|
||||
|
||||
// Create separate MemoryBlocks representing the stubs and pointers.
|
||||
sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize);
|
||||
|
@ -152,7 +152,7 @@ std::error_code OrcX86_64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
|||
if (auto EC = sys::Memory::protectMappedMemory(StubsBlock,
|
||||
sys::Memory::MF_READ |
|
||||
sys::Memory::MF_EXEC))
|
||||
return EC;
|
||||
return errorCodeToError(EC);
|
||||
|
||||
// Initialize all pointers to point at FailureAddress.
|
||||
void **Ptr = reinterpret_cast<void**>(PtrsBlock.base());
|
||||
|
@ -161,7 +161,7 @@ std::error_code OrcX86_64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
|||
|
||||
StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem));
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void OrcI386::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn,
|
||||
|
@ -223,9 +223,9 @@ void OrcI386::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
|
|||
Trampolines[I] = CallRelImm | (ResolverRel << 8);
|
||||
}
|
||||
|
||||
std::error_code OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
||||
unsigned MinStubs,
|
||||
void *InitialPtrVal) {
|
||||
Error OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
||||
unsigned MinStubs,
|
||||
void *InitialPtrVal) {
|
||||
// Stub format is:
|
||||
//
|
||||
// .section __orc_stubs
|
||||
|
@ -263,7 +263,7 @@ std::error_code OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
|||
EC));
|
||||
|
||||
if (EC)
|
||||
return EC;
|
||||
return errorCodeToError(EC);
|
||||
|
||||
// Create separate MemoryBlocks representing the stubs and pointers.
|
||||
sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize);
|
||||
|
@ -280,7 +280,7 @@ std::error_code OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
|||
if (auto EC = sys::Memory::protectMappedMemory(StubsBlock,
|
||||
sys::Memory::MF_READ |
|
||||
sys::Memory::MF_EXEC))
|
||||
return EC;
|
||||
return errorCodeToError(EC);
|
||||
|
||||
// Initialize all pointers to point at FailureAddress.
|
||||
void **Ptr = reinterpret_cast<void**>(PtrsBlock.base());
|
||||
|
@ -289,7 +289,7 @@ std::error_code OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
|
|||
|
||||
StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem));
|
||||
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
} // End namespace orc.
|
||||
|
|
|
@ -28,6 +28,11 @@ LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM) {
|
|||
return wrap(JITStack);
|
||||
}
|
||||
|
||||
const char *LLVMOrcGetErrorMsg(LLVMOrcJITStackRef JITStack) {
|
||||
OrcCBindingsStack &J = *unwrap(JITStack);
|
||||
return J.getErrorMessage().c_str();
|
||||
}
|
||||
|
||||
void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledName,
|
||||
const char *SymbolName) {
|
||||
OrcCBindingsStack &J = *unwrap(JITStack);
|
||||
|
@ -48,18 +53,18 @@ LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack,
|
|||
return J.createLazyCompileCallback(Callback, CallbackCtx);
|
||||
}
|
||||
|
||||
void LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
|
||||
const char *StubName,
|
||||
LLVMOrcTargetAddress InitAddr) {
|
||||
LLVMOrcErrorCode LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
|
||||
const char *StubName,
|
||||
LLVMOrcTargetAddress InitAddr) {
|
||||
OrcCBindingsStack &J = *unwrap(JITStack);
|
||||
J.createIndirectStub(StubName, InitAddr);
|
||||
return J.createIndirectStub(StubName, InitAddr);
|
||||
}
|
||||
|
||||
void LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
|
||||
const char *StubName,
|
||||
LLVMOrcTargetAddress NewAddr) {
|
||||
LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
|
||||
const char *StubName,
|
||||
LLVMOrcTargetAddress NewAddr) {
|
||||
OrcCBindingsStack &J = *unwrap(JITStack);
|
||||
J.setIndirectStubPointer(StubName, NewAddr);
|
||||
return J.setIndirectStubPointer(StubName, NewAddr);
|
||||
}
|
||||
|
||||
LLVMOrcModuleHandle
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm-c/OrcBindings.h"
|
||||
|
||||
namespace llvm {
|
||||
|
@ -131,12 +132,16 @@ public:
|
|||
return CCInfo.getAddress();
|
||||
}
|
||||
|
||||
void createIndirectStub(StringRef StubName, orc::TargetAddress Addr) {
|
||||
IndirectStubsMgr->createStub(StubName, Addr, JITSymbolFlags::Exported);
|
||||
LLVMOrcErrorCode
|
||||
createIndirectStub(StringRef StubName, orc::TargetAddress Addr) {
|
||||
return mapError(
|
||||
IndirectStubsMgr->createStub(StubName, Addr,
|
||||
JITSymbolFlags::Exported));
|
||||
}
|
||||
|
||||
void setIndirectStubPointer(StringRef Name, orc::TargetAddress Addr) {
|
||||
IndirectStubsMgr->updatePointer(Name, Addr);
|
||||
LLVMOrcErrorCode
|
||||
setIndirectStubPointer(StringRef Name, orc::TargetAddress Addr) {
|
||||
return mapError(IndirectStubsMgr->updatePointer(Name, Addr));
|
||||
}
|
||||
|
||||
std::shared_ptr<RuntimeDyld::SymbolResolver>
|
||||
|
@ -243,6 +248,10 @@ public:
|
|||
return GenericHandles[H]->findSymbolIn(Name, ExportedSymbolsOnly);
|
||||
}
|
||||
|
||||
const std::string& getErrorMessage() const {
|
||||
return ErrMsg;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename LayerT>
|
||||
|
@ -261,6 +270,19 @@ private:
|
|||
return NewHandle;
|
||||
}
|
||||
|
||||
LLVMOrcErrorCode mapError(Error Err) {
|
||||
LLVMOrcErrorCode Result = LLVMOrcErrSuccess;
|
||||
handleAllErrors(std::move(Err),
|
||||
[&](ErrorInfoBase &EIB) {
|
||||
// Handler of last resort.
|
||||
Result = LLVMOrcErrGeneric;
|
||||
ErrMsg = "";
|
||||
raw_string_ostream ErrStream(ErrMsg);
|
||||
EIB.log(ErrStream);
|
||||
});
|
||||
return Result;
|
||||
}
|
||||
|
||||
DataLayout DL;
|
||||
SectionMemoryManager CCMgrMemMgr;
|
||||
|
||||
|
@ -276,6 +298,7 @@ private:
|
|||
|
||||
orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
|
||||
std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
|
||||
std::string ErrMsg;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
|
|
@ -51,9 +51,10 @@ static ManagedStatic<OrcErrorCategory> OrcErrCat;
|
|||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
std::error_code orcError(OrcErrorCode ErrCode) {
|
||||
Error orcError(OrcErrorCode ErrCode) {
|
||||
typedef std::underlying_type<OrcErrorCode>::type UT;
|
||||
return std::error_code(static_cast<UT>(ErrCode), *OrcErrCat);
|
||||
return errorCodeToError(std::error_code(static_cast<UT>(ErrCode),
|
||||
*OrcErrCat));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ typedef OrcX86_64 HostOrcArch;
|
|||
typedef OrcGenericArchitecture HostOrcArch;
|
||||
#endif
|
||||
|
||||
ExitOnError ExitOnErr;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if (argc != 3) {
|
||||
|
@ -24,6 +26,8 @@ int main(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
ExitOnErr.setBanner(std::string(argv[0]) + ":");
|
||||
|
||||
int InFD;
|
||||
int OutFD;
|
||||
{
|
||||
|
@ -55,20 +59,15 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
while (1) {
|
||||
uint32_t RawId;
|
||||
if (auto EC = Server.startReceivingFunction(Channel, RawId)) {
|
||||
errs() << "Error: " << EC.message() << "\n";
|
||||
return 1;
|
||||
}
|
||||
ExitOnErr(Server.startReceivingFunction(Channel, RawId));
|
||||
auto Id = static_cast<JITServer::JITFuncId>(RawId);
|
||||
switch (Id) {
|
||||
case JITServer::TerminateSessionId:
|
||||
Server.handleTerminateSession();
|
||||
ExitOnErr(Server.handleTerminateSession());
|
||||
return 0;
|
||||
default:
|
||||
if (auto EC = Server.handleKnownFunction(Id)) {
|
||||
errs() << "Error: " << EC.message() << "\n";
|
||||
return 1;
|
||||
}
|
||||
ExitOnErr(Server.handleKnownFunction(Id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,23 +29,43 @@ class FDRPCChannel final : public llvm::orc::remote::RPCChannel {
|
|||
public:
|
||||
FDRPCChannel(int InFD, int OutFD) : InFD(InFD), OutFD(OutFD) {}
|
||||
|
||||
std::error_code readBytes(char *Dst, unsigned Size) override {
|
||||
llvm::Error readBytes(char *Dst, unsigned Size) override {
|
||||
assert(Dst && "Attempt to read into null.");
|
||||
ssize_t ReadResult = ::read(InFD, Dst, Size);
|
||||
if (ReadResult != (ssize_t)Size)
|
||||
return std::error_code(errno, std::generic_category());
|
||||
return std::error_code();
|
||||
ssize_t Completed = 0;
|
||||
while (Completed < Size) {
|
||||
ssize_t Read = ::read(InFD, Dst + Completed, Size - Completed);
|
||||
if (Read <= 0) {
|
||||
auto ErrNo = errno;
|
||||
if (ErrNo == EAGAIN || ErrNo == EINTR)
|
||||
continue;
|
||||
else
|
||||
return llvm::errorCodeToError(
|
||||
std::error_code(errno, std::generic_category()));
|
||||
}
|
||||
Completed += Read;
|
||||
}
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
std::error_code appendBytes(const char *Src, unsigned Size) override {
|
||||
llvm::Error appendBytes(const char *Src, unsigned Size) override {
|
||||
assert(Src && "Attempt to append from null.");
|
||||
ssize_t WriteResult = ::write(OutFD, Src, Size);
|
||||
if (WriteResult != (ssize_t)Size)
|
||||
std::error_code(errno, std::generic_category());
|
||||
return std::error_code();
|
||||
ssize_t Completed = 0;
|
||||
while (Completed < Size) {
|
||||
ssize_t Written = ::write(OutFD, Src + Completed, Size - Completed);
|
||||
if (Written < 0) {
|
||||
auto ErrNo = errno;
|
||||
if (ErrNo == EAGAIN || ErrNo == EINTR)
|
||||
continue;
|
||||
else
|
||||
return llvm::errorCodeToError(
|
||||
std::error_code(errno, std::generic_category()));
|
||||
}
|
||||
Completed += Written;
|
||||
}
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
std::error_code send() override { return std::error_code(); }
|
||||
llvm::Error send() override { return llvm::Error::success(); }
|
||||
|
||||
private:
|
||||
int InFD, OutFD;
|
||||
|
|
|
@ -235,6 +235,8 @@ namespace {
|
|||
clEnumValN(FloatABI::Hard, "hard",
|
||||
"Hard float ABI (uses FP registers)"),
|
||||
clEnumValEnd));
|
||||
|
||||
ExitOnError ExitOnErr;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -373,6 +375,9 @@ int main(int argc, char **argv, char * const *envp) {
|
|||
|
||||
atexit(llvm_shutdown); // Call llvm_shutdown() on exit.
|
||||
|
||||
if (argc > 1)
|
||||
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
|
||||
|
||||
// If we have a native target, initialize it to ensure it is linked in and
|
||||
// usable by the JIT.
|
||||
InitializeNativeTarget();
|
||||
|
@ -648,18 +653,11 @@ int main(int argc, char **argv, char * const *envp) {
|
|||
|
||||
// Create a remote target client running over the channel.
|
||||
typedef orc::remote::OrcRemoteTargetClient<orc::remote::RPCChannel> MyRemote;
|
||||
ErrorOr<MyRemote> R = MyRemote::Create(*C);
|
||||
if (!R) {
|
||||
errs() << "Could not create remote: " << R.getError().message() << "\n";
|
||||
exit(1);
|
||||
}
|
||||
MyRemote R = ExitOnErr(MyRemote::Create(*C));
|
||||
|
||||
// Create a remote memory manager.
|
||||
std::unique_ptr<MyRemote::RCMemoryManager> RemoteMM;
|
||||
if (auto EC = R->createRemoteMemoryManager(RemoteMM)) {
|
||||
errs() << "Could not create remote memory manager: " << EC.message() << "\n";
|
||||
exit(1);
|
||||
}
|
||||
ExitOnErr(R.createRemoteMemoryManager(RemoteMM));
|
||||
|
||||
// Forward MCJIT's memory manager calls to the remote memory manager.
|
||||
static_cast<ForwardingMemoryManager*>(RTDyldMM)->setMemMgr(
|
||||
|
@ -669,13 +667,9 @@ int main(int argc, char **argv, char * const *envp) {
|
|||
static_cast<ForwardingMemoryManager*>(RTDyldMM)->setResolver(
|
||||
orc::createLambdaResolver(
|
||||
[&](const std::string &Name) {
|
||||
if (auto AddrOrErr = R->getSymbolAddress(Name))
|
||||
return RuntimeDyld::SymbolInfo(*AddrOrErr, JITSymbolFlags::Exported);
|
||||
else {
|
||||
errs() << "Failure during symbol lookup: "
|
||||
<< AddrOrErr.getError().message() << "\n";
|
||||
exit(1);
|
||||
}
|
||||
if (auto Addr = ExitOnErr(R.getSymbolAddress(Name)))
|
||||
return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported);
|
||||
return RuntimeDyld::SymbolInfo(nullptr);
|
||||
},
|
||||
[](const std::string &Name) { return nullptr; }
|
||||
));
|
||||
|
@ -687,10 +681,7 @@ int main(int argc, char **argv, char * const *envp) {
|
|||
EE->finalizeObject();
|
||||
DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at 0x"
|
||||
<< format("%llx", Entry) << "\n");
|
||||
if (auto ResultOrErr = R->callIntVoid(Entry))
|
||||
Result = *ResultOrErr;
|
||||
else
|
||||
errs() << "ERROR: " << ResultOrErr.getError().message() << "\n";
|
||||
Result = ExitOnErr(R.callIntVoid(Entry));
|
||||
|
||||
// Like static constructors, the remote target MCJIT support doesn't handle
|
||||
// this yet. It could. FIXME.
|
||||
|
@ -701,7 +692,7 @@ int main(int argc, char **argv, char * const *envp) {
|
|||
EE.reset();
|
||||
|
||||
// Signal the remote target that we're done JITing.
|
||||
R->terminateSession();
|
||||
ExitOnErr(R.terminateSession());
|
||||
}
|
||||
|
||||
return Result;
|
||||
|
|
|
@ -25,12 +25,12 @@ public:
|
|||
|
||||
class DummyStubsManager : public orc::IndirectStubsManager {
|
||||
public:
|
||||
std::error_code createStub(StringRef StubName, TargetAddress InitAddr,
|
||||
Error createStub(StringRef StubName, TargetAddress InitAddr,
|
||||
JITSymbolFlags Flags) override {
|
||||
llvm_unreachable("Not implemented");
|
||||
}
|
||||
|
||||
std::error_code createStubs(const StubInitsMap &StubInits) override {
|
||||
Error createStubs(const StubInitsMap &StubInits) override {
|
||||
llvm_unreachable("Not implemented");
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ public:
|
|||
llvm_unreachable("Not implemented");
|
||||
}
|
||||
|
||||
std::error_code updatePointer(StringRef Name,
|
||||
Error updatePointer(StringRef Name,
|
||||
TargetAddress NewAddr) override {
|
||||
llvm_unreachable("Not implemented");
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
QueueChannel(Queue &InQueue, Queue &OutQueue)
|
||||
: InQueue(InQueue), OutQueue(OutQueue) {}
|
||||
|
||||
std::error_code readBytes(char *Dst, unsigned Size) override {
|
||||
Error readBytes(char *Dst, unsigned Size) override {
|
||||
while (Size != 0) {
|
||||
// If there's nothing to read then yield.
|
||||
while (InQueue.empty())
|
||||
|
@ -43,17 +43,17 @@ public:
|
|||
InQueue.pop();
|
||||
}
|
||||
}
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code appendBytes(const char *Src, unsigned Size) override {
|
||||
Error appendBytes(const char *Src, unsigned Size) override {
|
||||
std::lock_guard<std::mutex> Lock(OutQueue.getLock());
|
||||
while (Size--)
|
||||
OutQueue.push(*Src++);
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::error_code send() override { return std::error_code(); }
|
||||
Error send() override { return Error::success(); }
|
||||
|
||||
private:
|
||||
Queue &InQueue;
|
||||
|
@ -95,7 +95,7 @@ TEST_F(DummyRPC, TestAsyncVoidBool) {
|
|||
[&](bool &B) {
|
||||
EXPECT_EQ(B, true)
|
||||
<< "Bool serialization broken";
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
});
|
||||
EXPECT_FALSE(EC) << "Simple expect over queue failed";
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ TEST_F(DummyRPC, TestAsyncIntInt) {
|
|||
{
|
||||
// Expect a call to Proc1.
|
||||
auto EC = expect<IntInt>(C2,
|
||||
[&](int32_t I) {
|
||||
[&](int32_t I) -> Expected<int32_t> {
|
||||
EXPECT_EQ(I, 21)
|
||||
<< "Bool serialization broken";
|
||||
return 2 * I;
|
||||
|
@ -202,7 +202,7 @@ TEST_F(DummyRPC, TestSerialization) {
|
|||
<< "std::string serialization broken";
|
||||
EXPECT_EQ(v, std::vector<int>({42, 7}))
|
||||
<< "std::vector serialization broken";
|
||||
return std::error_code();
|
||||
return Error::success();
|
||||
});
|
||||
EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue