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