1fe6060f1SDimitry Andric //===------ ExecutorAddress.h - Executing process address -------*- C++ -*-===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric // 9fe6060f1SDimitry Andric // Represents an address in the executing program. 10fe6060f1SDimitry Andric // 11fe6060f1SDimitry Andric // This file was derived from 12fe6060f1SDimitry Andric // llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h. 13fe6060f1SDimitry Andric // 14fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 15fe6060f1SDimitry Andric 16fe6060f1SDimitry Andric #ifndef ORC_RT_EXECUTOR_ADDRESS_H 17fe6060f1SDimitry Andric #define ORC_RT_EXECUTOR_ADDRESS_H 18fe6060f1SDimitry Andric 19fe6060f1SDimitry Andric #include "adt.h" 20fe6060f1SDimitry Andric #include "simple_packed_serialization.h" 21fe6060f1SDimitry Andric 22fe6060f1SDimitry Andric #include <cassert> 23fe6060f1SDimitry Andric #include <type_traits> 24fe6060f1SDimitry Andric 25fe6060f1SDimitry Andric namespace __orc_rt { 26fe6060f1SDimitry Andric 27*bdd1243dSDimitry Andric using ExecutorAddrDiff = uint64_t; 28fe6060f1SDimitry Andric 29fe6060f1SDimitry Andric /// Represents an address in the executor process. 30349cc55cSDimitry Andric class ExecutorAddr { 31fe6060f1SDimitry Andric public: 32*bdd1243dSDimitry Andric /// A wrap/unwrap function that leaves pointers unmodified. 33*bdd1243dSDimitry Andric template <typename T> using rawPtr = __orc_rt::identity<T *>; 34*bdd1243dSDimitry Andric 35*bdd1243dSDimitry Andric /// Default wrap function to use on this host. 36*bdd1243dSDimitry Andric template <typename T> using defaultWrap = rawPtr<T>; 37*bdd1243dSDimitry Andric 38*bdd1243dSDimitry Andric /// Default unwrap function to use on this host. 39*bdd1243dSDimitry Andric template <typename T> using defaultUnwrap = rawPtr<T>; 40*bdd1243dSDimitry Andric 41*bdd1243dSDimitry Andric /// Merges a tag into the raw address value: 42*bdd1243dSDimitry Andric /// P' = P | (TagValue << TagOffset). 43*bdd1243dSDimitry Andric class Tag { 44*bdd1243dSDimitry Andric public: Tag(uintptr_t TagValue,uintptr_t TagOffset)45*bdd1243dSDimitry Andric constexpr Tag(uintptr_t TagValue, uintptr_t TagOffset) 46*bdd1243dSDimitry Andric : TagMask(TagValue << TagOffset) {} 47*bdd1243dSDimitry Andric operator()48*bdd1243dSDimitry Andric template <typename T> constexpr T *operator()(T *P) { 49*bdd1243dSDimitry Andric return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) | TagMask); 50*bdd1243dSDimitry Andric } 51*bdd1243dSDimitry Andric 52*bdd1243dSDimitry Andric private: 53*bdd1243dSDimitry Andric uintptr_t TagMask; 54*bdd1243dSDimitry Andric }; 55*bdd1243dSDimitry Andric 56*bdd1243dSDimitry Andric /// Strips a tag of the given length from the given offset within the pointer: 57*bdd1243dSDimitry Andric /// P' = P & ~(((1 << TagLen) -1) << TagOffset) 58*bdd1243dSDimitry Andric class Untag { 59*bdd1243dSDimitry Andric public: Untag(uintptr_t TagLen,uintptr_t TagOffset)60*bdd1243dSDimitry Andric constexpr Untag(uintptr_t TagLen, uintptr_t TagOffset) 61*bdd1243dSDimitry Andric : UntagMask(~(((uintptr_t(1) << TagLen) - 1) << TagOffset)) {} 62*bdd1243dSDimitry Andric operator()63*bdd1243dSDimitry Andric template <typename T> constexpr T *operator()(T *P) { 64*bdd1243dSDimitry Andric return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) & UntagMask); 65*bdd1243dSDimitry Andric } 66*bdd1243dSDimitry Andric 67*bdd1243dSDimitry Andric private: 68*bdd1243dSDimitry Andric uintptr_t UntagMask; 69*bdd1243dSDimitry Andric }; 70*bdd1243dSDimitry Andric 71349cc55cSDimitry Andric ExecutorAddr() = default; ExecutorAddr(uint64_t Addr)72349cc55cSDimitry Andric explicit ExecutorAddr(uint64_t Addr) : Addr(Addr) {} 73fe6060f1SDimitry Andric 74349cc55cSDimitry Andric /// Create an ExecutorAddr from the given pointer. 75*bdd1243dSDimitry Andric template <typename T, typename UnwrapFn = defaultUnwrap<T>> 76*bdd1243dSDimitry Andric static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap = UnwrapFn()) { 77349cc55cSDimitry Andric return ExecutorAddr( 78*bdd1243dSDimitry Andric static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Unwrap(Ptr)))); 79fe6060f1SDimitry Andric } 80fe6060f1SDimitry Andric 81349cc55cSDimitry Andric /// Cast this ExecutorAddr to a pointer of the given type. 82*bdd1243dSDimitry Andric template <typename T, typename WrapFn = defaultWrap<std::remove_pointer_t<T>>> 83*bdd1243dSDimitry Andric std::enable_if_t<std::is_pointer<T>::value, T> 84*bdd1243dSDimitry Andric toPtr(WrapFn &&Wrap = WrapFn()) const { 85fe6060f1SDimitry Andric uintptr_t IntPtr = static_cast<uintptr_t>(Addr); 86*bdd1243dSDimitry Andric assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t"); 87*bdd1243dSDimitry Andric return Wrap(reinterpret_cast<T>(IntPtr)); 88*bdd1243dSDimitry Andric } 89*bdd1243dSDimitry Andric 90*bdd1243dSDimitry Andric /// Cast this ExecutorAddr to a pointer of the given function type. 91*bdd1243dSDimitry Andric template <typename T, typename WrapFn = defaultWrap<T>> 92*bdd1243dSDimitry Andric std::enable_if_t<std::is_function<T>::value, T *> 93*bdd1243dSDimitry Andric toPtr(WrapFn &&Wrap = WrapFn()) const { 94*bdd1243dSDimitry Andric uintptr_t IntPtr = static_cast<uintptr_t>(Addr); 95*bdd1243dSDimitry Andric assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t"); 96*bdd1243dSDimitry Andric return Wrap(reinterpret_cast<T *>(IntPtr)); 97fe6060f1SDimitry Andric } 98fe6060f1SDimitry Andric getValue()99fe6060f1SDimitry Andric uint64_t getValue() const { return Addr; } setValue(uint64_t Addr)100fe6060f1SDimitry Andric void setValue(uint64_t Addr) { this->Addr = Addr; } isNull()101fe6060f1SDimitry Andric bool isNull() const { return Addr == 0; } 102fe6060f1SDimitry Andric 103fe6060f1SDimitry Andric explicit operator bool() const { return Addr != 0; } 104fe6060f1SDimitry Andric 105349cc55cSDimitry Andric friend bool operator==(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 106fe6060f1SDimitry Andric return LHS.Addr == RHS.Addr; 107fe6060f1SDimitry Andric } 108fe6060f1SDimitry Andric 109349cc55cSDimitry Andric friend bool operator!=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 110fe6060f1SDimitry Andric return LHS.Addr != RHS.Addr; 111fe6060f1SDimitry Andric } 112fe6060f1SDimitry Andric 113349cc55cSDimitry Andric friend bool operator<(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 114fe6060f1SDimitry Andric return LHS.Addr < RHS.Addr; 115fe6060f1SDimitry Andric } 116fe6060f1SDimitry Andric 117349cc55cSDimitry Andric friend bool operator<=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 118fe6060f1SDimitry Andric return LHS.Addr <= RHS.Addr; 119fe6060f1SDimitry Andric } 120fe6060f1SDimitry Andric 121349cc55cSDimitry Andric friend bool operator>(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 122fe6060f1SDimitry Andric return LHS.Addr > RHS.Addr; 123fe6060f1SDimitry Andric } 124fe6060f1SDimitry Andric 125349cc55cSDimitry Andric friend bool operator>=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 126fe6060f1SDimitry Andric return LHS.Addr >= RHS.Addr; 127fe6060f1SDimitry Andric } 128fe6060f1SDimitry Andric 129349cc55cSDimitry Andric ExecutorAddr &operator++() { 130fe6060f1SDimitry Andric ++Addr; 131fe6060f1SDimitry Andric return *this; 132fe6060f1SDimitry Andric } 133349cc55cSDimitry Andric ExecutorAddr &operator--() { 134fe6060f1SDimitry Andric --Addr; 135fe6060f1SDimitry Andric return *this; 136fe6060f1SDimitry Andric } 137349cc55cSDimitry Andric ExecutorAddr operator++(int) { return ExecutorAddr(Addr++); } 138349cc55cSDimitry Andric ExecutorAddr operator--(int) { return ExecutorAddr(Addr++); } 139fe6060f1SDimitry Andric 140349cc55cSDimitry Andric ExecutorAddr &operator+=(const ExecutorAddrDiff Delta) { 141*bdd1243dSDimitry Andric Addr += Delta; 142fe6060f1SDimitry Andric return *this; 143fe6060f1SDimitry Andric } 144fe6060f1SDimitry Andric 145349cc55cSDimitry Andric ExecutorAddr &operator-=(const ExecutorAddrDiff Delta) { 146*bdd1243dSDimitry Andric Addr -= Delta; 147fe6060f1SDimitry Andric return *this; 148fe6060f1SDimitry Andric } 149fe6060f1SDimitry Andric 150fe6060f1SDimitry Andric private: 151fe6060f1SDimitry Andric uint64_t Addr = 0; 152fe6060f1SDimitry Andric }; 153fe6060f1SDimitry Andric 154fe6060f1SDimitry Andric /// Subtracting two addresses yields an offset. 155349cc55cSDimitry Andric inline ExecutorAddrDiff operator-(const ExecutorAddr &LHS, 156349cc55cSDimitry Andric const ExecutorAddr &RHS) { 157fe6060f1SDimitry Andric return ExecutorAddrDiff(LHS.getValue() - RHS.getValue()); 158fe6060f1SDimitry Andric } 159fe6060f1SDimitry Andric 160fe6060f1SDimitry Andric /// Adding an offset and an address yields an address. 161349cc55cSDimitry Andric inline ExecutorAddr operator+(const ExecutorAddr &LHS, 162fe6060f1SDimitry Andric const ExecutorAddrDiff &RHS) { 163*bdd1243dSDimitry Andric return ExecutorAddr(LHS.getValue() + RHS); 164fe6060f1SDimitry Andric } 165fe6060f1SDimitry Andric 166fe6060f1SDimitry Andric /// Adding an address and an offset yields an address. 167349cc55cSDimitry Andric inline ExecutorAddr operator+(const ExecutorAddrDiff &LHS, 168349cc55cSDimitry Andric const ExecutorAddr &RHS) { 169*bdd1243dSDimitry Andric return ExecutorAddr(LHS + RHS.getValue()); 170fe6060f1SDimitry Andric } 171fe6060f1SDimitry Andric 172fe6060f1SDimitry Andric /// Represents an address range in the exceutor process. 173349cc55cSDimitry Andric struct ExecutorAddrRange { 174349cc55cSDimitry Andric ExecutorAddrRange() = default; ExecutorAddrRangeExecutorAddrRange175349cc55cSDimitry Andric ExecutorAddrRange(ExecutorAddr Start, ExecutorAddr End) 176349cc55cSDimitry Andric : Start(Start), End(End) {} ExecutorAddrRangeExecutorAddrRange177349cc55cSDimitry Andric ExecutorAddrRange(ExecutorAddr Start, ExecutorAddrDiff Size) 178349cc55cSDimitry Andric : Start(Start), End(Start + Size) {} 179fe6060f1SDimitry Andric emptyExecutorAddrRange180349cc55cSDimitry Andric bool empty() const { return Start == End; } sizeExecutorAddrRange181349cc55cSDimitry Andric ExecutorAddrDiff size() const { return End - Start; } 182349cc55cSDimitry Andric 183349cc55cSDimitry Andric friend bool operator==(const ExecutorAddrRange &LHS, 184349cc55cSDimitry Andric const ExecutorAddrRange &RHS) { 185349cc55cSDimitry Andric return LHS.Start == RHS.Start && LHS.End == RHS.End; 186349cc55cSDimitry Andric } 187349cc55cSDimitry Andric friend bool operator!=(const ExecutorAddrRange &LHS, 188349cc55cSDimitry Andric const ExecutorAddrRange &RHS) { 189349cc55cSDimitry Andric return !(LHS == RHS); 190349cc55cSDimitry Andric } containsExecutorAddrRange191349cc55cSDimitry Andric bool contains(ExecutorAddr Addr) const { return Start <= Addr && Addr < End; } overlapsExecutorAddrRange192349cc55cSDimitry Andric bool overlaps(const ExecutorAddrRange &Other) { 193349cc55cSDimitry Andric return !(Other.End <= Start || End <= Other.Start); 194349cc55cSDimitry Andric } 195fe6060f1SDimitry Andric toSpanExecutorAddrRange196fe6060f1SDimitry Andric template <typename T> span<T> toSpan() const { 197*bdd1243dSDimitry Andric assert(size() % sizeof(T) == 0 && 198fe6060f1SDimitry Andric "AddressRange is not a multiple of sizeof(T)"); 199*bdd1243dSDimitry Andric return span<T>(Start.toPtr<T *>(), size() / sizeof(T)); 200fe6060f1SDimitry Andric } 201fe6060f1SDimitry Andric 202349cc55cSDimitry Andric ExecutorAddr Start; 203349cc55cSDimitry Andric ExecutorAddr End; 204fe6060f1SDimitry Andric }; 205fe6060f1SDimitry Andric 206349cc55cSDimitry Andric /// SPS serializatior for ExecutorAddr. 207349cc55cSDimitry Andric template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> { 208fe6060f1SDimitry Andric public: size(const ExecutorAddr & EA)209349cc55cSDimitry Andric static size_t size(const ExecutorAddr &EA) { 210fe6060f1SDimitry Andric return SPSArgList<uint64_t>::size(EA.getValue()); 211fe6060f1SDimitry Andric } 212fe6060f1SDimitry Andric serialize(SPSOutputBuffer & BOB,const ExecutorAddr & EA)213349cc55cSDimitry Andric static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) { 214fe6060f1SDimitry Andric return SPSArgList<uint64_t>::serialize(BOB, EA.getValue()); 215fe6060f1SDimitry Andric } 216fe6060f1SDimitry Andric deserialize(SPSInputBuffer & BIB,ExecutorAddr & EA)217349cc55cSDimitry Andric static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) { 218fe6060f1SDimitry Andric uint64_t Tmp; 219fe6060f1SDimitry Andric if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp)) 220fe6060f1SDimitry Andric return false; 221349cc55cSDimitry Andric EA = ExecutorAddr(Tmp); 222fe6060f1SDimitry Andric return true; 223fe6060f1SDimitry Andric } 224fe6060f1SDimitry Andric }; 225fe6060f1SDimitry Andric 226349cc55cSDimitry Andric using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>; 227fe6060f1SDimitry Andric 228fe6060f1SDimitry Andric /// Serialization traits for address ranges. 229fe6060f1SDimitry Andric template <> 230349cc55cSDimitry Andric class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> { 231fe6060f1SDimitry Andric public: size(const ExecutorAddrRange & Value)232349cc55cSDimitry Andric static size_t size(const ExecutorAddrRange &Value) { 233349cc55cSDimitry Andric return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(Value.Start, 234349cc55cSDimitry Andric Value.End); 235fe6060f1SDimitry Andric } 236fe6060f1SDimitry Andric serialize(SPSOutputBuffer & BOB,const ExecutorAddrRange & Value)237349cc55cSDimitry Andric static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) { 238349cc55cSDimitry Andric return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize( 239349cc55cSDimitry Andric BOB, Value.Start, Value.End); 240fe6060f1SDimitry Andric } 241fe6060f1SDimitry Andric deserialize(SPSInputBuffer & BIB,ExecutorAddrRange & Value)242349cc55cSDimitry Andric static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) { 243349cc55cSDimitry Andric return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize( 244349cc55cSDimitry Andric BIB, Value.Start, Value.End); 245fe6060f1SDimitry Andric } 246fe6060f1SDimitry Andric }; 247fe6060f1SDimitry Andric 248349cc55cSDimitry Andric using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>; 249fe6060f1SDimitry Andric 250fe6060f1SDimitry Andric } // End namespace __orc_rt 251fe6060f1SDimitry Andric 25281ad6265SDimitry Andric namespace std { 25381ad6265SDimitry Andric 25481ad6265SDimitry Andric // Make ExecutorAddr hashable. 25581ad6265SDimitry Andric template <> struct hash<__orc_rt::ExecutorAddr> { 25681ad6265SDimitry Andric size_t operator()(const __orc_rt::ExecutorAddr &A) const { 25781ad6265SDimitry Andric return hash<uint64_t>()(A.getValue()); 25881ad6265SDimitry Andric } 25981ad6265SDimitry Andric }; 26081ad6265SDimitry Andric 26181ad6265SDimitry Andric } // namespace std 26281ad6265SDimitry Andric 263fe6060f1SDimitry Andric #endif // ORC_RT_EXECUTOR_ADDRESS_H 264