Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/orc/executor_address.h
39566 views
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
using ExecutorAddrDiff = uint64_t;
28
29
/// Represents an address in the executor process.
30
class ExecutorAddr {
31
public:
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
150
private:
151
uint64_t Addr = 0;
152
};
153
154
/// Subtracting two addresses yields an offset.
155
inline 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.
161
inline 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.
167
inline 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.
173
struct 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.
207
template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> {
208
public:
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
226
using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>;
227
228
/// Serialization traits for address ranges.
229
template <>
230
class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> {
231
public:
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
248
using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>;
249
250
} // End namespace __orc_rt
251
252
namespace std {
253
254
// Make ExecutorAddr hashable.
255
template <> 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 std
262
263
#endif // ORC_RT_EXECUTOR_ADDRESS_H
264
265