WPILibC++ 2023.4.3
PointerIntPair.h
Go to the documentation of this file.
1//===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- 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/// \file
10/// This file defines the PointerIntPair class.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef WPIUTIL_WPI_POINTERINTPAIR_H
15#define WPIUTIL_WPI_POINTERINTPAIR_H
16
17#include "wpi/Compiler.h"
19#include "wpi/type_traits.h"
20#include <cassert>
21#include <cstdint>
22#include <limits>
23
24namespace wpi {
25
26template <typename T, typename Enable> struct DenseMapInfo;
27template <typename PointerT, unsigned IntBits, typename PtrTraits>
28struct PointerIntPairInfo;
29
30/// PointerIntPair - This class implements a pair of a pointer and small
31/// integer. It is designed to represent this in the space required by one
32/// pointer by bitmangling the integer into the low part of the pointer. This
33/// can only be done for small integers: typically up to 3 bits, but it depends
34/// on the number of bits available according to PointerLikeTypeTraits for the
35/// type.
36///
37/// Note that PointerIntPair always puts the IntVal part in the highest bits
38/// possible. For example, PointerIntPair<void*, 1, bool> will put the bit for
39/// the bool into bit #2, not bit #0, which allows the low two bits to be used
40/// for something else. For example, this allows:
41/// PointerIntPair<PointerIntPair<void*, 1, bool>, 1, bool>
42/// ... and the two bools will land in different bits.
43template <typename PointerTy, unsigned IntBits, typename IntType = unsigned,
44 typename PtrTraits = PointerLikeTypeTraits<PointerTy>,
45 typename Info = PointerIntPairInfo<PointerTy, IntBits, PtrTraits>>
47 // Used by MSVC visualizer and generally helpful for debugging/visualizing.
48 using InfoTy = Info;
49 intptr_t Value = 0;
50
51public:
52 constexpr PointerIntPair() = default;
53
54 PointerIntPair(PointerTy PtrVal, IntType IntVal) {
55 setPointerAndInt(PtrVal, IntVal);
56 }
57
58 explicit PointerIntPair(PointerTy PtrVal) { initWithPointer(PtrVal); }
59
60 PointerTy getPointer() const { return Info::getPointer(Value); }
61
62 IntType getInt() const { return (IntType)Info::getInt(Value); }
63
64 void setPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION {
65 Value = Info::updatePointer(Value, PtrVal);
66 }
67
68 void setInt(IntType IntVal) LLVM_LVALUE_FUNCTION {
69 Value = Info::updateInt(Value, static_cast<intptr_t>(IntVal));
70 }
71
72 void initWithPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION {
73 Value = Info::updatePointer(0, PtrVal);
74 }
75
76 void setPointerAndInt(PointerTy PtrVal, IntType IntVal) LLVM_LVALUE_FUNCTION {
77 Value = Info::updateInt(Info::updatePointer(0, PtrVal),
78 static_cast<intptr_t>(IntVal));
79 }
80
81 PointerTy const *getAddrOfPointer() const {
82 return const_cast<PointerIntPair *>(this)->getAddrOfPointer();
83 }
84
85 PointerTy *getAddrOfPointer() {
86 assert(Value == reinterpret_cast<intptr_t>(getPointer()) &&
87 "Can only return the address if IntBits is cleared and "
88 "PtrTraits doesn't change the pointer");
89 return reinterpret_cast<PointerTy *>(&Value);
90 }
91
92 void *getOpaqueValue() const { return reinterpret_cast<void *>(Value); }
93
95 Value = reinterpret_cast<intptr_t>(Val);
96 }
97
101 return P;
102 }
103
104 // Allow PointerIntPairs to be created from const void * if and only if the
105 // pointer type could be created from a const void *.
106 static PointerIntPair getFromOpaqueValue(const void *V) {
107 (void)PtrTraits::getFromVoidPointer(V);
108 return getFromOpaqueValue(const_cast<void *>(V));
109 }
110
111 bool operator==(const PointerIntPair &RHS) const {
112 return Value == RHS.Value;
113 }
114
115 bool operator!=(const PointerIntPair &RHS) const {
116 return Value != RHS.Value;
117 }
118
119 bool operator<(const PointerIntPair &RHS) const { return Value < RHS.Value; }
120 bool operator>(const PointerIntPair &RHS) const { return Value > RHS.Value; }
121
122 bool operator<=(const PointerIntPair &RHS) const {
123 return Value <= RHS.Value;
124 }
125
126 bool operator>=(const PointerIntPair &RHS) const {
127 return Value >= RHS.Value;
128 }
129};
130
131
132template <typename PointerT, unsigned IntBits, typename PtrTraits>
134 static_assert(PtrTraits::NumLowBitsAvailable <
135 std::numeric_limits<uintptr_t>::digits,
136 "cannot use a pointer type that has all bits free");
137 static_assert(IntBits <= PtrTraits::NumLowBitsAvailable,
138 "PointerIntPair with integer size too large for pointer");
140 /// PointerBitMask - The bits that come from the pointer.
142 ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable) - 1),
143
144 /// IntShift - The number of low bits that we reserve for other uses, and
145 /// keep zero.
146 IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable - IntBits,
147
148 /// IntMask - This is the unshifted mask for valid bits of the int type.
149 IntMask = (uintptr_t)(((intptr_t)1 << IntBits) - 1),
150
151 // ShiftedIntMask - This is the bits for the integer shifted in place.
153 };
154
155 static PointerT getPointer(intptr_t Value) {
156 return PtrTraits::getFromVoidPointer(
157 reinterpret_cast<void *>(Value & PointerBitMask));
158 }
159
160 static intptr_t getInt(intptr_t Value) {
161 return (Value >> IntShift) & IntMask;
162 }
163
164 static intptr_t updatePointer(intptr_t OrigValue, PointerT Ptr) {
165 intptr_t PtrWord =
166 reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr));
167 assert((PtrWord & ~PointerBitMask) == 0 &&
168 "Pointer is not sufficiently aligned");
169 // Preserve all low bits, just update the pointer.
170 return PtrWord | (OrigValue & ~PointerBitMask);
171 }
172
173 static intptr_t updateInt(intptr_t OrigValue, intptr_t Int) {
174 intptr_t IntWord = static_cast<intptr_t>(Int);
175 assert((IntWord & ~IntMask) == 0 && "Integer too large for field");
176
177 // Preserve all bits other than the ones we are updating.
178 return (OrigValue & ~ShiftedIntMask) | IntWord << IntShift;
179 }
180};
181
182// Provide specialization of DenseMapInfo for PointerIntPair.
183template <typename PointerTy, unsigned IntBits, typename IntType>
184struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>, void> {
186
187 static Ty getEmptyKey() {
188 uintptr_t Val = static_cast<uintptr_t>(-1);
189 Val <<= PointerLikeTypeTraits<Ty>::NumLowBitsAvailable;
190 return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
191 }
192
194 uintptr_t Val = static_cast<uintptr_t>(-2);
195 Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
196 return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
197 }
198
199 static unsigned getHashValue(Ty V) {
200 uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue());
201 return unsigned(IV) ^ unsigned(IV >> 9);
202 }
203
204 static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; }
205};
206
207// Teach SmallPtrSet that PointerIntPair is "basically a pointer".
208template <typename PointerTy, unsigned IntBits, typename IntType,
209 typename PtrTraits>
211 PointerIntPair<PointerTy, IntBits, IntType, PtrTraits>> {
212 static inline void *
214 return P.getOpaqueValue();
215 }
216
220 }
221
223 getFromVoidPointer(const void *P) {
225 }
226
227 static constexpr int NumLowBitsAvailable =
228 PtrTraits::NumLowBitsAvailable - IntBits;
229};
230
231} // end namespace wpi
232
233#endif // WPIUTIL_WPI_POINTERINTPAIR_H
#define LLVM_LVALUE_FUNCTION
Expands to '&' if ref-qualifiers for *this are supported.
Definition: Compiler.h:118
PointerIntPair - This class implements a pair of a pointer and small integer.
Definition: PointerIntPair.h:46
PointerIntPair(PointerTy PtrVal)
Definition: PointerIntPair.h:58
void setPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION
Definition: PointerIntPair.h:64
void setPointerAndInt(PointerTy PtrVal, IntType IntVal) LLVM_LVALUE_FUNCTION
Definition: PointerIntPair.h:76
bool operator>=(const PointerIntPair &RHS) const
Definition: PointerIntPair.h:126
constexpr PointerIntPair()=default
bool operator<(const PointerIntPair &RHS) const
Definition: PointerIntPair.h:119
PointerTy const * getAddrOfPointer() const
Definition: PointerIntPair.h:81
PointerIntPair(PointerTy PtrVal, IntType IntVal)
Definition: PointerIntPair.h:54
static PointerIntPair getFromOpaqueValue(void *V)
Definition: PointerIntPair.h:98
static PointerIntPair getFromOpaqueValue(const void *V)
Definition: PointerIntPair.h:106
bool operator>(const PointerIntPair &RHS) const
Definition: PointerIntPair.h:120
bool operator==(const PointerIntPair &RHS) const
Definition: PointerIntPair.h:111
void * getOpaqueValue() const
Definition: PointerIntPair.h:92
void setFromOpaqueValue(void *Val) LLVM_LVALUE_FUNCTION
Definition: PointerIntPair.h:94
IntType getInt() const
Definition: PointerIntPair.h:62
PointerTy getPointer() const
Definition: PointerIntPair.h:60
void initWithPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION
Definition: PointerIntPair.h:72
bool operator!=(const PointerIntPair &RHS) const
Definition: PointerIntPair.h:115
PointerTy * getAddrOfPointer()
Definition: PointerIntPair.h:85
bool operator<=(const PointerIntPair &RHS) const
Definition: PointerIntPair.h:122
void setInt(IntType IntVal) LLVM_LVALUE_FUNCTION
Definition: PointerIntPair.h:68
uint128_t uintptr_t
Definition: format.h:432
/file This file defines the SmallVector class.
Definition: AprilTagFieldLayout.h:18
static unsigned getHashValue(Ty V)
Definition: PointerIntPair.h:199
static bool isEqual(const Ty &LHS, const Ty &RHS)
Definition: PointerIntPair.h:204
An information struct used to provide DenseMap with the various necessary components for a given valu...
Definition: DenseMapInfo.h:49
Definition: PointerIntPair.h:133
static intptr_t getInt(intptr_t Value)
Definition: PointerIntPair.h:160
MaskAndShiftConstants
Definition: PointerIntPair.h:139
@ PointerBitMask
PointerBitMask - The bits that come from the pointer.
Definition: PointerIntPair.h:141
@ IntMask
IntMask - This is the unshifted mask for valid bits of the int type.
Definition: PointerIntPair.h:149
@ IntShift
IntShift - The number of low bits that we reserve for other uses, and keep zero.
Definition: PointerIntPair.h:146
@ ShiftedIntMask
Definition: PointerIntPair.h:152
static PointerT getPointer(intptr_t Value)
Definition: PointerIntPair.h:155
static intptr_t updatePointer(intptr_t OrigValue, PointerT Ptr)
Definition: PointerIntPair.h:164
static intptr_t updateInt(intptr_t OrigValue, intptr_t Int)
Definition: PointerIntPair.h:173
static void * getAsVoidPointer(const PointerIntPair< PointerTy, IntBits, IntType > &P)
Definition: PointerIntPair.h:213
static PointerIntPair< PointerTy, IntBits, IntType > getFromVoidPointer(const void *P)
Definition: PointerIntPair.h:223
static PointerIntPair< PointerTy, IntBits, IntType > getFromVoidPointer(void *P)
Definition: PointerIntPair.h:218
A traits type that is used to handle pointer types and things that are just wrappers for pointers as ...
Definition: PointerLikeTypeTraits.h:25