summaryrefslogtreecommitdiff
path: root/include/llvm/ExecutionEngine
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
commit044eb2f6afba375a914ac9d8024f8f5142bb912e (patch)
tree1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /include/llvm/ExecutionEngine
parenteb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff)
Notes
Diffstat (limited to 'include/llvm/ExecutionEngine')
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h7
-rw-r--r--include/llvm/ExecutionEngine/JITSymbol.h43
-rw-r--r--include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h35
-rw-r--r--include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h11
-rw-r--r--include/llvm/ExecutionEngine/Orc/IndirectionUtils.h32
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcError.h3
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h483
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h263
-rw-r--r--include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h55
-rw-r--r--include/llvm/ExecutionEngine/Orc/RPCSerialization.h14
-rw-r--r--include/llvm/ExecutionEngine/Orc/RPCUtils.h14
-rw-r--r--include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h38
-rw-r--r--include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h538
-rw-r--r--include/llvm/ExecutionEngine/Orc/SymbolStringPool.h136
-rw-r--r--include/llvm/ExecutionEngine/SectionMemoryManager.h75
15 files changed, 1278 insertions, 469 deletions
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
index 2830a2628753..77c23b46d320 100644
--- a/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -535,12 +535,13 @@ private:
std::shared_ptr<JITSymbolResolver> Resolver;
TargetOptions Options;
Optional<Reloc::Model> RelocModel;
- CodeModel::Model CMModel;
+ Optional<CodeModel::Model> CMModel;
std::string MArch;
std::string MCPU;
SmallVector<std::string, 4> MAttrs;
bool VerifyModules;
bool UseOrcMCJITReplacement;
+ bool EmulatedTLS = true;
public:
/// Default constructor for EngineBuilder.
@@ -641,6 +642,10 @@ public:
this->UseOrcMCJITReplacement = UseOrcMCJITReplacement;
}
+ void setEmulatedTLS(bool EmulatedTLS) {
+ this->EmulatedTLS = EmulatedTLS;
+ }
+
TargetMachine *selectTarget();
/// selectTarget - Pick a target either via -march or by guessing the native
diff --git a/include/llvm/ExecutionEngine/JITSymbol.h b/include/llvm/ExecutionEngine/JITSymbol.h
index 4172f240ba39..933b3ea8e13d 100644
--- a/include/llvm/ExecutionEngine/JITSymbol.h
+++ b/include/llvm/ExecutionEngine/JITSymbol.h
@@ -40,6 +40,7 @@ using JITTargetAddress = uint64_t;
class JITSymbolFlags {
public:
using UnderlyingType = uint8_t;
+ using TargetFlagsType = uint64_t;
enum FlagNames : UnderlyingType {
None = 0,
@@ -56,32 +57,48 @@ public:
/// @brief Construct a JITSymbolFlags instance from the given flags.
JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
+ /// @brief Construct a JITSymbolFlags instance from the given flags and target
+ /// flags.
+ JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags)
+ : Flags(Flags), TargetFlags(TargetFlags) {}
+
/// @brief Return true if there was an error retrieving this symbol.
bool hasError() const {
return (Flags & HasError) == HasError;
}
- /// @brief Returns true is the Weak flag is set.
+ /// @brief Returns true if the Weak flag is set.
bool isWeak() const {
return (Flags & Weak) == Weak;
}
- /// @brief Returns true is the Weak flag is set.
+ /// @brief Returns true if the Common flag is set.
bool isCommon() const {
return (Flags & Common) == Common;
}
+ /// @brief Returns true if the symbol isn't weak or common.
bool isStrongDefinition() const {
return !isWeak() && !isCommon();
}
- /// @brief Returns true is the Weak flag is set.
+ /// @brief Returns true if the Exported flag is set.
bool isExported() const {
return (Flags & Exported) == Exported;
}
+ /// @brief Implicitly convert to the underlying flags type.
operator UnderlyingType&() { return Flags; }
+ /// @brief Implicitly convert to the underlying flags type.
+ operator const UnderlyingType&() const { return Flags; }
+
+ /// @brief Return a reference to the target-specific flags.
+ TargetFlagsType& getTargetFlags() { return TargetFlags; }
+
+ /// @brief Return a reference to the target-specific flags.
+ const TargetFlagsType& getTargetFlags() const { return TargetFlags; }
+
/// Construct a JITSymbolFlags value based on the flags of the given global
/// value.
static JITSymbolFlags fromGlobalValue(const GlobalValue &GV);
@@ -92,6 +109,26 @@ public:
private:
UnderlyingType Flags = None;
+ TargetFlagsType TargetFlags = 0;
+};
+
+/// @brief ARM-specific JIT symbol flags.
+/// FIXME: This should be moved into a target-specific header.
+class ARMJITSymbolFlags {
+public:
+ ARMJITSymbolFlags() = default;
+
+ enum FlagNames {
+ None = 0,
+ Thumb = 1 << 0
+ };
+
+ operator JITSymbolFlags::TargetFlagsType&() { return Flags; }
+
+ static ARMJITSymbolFlags fromObjectSymbol(
+ const object::BasicSymbolRef &Symbol);
+private:
+ JITSymbolFlags::TargetFlagsType Flags = 0;
};
/// @brief Represents a symbol that has been evaluated to an address already.
diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
index 27b5457fc8ff..a961992c2147 100644
--- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
@@ -140,12 +140,6 @@ private:
struct LogicalDylib {
using SymbolResolverFtor = std::function<JITSymbol(const std::string&)>;
- using ModuleAdderFtor =
- std::function<typename BaseLayerT::ModuleHandleT(
- BaseLayerT&,
- std::unique_ptr<Module>,
- std::unique_ptr<JITSymbolResolver>)>;
-
struct SourceModuleEntry {
std::shared_ptr<Module> SourceMod;
std::set<Function*> StubsToClone;
@@ -349,19 +343,22 @@ private:
// Create a callback, associate it with the stub for the function,
// and set the compile action to compile the partition containing the
// function.
- auto CCInfo = CompileCallbackMgr.getCompileCallback();
- StubInits[MangledName] =
- std::make_pair(CCInfo.getAddress(),
- JITSymbolFlags::fromGlobalValue(F));
- CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress {
- if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
- return *FnImplAddrOrErr;
- else {
- // FIXME: Report error, return to 'abort' or something similar.
- consumeError(FnImplAddrOrErr.takeError());
- return 0;
- }
- });
+ if (auto CCInfoOrErr = CompileCallbackMgr.getCompileCallback()) {
+ auto &CCInfo = *CCInfoOrErr;
+ StubInits[MangledName] =
+ std::make_pair(CCInfo.getAddress(),
+ JITSymbolFlags::fromGlobalValue(F));
+ CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress {
+ if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
+ return *FnImplAddrOrErr;
+ else {
+ // FIXME: Report error, return to 'abort' or something similar.
+ consumeError(FnImplAddrOrErr.takeError());
+ return 0;
+ }
+ });
+ } else
+ return CCInfoOrErr.takeError();
}
if (auto Err = LD.StubsMgr->createStubs(StubInits))
diff --git a/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h b/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
index ff54ef625ebb..8a48c36f4141 100644
--- a/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
@@ -46,13 +46,14 @@ public:
/// @brief Add the given module to the JIT.
/// @return A handle for the added modules.
- ModuleHandleT addModule(std::shared_ptr<Module> M,
- std::shared_ptr<JITSymbolResolver> Resolver) {
+ Expected<ModuleHandleT>
+ addModule(std::shared_ptr<Module> M,
+ std::shared_ptr<JITSymbolResolver> Resolver) {
return BaseLayer.addModule(std::move(M), std::move(Resolver));
}
/// @brief Remove the module set associated with the handle H.
- void removeModule(ModuleHandleT H) { BaseLayer.removeModule(H); }
+ Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); }
/// @brief Manually set the address to return for the given symbol.
void setGlobalMapping(const std::string &Name, JITTargetAddress Addr) {
@@ -96,8 +97,8 @@ public:
/// @brief Immediately emit and finalize the module set represented by the
/// given handle.
/// @param H Handle for module set to emit/finalize.
- void emitAndFinalize(ModuleHandleT H) {
- BaseLayer.emitAndFinalize(H);
+ Error emitAndFinalize(ModuleHandleT H) {
+ return BaseLayer.emitAndFinalize(H);
}
private:
diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
index e038093d7628..029b86a6d2ca 100644
--- a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
+++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -105,10 +105,13 @@ public:
}
/// @brief Reserve a compile callback.
- CompileCallbackInfo getCompileCallback() {
- JITTargetAddress TrampolineAddr = getAvailableTrampolineAddr();
- auto &Compile = this->ActiveTrampolines[TrampolineAddr];
- return CompileCallbackInfo(TrampolineAddr, Compile);
+ Expected<CompileCallbackInfo> getCompileCallback() {
+ if (auto TrampolineAddrOrErr = getAvailableTrampolineAddr()) {
+ const auto &TrampolineAddr = *TrampolineAddrOrErr;
+ auto &Compile = this->ActiveTrampolines[TrampolineAddr];
+ return CompileCallbackInfo(TrampolineAddr, Compile);
+ } else
+ return TrampolineAddrOrErr.takeError();
}
/// @brief Get a CompileCallbackInfo for an existing callback.
@@ -138,9 +141,10 @@ protected:
std::vector<JITTargetAddress> AvailableTrampolines;
private:
- JITTargetAddress getAvailableTrampolineAddr() {
+ Expected<JITTargetAddress> getAvailableTrampolineAddr() {
if (this->AvailableTrampolines.empty())
- grow();
+ if (auto Err = grow())
+ return std::move(Err);
assert(!this->AvailableTrampolines.empty() &&
"Failed to grow available trampolines.");
JITTargetAddress TrampolineAddr = this->AvailableTrampolines.back();
@@ -149,7 +153,7 @@ private:
}
// Create new trampolines - to be implemented in subclasses.
- virtual void grow() = 0;
+ virtual Error grow() = 0;
virtual void anchor();
};
@@ -188,7 +192,7 @@ private:
reinterpret_cast<uintptr_t>(TrampolineId)));
}
- void grow() override {
+ Error grow() override {
assert(this->AvailableTrampolines.empty() && "Growing prematurely?");
std::error_code EC;
@@ -196,7 +200,8 @@ private:
sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
sys::Process::getPageSize(), nullptr,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
- assert(!EC && "Failed to allocate trampoline block");
+ if (EC)
+ return errorCodeToError(EC);
unsigned NumTrampolines =
(sys::Process::getPageSize() - TargetT::PointerSize) /
@@ -211,12 +216,13 @@ private:
static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(
TrampolineMem + (I * TargetT::TrampolineSize))));
- EC = sys::Memory::protectMappedMemory(TrampolineBlock.getMemoryBlock(),
- sys::Memory::MF_READ |
- sys::Memory::MF_EXEC);
- assert(!EC && "Failed to mprotect trampoline block");
+ if (auto EC = sys::Memory::protectMappedMemory(
+ TrampolineBlock.getMemoryBlock(),
+ sys::Memory::MF_READ | sys::Memory::MF_EXEC))
+ return errorCodeToError(EC);
TrampolineBlocks.push_back(std::move(TrampolineBlock));
+ return Error::success();
}
sys::OwningMemoryBlock ResolverBlock;
diff --git a/include/llvm/ExecutionEngine/Orc/OrcError.h b/include/llvm/ExecutionEngine/Orc/OrcError.h
index e6374b70967a..e1ac87075ac0 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcError.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcError.h
@@ -33,7 +33,8 @@ enum class OrcErrorCode : int {
RPCResponseAbandoned,
UnexpectedRPCCall,
UnexpectedRPCResponse,
- UnknownErrorCodeFromRemote
+ UnknownErrorCodeFromRemote,
+ UnknownResourceHandle
};
std::error_code orcError(OrcErrorCode ErrCode);
diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
index da02250ba169..7179e5ff66fd 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
@@ -53,27 +53,26 @@ namespace remote {
/// Each of the utility classes talks to a JIT server (an instance of the
/// OrcRemoteTargetServer class) via an RPC system (see RPCUtils.h) to carry out
/// its actions.
-template <typename ChannelT>
-class OrcRemoteTargetClient : public OrcRemoteTargetRPCAPI {
+class OrcRemoteTargetClient
+ : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
public:
- /// Remote memory manager.
- class RCMemoryManager : public RuntimeDyld::MemoryManager {
- public:
- RCMemoryManager(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id)
- : Client(Client), Id(Id) {
- DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
- }
-
- RCMemoryManager(const RCMemoryManager &) = delete;
- RCMemoryManager &operator=(const RCMemoryManager &) = delete;
- RCMemoryManager(RCMemoryManager &&) = default;
- RCMemoryManager &operator=(RCMemoryManager &&) = default;
+ /// Remote-mapped RuntimeDyld-compatible memory manager.
+ class RemoteRTDyldMemoryManager : public RuntimeDyld::MemoryManager {
+ friend class OrcRemoteTargetClient;
- ~RCMemoryManager() override {
+ public:
+ ~RemoteRTDyldMemoryManager() {
Client.destroyRemoteAllocator(Id);
DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
}
+ RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete;
+ RemoteRTDyldMemoryManager &
+ operator=(const RemoteRTDyldMemoryManager &) = delete;
+ RemoteRTDyldMemoryManager(RemoteRTDyldMemoryManager &&) = default;
+ RemoteRTDyldMemoryManager &
+ operator=(RemoteRTDyldMemoryManager &&) = default;
+
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
StringRef SectionName) override {
@@ -117,12 +116,8 @@ 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.takeError() && "Failed reserving remote memory.");
- }
+ Unmapped.back().RemoteCodeAddr =
+ Client.reserveMem(Id, CodeSize, CodeAlign);
DEBUG(dbgs() << " code: "
<< format("0x%016x", Unmapped.back().RemoteCodeAddr)
@@ -131,12 +126,8 @@ public:
}
if (RODataSize != 0) {
- if (auto AddrOrErr = Client.reserveMem(Id, RODataSize, RODataAlign))
- Unmapped.back().RemoteRODataAddr = *AddrOrErr;
- else {
- // FIXME; Add error to poll.
- assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
- }
+ Unmapped.back().RemoteRODataAddr =
+ Client.reserveMem(Id, RODataSize, RODataAlign);
DEBUG(dbgs() << " ro-data: "
<< format("0x%016x", Unmapped.back().RemoteRODataAddr)
@@ -145,12 +136,8 @@ public:
}
if (RWDataSize != 0) {
- if (auto AddrOrErr = Client.reserveMem(Id, RWDataSize, RWDataAlign))
- Unmapped.back().RemoteRWDataAddr = *AddrOrErr;
- else {
- // FIXME; Add error to poll.
- assert(!AddrOrErr.takeError() && "Failed reserving remote memory.");
- }
+ Unmapped.back().RemoteRWDataAddr =
+ Client.reserveMem(Id, RWDataSize, RWDataAlign);
DEBUG(dbgs() << " rw-data: "
<< format("0x%016x", Unmapped.back().RemoteRWDataAddr)
@@ -168,10 +155,8 @@ public:
void deregisterEHFrames() override {
for (auto &Frame : RegisteredEHFrames) {
- auto Err = Client.deregisterEHFrames(Frame.Addr, Frame.Size);
// FIXME: Add error poll.
- assert(!Err && "Failed to register remote EH frames.");
- (void)Err;
+ Client.deregisterEHFrames(Frame.Addr, Frame.Size);
}
}
@@ -179,44 +164,12 @@ public:
const object::ObjectFile &Obj) override {
DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
for (auto &ObjAllocs : Unmapped) {
- {
- JITTargetAddress NextCodeAddr = ObjAllocs.RemoteCodeAddr;
- for (auto &Alloc : ObjAllocs.CodeAllocs) {
- NextCodeAddr = alignTo(NextCodeAddr, Alloc.getAlign());
- Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextCodeAddr);
- DEBUG(dbgs() << " code: "
- << static_cast<void *>(Alloc.getLocalAddress())
- << " -> " << format("0x%016x", NextCodeAddr) << "\n");
- Alloc.setRemoteAddress(NextCodeAddr);
- NextCodeAddr += Alloc.getSize();
- }
- }
- {
- JITTargetAddress NextRODataAddr = ObjAllocs.RemoteRODataAddr;
- for (auto &Alloc : ObjAllocs.RODataAllocs) {
- NextRODataAddr = alignTo(NextRODataAddr, Alloc.getAlign());
- Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextRODataAddr);
- DEBUG(dbgs() << " ro-data: "
- << static_cast<void *>(Alloc.getLocalAddress())
- << " -> " << format("0x%016x", NextRODataAddr)
- << "\n");
- Alloc.setRemoteAddress(NextRODataAddr);
- NextRODataAddr += Alloc.getSize();
- }
- }
- {
- JITTargetAddress NextRWDataAddr = ObjAllocs.RemoteRWDataAddr;
- for (auto &Alloc : ObjAllocs.RWDataAllocs) {
- NextRWDataAddr = alignTo(NextRWDataAddr, Alloc.getAlign());
- Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextRWDataAddr);
- DEBUG(dbgs() << " rw-data: "
- << static_cast<void *>(Alloc.getLocalAddress())
- << " -> " << format("0x%016x", NextRWDataAddr)
- << "\n");
- Alloc.setRemoteAddress(NextRWDataAddr);
- NextRWDataAddr += Alloc.getSize();
- }
- }
+ mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
+ ObjAllocs.RemoteCodeAddr);
+ mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,
+ ObjAllocs.RemoteRODataAddr);
+ mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,
+ ObjAllocs.RemoteRWDataAddr);
Unfinalized.push_back(std::move(ObjAllocs));
}
Unmapped.clear();
@@ -226,114 +179,17 @@ public:
DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
for (auto &ObjAllocs : Unfinalized) {
- for (auto &Alloc : ObjAllocs.CodeAllocs) {
- DEBUG(dbgs() << " copying code: "
- << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
- << format("0x%016x", Alloc.getRemoteAddress()) << " ("
- << Alloc.getSize() << " bytes)\n");
- 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");
- 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;
- }
- }
+ if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
+ sys::Memory::MF_READ | sys::Memory::MF_EXEC))
+ return true;
- for (auto &Alloc : ObjAllocs.RODataAllocs) {
- DEBUG(dbgs() << " copying ro-data: "
- << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
- << format("0x%016x", Alloc.getRemoteAddress()) << " ("
- << Alloc.getSize() << " bytes)\n");
- 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");
- 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) {
- DEBUG(dbgs() << " copying rw-data: "
- << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
- << format("0x%016x", Alloc.getRemoteAddress()) << " ("
- << Alloc.getSize() << " bytes)\n");
- 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 (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr,
+ sys::Memory::MF_READ))
+ return true;
- if (ObjAllocs.RemoteRWDataAddr) {
- DEBUG(dbgs() << " setting RW- permissions on rw-data block: "
- << format("0x%016x", ObjAllocs.RemoteRWDataAddr)
- << "\n");
- 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;
- }
- }
+ if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr,
+ sys::Memory::MF_READ | sys::Memory::MF_WRITE))
+ return true;
}
Unfinalized.clear();
@@ -402,6 +258,60 @@ public:
std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs;
};
+ RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client,
+ ResourceIdMgr::ResourceId Id)
+ : Client(Client), Id(Id) {
+ DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
+ }
+
+ // Maps all allocations in Allocs to aligned blocks
+ void mapAllocsToRemoteAddrs(RuntimeDyld &Dyld, std::vector<Alloc> &Allocs,
+ JITTargetAddress NextAddr) {
+ for (auto &Alloc : Allocs) {
+ NextAddr = alignTo(NextAddr, Alloc.getAlign());
+ Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr);
+ DEBUG(dbgs() << " " << static_cast<void *>(Alloc.getLocalAddress())
+ << " -> " << format("0x%016x", NextAddr) << "\n");
+ Alloc.setRemoteAddress(NextAddr);
+
+ // Only advance NextAddr if it was non-null to begin with,
+ // otherwise leave it as null.
+ if (NextAddr)
+ NextAddr += Alloc.getSize();
+ }
+ }
+
+ // Copies data for each alloc in the list, then set permissions on the
+ // segment.
+ bool copyAndProtect(const std::vector<Alloc> &Allocs,
+ JITTargetAddress RemoteSegmentAddr,
+ unsigned Permissions) {
+ if (RemoteSegmentAddr) {
+ assert(!Allocs.empty() && "No sections in allocated segment");
+
+ for (auto &Alloc : Allocs) {
+ DEBUG(dbgs() << " copying section: "
+ << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
+ << format("0x%016x", Alloc.getRemoteAddress()) << " ("
+ << Alloc.getSize() << " bytes)\n";);
+
+ if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
+ Alloc.getSize()))
+ return true;
+ }
+
+ DEBUG(dbgs() << " setting "
+ << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
+ << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
+ << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
+ << " permissions on block: "
+ << format("0x%016x", RemoteSegmentAddr) << "\n");
+ if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
+ return true;
+ }
+ return false;
+ }
+
OrcRemoteTargetClient &Client;
ResourceIdMgr::ResourceId Id;
std::vector<ObjectAllocs> Unmapped;
@@ -416,17 +326,14 @@ public:
};
/// Remote indirect stubs manager.
- class RCIndirectStubsManager : public IndirectStubsManager {
+ class RemoteIndirectStubsManager : public IndirectStubsManager {
public:
- RCIndirectStubsManager(OrcRemoteTargetClient &Remote,
- ResourceIdMgr::ResourceId Id)
- : Remote(Remote), Id(Id) {}
-
- ~RCIndirectStubsManager() override {
- if (auto Err = Remote.destroyIndirectStubsManager(Id)) {
- // FIXME: Thread this error back to clients.
- consumeError(std::move(Err));
- }
+ RemoteIndirectStubsManager(OrcRemoteTargetClient &Client,
+ ResourceIdMgr::ResourceId Id)
+ : Client(Client), Id(Id) {}
+
+ ~RemoteIndirectStubsManager() override {
+ Client.destroyIndirectStubsManager(Id);
}
Error createStub(StringRef StubName, JITTargetAddress StubAddr,
@@ -474,7 +381,7 @@ public:
auto I = StubIndexes.find(Name);
assert(I != StubIndexes.end() && "No stub pointer for symbol");
auto Key = I->second.first;
- return Remote.writePointer(getPtrAddr(Key), NewAddr);
+ return Client.writePointer(getPtrAddr(Key), NewAddr);
}
private:
@@ -484,12 +391,7 @@ public:
unsigned NumStubs;
};
- OrcRemoteTargetClient &Remote;
- ResourceIdMgr::ResourceId Id;
- std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos;
using StubKey = std::pair<uint16_t, uint16_t>;
- std::vector<StubKey> FreeStubs;
- StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
Error reserveStubs(unsigned NumStubs) {
if (NumStubs <= FreeStubs.size())
@@ -500,7 +402,7 @@ public:
JITTargetAddress PtrBase;
unsigned NumStubsEmitted;
- if (auto StubInfoOrErr = Remote.emitIndirectStubs(Id, NewStubsRequired))
+ if (auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired))
std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
else
return StubInfoOrErr.takeError();
@@ -519,58 +421,64 @@ public:
auto Key = FreeStubs.back();
FreeStubs.pop_back();
StubIndexes[StubName] = std::make_pair(Key, StubFlags);
- return Remote.writePointer(getPtrAddr(Key), InitAddr);
+ return Client.writePointer(getPtrAddr(Key), InitAddr);
}
JITTargetAddress getStubAddr(StubKey K) {
assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&
"Missing stub address");
return RemoteIndirectStubsInfos[K.first].StubBase +
- K.second * Remote.getIndirectStubSize();
+ K.second * Client.getIndirectStubSize();
}
JITTargetAddress getPtrAddr(StubKey K) {
assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&
"Missing pointer address");
return RemoteIndirectStubsInfos[K.first].PtrBase +
- K.second * Remote.getPointerSize();
+ K.second * Client.getPointerSize();
}
+
+ OrcRemoteTargetClient &Client;
+ ResourceIdMgr::ResourceId Id;
+ std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos;
+ std::vector<StubKey> FreeStubs;
+ StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
};
/// Remote compile callback manager.
- class RCCompileCallbackManager : public JITCompileCallbackManager {
+ class RemoteCompileCallbackManager : public JITCompileCallbackManager {
public:
- RCCompileCallbackManager(JITTargetAddress ErrorHandlerAddress,
- OrcRemoteTargetClient &Remote)
- : JITCompileCallbackManager(ErrorHandlerAddress), Remote(Remote) {}
+ RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
+ JITTargetAddress ErrorHandlerAddress)
+ : JITCompileCallbackManager(ErrorHandlerAddress), Client(Client) {}
private:
- void grow() override {
+ Error grow() override {
JITTargetAddress BlockAddr = 0;
uint32_t NumTrampolines = 0;
- if (auto TrampolineInfoOrErr = Remote.emitTrampolineBlock())
+ if (auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
- else {
- // FIXME: Return error.
- llvm_unreachable("Failed to create trampolines");
- }
+ else
+ return TrampolineInfoOrErr.takeError();
- uint32_t TrampolineSize = Remote.getTrampolineSize();
+ uint32_t TrampolineSize = Client.getTrampolineSize();
for (unsigned I = 0; I < NumTrampolines; ++I)
this->AvailableTrampolines.push_back(BlockAddr + (I * TrampolineSize));
+
+ return Error::success();
}
- OrcRemoteTargetClient &Remote;
+ OrcRemoteTargetClient &Client;
};
/// 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 Expected<std::unique_ptr<OrcRemoteTargetClient>>
- Create(ChannelT &Channel) {
+ Create(rpc::RawByteChannel &Channel, std::function<void(Error)> ReportError) {
Error Err = Error::success();
- std::unique_ptr<OrcRemoteTargetClient> Client(
- new OrcRemoteTargetClient(Channel, Err));
+ auto Client = std::unique_ptr<OrcRemoteTargetClient>(
+ new OrcRemoteTargetClient(Channel, std::move(ReportError), Err));
if (Err)
return std::move(Err);
return std::move(Client);
@@ -580,7 +488,7 @@ public:
/// its result.
Expected<int> callIntVoid(JITTargetAddress Addr) {
DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
- return callB<CallIntVoid>(Addr);
+ return callB<exec::CallIntVoid>(Addr);
}
/// Call the int(int, char*[]) function at the given address in the target and
@@ -589,7 +497,7 @@ public:
const std::vector<std::string> &Args) {
DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
<< "\n");
- return callB<CallMain>(Addr, Args);
+ return callB<exec::CallMain>(Addr, Args);
}
/// Call the void() function at the given address in the target and wait for
@@ -597,45 +505,39 @@ public:
Error callVoidVoid(JITTargetAddress Addr) {
DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
<< "\n");
- return callB<CallVoidVoid>(Addr);
+ return callB<exec::CallVoidVoid>(Addr);
}
/// Create an RCMemoryManager which will allocate its memory on the remote
/// target.
- Error createRemoteMemoryManager(std::unique_ptr<RCMemoryManager> &MM) {
- assert(!MM && "MemoryManager should be null before creation.");
-
+ Expected<std::unique_ptr<RemoteRTDyldMemoryManager>>
+ createRemoteMemoryManager() {
auto Id = AllocatorIds.getNext();
- if (auto Err = callB<CreateRemoteAllocator>(Id))
- return Err;
- MM = llvm::make_unique<RCMemoryManager>(*this, Id);
- return Error::success();
+ if (auto Err = callB<mem::CreateRemoteAllocator>(Id))
+ return std::move(Err);
+ return std::unique_ptr<RemoteRTDyldMemoryManager>(
+ new RemoteRTDyldMemoryManager(*this, Id));
}
/// Create an RCIndirectStubsManager that will allocate stubs on the remote
/// target.
- Error createIndirectStubsManager(std::unique_ptr<RCIndirectStubsManager> &I) {
- assert(!I && "Indirect stubs manager should be null before creation.");
+ Expected<std::unique_ptr<RemoteIndirectStubsManager>>
+ createIndirectStubsManager() {
auto Id = IndirectStubOwnerIds.getNext();
- if (auto Err = callB<CreateIndirectStubsOwner>(Id))
- return Err;
- I = llvm::make_unique<RCIndirectStubsManager>(*this, Id);
- return Error::success();
+ if (auto Err = callB<stubs::CreateIndirectStubsOwner>(Id))
+ return std::move(Err);
+ return llvm::make_unique<RemoteIndirectStubsManager>(*this, Id);
}
- Expected<RCCompileCallbackManager &>
+ Expected<RemoteCompileCallbackManager &>
enableCompileCallbacks(JITTargetAddress 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 = callB<EmitResolverBlock>())
+ if (auto Err = callB<stubs::EmitResolverBlock>())
return std::move(Err);
// Create the callback manager.
- CallbackManager.emplace(ErrorHandlerAddress, *this);
- RCCompileCallbackManager &Mgr = *CallbackManager;
+ CallbackManager.emplace(*this, ErrorHandlerAddress);
+ RemoteCompileCallbackManager &Mgr = *CallbackManager;
return Mgr;
}
@@ -643,45 +545,43 @@ public:
/// symbol resolvers *after* they've searched the local symbol table in the
/// JIT stack.
Expected<JITTargetAddress> getSymbolAddress(StringRef Name) {
- // Check for an 'out-of-band' error, e.g. from an MM destructor.
- if (ExistingError)
- return std::move(ExistingError);
-
- return callB<GetSymbolAddress>(Name);
+ return callB<utils::GetSymbolAddress>(Name);
}
/// Get the triple for the remote target.
const std::string &getTargetTriple() const { return RemoteTargetTriple; }
- Error terminateSession() { return callB<TerminateSession>(); }
+ Error terminateSession() { return callB<utils::TerminateSession>(); }
private:
- OrcRemoteTargetClient(ChannelT &Channel, Error &Err)
- : OrcRemoteTargetRPCAPI(Channel) {
+ OrcRemoteTargetClient(rpc::RawByteChannel &Channel,
+ std::function<void(Error)> ReportError, Error &Err)
+ : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
+ ReportError(std::move(ReportError)) {
ErrorAsOutParameter EAO(&Err);
- addHandler<RequestCompile>(
+ addHandler<utils::RequestCompile>(
[this](JITTargetAddress Addr) -> JITTargetAddress {
if (CallbackManager)
return CallbackManager->executeCompileCallback(Addr);
return 0;
});
- if (auto RIOrErr = callB<GetRemoteInfo>()) {
+ if (auto RIOrErr = callB<utils::GetRemoteInfo>()) {
std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
Err = Error::success();
- } else {
- Err = joinErrors(RIOrErr.takeError(), std::move(ExistingError));
- }
+ } else
+ Err = RIOrErr.takeError();
}
- Error deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
- return callB<RegisterEHFrames>(Addr, Size);
+ void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
+ if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
+ ReportError(std::move(Err));
}
void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
- if (auto Err = callB<DestroyRemoteAllocator>(Id)) {
+ if (auto Err = callB<mem::DestroyRemoteAllocator>(Id)) {
// FIXME: This will be triggered by a removeModuleSet call: Propagate
// error return up through that.
llvm_unreachable("Failed to destroy remote allocator.");
@@ -689,22 +589,19 @@ private:
}
}
- Error destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
+ void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
IndirectStubOwnerIds.release(Id);
- return callB<DestroyIndirectStubsOwner>(Id);
+ if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
+ ReportError(std::move(Err));
}
Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
emitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) {
- return callB<EmitIndirectStubs>(Id, NumStubsRequired);
+ return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired);
}
Expected<std::tuple<JITTargetAddress, uint32_t>> emitTrampolineBlock() {
- // Check for an 'out-of-band' error, e.g. from an MM destructor.
- if (ExistingError)
- return std::move(ExistingError);
-
- return callB<EmitTrampolineBlock>();
+ return callB<stubs::EmitTrampolineBlock>();
}
uint32_t getIndirectStubSize() const { return RemoteIndirectStubSize; }
@@ -713,59 +610,57 @@ private:
uint32_t getTrampolineSize() const { return RemoteTrampolineSize; }
- Expected<std::vector<char>> readMem(char *Dst, JITTargetAddress Src,
- uint64_t Size) {
- // Check for an 'out-of-band' error, e.g. from an MM destructor.
- if (ExistingError)
- return std::move(ExistingError);
-
- return callB<ReadMem>(Src, Size);
+ Expected<std::vector<uint8_t>> readMem(char *Dst, JITTargetAddress Src,
+ uint64_t Size) {
+ return callB<mem::ReadMem>(Src, Size);
}
Error registerEHFrames(JITTargetAddress &RAddr, uint32_t Size) {
- return callB<RegisterEHFrames>(RAddr, Size);
+ // FIXME: Duplicate error and report it via ReportError too?
+ return callB<eh::RegisterEHFrames>(RAddr, Size);
}
- Expected<JITTargetAddress> 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 std::move(ExistingError);
-
- return callB<ReserveMem>(Id, Size, Align);
+ JITTargetAddress reserveMem(ResourceIdMgr::ResourceId Id, uint64_t Size,
+ uint32_t Align) {
+ if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
+ return *AddrOrErr;
+ else {
+ ReportError(AddrOrErr.takeError());
+ return 0;
+ }
}
- Error setProtections(ResourceIdMgr::ResourceId Id,
- JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
- return callB<SetProtections>(Id, RemoteSegAddr, ProtFlags);
+ bool setProtections(ResourceIdMgr::ResourceId Id,
+ JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
+ if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
+ ReportError(std::move(Err));
+ return true;
+ } else
+ return false;
}
- Error writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
- // Check for an 'out-of-band' error, e.g. from an MM destructor.
- if (ExistingError)
- return std::move(ExistingError);
-
- return callB<WriteMem>(DirectBufferWriter(Src, Addr, Size));
+ bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
+ if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) {
+ ReportError(std::move(Err));
+ return true;
+ } else
+ return false;
}
Error writePointer(JITTargetAddress Addr, JITTargetAddress PtrVal) {
- // Check for an 'out-of-band' error, e.g. from an MM destructor.
- if (ExistingError)
- return std::move(ExistingError);
-
- return callB<WritePtr>(Addr, PtrVal);
+ return callB<mem::WritePtr>(Addr, PtrVal);
}
static Error doNothing() { return Error::success(); }
- Error ExistingError = Error::success();
+ std::function<void(Error)> ReportError;
std::string RemoteTargetTriple;
uint32_t RemotePointerSize = 0;
uint32_t RemotePageSize = 0;
uint32_t RemoteTrampolineSize = 0;
uint32_t RemoteIndirectStubSize = 0;
ResourceIdMgr AllocatorIds, IndirectStubOwnerIds;
- Optional<RCCompileCallbackManager> CallbackManager;
+ Optional<RemoteCompileCallbackManager> CallbackManager;
};
} // end namespace remote
diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
index 07ae7f04d1a0..bc0da0f9a730 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h
@@ -25,6 +25,37 @@ namespace orc {
namespace remote {
+/// Template error for missing resources.
+template <typename ResourceIdT>
+class ResourceNotFound
+ : public ErrorInfo<ResourceNotFound<ResourceIdT>> {
+public:
+ static char ID;
+
+ ResourceNotFound(ResourceIdT ResourceId,
+ std::string ResourceDescription = "")
+ : ResourceId(std::move(ResourceId)),
+ ResourceDescription(std::move(ResourceDescription)) {}
+
+ std::error_code convertToErrorCode() const override {
+ return orcError(OrcErrorCode::UnknownResourceHandle);
+ }
+
+ void log(raw_ostream &OS) const override {
+ OS << (ResourceDescription.empty()
+ ? "Remote resource with id "
+ : ResourceDescription)
+ << " " << ResourceId << " not found";
+ }
+
+private:
+ ResourceIdT ResourceId;
+ std::string ResourceDescription;
+};
+
+template <typename ResourceIdT>
+char ResourceNotFound<ResourceIdT>::ID = 0;
+
class DirectBufferWriter {
public:
DirectBufferWriter() = default;
@@ -45,6 +76,32 @@ private:
namespace rpc {
+template <>
+class RPCTypeName<JITSymbolFlags> {
+public:
+ static const char *getName() { return "JITSymbolFlags"; }
+};
+
+template <typename ChannelT>
+class SerializationTraits<ChannelT, JITSymbolFlags> {
+public:
+
+ static Error serialize(ChannelT &C, const JITSymbolFlags &Flags) {
+ return serializeSeq(C, static_cast<JITSymbolFlags::UnderlyingType>(Flags),
+ Flags.getTargetFlags());
+ }
+
+ static Error deserialize(ChannelT &C, JITSymbolFlags &Flags) {
+ JITSymbolFlags::UnderlyingType JITFlags;
+ JITSymbolFlags::TargetFlagsType TargetFlags;
+ if (auto Err = deserializeSeq(C, JITFlags, TargetFlags))
+ return Err;
+ Flags = JITSymbolFlags(static_cast<JITSymbolFlags::FlagNames>(JITFlags),
+ TargetFlags);
+ return Error::success();
+ }
+};
+
template <> class RPCTypeName<remote::DirectBufferWriter> {
public:
static const char *getName() { return "DirectBufferWriter"; }
@@ -83,41 +140,66 @@ public:
namespace remote {
-class OrcRemoteTargetRPCAPI
- : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
-protected:
- class ResourceIdMgr {
- public:
- using ResourceId = uint64_t;
- static const ResourceId InvalidId = ~0U;
-
- ResourceId getNext() {
- if (!FreeIds.empty()) {
- ResourceId I = FreeIds.back();
- FreeIds.pop_back();
- return I;
- }
- return NextId++;
+class ResourceIdMgr {
+public:
+ using ResourceId = uint64_t;
+ static const ResourceId InvalidId = ~0U;
+
+ ResourceIdMgr() = default;
+ explicit ResourceIdMgr(ResourceId FirstValidId)
+ : NextId(std::move(FirstValidId)) {}
+
+ ResourceId getNext() {
+ if (!FreeIds.empty()) {
+ ResourceId I = FreeIds.back();
+ FreeIds.pop_back();
+ return I;
}
+ assert(NextId + 1 != ~0ULL && "All ids allocated");
+ return NextId++;
+ }
+
+ void release(ResourceId I) { FreeIds.push_back(I); }
+
+private:
+ ResourceId NextId = 1;
+ std::vector<ResourceId> FreeIds;
+};
- void release(ResourceId I) { FreeIds.push_back(I); }
+/// Registers EH frames on the remote.
+namespace eh {
- private:
- ResourceId NextId = 0;
- std::vector<ResourceId> FreeIds;
+ /// Registers EH frames on the remote.
+ class RegisterEHFrames
+ : public rpc::Function<RegisterEHFrames,
+ void(JITTargetAddress Addr, uint32_t Size)> {
+ public:
+ static const char *getName() { return "RegisterEHFrames"; }
};
-public:
- // FIXME: Remove constructors once MSVC supports synthesizing move-ops.
- OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C)
- : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(C, true) {}
+ /// Deregisters EH frames on the remote.
+ class DeregisterEHFrames
+ : public rpc::Function<DeregisterEHFrames,
+ void(JITTargetAddress Addr, uint32_t Size)> {
+ public:
+ static const char *getName() { return "DeregisterEHFrames"; }
+ };
+
+} // end namespace eh
+
+/// RPC functions for executing remote code.
+namespace exec {
+ /// Call an 'int32_t()'-type function on the remote, returns the called
+ /// function's return value.
class CallIntVoid
: public rpc::Function<CallIntVoid, int32_t(JITTargetAddress Addr)> {
public:
static const char *getName() { return "CallIntVoid"; }
};
+ /// Call an 'int32_t(int32_t, char**)'-type function on the remote, returns the
+ /// called function's return value.
class CallMain
: public rpc::Function<CallMain, int32_t(JITTargetAddress Addr,
std::vector<std::string> Args)> {
@@ -125,12 +207,20 @@ public:
static const char *getName() { return "CallMain"; }
};
+ /// Calls a 'void()'-type function on the remote, returns when the called
+ /// function completes.
class CallVoidVoid
: public rpc::Function<CallVoidVoid, void(JITTargetAddress FnAddr)> {
public:
static const char *getName() { return "CallVoidVoid"; }
};
+} // end namespace exec
+
+/// RPC functions for remote memory management / inspection / modification.
+namespace mem {
+
+ /// Creates a memory allocator on the remote.
class CreateRemoteAllocator
: public rpc::Function<CreateRemoteAllocator,
void(ResourceIdMgr::ResourceId AllocatorID)> {
@@ -138,27 +228,68 @@ public:
static const char *getName() { return "CreateRemoteAllocator"; }
};
- class CreateIndirectStubsOwner
- : public rpc::Function<CreateIndirectStubsOwner,
- void(ResourceIdMgr::ResourceId StubOwnerID)> {
+ /// Destroys a remote allocator, freeing any memory allocated by it.
+ class DestroyRemoteAllocator
+ : public rpc::Function<DestroyRemoteAllocator,
+ void(ResourceIdMgr::ResourceId AllocatorID)> {
public:
- static const char *getName() { return "CreateIndirectStubsOwner"; }
+ static const char *getName() { return "DestroyRemoteAllocator"; }
};
- class DeregisterEHFrames
- : public rpc::Function<DeregisterEHFrames,
- void(JITTargetAddress Addr, uint32_t Size)> {
+ /// Read a remote memory block.
+ class ReadMem
+ : public rpc::Function<ReadMem, std::vector<uint8_t>(JITTargetAddress Src,
+ uint64_t Size)> {
public:
- static const char *getName() { return "DeregisterEHFrames"; }
+ static const char *getName() { return "ReadMem"; }
};
- class DestroyRemoteAllocator
- : public rpc::Function<DestroyRemoteAllocator,
- void(ResourceIdMgr::ResourceId AllocatorID)> {
+ /// Reserve a block of memory on the remote via the given allocator.
+ class ReserveMem
+ : public rpc::Function<ReserveMem,
+ JITTargetAddress(ResourceIdMgr::ResourceId AllocID,
+ uint64_t Size, uint32_t Align)> {
public:
- static const char *getName() { return "DestroyRemoteAllocator"; }
+ static const char *getName() { return "ReserveMem"; }
+ };
+
+ /// Set the memory protection on a memory block.
+ class SetProtections
+ : public rpc::Function<SetProtections,
+ void(ResourceIdMgr::ResourceId AllocID,
+ JITTargetAddress Dst, uint32_t ProtFlags)> {
+ public:
+ static const char *getName() { return "SetProtections"; }
+ };
+
+ /// Write to a remote memory block.
+ class WriteMem
+ : public rpc::Function<WriteMem, void(remote::DirectBufferWriter DB)> {
+ public:
+ static const char *getName() { return "WriteMem"; }
+ };
+
+ /// Write to a remote pointer.
+ class WritePtr : public rpc::Function<WritePtr, void(JITTargetAddress Dst,
+ JITTargetAddress Val)> {
+ public:
+ static const char *getName() { return "WritePtr"; }
+ };
+
+} // end namespace mem
+
+/// RPC functions for remote stub and trampoline management.
+namespace stubs {
+
+ /// Creates an indirect stub owner on the remote.
+ class CreateIndirectStubsOwner
+ : public rpc::Function<CreateIndirectStubsOwner,
+ void(ResourceIdMgr::ResourceId StubOwnerID)> {
+ public:
+ static const char *getName() { return "CreateIndirectStubsOwner"; }
};
+ /// RPC function for destroying an indirect stubs owner.
class DestroyIndirectStubsOwner
: public rpc::Function<DestroyIndirectStubsOwner,
void(ResourceIdMgr::ResourceId StubsOwnerID)> {
@@ -177,6 +308,7 @@ public:
static const char *getName() { return "EmitIndirectStubs"; }
};
+ /// RPC function to emit the resolver block and return its address.
class EmitResolverBlock : public rpc::Function<EmitResolverBlock, void()> {
public:
static const char *getName() { return "EmitResolverBlock"; }
@@ -190,12 +322,10 @@ public:
static const char *getName() { return "EmitTrampolineBlock"; }
};
- class GetSymbolAddress
- : public rpc::Function<GetSymbolAddress,
- JITTargetAddress(std::string SymbolName)> {
- public:
- static const char *getName() { return "GetSymbolAddress"; }
- };
+} // end namespace stubs
+
+/// Miscelaneous RPC functions for dealing with remotes.
+namespace utils {
/// GetRemoteInfo result is (Triple, PointerSize, PageSize, TrampolineSize,
/// IndirectStubsSize).
@@ -207,28 +337,15 @@ public:
static const char *getName() { return "GetRemoteInfo"; }
};
- class ReadMem
- : public rpc::Function<ReadMem, std::vector<uint8_t>(JITTargetAddress Src,
- uint64_t Size)> {
- public:
- static const char *getName() { return "ReadMem"; }
- };
-
- class RegisterEHFrames
- : public rpc::Function<RegisterEHFrames,
- void(JITTargetAddress Addr, uint32_t Size)> {
- public:
- static const char *getName() { return "RegisterEHFrames"; }
- };
-
- class ReserveMem
- : public rpc::Function<ReserveMem,
- JITTargetAddress(ResourceIdMgr::ResourceId AllocID,
- uint64_t Size, uint32_t Align)> {
+ /// Get the address of a remote symbol.
+ class GetSymbolAddress
+ : public rpc::Function<GetSymbolAddress,
+ JITTargetAddress(std::string SymbolName)> {
public:
- static const char *getName() { return "ReserveMem"; }
+ static const char *getName() { return "GetSymbolAddress"; }
};
+ /// Request that the host execute a compile callback.
class RequestCompile
: public rpc::Function<
RequestCompile, JITTargetAddress(JITTargetAddress TrampolineAddr)> {
@@ -236,30 +353,20 @@ public:
static const char *getName() { return "RequestCompile"; }
};
- class SetProtections
- : public rpc::Function<SetProtections,
- void(ResourceIdMgr::ResourceId AllocID,
- JITTargetAddress Dst, uint32_t ProtFlags)> {
- public:
- static const char *getName() { return "SetProtections"; }
- };
-
+ /// Notify the remote and terminate the session.
class TerminateSession : public rpc::Function<TerminateSession, void()> {
public:
static const char *getName() { return "TerminateSession"; }
};
- class WriteMem
- : public rpc::Function<WriteMem, void(remote::DirectBufferWriter DB)> {
- public:
- static const char *getName() { return "WriteMem"; }
- };
+} // namespace utils
- class WritePtr : public rpc::Function<WritePtr, void(JITTargetAddress Dst,
- JITTargetAddress Val)> {
- public:
- static const char *getName() { return "WritePtr"; }
- };
+class OrcRemoteTargetRPCAPI
+ : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
+public:
+ // FIXME: Remove constructors once MSVC supports synthesizing move-ops.
+ OrcRemoteTargetRPCAPI(rpc::RawByteChannel &C)
+ : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(C, true) {}
};
} // end namespace remote
diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
index e7b6d64931b6..cf419d33004c 100644
--- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
+++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
@@ -45,7 +45,8 @@ namespace orc {
namespace remote {
template <typename ChannelT, typename TargetT>
-class OrcRemoteTargetServer : public OrcRemoteTargetRPCAPI {
+class OrcRemoteTargetServer
+ : public rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel> {
public:
using SymbolLookupFtor =
std::function<JITTargetAddress(const std::string &Name)>;
@@ -56,34 +57,38 @@ public:
OrcRemoteTargetServer(ChannelT &Channel, SymbolLookupFtor SymbolLookup,
EHFrameRegistrationFtor EHFramesRegister,
EHFrameRegistrationFtor EHFramesDeregister)
- : OrcRemoteTargetRPCAPI(Channel), SymbolLookup(std::move(SymbolLookup)),
+ : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
+ SymbolLookup(std::move(SymbolLookup)),
EHFramesRegister(std::move(EHFramesRegister)),
EHFramesDeregister(std::move(EHFramesDeregister)) {
using ThisT = typename std::remove_reference<decltype(*this)>::type;
- addHandler<CallIntVoid>(*this, &ThisT::handleCallIntVoid);
- addHandler<CallMain>(*this, &ThisT::handleCallMain);
- addHandler<CallVoidVoid>(*this, &ThisT::handleCallVoidVoid);
- addHandler<CreateRemoteAllocator>(*this,
- &ThisT::handleCreateRemoteAllocator);
- addHandler<CreateIndirectStubsOwner>(
+ addHandler<exec::CallIntVoid>(*this, &ThisT::handleCallIntVoid);
+ addHandler<exec::CallMain>(*this, &ThisT::handleCallMain);
+ addHandler<exec::CallVoidVoid>(*this, &ThisT::handleCallVoidVoid);
+ addHandler<mem::CreateRemoteAllocator>(*this,
+ &ThisT::handleCreateRemoteAllocator);
+ addHandler<mem::DestroyRemoteAllocator>(
+ *this, &ThisT::handleDestroyRemoteAllocator);
+ addHandler<mem::ReadMem>(*this, &ThisT::handleReadMem);
+ addHandler<mem::ReserveMem>(*this, &ThisT::handleReserveMem);
+ addHandler<mem::SetProtections>(*this, &ThisT::handleSetProtections);
+ addHandler<mem::WriteMem>(*this, &ThisT::handleWriteMem);
+ addHandler<mem::WritePtr>(*this, &ThisT::handleWritePtr);
+ addHandler<eh::RegisterEHFrames>(*this, &ThisT::handleRegisterEHFrames);
+ addHandler<eh::DeregisterEHFrames>(*this, &ThisT::handleDeregisterEHFrames);
+ addHandler<stubs::CreateIndirectStubsOwner>(
*this, &ThisT::handleCreateIndirectStubsOwner);
- addHandler<DeregisterEHFrames>(*this, &ThisT::handleDeregisterEHFrames);
- addHandler<DestroyRemoteAllocator>(*this,
- &ThisT::handleDestroyRemoteAllocator);
- addHandler<DestroyIndirectStubsOwner>(
+ addHandler<stubs::DestroyIndirectStubsOwner>(
*this, &ThisT::handleDestroyIndirectStubsOwner);
- addHandler<EmitIndirectStubs>(*this, &ThisT::handleEmitIndirectStubs);
- addHandler<EmitResolverBlock>(*this, &ThisT::handleEmitResolverBlock);
- addHandler<EmitTrampolineBlock>(*this, &ThisT::handleEmitTrampolineBlock);
- addHandler<GetSymbolAddress>(*this, &ThisT::handleGetSymbolAddress);
- addHandler<GetRemoteInfo>(*this, &ThisT::handleGetRemoteInfo);
- addHandler<ReadMem>(*this, &ThisT::handleReadMem);
- addHandler<RegisterEHFrames>(*this, &ThisT::handleRegisterEHFrames);
- addHandler<ReserveMem>(*this, &ThisT::handleReserveMem);
- addHandler<SetProtections>(*this, &ThisT::handleSetProtections);
- addHandler<TerminateSession>(*this, &ThisT::handleTerminateSession);
- addHandler<WriteMem>(*this, &ThisT::handleWriteMem);
- addHandler<WritePtr>(*this, &ThisT::handleWritePtr);
+ addHandler<stubs::EmitIndirectStubs>(*this,
+ &ThisT::handleEmitIndirectStubs);
+ addHandler<stubs::EmitResolverBlock>(*this,
+ &ThisT::handleEmitResolverBlock);
+ addHandler<stubs::EmitTrampolineBlock>(*this,
+ &ThisT::handleEmitTrampolineBlock);
+ addHandler<utils::GetSymbolAddress>(*this, &ThisT::handleGetSymbolAddress);
+ addHandler<utils::GetRemoteInfo>(*this, &ThisT::handleGetRemoteInfo);
+ addHandler<utils::TerminateSession>(*this, &ThisT::handleTerminateSession);
}
// FIXME: Remove move/copy ops once MSVC supports synthesizing move ops.
@@ -94,7 +99,7 @@ public:
OrcRemoteTargetServer &operator=(OrcRemoteTargetServer &&) = delete;
Expected<JITTargetAddress> requestCompile(JITTargetAddress TrampolineAddr) {
- return callB<RequestCompile>(TrampolineAddr);
+ return callB<utils::RequestCompile>(TrampolineAddr);
}
bool receivedTerminate() const { return TerminateFlag; }
diff --git a/include/llvm/ExecutionEngine/Orc/RPCSerialization.h b/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
index 1cb2448a3a44..569c50602f3a 100644
--- a/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
+++ b/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
@@ -361,13 +361,13 @@ public:
std::lock_guard<std::recursive_mutex> Lock(SerializersMutex);
// FIXME: Move capture Serialize once we have C++14.
Serializers[ErrorInfoT::classID()] =
- [KeyName, Serialize](ChannelT &C, const ErrorInfoBase &EIB) -> Error {
- assert(EIB.dynamicClassID() == ErrorInfoT::classID() &&
- "Serializer called for wrong error type");
- if (auto Err = serializeSeq(C, *KeyName))
- return Err;
- return Serialize(C, static_cast<const ErrorInfoT&>(EIB));
- };
+ [KeyName, Serialize](ChannelT &C, const ErrorInfoBase &EIB) -> Error {
+ assert(EIB.dynamicClassID() == ErrorInfoT::classID() &&
+ "Serializer called for wrong error type");
+ if (auto Err = serializeSeq(C, *KeyName))
+ return Err;
+ return Serialize(C, static_cast<const ErrorInfoT &>(EIB));
+ };
}
}
diff --git a/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/include/llvm/ExecutionEngine/Orc/RPCUtils.h
index 6212f64ff319..c278cb176853 100644
--- a/include/llvm/ExecutionEngine/Orc/RPCUtils.h
+++ b/include/llvm/ExecutionEngine/Orc/RPCUtils.h
@@ -534,6 +534,20 @@ public:
using ResultType = Error;
};
+template <typename... ArgTs>
+class AsyncHandlerTraits<ErrorSuccess(std::function<Error(Error)>, ArgTs...)> {
+public:
+ using Type = Error(ArgTs...);
+ using ResultType = Error;
+};
+
+template <typename... ArgTs>
+class AsyncHandlerTraits<void(std::function<Error(Error)>, ArgTs...)> {
+public:
+ using Type = Error(ArgTs...);
+ using ResultType = Error;
+};
+
template <typename ResponseHandlerT, typename... ArgTs>
class AsyncHandlerTraits<Error(ResponseHandlerT, ArgTs...)> :
public AsyncHandlerTraits<Error(typename std::decay<ResponseHandlerT>::type,
diff --git a/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
index e1016ef95f0c..246c57341f35 100644
--- a/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
@@ -41,9 +41,9 @@ public:
protected:
- /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
+ /// @brief Holds an object to be allocated/linked as a unit in the JIT.
///
- /// An instance of this class will be created for each set of objects added
+ /// An instance of this class will be created for each object added
/// via JITObjectLayer::addObject. Deleting the instance (via
/// removeObject) frees its memory, removing all symbol definitions that
/// had been provided by this instance. Higher level layers are responsible
@@ -83,7 +83,7 @@ protected:
using LinkedObjectListT = std::list<std::unique_ptr<LinkedObject>>;
public:
- /// @brief Handle to a set of loaded objects.
+ /// @brief Handle to a loaded object.
using ObjHandleT = LinkedObjectListT::iterator;
};
@@ -99,8 +99,9 @@ public:
using RTDyldObjectLinkingLayerBase::ObjectPtr;
/// @brief Functor for receiving object-loaded notifications.
- using NotifyLoadedFtor = std::function<void(ObjHandleT, const ObjectPtr &Obj,
- const LoadedObjectInfo &)>;
+ using NotifyLoadedFtor =
+ std::function<void(ObjHandleT, const ObjectPtr &Obj,
+ const RuntimeDyld::LoadedObjectInfo &)>;
/// @brief Functor for receiving finalization notifications.
using NotifyFinalizedFtor = std::function<void(ObjHandleT)>;
@@ -253,10 +254,9 @@ public:
this->ProcessAllSections = ProcessAllSections;
}
- /// @brief Add a set of objects (or archives) that will be treated as a unit
- /// for the purposes of symbol lookup and memory management.
+ /// @brief Add an object to the JIT.
///
- /// @return A handle that can be used to refer to the loaded objects (for
+ /// @return A handle that can be used to refer to the loaded object (for
/// symbol searching, finalization, freeing memory, etc.).
Expected<ObjHandleT> addObject(ObjectPtr Obj,
std::shared_ptr<JITSymbolResolver> Resolver) {
@@ -291,10 +291,10 @@ public:
return Handle;
}
- /// @brief Remove the set of objects associated with handle H.
+ /// @brief Remove the object associated with handle H.
///
- /// All memory allocated for the objects will be freed, and the sections and
- /// symbols they provided will no longer be available. No attempt is made to
+ /// All memory allocated for the object will be freed, and the sections and
+ /// symbols it provided will no longer be available. No attempt is made to
/// re-emit the missing symbols, and any use of these symbols (directly or
/// indirectly) will result in undefined behavior. If dependence tracking is
/// required to detect or resolve such issues it should be added at a higher
@@ -318,27 +318,27 @@ public:
return nullptr;
}
- /// @brief Search for the given named symbol in the context of the set of
- /// loaded objects represented by the handle H.
- /// @param H The handle for the object set to search in.
+ /// @brief Search for the given named symbol in the context of the loaded
+ /// object represented by the handle H.
+ /// @param H The handle for the object to search in.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it is found in the
- /// given object set.
+ /// given object.
JITSymbol findSymbolIn(ObjHandleT H, StringRef Name,
bool ExportedSymbolsOnly) {
return (*H)->getSymbol(Name, ExportedSymbolsOnly);
}
- /// @brief Map section addresses for the objects associated with the handle H.
+ /// @brief Map section addresses for the object associated with the handle H.
void mapSectionAddress(ObjHandleT H, const void *LocalAddress,
JITTargetAddress TargetAddr) {
(*H)->mapSectionAddress(LocalAddress, TargetAddr);
}
- /// @brief Immediately emit and finalize the object set represented by the
- /// given handle.
- /// @param H Handle for object set to emit/finalize.
+ /// @brief Immediately emit and finalize the object represented by the given
+ /// handle.
+ /// @param H Handle for object to emit/finalize.
Error emitAndFinalize(ObjHandleT H) {
(*H)->finalize();
return Error::success();
diff --git a/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h b/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
new file mode 100644
index 000000000000..17255954a99f
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
@@ -0,0 +1,538 @@
+//===------ RemoteObjectLayer.h - Forwards objs to a remote -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Forwards objects to a remote object layer via RPC.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
+
+#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
+#include <map>
+
+namespace llvm {
+namespace orc {
+
+/// RPC API needed by RemoteObjectClientLayer and RemoteObjectServerLayer.
+class RemoteObjectLayerAPI {
+public:
+
+ using ObjHandleT = remote::ResourceIdMgr::ResourceId;
+
+protected:
+
+ using RemoteSymbolId = remote::ResourceIdMgr::ResourceId;
+ using RemoteSymbol = std::pair<RemoteSymbolId, JITSymbolFlags>;
+
+public:
+
+ using BadSymbolHandleError = remote::ResourceNotFound<RemoteSymbolId>;
+ using BadObjectHandleError = remote::ResourceNotFound<ObjHandleT>;
+
+protected:
+
+ static const ObjHandleT InvalidObjectHandleId = 0;
+ static const RemoteSymbolId NullSymbolId = 0;
+
+ class AddObject
+ : public rpc::Function<AddObject, Expected<ObjHandleT>(std::string)> {
+ public:
+ static const char *getName() { return "AddObject"; }
+ };
+
+ class RemoveObject
+ : public rpc::Function<RemoveObject, Error(ObjHandleT)> {
+ public:
+ static const char *getName() { return "RemoveObject"; }
+ };
+
+ class FindSymbol
+ : public rpc::Function<FindSymbol, Expected<RemoteSymbol>(std::string,
+ bool)> {
+ public:
+ static const char *getName() { return "FindSymbol"; }
+ };
+
+ class FindSymbolIn
+ : public rpc::Function<FindSymbolIn,
+ Expected<RemoteSymbol>(ObjHandleT, std::string,
+ bool)> {
+ public:
+ static const char *getName() { return "FindSymbolIn"; }
+ };
+
+ class EmitAndFinalize
+ : public rpc::Function<EmitAndFinalize,
+ Error(ObjHandleT)> {
+ public:
+ static const char *getName() { return "EmitAndFinalize"; }
+ };
+
+ class Lookup
+ : public rpc::Function<Lookup,
+ Expected<RemoteSymbol>(ObjHandleT, std::string)> {
+ public:
+ static const char *getName() { return "Lookup"; }
+ };
+
+ class LookupInLogicalDylib
+ : public rpc::Function<LookupInLogicalDylib,
+ Expected<RemoteSymbol>(ObjHandleT, std::string)> {
+ public:
+ static const char *getName() { return "LookupInLogicalDylib"; }
+ };
+
+ class ReleaseRemoteSymbol
+ : public rpc::Function<ReleaseRemoteSymbol, Error(RemoteSymbolId)> {
+ public:
+ static const char *getName() { return "ReleaseRemoteSymbol"; }
+ };
+
+ class MaterializeRemoteSymbol
+ : public rpc::Function<MaterializeRemoteSymbol,
+ Expected<JITTargetAddress>(RemoteSymbolId)> {
+ public:
+ static const char *getName() { return "MaterializeRemoteSymbol"; }
+ };
+};
+
+/// Base class containing common utilities for RemoteObjectClientLayer and
+/// RemoteObjectServerLayer.
+template <typename RPCEndpoint>
+class RemoteObjectLayer : public RemoteObjectLayerAPI {
+public:
+
+ RemoteObjectLayer(RPCEndpoint &Remote,
+ std::function<void(Error)> ReportError)
+ : Remote(Remote), ReportError(std::move(ReportError)),
+ SymbolIdMgr(NullSymbolId + 1) {
+ using ThisT = RemoteObjectLayer<RPCEndpoint>;
+ Remote.template addHandler<ReleaseRemoteSymbol>(
+ *this, &ThisT::handleReleaseRemoteSymbol);
+ Remote.template addHandler<MaterializeRemoteSymbol>(
+ *this, &ThisT::handleMaterializeRemoteSymbol);
+ }
+
+protected:
+
+ /// This class is used as the symbol materializer for JITSymbols returned by
+ /// RemoteObjectLayerClient/RemoteObjectLayerServer -- the materializer knows
+ /// how to call back to the other RPC endpoint to get the address when
+ /// requested.
+ class RemoteSymbolMaterializer {
+ public:
+
+ /// Construct a RemoteSymbolMaterializer for the given RemoteObjectLayer
+ /// with the given Id.
+ RemoteSymbolMaterializer(RemoteObjectLayer &C,
+ RemoteSymbolId Id)
+ : C(C), Id(Id) {}
+
+ RemoteSymbolMaterializer(const RemoteSymbolMaterializer &Other)
+ : C(Other.C), Id(Other.Id) {
+ // FIXME: This is a horrible, auto_ptr-style, copy-as-move operation.
+ // It should be removed as soon as LLVM has C++14's generalized
+ // lambda capture (at which point the materializer can be moved
+ // into the lambda in remoteToJITSymbol below).
+ const_cast<RemoteSymbolMaterializer&>(Other).Id = 0;
+ }
+
+ RemoteSymbolMaterializer&
+ operator=(const RemoteSymbolMaterializer&) = delete;
+
+ /// Release the remote symbol.
+ ~RemoteSymbolMaterializer() {
+ if (Id)
+ C.releaseRemoteSymbol(Id);
+ }
+
+ /// Materialize the symbol on the remote and get its address.
+ Expected<JITTargetAddress> materialize() {
+ auto Addr = C.materializeRemoteSymbol(Id);
+ Id = 0;
+ return Addr;
+ }
+
+ private:
+ RemoteObjectLayer &C;
+ RemoteSymbolId Id;
+ };
+
+ /// Convenience function for getting a null remote symbol value.
+ RemoteSymbol nullRemoteSymbol() {
+ return RemoteSymbol(0, JITSymbolFlags());
+ }
+
+ /// Creates a StringError that contains a copy of Err's log message, then
+ /// sends that StringError to ReportError.
+ ///
+ /// This allows us to locally log error messages for errors that will actually
+ /// be delivered to the remote.
+ Error teeLog(Error Err) {
+ return handleErrors(std::move(Err),
+ [this](std::unique_ptr<ErrorInfoBase> EIB) {
+ ReportError(make_error<StringError>(
+ EIB->message(),
+ EIB->convertToErrorCode()));
+ return Error(std::move(EIB));
+ });
+ }
+
+ Error badRemoteSymbolIdError(RemoteSymbolId Id) {
+ return make_error<BadSymbolHandleError>(Id, "Remote JIT Symbol");
+ }
+
+ Error badObjectHandleError(ObjHandleT H) {
+ return make_error<RemoteObjectLayerAPI::BadObjectHandleError>(
+ H, "Bad object handle");
+ }
+
+ /// Create a RemoteSymbol wrapping the given JITSymbol.
+ Expected<RemoteSymbol> jitSymbolToRemote(JITSymbol Sym) {
+ if (Sym) {
+ auto Id = SymbolIdMgr.getNext();
+ auto Flags = Sym.getFlags();
+ assert(!InUseSymbols.count(Id) && "Symbol id already in use");
+ InUseSymbols.insert(std::make_pair(Id, std::move(Sym)));
+ return RemoteSymbol(Id, Flags);
+ } else if (auto Err = Sym.takeError())
+ return teeLog(std::move(Err));
+ // else...
+ return nullRemoteSymbol();
+ }
+
+ /// Convert an Expected<RemoteSymbol> to a JITSymbol.
+ JITSymbol remoteToJITSymbol(Expected<RemoteSymbol> RemoteSymOrErr) {
+ if (RemoteSymOrErr) {
+ auto &RemoteSym = *RemoteSymOrErr;
+ if (RemoteSym == nullRemoteSymbol())
+ return nullptr;
+ // else...
+ RemoteSymbolMaterializer RSM(*this, RemoteSym.first);
+ auto Sym =
+ JITSymbol([RSM]() mutable { return RSM.materialize(); },
+ RemoteSym.second);
+ return Sym;
+ } else
+ return RemoteSymOrErr.takeError();
+ }
+
+ RPCEndpoint &Remote;
+ std::function<void(Error)> ReportError;
+
+private:
+
+ /// Notify the remote to release the given JITSymbol.
+ void releaseRemoteSymbol(RemoteSymbolId Id) {
+ if (auto Err = Remote.template callB<ReleaseRemoteSymbol>(Id))
+ ReportError(std::move(Err));
+ }
+
+ /// Notify the remote to materialize the JITSymbol with the given Id and
+ /// return its address.
+ Expected<JITTargetAddress> materializeRemoteSymbol(RemoteSymbolId Id) {
+ return Remote.template callB<MaterializeRemoteSymbol>(Id);
+ }
+
+ /// Release the JITSymbol with the given Id.
+ Error handleReleaseRemoteSymbol(RemoteSymbolId Id) {
+ auto SI = InUseSymbols.find(Id);
+ if (SI != InUseSymbols.end()) {
+ InUseSymbols.erase(SI);
+ return Error::success();
+ } else
+ return teeLog(badRemoteSymbolIdError(Id));
+ }
+
+ /// Run the materializer for the JITSymbol with the given Id and return its
+ /// address.
+ Expected<JITTargetAddress> handleMaterializeRemoteSymbol(RemoteSymbolId Id) {
+ auto SI = InUseSymbols.find(Id);
+ if (SI != InUseSymbols.end()) {
+ auto AddrOrErr = SI->second.getAddress();
+ InUseSymbols.erase(SI);
+ SymbolIdMgr.release(Id);
+ if (AddrOrErr)
+ return *AddrOrErr;
+ else
+ return teeLog(AddrOrErr.takeError());
+ } else {
+ return teeLog(badRemoteSymbolIdError(Id));
+ }
+ }
+
+ remote::ResourceIdMgr SymbolIdMgr;
+ std::map<RemoteSymbolId, JITSymbol> InUseSymbols;
+};
+
+/// RemoteObjectClientLayer forwards the ORC Object Layer API over an RPC
+/// connection.
+///
+/// This class can be used as the base layer of a JIT stack on the client and
+/// will forward operations to a corresponding RemoteObjectServerLayer on the
+/// server (which can be composed on top of a "real" object layer like
+/// RTDyldObjectLinkingLayer to actually carry out the operations).
+///
+/// Sending relocatable objects to the server (rather than fully relocated
+/// bits) allows JIT'd code to be cached on the server side and re-used in
+/// subsequent JIT sessions.
+template <typename RPCEndpoint>
+class RemoteObjectClientLayer : public RemoteObjectLayer<RPCEndpoint> {
+private:
+
+ using AddObject = RemoteObjectLayerAPI::AddObject;
+ using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
+ using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
+ using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
+ using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
+ using Lookup = RemoteObjectLayerAPI::Lookup;
+ using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;
+
+ using RemoteObjectLayer<RPCEndpoint>::teeLog;
+ using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
+ using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;
+
+public:
+
+ using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
+ using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
+
+ using ObjectPtr =
+ std::shared_ptr<object::OwningBinary<object::ObjectFile>>;
+
+ /// Create a RemoteObjectClientLayer that communicates with a
+ /// RemoteObjectServerLayer instance via the given RPCEndpoint.
+ ///
+ /// The ReportError functor can be used locally log errors that are intended
+ /// to be sent sent
+ RemoteObjectClientLayer(RPCEndpoint &Remote,
+ std::function<void(Error)> ReportError)
+ : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {
+ using ThisT = RemoteObjectClientLayer<RPCEndpoint>;
+ Remote.template addHandler<Lookup>(*this, &ThisT::lookup);
+ Remote.template addHandler<LookupInLogicalDylib>(
+ *this, &ThisT::lookupInLogicalDylib);
+ }
+
+ /// @brief Add an object to the JIT.
+ ///
+ /// @return A handle that can be used to refer to the loaded object (for
+ /// symbol searching, finalization, freeing memory, etc.).
+ Expected<ObjHandleT>
+ addObject(ObjectPtr Object, std::shared_ptr<JITSymbolResolver> Resolver) {
+ StringRef ObjBuffer = Object->getBinary()->getData();
+ if (auto HandleOrErr =
+ this->Remote.template callB<AddObject>(ObjBuffer)) {
+ auto &Handle = *HandleOrErr;
+ // FIXME: Return an error for this:
+ assert(!Resolvers.count(Handle) && "Handle already in use?");
+ Resolvers[Handle] = std::move(Resolver);
+ return Handle;
+ } else
+ return HandleOrErr.takeError();
+ }
+
+ /// @brief Remove the given object from the JIT.
+ Error removeObject(ObjHandleT H) {
+ return this->Remote.template callB<RemoveObject>(H);
+ }
+
+ /// @brief Search for the given named symbol.
+ JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
+ return remoteToJITSymbol(
+ this->Remote.template callB<FindSymbol>(Name,
+ ExportedSymbolsOnly));
+ }
+
+ /// @brief Search for the given named symbol within the given context.
+ JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) {
+ return remoteToJITSymbol(
+ this->Remote.template callB<FindSymbolIn>(H, Name,
+ ExportedSymbolsOnly));
+ }
+
+ /// @brief Immediately emit and finalize the object with the given handle.
+ Error emitAndFinalize(ObjHandleT H) {
+ return this->Remote.template callB<EmitAndFinalize>(H);
+ }
+
+private:
+
+ Expected<RemoteSymbol> lookup(ObjHandleT H, const std::string &Name) {
+ auto RI = Resolvers.find(H);
+ if (RI != Resolvers.end()) {
+ return this->jitSymbolToRemote(RI->second->findSymbol(Name));
+ } else
+ return teeLog(badObjectHandleError(H));
+ }
+
+ Expected<RemoteSymbol> lookupInLogicalDylib(ObjHandleT H,
+ const std::string &Name) {
+ auto RI = Resolvers.find(H);
+ if (RI != Resolvers.end())
+ return this->jitSymbolToRemote(
+ RI->second->findSymbolInLogicalDylib(Name));
+ else
+ return teeLog(badObjectHandleError(H));
+ }
+
+ std::map<remote::ResourceIdMgr::ResourceId,
+ std::shared_ptr<JITSymbolResolver>> Resolvers;
+};
+
+/// RemoteObjectServerLayer acts as a server and handling RPC calls for the
+/// object layer API from the given RPC connection.
+///
+/// This class can be composed on top of a 'real' object layer (e.g.
+/// RTDyldObjectLinkingLayer) to do the actual work of relocating objects
+/// and making them executable.
+template <typename BaseLayerT, typename RPCEndpoint>
+class RemoteObjectServerLayer : public RemoteObjectLayer<RPCEndpoint> {
+private:
+
+ using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
+ using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
+
+ using AddObject = RemoteObjectLayerAPI::AddObject;
+ using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
+ using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
+ using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
+ using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
+ using Lookup = RemoteObjectLayerAPI::Lookup;
+ using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;
+
+ using RemoteObjectLayer<RPCEndpoint>::teeLog;
+ using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
+ using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;
+
+public:
+
+ /// Create a RemoteObjectServerLayer with the given base layer (which must be
+ /// an object layer), RPC endpoint, and error reporter function.
+ RemoteObjectServerLayer(BaseLayerT &BaseLayer,
+ RPCEndpoint &Remote,
+ std::function<void(Error)> ReportError)
+ : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),
+ BaseLayer(BaseLayer), HandleIdMgr(1) {
+ using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>;
+
+ Remote.template addHandler<AddObject>(*this, &ThisT::addObject);
+ Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject);
+ Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol);
+ Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn);
+ Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize);
+ }
+
+private:
+
+ class StringMemoryBuffer : public MemoryBuffer {
+ public:
+ StringMemoryBuffer(std::string Buffer)
+ : Buffer(std::move(Buffer)) {
+ init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(),
+ false);
+ }
+
+ BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
+ private:
+ std::string Buffer;
+ };
+
+ JITSymbol lookup(ObjHandleT Id, const std::string &Name) {
+ return remoteToJITSymbol(
+ this->Remote.template callB<Lookup>(Id, Name));
+ }
+
+ JITSymbol lookupInLogicalDylib(ObjHandleT Id, const std::string &Name) {
+ return remoteToJITSymbol(
+ this->Remote.template callB<LookupInLogicalDylib>(Id, Name));
+ }
+
+ Expected<ObjHandleT> addObject(std::string ObjBuffer) {
+ auto Buffer = llvm::make_unique<StringMemoryBuffer>(std::move(ObjBuffer));
+ if (auto ObjectOrErr =
+ object::ObjectFile::createObjectFile(Buffer->getMemBufferRef())) {
+ auto Object =
+ std::make_shared<object::OwningBinary<object::ObjectFile>>(
+ std::move(*ObjectOrErr), std::move(Buffer));
+
+ auto Id = HandleIdMgr.getNext();
+ assert(!BaseLayerHandles.count(Id) && "Id already in use?");
+
+ auto Resolver =
+ createLambdaResolver(
+ [this, Id](const std::string &Name) { return lookup(Id, Name); },
+ [this, Id](const std::string &Name) {
+ return lookupInLogicalDylib(Id, Name);
+ });
+
+ if (auto HandleOrErr =
+ BaseLayer.addObject(std::move(Object), std::move(Resolver))) {
+ BaseLayerHandles[Id] = std::move(*HandleOrErr);
+ return Id;
+ } else
+ return teeLog(HandleOrErr.takeError());
+ } else
+ return teeLog(ObjectOrErr.takeError());
+ }
+
+ Error removeObject(ObjHandleT H) {
+ auto HI = BaseLayerHandles.find(H);
+ if (HI != BaseLayerHandles.end()) {
+ if (auto Err = BaseLayer.removeObject(HI->second))
+ return teeLog(std::move(Err));
+ return Error::success();
+ } else
+ return teeLog(badObjectHandleError(H));
+ }
+
+ Expected<RemoteSymbol> findSymbol(const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ if (auto Sym = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
+ return this->jitSymbolToRemote(std::move(Sym));
+ else if (auto Err = Sym.takeError())
+ return teeLog(std::move(Err));
+ return this->nullRemoteSymbol();
+ }
+
+ Expected<RemoteSymbol> findSymbolIn(ObjHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ auto HI = BaseLayerHandles.find(H);
+ if (HI != BaseLayerHandles.end()) {
+ if (auto Sym = BaseLayer.findSymbolIn(HI->second, Name, ExportedSymbolsOnly))
+ return this->jitSymbolToRemote(std::move(Sym));
+ else if (auto Err = Sym.takeError())
+ return teeLog(std::move(Err));
+ return this->nullRemoteSymbol();
+ } else
+ return teeLog(badObjectHandleError(H));
+ }
+
+ Error emitAndFinalize(ObjHandleT H) {
+ auto HI = BaseLayerHandles.find(H);
+ if (HI != BaseLayerHandles.end()) {
+ if (auto Err = BaseLayer.emitAndFinalize(HI->second))
+ return teeLog(std::move(Err));
+ return Error::success();
+ } else
+ return teeLog(badObjectHandleError(H));
+ }
+
+ BaseLayerT &BaseLayer;
+ remote::ResourceIdMgr HandleIdMgr;
+ std::map<ObjHandleT, typename BaseLayerT::ObjHandleT> BaseLayerHandles;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
diff --git a/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
new file mode 100644
index 000000000000..b01fbd44bacd
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
@@ -0,0 +1,136 @@
+//===- SymbolStringPool.h - Multi-threaded pool for JIT symbols -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains a multi-threaded string pool suitable for use with ORC.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
+#define LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
+
+#include "llvm/ADT/StringMap.h"
+#include <atomic>
+#include <mutex>
+
+namespace llvm {
+namespace orc {
+
+class SymbolStringPtr;
+
+/// @brief String pool for symbol names used by the JIT.
+class SymbolStringPool {
+ friend class SymbolStringPtr;
+public:
+ /// @brief Create a symbol string pointer from the given string.
+ SymbolStringPtr intern(StringRef S);
+
+ /// @brief Remove from the pool any entries that are no longer referenced.
+ void clearDeadEntries();
+
+ /// @brief Returns true if the pool is empty.
+ bool empty() const;
+private:
+ using RefCountType = std::atomic<uint64_t>;
+ using PoolMap = StringMap<RefCountType>;
+ using PoolMapEntry = StringMapEntry<RefCountType>;
+ mutable std::mutex PoolMutex;
+ PoolMap Pool;
+};
+
+/// @brief Pointer to a pooled string representing a symbol name.
+class SymbolStringPtr {
+ friend class SymbolStringPool;
+public:
+ SymbolStringPtr() = default;
+ SymbolStringPtr(const SymbolStringPtr &Other)
+ : S(Other.S) {
+ if (S)
+ ++S->getValue();
+ }
+
+ SymbolStringPtr& operator=(const SymbolStringPtr &Other) {
+ if (S)
+ --S->getValue();
+ S = Other.S;
+ if (S)
+ ++S->getValue();
+ return *this;
+ }
+
+ SymbolStringPtr(SymbolStringPtr &&Other) : S(nullptr) {
+ std::swap(S, Other.S);
+ }
+
+ SymbolStringPtr& operator=(SymbolStringPtr &&Other) {
+ if (S)
+ --S->getValue();
+ S = nullptr;
+ std::swap(S, Other.S);
+ return *this;
+ }
+
+ ~SymbolStringPtr() {
+ if (S)
+ --S->getValue();
+ }
+
+ bool operator==(const SymbolStringPtr &Other) const {
+ return S == Other.S;
+ }
+
+ bool operator!=(const SymbolStringPtr &Other) const {
+ return !(*this == Other);
+ }
+
+ bool operator<(const SymbolStringPtr &Other) const {
+ return S->getValue() < Other.S->getValue();
+ }
+
+private:
+
+ SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
+ : S(S) {
+ if (S)
+ ++S->getValue();
+ }
+
+ SymbolStringPool::PoolMapEntry *S = nullptr;
+};
+
+inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
+ std::lock_guard<std::mutex> Lock(PoolMutex);
+ auto I = Pool.find(S);
+ if (I != Pool.end())
+ return SymbolStringPtr(&*I);
+
+ bool Added;
+ std::tie(I, Added) = Pool.try_emplace(S, 0);
+ assert(Added && "Insert should always succeed here");
+ return SymbolStringPtr(&*I);
+}
+
+inline void SymbolStringPool::clearDeadEntries() {
+ std::lock_guard<std::mutex> Lock(PoolMutex);
+ for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
+ auto Tmp = std::next(I);
+ if (I->second == 0)
+ Pool.erase(I);
+ I = Tmp;
+ }
+}
+
+inline bool SymbolStringPool::empty() const {
+ std::lock_guard<std::mutex> Lock(PoolMutex);
+ return Pool.empty();
+}
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h
index 3b2af11cdaf4..d76e37113c66 100644
--- a/include/llvm/ExecutionEngine/SectionMemoryManager.h
+++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h
@@ -40,9 +40,75 @@ namespace llvm {
/// directly. Clients of MCJIT should call MCJIT::finalizeObject.
class SectionMemoryManager : public RTDyldMemoryManager {
public:
- SectionMemoryManager() = default;
- SectionMemoryManager(const SectionMemoryManager&) = delete;
- void operator=(const SectionMemoryManager&) = delete;
+ /// This enum describes the various reasons to allocate pages from
+ /// allocateMappedMemory.
+ enum class AllocationPurpose {
+ Code,
+ ROData,
+ RWData,
+ };
+
+ /// Implementations of this interface are used by SectionMemoryManager to
+ /// request pages from the operating system.
+ class MemoryMapper {
+ public:
+ /// This method attempts to allocate \p NumBytes bytes of virtual memory for
+ /// \p Purpose. \p NearBlock may point to an existing allocation, in which
+ /// case an attempt is made to allocate more memory near the existing block.
+ /// The actual allocated address is not guaranteed to be near the requested
+ /// address. \p Flags is used to set the initial protection flags for the
+ /// block of the memory. \p EC [out] returns an object describing any error
+ /// that occurs.
+ ///
+ /// This method may allocate more than the number of bytes requested. The
+ /// actual number of bytes allocated is indicated in the returned
+ /// MemoryBlock.
+ ///
+ /// The start of the allocated block must be aligned with the system
+ /// allocation granularity (64K on Windows, page size on Linux). If the
+ /// address following \p NearBlock is not so aligned, it will be rounded up
+ /// to the next allocation granularity boundary.
+ ///
+ /// \r a non-null MemoryBlock if the function was successful, otherwise a
+ /// null MemoryBlock with \p EC describing the error.
+ virtual sys::MemoryBlock
+ allocateMappedMemory(AllocationPurpose Purpose, size_t NumBytes,
+ const sys::MemoryBlock *const NearBlock,
+ unsigned Flags, std::error_code &EC) = 0;
+
+ /// This method sets the protection flags for a block of memory to the state
+ /// specified by \p Flags. The behavior is not specified if the memory was
+ /// not allocated using the allocateMappedMemory method.
+ /// \p Block describes the memory block to be protected.
+ /// \p Flags specifies the new protection state to be assigned to the block.
+ ///
+ /// If \p Flags is MF_WRITE, the actual behavior varies with the operating
+ /// system (i.e. MF_READ | MF_WRITE on Windows) and the target architecture
+ /// (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
+ ///
+ /// \r error_success if the function was successful, or an error_code
+ /// describing the failure if an error occurred.
+ virtual std::error_code protectMappedMemory(const sys::MemoryBlock &Block,
+ unsigned Flags) = 0;
+
+ /// This method releases a block of memory that was allocated with the
+ /// allocateMappedMemory method. It should not be used to release any memory
+ /// block allocated any other way.
+ /// \p Block describes the memory to be released.
+ ///
+ /// \r error_success if the function was successful, or an error_code
+ /// describing the failure if an error occurred.
+ virtual std::error_code releaseMappedMemory(sys::MemoryBlock &M) = 0;
+
+ virtual ~MemoryMapper();
+ };
+
+ /// Creates a SectionMemoryManager instance with \p MM as the associated
+ /// memory mapper. If \p MM is nullptr then a default memory mapper is used
+ /// that directly calls into the operating system.
+ SectionMemoryManager(MemoryMapper *MM = nullptr);
+ SectionMemoryManager(const SectionMemoryManager &) = delete;
+ void operator=(const SectionMemoryManager &) = delete;
~SectionMemoryManager() override;
/// \brief Allocates a memory block of (at least) the given size suitable for
@@ -110,7 +176,7 @@ private:
sys::MemoryBlock Near;
};
- uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size,
+ uint8_t *allocateSection(AllocationPurpose Purpose, uintptr_t Size,
unsigned Alignment);
std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
@@ -119,6 +185,7 @@ private:
MemoryGroup CodeMem;
MemoryGroup RWDataMem;
MemoryGroup RODataMem;
+ MemoryMapper &MMapper;
};
} // end namespace llvm