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 StartAddress, ExecutorAddr EndAddress) 139 : StartAddress(StartAddress), EndAddress(EndAddress) {} 140 141 bool empty() const { return StartAddress == EndAddress; } 142 ExecutorAddrDiff size() const { return EndAddress - StartAddress; } 143 144 template <typename T> span<T> toSpan() const { 145 assert(size().getValue() % sizeof(T) == 0 && 146 "AddressRange is not a multiple of sizeof(T)"); 147 return span<T>(StartAddress.toPtr<T *>(), size().getValue() / sizeof(T)); 148 } 149 150 ExecutorAddr StartAddress; 151 ExecutorAddr EndAddress; 152 }; 153 154 /// SPS serializatior for ExecutorAddr. 155 template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> { 156 public: 157 static size_t size(const ExecutorAddr &EA) { 158 return SPSArgList<uint64_t>::size(EA.getValue()); 159 } 160 161 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) { 162 return SPSArgList<uint64_t>::serialize(BOB, EA.getValue()); 163 } 164 165 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) { 166 uint64_t Tmp; 167 if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp)) 168 return false; 169 EA = ExecutorAddr(Tmp); 170 return true; 171 } 172 }; 173 174 using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>; 175 176 /// Serialization traits for address ranges. 177 template <> 178 class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> { 179 public: 180 static size_t size(const ExecutorAddrRange &Value) { 181 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size( 182 Value.StartAddress, Value.EndAddress); 183 } 184 185 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) { 186 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize( 187 BOB, Value.StartAddress, Value.EndAddress); 188 } 189 190 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) { 191 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize( 192 BIB, Value.StartAddress, Value.EndAddress); 193 } 194 }; 195 196 using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>; 197 198 } // End namespace __orc_rt 199 200 #endif // ORC_RT_EXECUTOR_ADDRESS_H 201