From a6848c80344615aeb34eb2f0394218f2d7a647b7 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Fri, 9 Jul 2021 08:24:08 +1000 Subject: [PATCH] [ORC] Flesh out ExecutorAddress, rename CommonOrcRuntimeTypes header. Renames CommonOrcRuntimeTypes.h to ExecutorAddress.h and moves ExecutorAddress into the 'orc' namespace (rather than orc::shared). Also makes ExecutorAddress a class, adds an ExecutorAddrDiff type and some arithmetic operations on the pair (subtracting two addresses yields an addrdiff, adding an addrdiff and an address yields an address). --- .../llvm/ExecutionEngine/Orc/MachOPlatform.h | 16 +- .../Orc/Shared/CommonOrcRuntimeTypes.h | 68 ------ .../Orc/Shared/ExecutorAddress.h | 203 ++++++++++++++++++ lib/ExecutionEngine/Orc/MachOPlatform.cpp | 67 +++--- 4 files changed, 245 insertions(+), 109 deletions(-) delete mode 100644 include/llvm/ExecutionEngine/Orc/Shared/CommonOrcRuntimeTypes.h create mode 100644 include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h diff --git a/include/llvm/ExecutionEngine/Orc/MachOPlatform.h b/include/llvm/ExecutionEngine/Orc/MachOPlatform.h index 9eb2ce33cf8..e708604a19e 100644 --- a/include/llvm/ExecutionEngine/Orc/MachOPlatform.h +++ b/include/llvm/ExecutionEngine/Orc/MachOPlatform.h @@ -17,7 +17,7 @@ #include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" -#include "llvm/ExecutionEngine/Orc/Shared/CommonOrcRuntimeTypes.h" +#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" #include #include @@ -32,13 +32,13 @@ bool objCRegistrationEnabled(); class MachOJITDylibInitializers { public: - using RawPointerSectionList = std::vector; + using RawPointerSectionList = std::vector; void setObjCImageInfoAddr(JITTargetAddress ObjCImageInfoAddr) { this->ObjCImageInfoAddr = ObjCImageInfoAddr; } - void addModInitsSection(shared::ExecutorAddressRange ModInit) { + void addModInitsSection(ExecutorAddressRange ModInit) { ModInitSections.push_back(std::move(ModInit)); } @@ -46,7 +46,7 @@ public: return ModInitSections; } - void addObjCSelRefsSection(shared::ExecutorAddressRange ObjCSelRefs) { + void addObjCSelRefsSection(ExecutorAddressRange ObjCSelRefs) { ObjCSelRefsSections.push_back(std::move(ObjCSelRefs)); } @@ -54,7 +54,7 @@ public: return ObjCSelRefsSections; } - void addObjCClassListSection(shared::ExecutorAddressRange ObjCClassList) { + void addObjCClassListSection(ExecutorAddressRange ObjCClassList) { ObjCClassListSections.push_back(std::move(ObjCClassList)); } @@ -145,9 +145,9 @@ private: }; void registerInitInfo(JITDylib &JD, JITTargetAddress ObjCImageInfoAddr, - shared::ExecutorAddressRange ModInits, - shared::ExecutorAddressRange ObjCSelRefs, - shared::ExecutorAddressRange ObjCClassList); + ExecutorAddressRange ModInits, + ExecutorAddressRange ObjCSelRefs, + ExecutorAddressRange ObjCClassList); ExecutionSession &ES; ObjectLinkingLayer &ObjLinkingLayer; diff --git a/include/llvm/ExecutionEngine/Orc/Shared/CommonOrcRuntimeTypes.h b/include/llvm/ExecutionEngine/Orc/Shared/CommonOrcRuntimeTypes.h deleted file mode 100644 index efc4409b84f..00000000000 --- a/include/llvm/ExecutionEngine/Orc/Shared/CommonOrcRuntimeTypes.h +++ /dev/null @@ -1,68 +0,0 @@ -//===------------------- CommonOrcRuntimeTypes.h ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Generic types usable with SPS and the ORC runtime. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_COMMONORCRUNTIMETYPES_H -#define LLVM_EXECUTIONENGINE_ORC_SHARED_COMMONORCRUNTIMETYPES_H - -#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" - -namespace llvm { -namespace orc { -namespace shared { - -// Placeholder for future replacement for JITTargetAddress. -using ExecutorAddress = uint64_t; - -/// Represents an address range in the exceutor process. -struct ExecutorAddressRange { - ExecutorAddressRange() = default; - ExecutorAddressRange(ExecutorAddress StartAddress, ExecutorAddress EndAddress) - : StartAddress(StartAddress), EndAddress(EndAddress) {} - - bool empty() const { return StartAddress == EndAddress; } - size_t size() const { return EndAddress - StartAddress; } - - ExecutorAddress StartAddress = 0; - ExecutorAddress EndAddress = 0; -}; - -using SPSExecutorAddressRange = - SPSTuple; - -/// Serialization traits for address ranges. -template <> -class SPSSerializationTraits { -public: - static size_t size(const ExecutorAddressRange &Value) { - return SPSArgList::size( - Value.StartAddress, Value.EndAddress); - } - - static bool serialize(SPSOutputBuffer &BOB, - const ExecutorAddressRange &Value) { - return SPSArgList::serialize( - BOB, Value.StartAddress, Value.EndAddress); - } - - static bool deserialize(SPSInputBuffer &BIB, ExecutorAddressRange &Value) { - return SPSArgList::deserialize( - BIB, Value.StartAddress, Value.EndAddress); - } -}; - -using SPSExecutorAddressRangeSequence = SPSSequence; - -} // End namespace shared. -} // End namespace orc. -} // End namespace llvm. - -#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_COMMONORCRUNTIMETYPES_H diff --git a/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h b/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h new file mode 100644 index 00000000000..78a6623d759 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h @@ -0,0 +1,203 @@ +//===------ ExecutorAddress.h - Executing process address -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Represents an address in the executing program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H +#define LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H + +#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" + +#include +#include + +namespace llvm { +namespace orc { + +/// Represents the difference between two addresses in the executor process. +class ExecutorAddrDiff { +public: + ExecutorAddrDiff() = default; + explicit ExecutorAddrDiff(uint64_t Value) : Value(Value) {} + + uint64_t getValue() const { return Value; } + +private: + int64_t Value = 0; +}; + +/// Represents an address in the executor process. +class ExecutorAddress { +public: + ExecutorAddress() = default; + explicit ExecutorAddress(uint64_t Addr) : Addr(Addr) {} + + /// Create an ExecutorAddress from the given pointer. + /// Warning: This should only be used when JITing in-process. + template static ExecutorAddress fromPtr(T *Value) { + return ExecutorAddress( + static_cast(reinterpret_cast(Value))); + } + + /// Cast this ExecutorAddress to a pointer of the given type. + /// Warning: This should only be esude when JITing in-process. + template T toPtr() const { + static_assert(std::is_pointer::value, "T must be a pointer type"); + uintptr_t IntPtr = static_cast(Addr); + assert(IntPtr == Addr && + "JITTargetAddress value out of range for uintptr_t"); + return reinterpret_cast(IntPtr); + } + + uint64_t getValue() const { return Addr; } + void setValue(uint64_t Addr) { this->Addr = Addr; } + bool isNull() const { return Addr == 0; } + + explicit operator bool() const { return Addr != 0; } + + friend bool operator==(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr == RHS.Addr; + } + + friend bool operator!=(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr != RHS.Addr; + } + + friend bool operator<(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr < RHS.Addr; + } + + friend bool operator<=(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr <= RHS.Addr; + } + + friend bool operator>(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr > RHS.Addr; + } + + friend bool operator>=(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return LHS.Addr >= RHS.Addr; + } + + ExecutorAddress &operator++() { + ++Addr; + return *this; + } + ExecutorAddress &operator--() { + --Addr; + return *this; + } + ExecutorAddress operator++(int) { return ExecutorAddress(Addr++); } + ExecutorAddress operator--(int) { return ExecutorAddress(Addr++); } + + ExecutorAddress &operator+=(const ExecutorAddrDiff Delta) { + Addr += Delta.getValue(); + return *this; + } + + ExecutorAddress &operator-=(const ExecutorAddrDiff Delta) { + Addr -= Delta.getValue(); + return *this; + } + +private: + uint64_t Addr = 0; +}; + +/// Subtracting two addresses yields an offset. +inline ExecutorAddrDiff operator-(const ExecutorAddress &LHS, + const ExecutorAddress &RHS) { + return ExecutorAddrDiff(LHS.getValue() - RHS.getValue()); +} + +/// Adding an offset and an address yields an address. +inline ExecutorAddress operator+(const ExecutorAddress &LHS, + const ExecutorAddrDiff &RHS) { + return ExecutorAddress(LHS.getValue() + RHS.getValue()); +} + +/// Adding an address and an offset yields an address. +inline ExecutorAddress operator+(const ExecutorAddrDiff &LHS, + const ExecutorAddress &RHS) { + return ExecutorAddress(LHS.getValue() + RHS.getValue()); +} + +/// Represents an address range in the exceutor process. +struct ExecutorAddressRange { + ExecutorAddressRange() = default; + ExecutorAddressRange(ExecutorAddress StartAddress, ExecutorAddress EndAddress) + : StartAddress(StartAddress), EndAddress(EndAddress) {} + + bool empty() const { return StartAddress == EndAddress; } + ExecutorAddrDiff size() const { return EndAddress - StartAddress; } + + ExecutorAddress StartAddress; + ExecutorAddress EndAddress; +}; + +namespace shared { + +/// SPS serializatior for ExecutorAddress. +template <> class SPSSerializationTraits { +public: + static size_t size(const ExecutorAddress &EA) { + return SPSArgList::size(EA.getValue()); + } + + static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddress &EA) { + return SPSArgList::serialize(BOB, EA.getValue()); + } + + static bool deserialize(SPSInputBuffer &BIB, ExecutorAddress &EA) { + uint64_t Tmp; + if (!SPSArgList::deserialize(BIB, Tmp)) + return false; + EA = ExecutorAddress(Tmp); + return true; + } +}; + +using SPSExecutorAddressRange = + SPSTuple; + +/// Serialization traits for address ranges. +template <> +class SPSSerializationTraits { +public: + static size_t size(const ExecutorAddressRange &Value) { + return SPSArgList::size( + Value.StartAddress, Value.EndAddress); + } + + static bool serialize(SPSOutputBuffer &BOB, + const ExecutorAddressRange &Value) { + return SPSArgList::serialize( + BOB, Value.StartAddress, Value.EndAddress); + } + + static bool deserialize(SPSInputBuffer &BIB, ExecutorAddressRange &Value) { + return SPSArgList::deserialize( + BIB, Value.StartAddress, Value.EndAddress); + } +}; + +using SPSExecutorAddressRangeSequence = SPSSequence; + +} // End namespace shared. +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H diff --git a/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/lib/ExecutionEngine/Orc/MachOPlatform.cpp index 39557a485cf..dd421f91166 100644 --- a/lib/ExecutionEngine/Orc/MachOPlatform.cpp +++ b/lib/ExecutionEngine/Orc/MachOPlatform.cpp @@ -88,13 +88,12 @@ bool objCRegistrationEnabled() { void MachOJITDylibInitializers::runModInits() const { for (const auto &ModInit : ModInitSections) { - assert(ModInit.size() % sizeof(uintptr_t) == 0 && + assert(ModInit.size().getValue() % sizeof(uintptr_t) == 0 && "ModInit section size is not a pointer multiple?"); - for (uintptr_t * - InitPtr = - jitTargetAddressToPointer(ModInit.StartAddress), - *InitEnd = - jitTargetAddressToPointer(ModInit.EndAddress); + for (uintptr_t *InitPtr = jitTargetAddressToPointer( + ModInit.StartAddress.getValue()), + *InitEnd = jitTargetAddressToPointer( + ModInit.EndAddress.getValue()); InitPtr != InitEnd; ++InitPtr) { auto *Initializer = reinterpret_cast(*InitPtr); Initializer(); @@ -106,15 +105,15 @@ void MachOJITDylibInitializers::registerObjCSelectors() const { assert(objCRegistrationEnabled() && "ObjC registration not enabled."); for (const auto &ObjCSelRefs : ObjCSelRefsSections) { - assert(ObjCSelRefs.size() % sizeof(uintptr_t) == 0 && + assert(ObjCSelRefs.size().getValue() % sizeof(uintptr_t) == 0 && "ObjCSelRefs section size is not a pointer multiple?"); - for (JITTargetAddress SelEntryAddr = ObjCSelRefs.StartAddress; + for (auto SelEntryAddr = ObjCSelRefs.StartAddress; SelEntryAddr != ObjCSelRefs.EndAddress; - SelEntryAddr += sizeof(uintptr_t)) { + SelEntryAddr += ExecutorAddrDiff(sizeof(uintptr_t))) { const auto *SelName = - *jitTargetAddressToPointer(SelEntryAddr); + *jitTargetAddressToPointer(SelEntryAddr.getValue()); auto Sel = sel_registerName(SelName); - *jitTargetAddressToPointer(SelEntryAddr) = Sel; + *jitTargetAddressToPointer(SelEntryAddr.getValue()) = Sel; } } } @@ -135,14 +134,13 @@ Error MachOJITDylibInitializers::registerObjCClasses() const { auto ClassSelector = sel_registerName("class"); for (const auto &ObjCClassList : ObjCClassListSections) { - assert(ObjCClassList.size() % sizeof(uintptr_t) == 0 && + assert(ObjCClassList.size().getValue() % sizeof(uintptr_t) == 0 && "ObjCClassList section size is not a pointer multiple?"); - for (JITTargetAddress ClassPtrAddr = ObjCClassList.StartAddress; + for (auto ClassPtrAddr = ObjCClassList.StartAddress; ClassPtrAddr != ObjCClassList.EndAddress; - ClassPtrAddr += sizeof(uintptr_t)) { - auto Cls = *jitTargetAddressToPointer(ClassPtrAddr); - auto *ClassCompiled = - *jitTargetAddressToPointer(ClassPtrAddr); + ClassPtrAddr += ExecutorAddrDiff(sizeof(uintptr_t))) { + auto Cls = *ClassPtrAddr.toPtr(); + auto *ClassCompiled = *ClassPtrAddr.toPtr(); objc_msgSend(reinterpret_cast(ClassCompiled->Parent), ClassSelector); auto Registered = objc_readClassPair(Cls, ImageInfo); @@ -272,11 +270,11 @@ MachOPlatform::getDeinitializerSequence(JITDylib &JD) { return FullDeinitSeq; } -void MachOPlatform::registerInitInfo( - JITDylib &JD, JITTargetAddress ObjCImageInfoAddr, - shared::ExecutorAddressRange ModInits, - shared::ExecutorAddressRange ObjCSelRefs, - shared::ExecutorAddressRange ObjCClassList) { +void MachOPlatform::registerInitInfo(JITDylib &JD, + JITTargetAddress ObjCImageInfoAddr, + ExecutorAddressRange ModInits, + ExecutorAddressRange ObjCSelRefs, + ExecutorAddressRange ObjCClassList) { std::lock_guard Lock(InitSeqsMutex); auto &InitSeq = InitSeqs[&JD]; @@ -293,17 +291,18 @@ void MachOPlatform::registerInitInfo( InitSeq.addObjCClassListSection(std::move(ObjCClassList)); } -static Expected -getSectionExtent(jitlink::LinkGraph &G, StringRef SectionName) { +static Expected getSectionExtent(jitlink::LinkGraph &G, + StringRef SectionName) { auto *Sec = G.findSectionByName(SectionName); if (!Sec) - return shared::ExecutorAddressRange(); + return ExecutorAddressRange(); jitlink::SectionRange R(*Sec); if (R.getSize() % G.getPointerSize() != 0) return make_error(SectionName + " section size is not a " "multiple of the pointer size", inconvertibleErrorCode()); - return shared::ExecutorAddressRange{R.getStart(), R.getEnd()}; + return ExecutorAddressRange(ExecutorAddress(R.getStart()), + ExecutorAddress(R.getEnd())); } void MachOPlatform::InitScraperPlugin::modifyPassConfig( @@ -332,7 +331,7 @@ void MachOPlatform::InitScraperPlugin::modifyPassConfig( Config.PostFixupPasses.push_back([this, &JD = MR.getTargetJITDylib()]( jitlink::LinkGraph &G) -> Error { - shared::ExecutorAddressRange ModInits, ObjCSelRefs, ObjCClassList; + ExecutorAddressRange ModInits, ObjCSelRefs, ObjCClassList; JITTargetAddress ObjCImageInfoAddr = 0; if (auto *ObjCImageInfoSec = @@ -364,26 +363,28 @@ void MachOPlatform::InitScraperPlugin::modifyPassConfig( LLVM_DEBUG({ dbgs() << "MachOPlatform: Scraped " << G.getName() << " init sections:\n"; dbgs() << " __objc_selrefs: "; - auto NumObjCSelRefs = ObjCSelRefs.size() / sizeof(uintptr_t); + auto NumObjCSelRefs = ObjCSelRefs.size().getValue() / sizeof(uintptr_t); if (NumObjCSelRefs) dbgs() << NumObjCSelRefs << " pointer(s) at " - << formatv("{0:x16}", ObjCSelRefs.StartAddress) << "\n"; + << formatv("{0:x16}", ObjCSelRefs.StartAddress.getValue()) + << "\n"; else dbgs() << "none\n"; dbgs() << " __objc_classlist: "; - auto NumObjCClasses = ObjCClassList.size() / sizeof(uintptr_t); + auto NumObjCClasses = ObjCClassList.size().getValue() / sizeof(uintptr_t); if (NumObjCClasses) dbgs() << NumObjCClasses << " pointer(s) at " - << formatv("{0:x16}", ObjCClassList.StartAddress) << "\n"; + << formatv("{0:x16}", ObjCClassList.StartAddress.getValue()) + << "\n"; else dbgs() << "none\n"; dbgs() << " __mod_init_func: "; - auto NumModInits = ModInits.size() / sizeof(uintptr_t); + auto NumModInits = ModInits.size().getValue() / sizeof(uintptr_t); if (NumModInits) dbgs() << NumModInits << " pointer(s) at " - << formatv("{0:x16}", ModInits.StartAddress) << "\n"; + << formatv("{0:x16}", ModInits.StartAddress.getValue()) << "\n"; else dbgs() << "none\n"; });