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 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H 14 #define LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H 15 16 #include "llvm/ADT/DenseMapInfo.h" 17 #include "llvm/ADT/identity.h" 18 #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" 19 #include "llvm/Support/FormatVariadic.h" 20 #include "llvm/Support/raw_ostream.h" 21 22 #include <cassert> 23 #include <type_traits> 24 25 namespace llvm { 26 namespace orc { 27 28 using ExecutorAddrDiff = uint64_t; 29 30 /// Represents an address in the executor process. 31 class ExecutorAddr { 32 public: 33 /// A wrap/unwrap function that leaves pointers unmodified. 34 template <typename T> using rawPtr = llvm::identity<T *>; 35 36 /// Default wrap function to use on this host. 37 template <typename T> using defaultWrap = rawPtr<T>; 38 39 /// Default unwrap function to use on this host. 40 template <typename T> using defaultUnwrap = rawPtr<T>; 41 42 /// Merges a tag into the raw address value: 43 /// P' = P | (TagValue << TagOffset). 44 class Tag { 45 public: Tag(uintptr_t TagValue,uintptr_t TagOffset)46 constexpr Tag(uintptr_t TagValue, uintptr_t TagOffset) 47 : TagMask(TagValue << TagOffset) {} 48 operator()49 template <typename T> constexpr T *operator()(T *P) { 50 return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) | TagMask); 51 } 52 53 private: 54 uintptr_t TagMask; 55 }; 56 57 /// Strips a tag of the given length from the given offset within the pointer: 58 /// P' = P & ~(((1 << TagLen) -1) << TagOffset) 59 class Untag { 60 public: Untag(uintptr_t TagLen,uintptr_t TagOffset)61 constexpr Untag(uintptr_t TagLen, uintptr_t TagOffset) 62 : UntagMask(~(((uintptr_t(1) << TagLen) - 1) << TagOffset)) {} 63 operator()64 template <typename T> constexpr T *operator()(T *P) { 65 return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) & UntagMask); 66 } 67 68 private: 69 uintptr_t UntagMask; 70 }; 71 72 ExecutorAddr() = default; 73 74 /// Create an ExecutorAddr from the given value. ExecutorAddr(uint64_t Addr)75 explicit constexpr ExecutorAddr(uint64_t Addr) : Addr(Addr) {} 76 77 /// Create an ExecutorAddr from the given pointer. 78 /// Warning: This should only be used when JITing in-process. 79 template <typename T, typename UnwrapFn = defaultUnwrap<T>> 80 static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap = UnwrapFn()) { 81 return ExecutorAddr( 82 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Unwrap(Ptr)))); 83 } 84 85 /// Cast this ExecutorAddr to a pointer of the given type. 86 /// Warning: This should only be used when JITing in-process. 87 template <typename T, typename WrapFn = defaultWrap<std::remove_pointer_t<T>>> 88 std::enable_if_t<std::is_pointer<T>::value, T> 89 toPtr(WrapFn &&Wrap = WrapFn()) const { 90 uintptr_t IntPtr = static_cast<uintptr_t>(Addr); 91 assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t"); 92 return Wrap(reinterpret_cast<T>(IntPtr)); 93 } 94 95 /// Cast this ExecutorAddr to a pointer of the given function type. 96 /// Warning: This should only be used when JITing in-process. 97 template <typename T, typename WrapFn = defaultWrap<T>> 98 std::enable_if_t<std::is_function<T>::value, T *> 99 toPtr(WrapFn &&Wrap = WrapFn()) const { 100 uintptr_t IntPtr = static_cast<uintptr_t>(Addr); 101 assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t"); 102 return Wrap(reinterpret_cast<T *>(IntPtr)); 103 } 104 getValue()105 uint64_t getValue() const { return Addr; } setValue(uint64_t Addr)106 void setValue(uint64_t Addr) { this->Addr = Addr; } isNull()107 bool isNull() const { return Addr == 0; } 108 109 explicit operator bool() const { return Addr != 0; } 110 111 friend bool operator==(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 112 return LHS.Addr == RHS.Addr; 113 } 114 115 friend bool operator!=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 116 return LHS.Addr != RHS.Addr; 117 } 118 119 friend bool operator<(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 120 return LHS.Addr < RHS.Addr; 121 } 122 123 friend bool operator<=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 124 return LHS.Addr <= RHS.Addr; 125 } 126 127 friend bool operator>(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 128 return LHS.Addr > RHS.Addr; 129 } 130 131 friend bool operator>=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 132 return LHS.Addr >= RHS.Addr; 133 } 134 135 ExecutorAddr &operator++() { 136 ++Addr; 137 return *this; 138 } 139 ExecutorAddr &operator--() { 140 --Addr; 141 return *this; 142 } 143 ExecutorAddr operator++(int) { return ExecutorAddr(Addr++); } 144 ExecutorAddr operator--(int) { return ExecutorAddr(Addr--); } 145 146 ExecutorAddr &operator+=(const ExecutorAddrDiff &Delta) { 147 Addr += Delta; 148 return *this; 149 } 150 151 ExecutorAddr &operator-=(const ExecutorAddrDiff &Delta) { 152 Addr -= Delta; 153 return *this; 154 } 155 156 private: 157 uint64_t Addr = 0; 158 }; 159 160 /// Subtracting two addresses yields an offset. 161 inline ExecutorAddrDiff operator-(const ExecutorAddr &LHS, 162 const ExecutorAddr &RHS) { 163 return ExecutorAddrDiff(LHS.getValue() - RHS.getValue()); 164 } 165 166 /// Adding an offset and an address yields an address. 167 inline ExecutorAddr operator+(const ExecutorAddr &LHS, 168 const ExecutorAddrDiff &RHS) { 169 return ExecutorAddr(LHS.getValue() + RHS); 170 } 171 172 /// Adding an address and an offset yields an address. 173 inline ExecutorAddr operator+(const ExecutorAddrDiff &LHS, 174 const ExecutorAddr &RHS) { 175 return ExecutorAddr(LHS + RHS.getValue()); 176 } 177 178 /// Subtracting an offset from an address yields an address. 179 inline ExecutorAddr operator-(const ExecutorAddr &LHS, 180 const ExecutorAddrDiff &RHS) { 181 return ExecutorAddr(LHS.getValue() - RHS); 182 } 183 184 /// Taking the modulus of an address and a diff yields a diff. 185 inline ExecutorAddrDiff operator%(const ExecutorAddr &LHS, 186 const ExecutorAddrDiff &RHS) { 187 return ExecutorAddrDiff(LHS.getValue() % RHS); 188 } 189 190 /// Represents an address range in the exceutor process. 191 struct ExecutorAddrRange { 192 ExecutorAddrRange() = default; ExecutorAddrRangeExecutorAddrRange193 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddr End) 194 : Start(Start), End(End) {} ExecutorAddrRangeExecutorAddrRange195 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddrDiff Size) 196 : Start(Start), End(Start + Size) {} 197 emptyExecutorAddrRange198 bool empty() const { return Start == End; } sizeExecutorAddrRange199 ExecutorAddrDiff size() const { return End - Start; } 200 201 friend bool operator==(const ExecutorAddrRange &LHS, 202 const ExecutorAddrRange &RHS) { 203 return LHS.Start == RHS.Start && LHS.End == RHS.End; 204 } 205 friend bool operator!=(const ExecutorAddrRange &LHS, 206 const ExecutorAddrRange &RHS) { 207 return !(LHS == RHS); 208 } containsExecutorAddrRange209 bool contains(ExecutorAddr Addr) const { return Start <= Addr && Addr < End; } overlapsExecutorAddrRange210 bool overlaps(const ExecutorAddrRange &Other) { 211 return !(Other.End <= Start || End <= Other.Start); 212 } 213 214 ExecutorAddr Start; 215 ExecutorAddr End; 216 }; 217 218 inline raw_ostream &operator<<(raw_ostream &OS, const ExecutorAddr &A) { 219 return OS << formatv("{0:x}", A.getValue()); 220 } 221 222 inline raw_ostream &operator<<(raw_ostream &OS, const ExecutorAddrRange &R) { 223 return OS << formatv("{0:x} -- {1:x}", R.Start.getValue(), R.End.getValue()); 224 } 225 226 namespace shared { 227 228 class SPSExecutorAddr {}; 229 230 /// SPS serializatior for ExecutorAddr. 231 template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> { 232 public: size(const ExecutorAddr & EA)233 static size_t size(const ExecutorAddr &EA) { 234 return SPSArgList<uint64_t>::size(EA.getValue()); 235 } 236 serialize(SPSOutputBuffer & BOB,const ExecutorAddr & EA)237 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) { 238 return SPSArgList<uint64_t>::serialize(BOB, EA.getValue()); 239 } 240 deserialize(SPSInputBuffer & BIB,ExecutorAddr & EA)241 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) { 242 uint64_t Tmp; 243 if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp)) 244 return false; 245 EA = ExecutorAddr(Tmp); 246 return true; 247 } 248 }; 249 250 using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>; 251 252 /// Serialization traits for address ranges. 253 template <> 254 class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> { 255 public: size(const ExecutorAddrRange & Value)256 static size_t size(const ExecutorAddrRange &Value) { 257 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(Value.Start, 258 Value.End); 259 } 260 serialize(SPSOutputBuffer & BOB,const ExecutorAddrRange & Value)261 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) { 262 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize( 263 BOB, Value.Start, Value.End); 264 } 265 deserialize(SPSInputBuffer & BIB,ExecutorAddrRange & Value)266 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) { 267 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize( 268 BIB, Value.Start, Value.End); 269 } 270 }; 271 272 using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>; 273 274 } // End namespace shared. 275 } // End namespace orc. 276 277 // Provide DenseMapInfo for ExecutorAddrs. 278 template <> struct DenseMapInfo<orc::ExecutorAddr> { 279 static inline orc::ExecutorAddr getEmptyKey() { 280 return orc::ExecutorAddr(DenseMapInfo<uint64_t>::getEmptyKey()); 281 } 282 static inline orc::ExecutorAddr getTombstoneKey() { 283 return orc::ExecutorAddr(DenseMapInfo<uint64_t>::getTombstoneKey()); 284 } 285 286 static unsigned getHashValue(const orc::ExecutorAddr &Addr) { 287 return DenseMapInfo<uint64_t>::getHashValue(Addr.getValue()); 288 } 289 290 static bool isEqual(const orc::ExecutorAddr &LHS, 291 const orc::ExecutorAddr &RHS) { 292 return DenseMapInfo<uint64_t>::isEqual(LHS.getValue(), RHS.getValue()); 293 } 294 }; 295 296 } // End namespace llvm. 297 298 #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H 299