From ef5a0ee2c3dad1c0e2fc51cf260a76d2acadf063 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 25 Apr 2016 19:56:45 +0000 Subject: [PATCH] [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 --- llvm/include/llvm-c/OrcBindings.h | 26 +- .../ExecutionEngine/Orc/IndirectionUtils.h | 38 +- .../Orc/OrcArchitectureSupport.h | 22 +- .../llvm/ExecutionEngine/Orc/OrcError.h | 3 +- .../Orc/OrcRemoteTargetClient.h | 385 ++++++++++-------- .../Orc/OrcRemoteTargetRPCAPI.h | 10 +- .../Orc/OrcRemoteTargetServer.h | 140 +++---- .../llvm/ExecutionEngine/Orc/RPCChannel.h | 131 +++--- .../llvm/ExecutionEngine/Orc/RPCUtils.h | 204 +++++----- .../Orc/OrcArchitectureSupport.cpp | 24 +- llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp | 21 +- .../ExecutionEngine/Orc/OrcCBindingsStack.h | 31 +- llvm/lib/ExecutionEngine/Orc/OrcError.cpp | 5 +- llvm/tools/lli/ChildTarget/ChildTarget.cpp | 17 +- llvm/tools/lli/RemoteJITUtils.h | 42 +- llvm/tools/lli/lli.cpp | 33 +- .../Orc/CompileOnDemandLayerTest.cpp | 6 +- .../ExecutionEngine/Orc/RPCUtilsTest.cpp | 16 +- 18 files changed, 621 insertions(+), 533 deletions(-) diff --git a/llvm/include/llvm-c/OrcBindings.h b/llvm/include/llvm-c/OrcBindings.h index 92e6ca310b13..4a2fa26abd47 100644 --- a/llvm/include/llvm-c/OrcBindings.h +++ b/llvm/include/llvm-c/OrcBindings.h @@ -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. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index 13b7dba3801d..615d6369a64d 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -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 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(static_cast(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, diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h index 7dd7bd353e32..c8e4e26d56d4 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h @@ -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 -class GenericIndirectStubsInfo { +template 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(StubsMem.base()) + NumStubs * StubSize; + char *PtrsBase = static_cast(StubsMem.base()) + NumStubs * StubSize; return reinterpret_cast(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. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h index aeee03f86e9d..1b3f25fae162 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h @@ -14,6 +14,7 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_ORCERROR_H #define LLVM_EXECUTIONENGINE_ORC_ORCERROR_H +#include "llvm/Support/Error.h" #include 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. diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h index a3964c5745d2..75bda1d589f0 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h @@ -36,25 +36,22 @@ namespace remote { template 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(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(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(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 FreeStubs; StringMap> 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 Create(ChannelT &Channel) { - std::error_code EC; - OrcRemoteTargetClient H(Channel, EC); - if (EC) - return EC; - return ErrorOr(std::move(H)); + static Expected Create(ChannelT &Channel) { + Error Err; + OrcRemoteTargetClient H(Channel, Err); + if (Err) + return std::move(Err); + return Expected(std::move(H)); } /// Call the int(void) function at the given address in the target and return /// its result. - ErrorOr callIntVoid(TargetAddress Addr) { + Expected 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(Channel, Listen, Addr); } /// Call the int(int, char*[]) function at the given address in the target and /// return its result. - ErrorOr callMain(TargetAddress Addr, - const std::vector &Args) { + Expected callMain(TargetAddress Addr, + const std::vector &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(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(Channel, Listen, Addr); } /// Create an RCMemoryManager which will allocate its memory on the remote /// target. - std::error_code - createRemoteMemoryManager(std::unique_ptr &MM) { + Error createRemoteMemoryManager(std::unique_ptr &MM) { assert(!MM && "MemoryManager should be null before creation."); auto Id = AllocatorIds.getNext(); - if (auto EC = callST(Channel, Id)) - return EC; + if (auto Err = callST(Channel, Id)) + return Err; MM = llvm::make_unique(*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 &I) { + Error createIndirectStubsManager(std::unique_ptr &I) { assert(!I && "Indirect stubs manager should be null before creation."); auto Id = IndirectStubOwnerIds.getNext(); - if (auto EC = callST(Channel, Id)) - return EC; + if (auto Err = callST(Channel, Id)) + return Err; I = llvm::make_unique(*this, Id); - return std::error_code(); + return Error::success(); + } + + Expected + 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(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 getSymbolAddress(StringRef Name) { + Expected 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(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(Channel); - } + Error terminateSession() { return callST(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(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(Channel, Addr, Size); } void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) { - if (auto EC = callST(Channel, Id)) { + if (auto Err = callST(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(Channel, Id); } - ErrorOr> - emitIndirectStubs(ResourceIdMgr::ResourceId Id, - uint32_t NumStubsRequired) { + Expected> + emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) { return callST(Channel, Id, NumStubsRequired); } - std::error_code emitResolverBlock() { + Expected> emitTrampolineBlock() { // Check for an 'out-of-band' error, e.g. from an MM destructor. if (ExistingError) - return ExistingError; - - return callST(Channel); - } - - ErrorOr> - emitTrampolineBlock() { - // Check for an 'out-of-band' error, e.g. from an MM destructor. - if (ExistingError) - return ExistingError; + return std::move(ExistingError); return callST(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(C, CompileCallback)) - return EC; - return std::error_code(); + if (auto Err = handle( + C, [&](TargetAddress Addr) -> Expected { + return CallbackManager->executeCompileCallback(Addr); + })) + return Err; + return Error::success(); } // else return orcError(OrcErrorCode::UnexpectedRPCCall); } - ErrorOr> readMem(char *Dst, TargetAddress Src, uint64_t Size) { + Expected> 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(Channel, Src, Size); } - std::error_code registerEHFrames(TargetAddress &RAddr, uint32_t Size) { + Error registerEHFrames(TargetAddress &RAddr, uint32_t Size) { return callST(Channel, RAddr, Size); } - ErrorOr reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size, - uint32_t Align) { + Expected 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(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(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(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(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 CompileCallback; + Optional CallbackManager; }; } // end namespace remote diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h index 6ba7468d0866..df0b5fe1cf41 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h @@ -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(); diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h index 88d3adb1867e..bf4299c69b24 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h @@ -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 requestCompile(TargetAddress TrampolineAddr) { - auto Listen = - [&](RPCChannel &C, uint32_t Id) { - return handleKnownFunction(static_cast(Id)); - }; + Expected requestCompile(TargetAddress TrampolineAddr) { + auto Listen = [&](RPCChannel &C, uint32_t Id) { + return handleKnownFunction(static_cast(Id)); + }; return callSTHandling(Channel, Listen, TrampolineAddr); } - void handleTerminateSession() { - handle(Channel, [](){ return std::error_code(); }); + Error handleTerminateSession() { + return handle(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 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(JITTargetAddr); - auto AddrOrErr = T->requestCompile( - static_cast( - reinterpret_cast(TrampolineAddr))); + auto AddrOrErr = T->requestCompile(static_cast( + reinterpret_cast(TrampolineAddr))); // FIXME: Allow customizable failure substitution functions. assert(AddrOrErr && "Compile request failed"); return *AddrOrErr; } - ErrorOr handleCallIntVoid(TargetAddress Addr) { + Expected handleCallIntVoid(TargetAddress Addr) { typedef int (*IntVoidFnTy)(); IntVoidFnTy Fn = reinterpret_cast(static_cast(Addr)); @@ -194,8 +192,8 @@ private: return Result; } - ErrorOr handleCallMain(TargetAddress Addr, - std::vector Args) { + Expected handleCallMain(TargetAddress Addr, + std::vector Args) { typedef int (*MainFnTy)(int, const char *[]); MainFnTy Fn = reinterpret_cast(static_cast(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(static_cast(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(static_cast(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> + Expected> 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(reinterpret_cast(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(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> - handleEmitTrampolineBlock() { + Expected> 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(reinterpret_cast(TrampolineMem)); + static_cast(reinterpret_cast(TrampolineMem)); return std::make_tuple(TrampolineBaseAddr, NumTrampolines); } - ErrorOr handleGetSymbolAddress(const std::string &Name) { + Expected handleGetSymbolAddress(const std::string &Name) { TargetAddress Addr = SymbolLookup(Name); DEBUG(dbgs() << " Symbol '" << Name << "' = " << format("0x%016x", Addr) << "\n"); return Addr; } - ErrorOr> + Expected> 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> - handleReadMem(TargetAddress RSrc, uint64_t Size) { + Expected> handleReadMem(TargetAddress RSrc, uint64_t Size) { char *Src = reinterpret_cast(static_cast(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(static_cast(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 - handleReserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size, - uint32_t Align) { + Expected 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(static_cast(Addr)); *Ptr = static_cast(PtrVal); - return std::error_code(); + return Error::success(); } ChannelT &Channel; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RPCChannel.h b/llvm/include/llvm/ExecutionEngine/Orc/RPCChannel.h index 98314aea163c..1664e04254a7 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/RPCChannel.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/RPCChannel.h @@ -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 -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 -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 @@ -100,7 +96,7 @@ typename std::enable_if< std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value, - std::error_code>::type + Error>::type serialize(RPCChannel &C, T V) { support::endian::byte_swap(V); return C.appendBytes(reinterpret_cast(&V), sizeof(T)); @@ -113,130 +109,125 @@ typename std::enable_if< std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value, - std::error_code>::type + Error>::type deserialize(RPCChannel &C, T &V) { - if (auto EC = C.readBytes(reinterpret_cast(&V), sizeof(T))) - return EC; + if (auto Err = C.readBytes(reinterpret_cast(&V), sizeof(T))) + return Err; support::endian::byte_swap(V); - return std::error_code(); + return Error::success(); } /// RPC channel serialization for enums. template -typename std::enable_if::value, std::error_code>::type +typename std::enable_if::value, Error>::type serialize(RPCChannel &C, T V) { return serialize(C, static_cast::type>(V)); } /// RPC channel deserialization for enums. template -typename std::enable_if::value, std::error_code>::type +typename std::enable_if::value, Error>::type deserialize(RPCChannel &C, T &V) { typename std::underlying_type::type Tmp; - std::error_code EC = deserialize(C, Tmp); + Error Err = deserialize(C, Tmp); V = static_cast(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(&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(&VN), 1)) - return EC; + if (auto Err = C.readBytes(reinterpret_cast(&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(S.size()))) - return EC; +inline Error serialize(RPCChannel &C, StringRef S) { + if (auto Err = serialize(C, static_cast(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 -inline std::error_code serializeTupleHelper(RPCChannel &C, - const TupleT &V, - llvm::index_sequence _) { +inline Error serializeTupleHelper(RPCChannel &C, const TupleT &V, + llvm::index_sequence _) { return serializeSeq(C, std::get(V)...); } /// RPC channel serialization for std::tuple. template -inline std::error_code serialize(RPCChannel &C, const std::tuple &V) { +inline Error serialize(RPCChannel &C, const std::tuple &V) { return serializeTupleHelper(C, V, llvm::index_sequence_for()); } // Serialization helper for std::tuple. template -inline std::error_code deserializeTupleHelper(RPCChannel &C, - TupleT &V, - llvm::index_sequence _) { +inline Error deserializeTupleHelper(RPCChannel &C, TupleT &V, + llvm::index_sequence _) { return deserializeSeq(C, std::get(V)...); } /// RPC channel deserialization for std::tuple. template -inline std::error_code deserialize(RPCChannel &C, std::tuple &V) { +inline Error deserialize(RPCChannel &C, std::tuple &V) { return deserializeTupleHelper(C, V, llvm::index_sequence_for()); } /// RPC channel serialization for ArrayRef. -template -std::error_code serialize(RPCChannel &C, const ArrayRef &A) { - if (auto EC = serialize(C, static_cast(A.size()))) - return EC; +template Error serialize(RPCChannel &C, const ArrayRef &A) { + if (auto Err = serialize(C, static_cast(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. -template -std::error_code serialize(RPCChannel &C, const std::vector &V) { +template Error serialize(RPCChannel &C, const std::vector &V) { return serialize(C, ArrayRef(V)); } /// RPC channel deserialization for std::array. -template -std::error_code deserialize(RPCChannel &C, std::vector &V) { +template Error deserialize(RPCChannel &C, std::vector &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 diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h index 4e18d55a36ed..ee5ccf98c04e 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h @@ -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 OptionalReturn; - typedef ErrorOr ErrorReturn; + typedef Expected ErrorReturn; static ErrorReturn optionalToErrorReturn(OptionalReturn &&V) { assert(V && "Return value not available"); @@ -102,21 +101,18 @@ protected: } template - static std::error_code readResult(ChannelT &C, - std::promise &P) { + static Error readResult(ChannelT &C, std::promise &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 &P) { @@ -124,19 +120,19 @@ protected: } template - static std::error_code respond(ChannelT &C, SequenceNumberT SeqNo, - const ErrorReturn &Result) { + static Error respond(ChannelT &C, SequenceNumberT SeqNo, + ErrorReturn &Result) { FunctionIdT ResponseId = RPCFunctionIdTraits::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 - static std::error_code readResult(ChannelT &C, - std::promise &P) { + static Error readResult(ChannelT &C, std::promise &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 &P) { P.set_value(false); } template - 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::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> { 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> { public: template - static std::error_code handle(ChannelT &C, HandlerT Handler) { + static Error handle(ChannelT &C, HandlerT Handler) { return readAndHandle(C, Handler, llvm::index_sequence_for()); } @@ -226,24 +221,28 @@ protected: typedef FunctionHelper Func; template - static std::error_code readAndHandle(ChannelT &C, HandlerT Handler, - llvm::index_sequence _) { + static Error readAndHandle(ChannelT &C, HandlerT Handler, + llvm::index_sequence _) { std::tuple 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(RPCArgs)...)) - return EC; + if (auto Err = deserializeSeq(C, SeqNo, std::get(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( - C, SeqNo, Handler(std::get(RPCArgs)...)); + // Run the handler and get the result. + auto Result = Handler(std::get(RPCArgs)...); + + // Return the result to the client. + return Func::template respond(C, SeqNo, + Result); } }; @@ -264,7 +263,7 @@ protected: // Helper that provides a Functor for deserializing arguments. template class ReadArgs { public: - std::error_code operator()() { return std::error_code(); } + Error operator()() { return Error::success(); } }; template @@ -273,7 +272,7 @@ protected: ReadArgs(ArgT &Arg, ArgTs &... Args) : ReadArgs(Args...), Arg(Arg) {} - std::error_code operator()(ArgT &ArgVal, ArgTs &... ArgVals) { + Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) { this->Arg = std::move(ArgVal); return ReadArgs::operator()(ArgVals...); } @@ -313,13 +312,13 @@ protected: /// arguments and sending the resulting bytes to 'Channel'. /// /// -/// handle(Channel, : +/// handle(Channel, : /// /// 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(Channel, : +/// expect(Channel, : /// /// 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> Func2; /// - /// if (auto EC = call(Channel, true)) - /// /* handle EC */; + /// if (auto Err = call(Channel, true)) + /// /* handle Err */; /// - /// if (auto EC = expect(Channel, + /// if (auto Err = expect(Channel, /// [](std::string &S, std::vector &V) { /// // Stuff. - /// return std::error_code(); + /// return Error::success(); /// }) - /// /* handle EC */; + /// /* handle Err */; /// template using Function = FunctionHelper; @@ -400,18 +399,18 @@ public: /// result. In multi-threaded mode the appendCallAsync method, which does not /// return the sequence numeber, should be preferred. template - ErrorOr> + Expected> appendCallAsyncWithSeq(ChannelT &C, const ArgTs &... Args) { auto SeqNo = SequenceNumberMgr.getSequenceNumber(); std::promise Promise; auto Result = Promise.get_future(); OutstandingResults[SeqNo] = - createOutstandingResult(std::move(Promise)); + createOutstandingResult(std::move(Promise)); - if (auto EC = CallHelper::call(C, SeqNo, + if (auto Err = CallHelper::call(C, SeqNo, Args...)) { abandonOutstandingResults(); - return EC; + return std::move(Err); } else return AsyncCallWithSeqResult(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 - ErrorOr> + Expected> callAsyncWithSeq(ChannelT &C, const ArgTs &... Args) { auto Result = appendCallAsyncWithSeq(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> (or a future for void functions). template - ErrorOr> - appendCallAsync(ChannelT &C, const ArgTs &... Args) { + Expected> appendCallAsync(ChannelT &C, + const ArgTs &... Args) { auto ResAndSeqOrErr = appendCallAsyncWithSeq(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 - ErrorOr> - callAsync(ChannelT &C, const ArgTs &... Args) { + Expected> callAsync(ChannelT &C, const ArgTs &... Args) { auto ResAndSeqOrErr = callAsyncWithSeq(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(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 - static std::error_code handle(ChannelT &C, HandlerT Handler) { + static Error handle(ChannelT &C, HandlerT Handler) { return HandlerHelper::handle(C, Handler); } /// Helper version of 'handle' for calling member functions. template - 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( C, MemberFnWrapper(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 - 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(C, Handler); @@ -517,9 +515,8 @@ public: /// Helper version of expect for calling member functions. template - 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( C, MemberFnWrapper(Instance, HandlerMethod)); } @@ -534,7 +531,7 @@ public: /// ... /// bool B; /// int I; - /// if (auto EC = expect(Channel, readArgs(B, I))) + /// if (auto Err = expect(Channel, readArgs(B, I))) /// /* Handle Args */ ; /// template @@ -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 - 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::InvalidId; - if (auto EC = startReceivingFunction(C, Id)) - return EC; + if (auto Err = startReceivingFunction(C, Id)) + return Err; if (Id == RPCFunctionIdTraits::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 &&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); } diff --git a/llvm/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp b/llvm/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp index 2503654a4034..4095a3b98ee1 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcArchitectureSupport.cpp @@ -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(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(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. diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp index d2379cd441d5..565a9d03ec9e 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcCBindings.cpp @@ -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 diff --git a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index def11dd3e93a..6b84c7b523f4 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -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 @@ -243,6 +248,10 @@ public: return GenericHandles[H]->findSymbolIn(Name, ExportedSymbolsOnly); } + const std::string& getErrorMessage() const { + return ErrMsg; + } + private: template @@ -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> IRStaticDestructorRunners; + std::string ErrMsg; }; } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/Orc/OrcError.cpp b/llvm/lib/ExecutionEngine/Orc/OrcError.cpp index 5e12c86c7045..37b49903ba7e 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcError.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcError.cpp @@ -51,9 +51,10 @@ static ManagedStatic OrcErrCat; namespace llvm { namespace orc { -std::error_code orcError(OrcErrorCode ErrCode) { +Error orcError(OrcErrorCode ErrCode) { typedef std::underlying_type::type UT; - return std::error_code(static_cast(ErrCode), *OrcErrCat); + return errorCodeToError(std::error_code(static_cast(ErrCode), + *OrcErrCat)); } } } diff --git a/llvm/tools/lli/ChildTarget/ChildTarget.cpp b/llvm/tools/lli/ChildTarget/ChildTarget.cpp index b7dcaaa3ea9c..1a6cd4211d08 100644 --- a/llvm/tools/lli/ChildTarget/ChildTarget.cpp +++ b/llvm/tools/lli/ChildTarget/ChildTarget.cpp @@ -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(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; } } diff --git a/llvm/tools/lli/RemoteJITUtils.h b/llvm/tools/lli/RemoteJITUtils.h index 63915d13ddef..ea6a04e2176a 100644 --- a/llvm/tools/lli/RemoteJITUtils.h +++ b/llvm/tools/lli/RemoteJITUtils.h @@ -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; diff --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp index f2e210d28dd6..1927355e8340 100644 --- a/llvm/tools/lli/lli.cpp +++ b/llvm/tools/lli/lli.cpp @@ -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 MyRemote; - ErrorOr 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 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(RTDyldMM)->setMemMgr( @@ -669,13 +667,9 @@ int main(int argc, char **argv, char * const *envp) { static_cast(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; diff --git a/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp index a27e649b616f..fedf163e4fb7 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp @@ -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"); } diff --git a/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp index 9bf861a595b6..b2680aa7d8a5 100644 --- a/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp @@ -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 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(C2, - [&](int32_t I) { + [&](int32_t I) -> Expected { 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({42, 7})) << "std::vector serialization broken"; - return std::error_code(); + return Error::success(); }); EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed"; }