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 /// Represents the difference between two addresses in the executor process. 28 class ExecutorAddrDiff { 29 public: 30 ExecutorAddrDiff() = default; 31 explicit ExecutorAddrDiff(uint64_t Value) : Value(Value) {} 32 33 uint64_t getValue() const { return Value; } 34 35 private: 36 int64_t Value = 0; 37 }; 38 39 /// Represents an address in the executor process. 40 class ExecutorAddr { 41 public: 42 ExecutorAddr() = default; 43 explicit ExecutorAddr(uint64_t Addr) : Addr(Addr) {} 44 45 /// Create an ExecutorAddr from the given pointer. 46 /// Warning: This should only be used when JITing in-process. 47 template <typename T> static ExecutorAddr fromPtr(T *Value) { 48 return ExecutorAddr( 49 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Value))); 50 } 51 52 /// Cast this ExecutorAddr to a pointer of the given type. 53 /// Warning: This should only be esude when JITing in-process. 54 template <typename T> T toPtr() const { 55 static_assert(std::is_pointer<T>::value, "T must be a pointer type"); 56 uintptr_t IntPtr = static_cast<uintptr_t>(Addr); 57 assert(IntPtr == Addr && 58 "JITTargetAddress 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.getValue(); 105 return *this; 106 } 107 108 ExecutorAddr &operator-=(const ExecutorAddrDiff Delta) { 109 Addr -= Delta.getValue(); 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.getValue()); 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.getValue() + RHS.getValue()); 133 } 134 135 /// Represents an address range in the exceutor process. 136 struct ExecutorAddrRange { 137 ExecutorAddrRange() = default; 138 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddr End) 139 : Start(Start), End(End) {} 140 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddrDiff Size) 141 : Start(Start), End(Start + Size) {} 142 143 bool empty() const { return Start == End; } 144 ExecutorAddrDiff size() const { return End - Start; } 145 146 friend bool operator==(const ExecutorAddrRange &LHS, 147 const ExecutorAddrRange &RHS) { 148 return LHS.Start == RHS.Start && LHS.End == RHS.End; 149 } 150 friend bool operator!=(const ExecutorAddrRange &LHS, 151 const ExecutorAddrRange &RHS) { 152 return !(LHS == RHS); 153 } 154 bool contains(ExecutorAddr Addr) const { return Start <= Addr && Addr < End; } 155 bool overlaps(const ExecutorAddrRange &Other) { 156 return !(Other.End <= Start || End <= Other.Start); 157 } 158 159 template <typename T> span<T> toSpan() const { 160 assert(size().getValue() % sizeof(T) == 0 && 161 "AddressRange is not a multiple of sizeof(T)"); 162 return span<T>(Start.toPtr<T *>(), size().getValue() / sizeof(T)); 163 } 164 165 ExecutorAddr Start; 166 ExecutorAddr End; 167 }; 168 169 /// SPS serializatior for ExecutorAddr. 170 template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> { 171 public: 172 static size_t size(const ExecutorAddr &EA) { 173 return SPSArgList<uint64_t>::size(EA.getValue()); 174 } 175 176 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) { 177 return SPSArgList<uint64_t>::serialize(BOB, EA.getValue()); 178 } 179 180 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) { 181 uint64_t Tmp; 182 if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp)) 183 return false; 184 EA = ExecutorAddr(Tmp); 185 return true; 186 } 187 }; 188 189 using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>; 190 191 /// Serialization traits for address ranges. 192 template <> 193 class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> { 194 public: 195 static size_t size(const ExecutorAddrRange &Value) { 196 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(Value.Start, 197 Value.End); 198 } 199 200 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) { 201 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize( 202 BOB, Value.Start, Value.End); 203 } 204 205 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) { 206 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize( 207 BIB, Value.Start, Value.End); 208 } 209 }; 210 211 using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>; 212 213 } // End namespace __orc_rt 214 215 namespace std { 216 217 // Make ExecutorAddr hashable. 218 template <> struct hash<__orc_rt::ExecutorAddr> { 219 size_t operator()(const __orc_rt::ExecutorAddr &A) const { 220 return hash<uint64_t>()(A.getValue()); 221 } 222 }; 223 224 } // namespace std 225 226 #endif // ORC_RT_EXECUTOR_ADDRESS_H 227