diff options
Diffstat (limited to 'include/llvm/ExecutionEngine')
| -rw-r--r-- | include/llvm/ExecutionEngine/ExecutionEngine.h | 7 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/JITSymbol.h | 43 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h | 35 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h | 11 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/IndirectionUtils.h | 32 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/OrcError.h | 3 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h | 483 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h | 263 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h | 55 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/RPCSerialization.h | 14 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/RPCUtils.h | 14 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h | 38 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h | 538 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/Orc/SymbolStringPool.h | 136 | ||||
| -rw-r--r-- | include/llvm/ExecutionEngine/SectionMemoryManager.h | 75 | 
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 | 
