1d89ec533Spatrick //===------ ExecutorAddress.h - Executing process address -------*- C++ -*-===// 2d89ec533Spatrick // 3d89ec533Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4d89ec533Spatrick // See https://llvm.org/LICENSE.txt for license information. 5d89ec533Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6d89ec533Spatrick // 7d89ec533Spatrick //===----------------------------------------------------------------------===// 8d89ec533Spatrick // 9d89ec533Spatrick // Represents an address in the executing program. 10d89ec533Spatrick // 11d89ec533Spatrick // This file was derived from 12d89ec533Spatrick // llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h. 13d89ec533Spatrick // 14d89ec533Spatrick //===----------------------------------------------------------------------===// 15d89ec533Spatrick 16d89ec533Spatrick #ifndef ORC_RT_EXECUTOR_ADDRESS_H 17d89ec533Spatrick #define ORC_RT_EXECUTOR_ADDRESS_H 18d89ec533Spatrick 19d89ec533Spatrick #include "adt.h" 20d89ec533Spatrick #include "simple_packed_serialization.h" 21d89ec533Spatrick 22d89ec533Spatrick #include <cassert> 23d89ec533Spatrick #include <type_traits> 24d89ec533Spatrick 25d89ec533Spatrick namespace __orc_rt { 26d89ec533Spatrick 27*810390e3Srobert using ExecutorAddrDiff = uint64_t; 28d89ec533Spatrick 29d89ec533Spatrick /// Represents an address in the executor process. 30*810390e3Srobert class ExecutorAddr { 31d89ec533Spatrick public: 32*810390e3Srobert /// A wrap/unwrap function that leaves pointers unmodified. 33*810390e3Srobert template <typename T> using rawPtr = __orc_rt::identity<T *>; 34d89ec533Spatrick 35*810390e3Srobert /// Default wrap function to use on this host. 36*810390e3Srobert template <typename T> using defaultWrap = rawPtr<T>; 37*810390e3Srobert 38*810390e3Srobert /// Default unwrap function to use on this host. 39*810390e3Srobert template <typename T> using defaultUnwrap = rawPtr<T>; 40*810390e3Srobert 41*810390e3Srobert /// Merges a tag into the raw address value: 42*810390e3Srobert /// P' = P | (TagValue << TagOffset). 43*810390e3Srobert class Tag { 44*810390e3Srobert public: Tag(uintptr_t TagValue,uintptr_t TagOffset)45*810390e3Srobert constexpr Tag(uintptr_t TagValue, uintptr_t TagOffset) 46*810390e3Srobert : TagMask(TagValue << TagOffset) {} 47*810390e3Srobert operator()48*810390e3Srobert template <typename T> constexpr T *operator()(T *P) { 49*810390e3Srobert return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) | TagMask); 50d89ec533Spatrick } 51d89ec533Spatrick 52*810390e3Srobert private: 53*810390e3Srobert uintptr_t TagMask; 54*810390e3Srobert }; 55*810390e3Srobert 56*810390e3Srobert /// Strips a tag of the given length from the given offset within the pointer: 57*810390e3Srobert /// P' = P & ~(((1 << TagLen) -1) << TagOffset) 58*810390e3Srobert class Untag { 59*810390e3Srobert public: Untag(uintptr_t TagLen,uintptr_t TagOffset)60*810390e3Srobert constexpr Untag(uintptr_t TagLen, uintptr_t TagOffset) 61*810390e3Srobert : UntagMask(~(((uintptr_t(1) << TagLen) - 1) << TagOffset)) {} 62*810390e3Srobert operator()63*810390e3Srobert template <typename T> constexpr T *operator()(T *P) { 64*810390e3Srobert return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) & UntagMask); 65*810390e3Srobert } 66*810390e3Srobert 67*810390e3Srobert private: 68*810390e3Srobert uintptr_t UntagMask; 69*810390e3Srobert }; 70*810390e3Srobert 71*810390e3Srobert ExecutorAddr() = default; ExecutorAddr(uint64_t Addr)72*810390e3Srobert explicit ExecutorAddr(uint64_t Addr) : Addr(Addr) {} 73*810390e3Srobert 74*810390e3Srobert /// Create an ExecutorAddr from the given pointer. 75*810390e3Srobert template <typename T, typename UnwrapFn = defaultUnwrap<T>> 76*810390e3Srobert static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap = UnwrapFn()) { 77*810390e3Srobert return ExecutorAddr( 78*810390e3Srobert static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Unwrap(Ptr)))); 79*810390e3Srobert } 80*810390e3Srobert 81*810390e3Srobert /// Cast this ExecutorAddr to a pointer of the given type. 82*810390e3Srobert template <typename T, typename WrapFn = defaultWrap<std::remove_pointer_t<T>>> 83*810390e3Srobert std::enable_if_t<std::is_pointer<T>::value, T> 84*810390e3Srobert toPtr(WrapFn &&Wrap = WrapFn()) const { 85d89ec533Spatrick uintptr_t IntPtr = static_cast<uintptr_t>(Addr); 86*810390e3Srobert assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t"); 87*810390e3Srobert return Wrap(reinterpret_cast<T>(IntPtr)); 88*810390e3Srobert } 89*810390e3Srobert 90*810390e3Srobert /// Cast this ExecutorAddr to a pointer of the given function type. 91*810390e3Srobert template <typename T, typename WrapFn = defaultWrap<T>> 92*810390e3Srobert std::enable_if_t<std::is_function<T>::value, T *> 93*810390e3Srobert toPtr(WrapFn &&Wrap = WrapFn()) const { 94*810390e3Srobert uintptr_t IntPtr = static_cast<uintptr_t>(Addr); 95*810390e3Srobert assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t"); 96*810390e3Srobert return Wrap(reinterpret_cast<T *>(IntPtr)); 97d89ec533Spatrick } 98d89ec533Spatrick getValue()99d89ec533Spatrick uint64_t getValue() const { return Addr; } setValue(uint64_t Addr)100d89ec533Spatrick void setValue(uint64_t Addr) { this->Addr = Addr; } isNull()101d89ec533Spatrick bool isNull() const { return Addr == 0; } 102d89ec533Spatrick 103d89ec533Spatrick explicit operator bool() const { return Addr != 0; } 104d89ec533Spatrick 105*810390e3Srobert friend bool operator==(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 106d89ec533Spatrick return LHS.Addr == RHS.Addr; 107d89ec533Spatrick } 108d89ec533Spatrick 109*810390e3Srobert friend bool operator!=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 110d89ec533Spatrick return LHS.Addr != RHS.Addr; 111d89ec533Spatrick } 112d89ec533Spatrick 113*810390e3Srobert friend bool operator<(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 114d89ec533Spatrick return LHS.Addr < RHS.Addr; 115d89ec533Spatrick } 116d89ec533Spatrick 117*810390e3Srobert friend bool operator<=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 118d89ec533Spatrick return LHS.Addr <= RHS.Addr; 119d89ec533Spatrick } 120d89ec533Spatrick 121*810390e3Srobert friend bool operator>(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 122d89ec533Spatrick return LHS.Addr > RHS.Addr; 123d89ec533Spatrick } 124d89ec533Spatrick 125*810390e3Srobert friend bool operator>=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 126d89ec533Spatrick return LHS.Addr >= RHS.Addr; 127d89ec533Spatrick } 128d89ec533Spatrick 129*810390e3Srobert ExecutorAddr &operator++() { 130d89ec533Spatrick ++Addr; 131d89ec533Spatrick return *this; 132d89ec533Spatrick } 133*810390e3Srobert ExecutorAddr &operator--() { 134d89ec533Spatrick --Addr; 135d89ec533Spatrick return *this; 136d89ec533Spatrick } 137*810390e3Srobert ExecutorAddr operator++(int) { return ExecutorAddr(Addr++); } 138*810390e3Srobert ExecutorAddr operator--(int) { return ExecutorAddr(Addr++); } 139d89ec533Spatrick 140*810390e3Srobert ExecutorAddr &operator+=(const ExecutorAddrDiff Delta) { 141*810390e3Srobert Addr += Delta; 142d89ec533Spatrick return *this; 143d89ec533Spatrick } 144d89ec533Spatrick 145*810390e3Srobert ExecutorAddr &operator-=(const ExecutorAddrDiff Delta) { 146*810390e3Srobert Addr -= Delta; 147d89ec533Spatrick return *this; 148d89ec533Spatrick } 149d89ec533Spatrick 150d89ec533Spatrick private: 151d89ec533Spatrick uint64_t Addr = 0; 152d89ec533Spatrick }; 153d89ec533Spatrick 154d89ec533Spatrick /// Subtracting two addresses yields an offset. 155*810390e3Srobert inline ExecutorAddrDiff operator-(const ExecutorAddr &LHS, 156*810390e3Srobert const ExecutorAddr &RHS) { 157d89ec533Spatrick return ExecutorAddrDiff(LHS.getValue() - RHS.getValue()); 158d89ec533Spatrick } 159d89ec533Spatrick 160d89ec533Spatrick /// Adding an offset and an address yields an address. 161*810390e3Srobert inline ExecutorAddr operator+(const ExecutorAddr &LHS, 162d89ec533Spatrick const ExecutorAddrDiff &RHS) { 163*810390e3Srobert return ExecutorAddr(LHS.getValue() + RHS); 164d89ec533Spatrick } 165d89ec533Spatrick 166d89ec533Spatrick /// Adding an address and an offset yields an address. 167*810390e3Srobert inline ExecutorAddr operator+(const ExecutorAddrDiff &LHS, 168*810390e3Srobert const ExecutorAddr &RHS) { 169*810390e3Srobert return ExecutorAddr(LHS + RHS.getValue()); 170d89ec533Spatrick } 171d89ec533Spatrick 172d89ec533Spatrick /// Represents an address range in the exceutor process. 173*810390e3Srobert struct ExecutorAddrRange { 174*810390e3Srobert ExecutorAddrRange() = default; ExecutorAddrRangeExecutorAddrRange175*810390e3Srobert ExecutorAddrRange(ExecutorAddr Start, ExecutorAddr End) 176*810390e3Srobert : Start(Start), End(End) {} ExecutorAddrRangeExecutorAddrRange177*810390e3Srobert ExecutorAddrRange(ExecutorAddr Start, ExecutorAddrDiff Size) 178*810390e3Srobert : Start(Start), End(Start + Size) {} 179d89ec533Spatrick emptyExecutorAddrRange180*810390e3Srobert bool empty() const { return Start == End; } sizeExecutorAddrRange181*810390e3Srobert ExecutorAddrDiff size() const { return End - Start; } 182d89ec533Spatrick 183*810390e3Srobert friend bool operator==(const ExecutorAddrRange &LHS, 184*810390e3Srobert const ExecutorAddrRange &RHS) { 185*810390e3Srobert return LHS.Start == RHS.Start && LHS.End == RHS.End; 186*810390e3Srobert } 187*810390e3Srobert friend bool operator!=(const ExecutorAddrRange &LHS, 188*810390e3Srobert const ExecutorAddrRange &RHS) { 189*810390e3Srobert return !(LHS == RHS); 190*810390e3Srobert } containsExecutorAddrRange191*810390e3Srobert bool contains(ExecutorAddr Addr) const { return Start <= Addr && Addr < End; } overlapsExecutorAddrRange192*810390e3Srobert bool overlaps(const ExecutorAddrRange &Other) { 193*810390e3Srobert return !(Other.End <= Start || End <= Other.Start); 194d89ec533Spatrick } 195d89ec533Spatrick toSpanExecutorAddrRange196*810390e3Srobert template <typename T> span<T> toSpan() const { 197*810390e3Srobert assert(size() % sizeof(T) == 0 && 198*810390e3Srobert "AddressRange is not a multiple of sizeof(T)"); 199*810390e3Srobert return span<T>(Start.toPtr<T *>(), size() / sizeof(T)); 200*810390e3Srobert } 201*810390e3Srobert 202*810390e3Srobert ExecutorAddr Start; 203*810390e3Srobert ExecutorAddr End; 204d89ec533Spatrick }; 205d89ec533Spatrick 206*810390e3Srobert /// SPS serializatior for ExecutorAddr. 207*810390e3Srobert template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> { 208d89ec533Spatrick public: size(const ExecutorAddr & EA)209*810390e3Srobert static size_t size(const ExecutorAddr &EA) { 210d89ec533Spatrick return SPSArgList<uint64_t>::size(EA.getValue()); 211d89ec533Spatrick } 212d89ec533Spatrick serialize(SPSOutputBuffer & BOB,const ExecutorAddr & EA)213*810390e3Srobert static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) { 214d89ec533Spatrick return SPSArgList<uint64_t>::serialize(BOB, EA.getValue()); 215d89ec533Spatrick } 216d89ec533Spatrick deserialize(SPSInputBuffer & BIB,ExecutorAddr & EA)217*810390e3Srobert static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) { 218d89ec533Spatrick uint64_t Tmp; 219d89ec533Spatrick if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp)) 220d89ec533Spatrick return false; 221*810390e3Srobert EA = ExecutorAddr(Tmp); 222d89ec533Spatrick return true; 223d89ec533Spatrick } 224d89ec533Spatrick }; 225d89ec533Spatrick 226*810390e3Srobert using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>; 227d89ec533Spatrick 228d89ec533Spatrick /// Serialization traits for address ranges. 229d89ec533Spatrick template <> 230*810390e3Srobert class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> { 231d89ec533Spatrick public: size(const ExecutorAddrRange & Value)232*810390e3Srobert static size_t size(const ExecutorAddrRange &Value) { 233*810390e3Srobert return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(Value.Start, 234*810390e3Srobert Value.End); 235d89ec533Spatrick } 236d89ec533Spatrick serialize(SPSOutputBuffer & BOB,const ExecutorAddrRange & Value)237*810390e3Srobert static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) { 238*810390e3Srobert return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize( 239*810390e3Srobert BOB, Value.Start, Value.End); 240d89ec533Spatrick } 241d89ec533Spatrick deserialize(SPSInputBuffer & BIB,ExecutorAddrRange & Value)242*810390e3Srobert static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) { 243*810390e3Srobert return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize( 244*810390e3Srobert BIB, Value.Start, Value.End); 245d89ec533Spatrick } 246d89ec533Spatrick }; 247d89ec533Spatrick 248*810390e3Srobert using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>; 249d89ec533Spatrick 250d89ec533Spatrick } // End namespace __orc_rt 251d89ec533Spatrick 252*810390e3Srobert namespace std { 253*810390e3Srobert 254*810390e3Srobert // Make ExecutorAddr hashable. 255*810390e3Srobert template <> struct hash<__orc_rt::ExecutorAddr> { 256*810390e3Srobert size_t operator()(const __orc_rt::ExecutorAddr &A) const { 257*810390e3Srobert return hash<uint64_t>()(A.getValue()); 258*810390e3Srobert } 259*810390e3Srobert }; 260*810390e3Srobert 261*810390e3Srobert } // namespace std 262*810390e3Srobert 263d89ec533Spatrick #endif // ORC_RT_EXECUTOR_ADDRESS_H 264