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