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 ExecutorAddress { 41 public: 42 ExecutorAddress() = default; 43 explicit ExecutorAddress(uint64_t Addr) : Addr(Addr) {} 44 45 /// Create an ExecutorAddress from the given pointer. 46 /// Warning: This should only be used when JITing in-process. 47 template <typename T> static ExecutorAddress fromPtr(T *Value) { 48 return ExecutorAddress( 49 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Value))); 50 } 51 52 /// Cast this ExecutorAddress 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 ExecutorAddress &LHS, 69 const ExecutorAddress &RHS) { 70 return LHS.Addr == RHS.Addr; 71 } 72 73 friend bool operator!=(const ExecutorAddress &LHS, 74 const ExecutorAddress &RHS) { 75 return LHS.Addr != RHS.Addr; 76 } 77 78 friend bool operator<(const ExecutorAddress &LHS, 79 const ExecutorAddress &RHS) { 80 return LHS.Addr < RHS.Addr; 81 } 82 83 friend bool operator<=(const ExecutorAddress &LHS, 84 const ExecutorAddress &RHS) { 85 return LHS.Addr <= RHS.Addr; 86 } 87 88 friend bool operator>(const ExecutorAddress &LHS, 89 const ExecutorAddress &RHS) { 90 return LHS.Addr > RHS.Addr; 91 } 92 93 friend bool operator>=(const ExecutorAddress &LHS, 94 const ExecutorAddress &RHS) { 95 return LHS.Addr >= RHS.Addr; 96 } 97 98 ExecutorAddress &operator++() { 99 ++Addr; 100 return *this; 101 } 102 ExecutorAddress &operator--() { 103 --Addr; 104 return *this; 105 } 106 ExecutorAddress operator++(int) { return ExecutorAddress(Addr++); } 107 ExecutorAddress operator--(int) { return ExecutorAddress(Addr++); } 108 109 ExecutorAddress &operator+=(const ExecutorAddrDiff Delta) { 110 Addr += Delta.getValue(); 111 return *this; 112 } 113 114 ExecutorAddress &operator-=(const ExecutorAddrDiff Delta) { 115 Addr -= Delta.getValue(); 116 return *this; 117 } 118 119 private: 120 uint64_t Addr = 0; 121 }; 122 123 /// Subtracting two addresses yields an offset. 124 inline ExecutorAddrDiff operator-(const ExecutorAddress &LHS, 125 const ExecutorAddress &RHS) { 126 return ExecutorAddrDiff(LHS.getValue() - RHS.getValue()); 127 } 128 129 /// Adding an offset and an address yields an address. 130 inline ExecutorAddress operator+(const ExecutorAddress &LHS, 131 const ExecutorAddrDiff &RHS) { 132 return ExecutorAddress(LHS.getValue() + RHS.getValue()); 133 } 134 135 /// Adding an address and an offset yields an address. 136 inline ExecutorAddress operator+(const ExecutorAddrDiff &LHS, 137 const ExecutorAddress &RHS) { 138 return ExecutorAddress(LHS.getValue() + RHS.getValue()); 139 } 140 141 /// Represents an address range in the exceutor process. 142 struct ExecutorAddressRange { 143 ExecutorAddressRange() = default; 144 ExecutorAddressRange(ExecutorAddress StartAddress, ExecutorAddress EndAddress) 145 : StartAddress(StartAddress), EndAddress(EndAddress) {} 146 147 bool empty() const { return StartAddress == EndAddress; } 148 ExecutorAddrDiff size() const { return EndAddress - StartAddress; } 149 150 template <typename T> span<T> toSpan() const { 151 assert(size().getValue() % sizeof(T) == 0 && 152 "AddressRange is not a multiple of sizeof(T)"); 153 return span<T>(StartAddress.toPtr<T *>(), size().getValue() / sizeof(T)); 154 } 155 156 ExecutorAddress StartAddress; 157 ExecutorAddress EndAddress; 158 }; 159 160 /// SPS serializatior for ExecutorAddress. 161 template <> class SPSSerializationTraits<SPSExecutorAddress, ExecutorAddress> { 162 public: 163 static size_t size(const ExecutorAddress &EA) { 164 return SPSArgList<uint64_t>::size(EA.getValue()); 165 } 166 167 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddress &EA) { 168 return SPSArgList<uint64_t>::serialize(BOB, EA.getValue()); 169 } 170 171 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddress &EA) { 172 uint64_t Tmp; 173 if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp)) 174 return false; 175 EA = ExecutorAddress(Tmp); 176 return true; 177 } 178 }; 179 180 using SPSExecutorAddressRange = 181 SPSTuple<SPSExecutorAddress, SPSExecutorAddress>; 182 183 /// Serialization traits for address ranges. 184 template <> 185 class SPSSerializationTraits<SPSExecutorAddressRange, ExecutorAddressRange> { 186 public: 187 static size_t size(const ExecutorAddressRange &Value) { 188 return SPSArgList<SPSExecutorAddress, SPSExecutorAddress>::size( 189 Value.StartAddress, Value.EndAddress); 190 } 191 192 static bool serialize(SPSOutputBuffer &BOB, 193 const ExecutorAddressRange &Value) { 194 return SPSArgList<SPSExecutorAddress, SPSExecutorAddress>::serialize( 195 BOB, Value.StartAddress, Value.EndAddress); 196 } 197 198 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddressRange &Value) { 199 return SPSArgList<SPSExecutorAddress, SPSExecutorAddress>::deserialize( 200 BIB, Value.StartAddress, Value.EndAddress); 201 } 202 }; 203 204 using SPSExecutorAddressRangeSequence = SPSSequence<SPSExecutorAddressRange>; 205 206 } // End namespace __orc_rt 207 208 #endif // ORC_RT_EXECUTOR_ADDRESS_H 209