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