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//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H
14#define LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H
15
16#include "llvm/ADT/DenseMapInfo.h"
17#include "llvm/ADT/identity.h"
18#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
19#include "llvm/Support/FormatVariadic.h"
20#include "llvm/Support/raw_ostream.h"
21
22#include <cassert>
23#include <type_traits>
24
25namespace llvm {
26namespace orc {
27
28using ExecutorAddrDiff = uint64_t;
29
30/// Represents an address in the executor process.
31class ExecutorAddr {
32public:
33 /// A wrap/unwrap function that leaves pointers unmodified.
34 template <typename T> using rawPtr = llvm::identity<T *>;
35
36 /// Default wrap function to use on this host.
37 template <typename T> using defaultWrap = rawPtr<T>;
38
39 /// Default unwrap function to use on this host.
40 template <typename T> using defaultUnwrap = rawPtr<T>;
41
42 /// Merges a tag into the raw address value:
43 /// P' = P | (TagValue << TagOffset).
44 class Tag {
45 public:
46 constexpr Tag(uintptr_t TagValue, uintptr_t TagOffset)
47 : TagMask(TagValue << TagOffset) {}
48
49 template <typename T> constexpr T *operator()(T *P) {
50 return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) | TagMask);
51 }
52
53 private:
54 uintptr_t TagMask;
55 };
56
57 /// Strips a tag of the given length from the given offset within the pointer:
58 /// P' = P & ~(((1 << TagLen) -1) << TagOffset)
59 class Untag {
60 public:
61 constexpr Untag(uintptr_t TagLen, uintptr_t TagOffset)
62 : UntagMask(~(((uintptr_t(1) << TagLen) - 1) << TagOffset)) {}
63
64 template <typename T> constexpr T *operator()(T *P) {
65 return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) & UntagMask);
66 }
67
68 private:
69 uintptr_t UntagMask;
70 };
71
72 ExecutorAddr() = default;
73
74 /// Create an ExecutorAddr from the given value.
75 explicit constexpr ExecutorAddr(uint64_t Addr) : Addr(Addr) {}
76
77 /// Create an ExecutorAddr from the given pointer.
78 /// Warning: This should only be used when JITing in-process.
79 template <typename T, typename UnwrapFn = defaultUnwrap<T>>
80 static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap = UnwrapFn()) {
81 return ExecutorAddr(
82 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Unwrap(Ptr))));
83 }
84
85 /// Cast this ExecutorAddr to a pointer of the given type.
86 /// Warning: This should only be used when JITing in-process.
87 template <typename T, typename WrapFn = defaultWrap<std::remove_pointer_t<T>>>
88 std::enable_if_t<std::is_pointer<T>::value, T>
89 toPtr(WrapFn &&Wrap = WrapFn()) const {
90 uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
91 assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t");
92 return Wrap(reinterpret_cast<T>(IntPtr));
93 }
94
95 /// Cast this ExecutorAddr to a pointer of the given function type.
96 /// Warning: This should only be used when JITing in-process.
97 template <typename T, typename WrapFn = defaultWrap<T>>
98 std::enable_if_t<std::is_function<T>::value, T *>
99 toPtr(WrapFn &&Wrap = WrapFn()) const {
100 uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
101 assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t");
102 return Wrap(reinterpret_cast<T *>(IntPtr));
103 }
104
105 uint64_t getValue() const { return Addr; }
106 void setValue(uint64_t Addr) { this->Addr = Addr; }
107 bool isNull() const { return Addr == 0; }
108
109 explicit operator bool() const { return Addr != 0; }
110
111 friend bool operator==(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
112 return LHS.Addr == RHS.Addr;
113 }
114
115 friend bool operator!=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
116 return LHS.Addr != RHS.Addr;
117 }
118
119 friend bool operator<(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
120 return LHS.Addr < RHS.Addr;
121 }
122
123 friend bool operator<=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
124 return LHS.Addr <= RHS.Addr;
125 }
126
127 friend bool operator>(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
128 return LHS.Addr > RHS.Addr;
129 }
130
131 friend bool operator>=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
132 return LHS.Addr >= RHS.Addr;
133 }
134
135 ExecutorAddr &operator++() {
136 ++Addr;
137 return *this;
138 }
139 ExecutorAddr &operator--() {
140 --Addr;
141 return *this;
142 }
143 ExecutorAddr operator++(int) { return ExecutorAddr(Addr++); }
144 ExecutorAddr operator--(int) { return ExecutorAddr(Addr--); }
145
146 ExecutorAddr &operator+=(const ExecutorAddrDiff &Delta) {
147 Addr += Delta;
148 return *this;
149 }
150
151 ExecutorAddr &operator-=(const ExecutorAddrDiff &Delta) {
152 Addr -= Delta;
153 return *this;
154 }
155
156private:
157 uint64_t Addr = 0;
158};
159
160/// Subtracting two addresses yields an offset.
161inline ExecutorAddrDiff operator-(const ExecutorAddr &LHS,
162 const ExecutorAddr &RHS) {
163 return ExecutorAddrDiff(LHS.getValue() - RHS.getValue());
164}
165
166/// Adding an offset and an address yields an address.
167inline ExecutorAddr operator+(const ExecutorAddr &LHS,
168 const ExecutorAddrDiff &RHS) {
169 return ExecutorAddr(LHS.getValue() + RHS);
170}
171
172/// Adding an address and an offset yields an address.
173inline ExecutorAddr operator+(const ExecutorAddrDiff &LHS,
174 const ExecutorAddr &RHS) {
175 return ExecutorAddr(LHS + RHS.getValue());
176}
177
178/// Subtracting an offset from an address yields an address.
179inline ExecutorAddr operator-(const ExecutorAddr &LHS,
180 const ExecutorAddrDiff &RHS) {
181 return ExecutorAddr(LHS.getValue() - RHS);
182}
183
184/// Taking the modulus of an address and a diff yields a diff.
185inline ExecutorAddrDiff operator%(const ExecutorAddr &LHS,
186 const ExecutorAddrDiff &RHS) {
187 return ExecutorAddrDiff(LHS.getValue() % RHS);
188}
189
190/// Represents an address range in the exceutor process.
191struct ExecutorAddrRange {
192 ExecutorAddrRange() = default;
193 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddr End)
194 : Start(Start), End(End) {}
195 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddrDiff Size)
196 : Start(Start), End(Start + Size) {}
197
198 bool empty() const { return Start == End; }
199 ExecutorAddrDiff size() const { return End - Start; }
200
201 friend bool operator==(const ExecutorAddrRange &LHS,
202 const ExecutorAddrRange &RHS) {
203 return LHS.Start == RHS.Start && LHS.End == RHS.End;
204 }
205 friend bool operator!=(const ExecutorAddrRange &LHS,
206 const ExecutorAddrRange &RHS) {
207 return !(LHS == RHS);
208 }
209 friend bool operator<(const ExecutorAddrRange &LHS,
210 const ExecutorAddrRange &RHS) {
211 return LHS.Start < RHS.Start ||
212 (LHS.Start == RHS.Start && LHS.End < RHS.End);
213 }
214 friend bool operator<=(const ExecutorAddrRange &LHS,
215 const ExecutorAddrRange &RHS) {
216 return LHS.Start < RHS.Start ||
217 (LHS.Start == RHS.Start && LHS.End <= RHS.End);
218 }
219 friend bool operator>(const ExecutorAddrRange &LHS,
220 const ExecutorAddrRange &RHS) {
221 return LHS.Start > RHS.Start ||
222 (LHS.Start == RHS.Start && LHS.End > RHS.End);
223 }
224 friend bool operator>=(const ExecutorAddrRange &LHS,
225 const ExecutorAddrRange &RHS) {
226 return LHS.Start > RHS.Start ||
227 (LHS.Start == RHS.Start && LHS.End >= RHS.End);
228 }
229
230 bool contains(ExecutorAddr Addr) const { return Start <= Addr && Addr < End; }
231 bool overlaps(const ExecutorAddrRange &Other) {
232 return !(Other.End <= Start || End <= Other.Start);
233 }
234
235 ExecutorAddr Start;
236 ExecutorAddr End;
237};
238
239inline raw_ostream &operator<<(raw_ostream &OS, const ExecutorAddr &A) {
240 return OS << formatv(Fmt: "{0:x}", Vals: A.getValue());
241}
242
243inline raw_ostream &operator<<(raw_ostream &OS, const ExecutorAddrRange &R) {
244 return OS << formatv(Fmt: "{0:x} -- {1:x}", Vals: R.Start.getValue(), Vals: R.End.getValue());
245}
246
247namespace shared {
248
249class SPSExecutorAddr {};
250
251/// SPS serializatior for ExecutorAddr.
252template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> {
253public:
254 static size_t size(const ExecutorAddr &EA) {
255 return SPSArgList<uint64_t>::size(Arg: EA.getValue());
256 }
257
258 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) {
259 return SPSArgList<uint64_t>::serialize(OB&: BOB, Arg: EA.getValue());
260 }
261
262 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) {
263 uint64_t Tmp;
264 if (!SPSArgList<uint64_t>::deserialize(IB&: BIB, Arg&: Tmp))
265 return false;
266 EA = ExecutorAddr(Tmp);
267 return true;
268 }
269};
270
271using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>;
272
273/// Serialization traits for address ranges.
274template <>
275class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> {
276public:
277 static size_t size(const ExecutorAddrRange &Value) {
278 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(Arg: Value.Start,
279 Args: Value.End);
280 }
281
282 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) {
283 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize(
284 OB&: BOB, Arg: Value.Start, Args: Value.End);
285 }
286
287 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) {
288 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize(
289 IB&: BIB, Arg&: Value.Start, Args&: Value.End);
290 }
291};
292
293using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>;
294
295} // End namespace shared.
296} // End namespace orc.
297
298// Provide DenseMapInfo for ExecutorAddrs.
299template <> struct DenseMapInfo<orc::ExecutorAddr> {
300 static inline orc::ExecutorAddr getEmptyKey() {
301 return orc::ExecutorAddr(DenseMapInfo<uint64_t>::getEmptyKey());
302 }
303 static inline orc::ExecutorAddr getTombstoneKey() {
304 return orc::ExecutorAddr(DenseMapInfo<uint64_t>::getTombstoneKey());
305 }
306
307 static unsigned getHashValue(const orc::ExecutorAddr &Addr) {
308 return DenseMapInfo<uint64_t>::getHashValue(Val: Addr.getValue());
309 }
310
311 static bool isEqual(const orc::ExecutorAddr &LHS,
312 const orc::ExecutorAddr &RHS) {
313 return DenseMapInfo<uint64_t>::isEqual(LHS: LHS.getValue(), RHS: RHS.getValue());
314 }
315};
316
317} // End namespace llvm.
318
319#endif // LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H
320

source code of llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h