264 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// Represents an address in the executing program.10//11// This file was derived from12// llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h.13//14//===----------------------------------------------------------------------===//15 16#ifndef ORC_RT_EXECUTOR_ADDRESS_H17#define ORC_RT_EXECUTOR_ADDRESS_H18 19#include "adt.h"20#include "simple_packed_serialization.h"21 22#include <cassert>23#include <type_traits>24 25namespace orc_rt {26 27using ExecutorAddrDiff = uint64_t;28 29/// Represents an address in the executor process.30class ExecutorAddr {31public:32 /// A wrap/unwrap function that leaves pointers unmodified.33 template <typename T> using rawPtr = orc_rt::identity<T *>;34 35 /// Default wrap function to use on this host.36 template <typename T> using defaultWrap = rawPtr<T>;37 38 /// Default unwrap function to use on this host.39 template <typename T> using defaultUnwrap = rawPtr<T>;40 41 /// Merges a tag into the raw address value:42 /// P' = P | (TagValue << TagOffset).43 class Tag {44 public:45 constexpr Tag(uintptr_t TagValue, uintptr_t TagOffset)46 : TagMask(TagValue << TagOffset) {}47 48 template <typename T> constexpr T *operator()(T *P) {49 return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) | TagMask);50 }51 52 private:53 uintptr_t TagMask;54 };55 56 /// Strips a tag of the given length from the given offset within the pointer:57 /// P' = P & ~(((1 << TagLen) -1) << TagOffset)58 class Untag {59 public:60 constexpr Untag(uintptr_t TagLen, uintptr_t TagOffset)61 : UntagMask(~(((uintptr_t(1) << TagLen) - 1) << TagOffset)) {}62 63 template <typename T> constexpr T *operator()(T *P) {64 return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) & UntagMask);65 }66 67 private:68 uintptr_t UntagMask;69 };70 71 ExecutorAddr() = default;72 explicit ExecutorAddr(uint64_t Addr) : Addr(Addr) {}73 74 /// Create an ExecutorAddr from the given pointer.75 template <typename T, typename UnwrapFn = defaultUnwrap<T>>76 static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap = UnwrapFn()) {77 return ExecutorAddr(78 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Unwrap(Ptr))));79 }80 81 /// Cast this ExecutorAddr to a pointer of the given type.82 template <typename T, typename WrapFn = defaultWrap<std::remove_pointer_t<T>>>83 std::enable_if_t<std::is_pointer<T>::value, T>84 toPtr(WrapFn &&Wrap = WrapFn()) const {85 uintptr_t IntPtr = static_cast<uintptr_t>(Addr);86 assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t");87 return Wrap(reinterpret_cast<T>(IntPtr));88 }89 90 /// Cast this ExecutorAddr to a pointer of the given function type.91 template <typename T, typename WrapFn = defaultWrap<T>>92 std::enable_if_t<std::is_function<T>::value, T *>93 toPtr(WrapFn &&Wrap = WrapFn()) const {94 uintptr_t IntPtr = static_cast<uintptr_t>(Addr);95 assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t");96 return Wrap(reinterpret_cast<T *>(IntPtr));97 }98 99 uint64_t getValue() const { return Addr; }100 void setValue(uint64_t Addr) { this->Addr = Addr; }101 bool isNull() const { return Addr == 0; }102 103 explicit operator bool() const { return Addr != 0; }104 105 friend bool operator==(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {106 return LHS.Addr == RHS.Addr;107 }108 109 friend bool operator!=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {110 return LHS.Addr != RHS.Addr;111 }112 113 friend bool operator<(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {114 return LHS.Addr < RHS.Addr;115 }116 117 friend bool operator<=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {118 return LHS.Addr <= RHS.Addr;119 }120 121 friend bool operator>(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {122 return LHS.Addr > RHS.Addr;123 }124 125 friend bool operator>=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {126 return LHS.Addr >= RHS.Addr;127 }128 129 ExecutorAddr &operator++() {130 ++Addr;131 return *this;132 }133 ExecutorAddr &operator--() {134 --Addr;135 return *this;136 }137 ExecutorAddr operator++(int) { return ExecutorAddr(Addr++); }138 ExecutorAddr operator--(int) { return ExecutorAddr(Addr++); }139 140 ExecutorAddr &operator+=(const ExecutorAddrDiff Delta) {141 Addr += Delta;142 return *this;143 }144 145 ExecutorAddr &operator-=(const ExecutorAddrDiff Delta) {146 Addr -= Delta;147 return *this;148 }149 150private:151 uint64_t Addr = 0;152};153 154/// Subtracting two addresses yields an offset.155inline ExecutorAddrDiff operator-(const ExecutorAddr &LHS,156 const ExecutorAddr &RHS) {157 return ExecutorAddrDiff(LHS.getValue() - RHS.getValue());158}159 160/// Adding an offset and an address yields an address.161inline ExecutorAddr operator+(const ExecutorAddr &LHS,162 const ExecutorAddrDiff &RHS) {163 return ExecutorAddr(LHS.getValue() + RHS);164}165 166/// Adding an address and an offset yields an address.167inline ExecutorAddr operator+(const ExecutorAddrDiff &LHS,168 const ExecutorAddr &RHS) {169 return ExecutorAddr(LHS + RHS.getValue());170}171 172/// Represents an address range in the exceutor process.173struct ExecutorAddrRange {174 ExecutorAddrRange() = default;175 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddr End)176 : Start(Start), End(End) {}177 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddrDiff Size)178 : Start(Start), End(Start + Size) {}179 180 bool empty() const { return Start == End; }181 ExecutorAddrDiff size() const { return End - Start; }182 183 friend bool operator==(const ExecutorAddrRange &LHS,184 const ExecutorAddrRange &RHS) {185 return LHS.Start == RHS.Start && LHS.End == RHS.End;186 }187 friend bool operator!=(const ExecutorAddrRange &LHS,188 const ExecutorAddrRange &RHS) {189 return !(LHS == RHS);190 }191 bool contains(ExecutorAddr Addr) const { return Start <= Addr && Addr < End; }192 bool overlaps(const ExecutorAddrRange &Other) {193 return !(Other.End <= Start || End <= Other.Start);194 }195 196 template <typename T> span<T> toSpan() const {197 assert(size() % sizeof(T) == 0 &&198 "AddressRange is not a multiple of sizeof(T)");199 return span<T>(Start.toPtr<T *>(), size() / sizeof(T));200 }201 202 ExecutorAddr Start;203 ExecutorAddr End;204};205 206/// SPS serializatior for ExecutorAddr.207template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> {208public:209 static size_t size(const ExecutorAddr &EA) {210 return SPSArgList<uint64_t>::size(EA.getValue());211 }212 213 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) {214 return SPSArgList<uint64_t>::serialize(BOB, EA.getValue());215 }216 217 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) {218 uint64_t Tmp;219 if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp))220 return false;221 EA = ExecutorAddr(Tmp);222 return true;223 }224};225 226using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>;227 228/// Serialization traits for address ranges.229template <>230class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> {231public:232 static size_t size(const ExecutorAddrRange &Value) {233 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(Value.Start,234 Value.End);235 }236 237 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) {238 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize(239 BOB, Value.Start, Value.End);240 }241 242 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) {243 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize(244 BIB, Value.Start, Value.End);245 }246};247 248using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>;249 250} // End namespace orc_rt251 252namespace std {253 254// Make ExecutorAddr hashable.255template <> struct hash<orc_rt::ExecutorAddr> {256 size_t operator()(const orc_rt::ExecutorAddr &A) const {257 return hash<uint64_t>()(A.getValue());258 }259};260 261} // namespace std262 263#endif // ORC_RT_EXECUTOR_ADDRESS_H264