File indexing completed on 2026-05-10 08:43:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H
0014 #define LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H
0015
0016 #include "llvm/ADT/DenseMapInfo.h"
0017 #include "llvm/ADT/identity.h"
0018 #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
0019 #include "llvm/Support/FormatVariadic.h"
0020 #include "llvm/Support/raw_ostream.h"
0021
0022 #include <cassert>
0023 #if __has_feature(ptrauth_calls)
0024 #include <ptrauth.h>
0025 #endif
0026 #include <type_traits>
0027
0028 namespace llvm {
0029 namespace orc {
0030
0031 using ExecutorAddrDiff = uint64_t;
0032
0033
0034 class ExecutorAddr {
0035 public:
0036
0037 template <typename T> using rawPtr = llvm::identity<T *>;
0038
0039 #if __has_feature(ptrauth_calls)
0040 template <typename T> class PtrauthSignDefault {
0041 public:
0042 constexpr T *operator()(T *P) {
0043 if (std::is_function_v<T>)
0044 return ptrauth_sign_unauthenticated(P, ptrauth_key_function_pointer, 0);
0045 else
0046 return P;
0047 }
0048 };
0049
0050 template <typename T> class PtrauthStripDefault {
0051 public:
0052 constexpr T *operator()(T *P) {
0053 return ptrauth_strip(P, ptrauth_key_function_pointer);
0054 }
0055 };
0056
0057
0058 template <typename T> using defaultWrap = PtrauthSignDefault<T>;
0059
0060
0061 template <typename T> using defaultUnwrap = PtrauthStripDefault<T>;
0062
0063 #else
0064
0065
0066 template <typename T> using defaultWrap = rawPtr<T>;
0067
0068
0069 template <typename T> using defaultUnwrap = rawPtr<T>;
0070
0071 #endif
0072
0073
0074
0075 class Tag {
0076 public:
0077 constexpr Tag(uintptr_t TagValue, uintptr_t TagOffset)
0078 : TagMask(TagValue << TagOffset) {}
0079
0080 template <typename T> constexpr T *operator()(T *P) {
0081 return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) | TagMask);
0082 }
0083
0084 private:
0085 uintptr_t TagMask;
0086 };
0087
0088
0089
0090 class Untag {
0091 public:
0092 constexpr Untag(uintptr_t TagLen, uintptr_t TagOffset)
0093 : UntagMask(~(((uintptr_t(1) << TagLen) - 1) << TagOffset)) {}
0094
0095 template <typename T> constexpr T *operator()(T *P) {
0096 return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) & UntagMask);
0097 }
0098
0099 private:
0100 uintptr_t UntagMask;
0101 };
0102
0103 ExecutorAddr() = default;
0104
0105
0106 explicit constexpr ExecutorAddr(uint64_t Addr) : Addr(Addr) {}
0107
0108
0109
0110 template <typename T, typename UnwrapFn = defaultUnwrap<T>>
0111 static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap = UnwrapFn()) {
0112 return ExecutorAddr(
0113 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Unwrap(Ptr))));
0114 }
0115
0116
0117
0118 template <typename T, typename WrapFn = defaultWrap<std::remove_pointer_t<T>>>
0119 std::enable_if_t<std::is_pointer<T>::value, T>
0120 toPtr(WrapFn &&Wrap = WrapFn()) const {
0121 uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
0122 assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t");
0123 return Wrap(reinterpret_cast<T>(IntPtr));
0124 }
0125
0126
0127
0128 template <typename T, typename WrapFn = defaultWrap<T>>
0129 std::enable_if_t<std::is_function<T>::value, T *>
0130 toPtr(WrapFn &&Wrap = WrapFn()) const {
0131 uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
0132 assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t");
0133 return Wrap(reinterpret_cast<T *>(IntPtr));
0134 }
0135
0136 uint64_t getValue() const { return Addr; }
0137 void setValue(uint64_t Addr) { this->Addr = Addr; }
0138 bool isNull() const { return Addr == 0; }
0139
0140 explicit operator bool() const { return Addr != 0; }
0141
0142 friend bool operator==(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
0143 return LHS.Addr == RHS.Addr;
0144 }
0145
0146 friend bool operator!=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
0147 return LHS.Addr != RHS.Addr;
0148 }
0149
0150 friend bool operator<(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
0151 return LHS.Addr < RHS.Addr;
0152 }
0153
0154 friend bool operator<=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
0155 return LHS.Addr <= RHS.Addr;
0156 }
0157
0158 friend bool operator>(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
0159 return LHS.Addr > RHS.Addr;
0160 }
0161
0162 friend bool operator>=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
0163 return LHS.Addr >= RHS.Addr;
0164 }
0165
0166 ExecutorAddr &operator++() {
0167 ++Addr;
0168 return *this;
0169 }
0170 ExecutorAddr &operator--() {
0171 --Addr;
0172 return *this;
0173 }
0174 ExecutorAddr operator++(int) { return ExecutorAddr(Addr++); }
0175 ExecutorAddr operator--(int) { return ExecutorAddr(Addr--); }
0176
0177 ExecutorAddr &operator+=(const ExecutorAddrDiff &Delta) {
0178 Addr += Delta;
0179 return *this;
0180 }
0181
0182 ExecutorAddr &operator-=(const ExecutorAddrDiff &Delta) {
0183 Addr -= Delta;
0184 return *this;
0185 }
0186
0187 private:
0188 uint64_t Addr = 0;
0189 };
0190
0191
0192 inline ExecutorAddrDiff operator-(const ExecutorAddr &LHS,
0193 const ExecutorAddr &RHS) {
0194 return ExecutorAddrDiff(LHS.getValue() - RHS.getValue());
0195 }
0196
0197
0198 inline ExecutorAddr operator+(const ExecutorAddr &LHS,
0199 const ExecutorAddrDiff &RHS) {
0200 return ExecutorAddr(LHS.getValue() + RHS);
0201 }
0202
0203
0204 inline ExecutorAddr operator+(const ExecutorAddrDiff &LHS,
0205 const ExecutorAddr &RHS) {
0206 return ExecutorAddr(LHS + RHS.getValue());
0207 }
0208
0209
0210 inline ExecutorAddr operator-(const ExecutorAddr &LHS,
0211 const ExecutorAddrDiff &RHS) {
0212 return ExecutorAddr(LHS.getValue() - RHS);
0213 }
0214
0215
0216 inline ExecutorAddrDiff operator%(const ExecutorAddr &LHS,
0217 const ExecutorAddrDiff &RHS) {
0218 return ExecutorAddrDiff(LHS.getValue() % RHS);
0219 }
0220
0221
0222 struct ExecutorAddrRange {
0223 ExecutorAddrRange() = default;
0224 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddr End)
0225 : Start(Start), End(End) {}
0226 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddrDiff Size)
0227 : Start(Start), End(Start + Size) {}
0228
0229 bool empty() const { return Start == End; }
0230 ExecutorAddrDiff size() const { return End - Start; }
0231
0232 friend bool operator==(const ExecutorAddrRange &LHS,
0233 const ExecutorAddrRange &RHS) {
0234 return LHS.Start == RHS.Start && LHS.End == RHS.End;
0235 }
0236 friend bool operator!=(const ExecutorAddrRange &LHS,
0237 const ExecutorAddrRange &RHS) {
0238 return !(LHS == RHS);
0239 }
0240 friend bool operator<(const ExecutorAddrRange &LHS,
0241 const ExecutorAddrRange &RHS) {
0242 return LHS.Start < RHS.Start ||
0243 (LHS.Start == RHS.Start && LHS.End < RHS.End);
0244 }
0245 friend bool operator<=(const ExecutorAddrRange &LHS,
0246 const ExecutorAddrRange &RHS) {
0247 return LHS.Start < RHS.Start ||
0248 (LHS.Start == RHS.Start && LHS.End <= RHS.End);
0249 }
0250 friend bool operator>(const ExecutorAddrRange &LHS,
0251 const ExecutorAddrRange &RHS) {
0252 return LHS.Start > RHS.Start ||
0253 (LHS.Start == RHS.Start && LHS.End > RHS.End);
0254 }
0255 friend bool operator>=(const ExecutorAddrRange &LHS,
0256 const ExecutorAddrRange &RHS) {
0257 return LHS.Start > RHS.Start ||
0258 (LHS.Start == RHS.Start && LHS.End >= RHS.End);
0259 }
0260
0261 bool contains(ExecutorAddr Addr) const { return Start <= Addr && Addr < End; }
0262 bool overlaps(const ExecutorAddrRange &Other) {
0263 return !(Other.End <= Start || End <= Other.Start);
0264 }
0265
0266 ExecutorAddr Start;
0267 ExecutorAddr End;
0268 };
0269
0270 inline raw_ostream &operator<<(raw_ostream &OS, const ExecutorAddr &A) {
0271 return OS << formatv("{0:x}", A.getValue());
0272 }
0273
0274 inline raw_ostream &operator<<(raw_ostream &OS, const ExecutorAddrRange &R) {
0275 return OS << formatv("{0:x} -- {1:x}", R.Start.getValue(), R.End.getValue());
0276 }
0277
0278 namespace shared {
0279
0280 class SPSExecutorAddr {};
0281
0282
0283 template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> {
0284 public:
0285 static size_t size(const ExecutorAddr &EA) {
0286 return SPSArgList<uint64_t>::size(EA.getValue());
0287 }
0288
0289 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) {
0290 return SPSArgList<uint64_t>::serialize(BOB, EA.getValue());
0291 }
0292
0293 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) {
0294 uint64_t Tmp;
0295 if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp))
0296 return false;
0297 EA = ExecutorAddr(Tmp);
0298 return true;
0299 }
0300 };
0301
0302 using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>;
0303
0304
0305 template <>
0306 class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> {
0307 public:
0308 static size_t size(const ExecutorAddrRange &Value) {
0309 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(Value.Start,
0310 Value.End);
0311 }
0312
0313 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) {
0314 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize(
0315 BOB, Value.Start, Value.End);
0316 }
0317
0318 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) {
0319 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize(
0320 BIB, Value.Start, Value.End);
0321 }
0322 };
0323
0324 using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>;
0325
0326 }
0327 }
0328
0329
0330 template <> struct DenseMapInfo<orc::ExecutorAddr> {
0331 static inline orc::ExecutorAddr getEmptyKey() {
0332 return orc::ExecutorAddr(DenseMapInfo<uint64_t>::getEmptyKey());
0333 }
0334 static inline orc::ExecutorAddr getTombstoneKey() {
0335 return orc::ExecutorAddr(DenseMapInfo<uint64_t>::getTombstoneKey());
0336 }
0337
0338 static unsigned getHashValue(const orc::ExecutorAddr &Addr) {
0339 return DenseMapInfo<uint64_t>::getHashValue(Addr.getValue());
0340 }
0341
0342 static bool isEqual(const orc::ExecutorAddr &LHS,
0343 const orc::ExecutorAddr &RHS) {
0344 return DenseMapInfo<uint64_t>::isEqual(LHS.getValue(), RHS.getValue());
0345 }
0346 };
0347
0348 }
0349
0350 #endif