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 LLVM_ADT_POINTERINTPAIR_H 15 #define LLVM_ADT_POINTERINTPAIR_H 16 17 #include "llvm/Support/Compiler.h" 18 #include "llvm/Support/PointerLikeTypeTraits.h" 19 #include "llvm/Support/type_traits.h" 20 #include <cassert> 21 #include <cstdint> 22 #include <limits> 23 24 namespace llvm { 25 26 template <typename T, typename Enable> struct DenseMapInfo; 27 template <typename PointerT, unsigned IntBits, typename PtrTraits> 28 struct 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. 43 template <typename PointerTy, unsigned IntBits, typename IntType = unsigned, 44 typename PtrTraits = PointerLikeTypeTraits<PointerTy>, 45 typename Info = PointerIntPairInfo<PointerTy, IntBits, PtrTraits>> 46 class PointerIntPair { 47 // Used by MSVC visualizer and generally helpful for debugging/visualizing. 48 using InfoTy = Info; 49 intptr_t Value = 0; 50 51 public: 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) & { 65 Value = Info::updatePointer(Value, PtrVal); 66 } 67 68 void setInt(IntType IntVal) & { 69 Value = Info::updateInt(Value, static_cast<intptr_t>(IntVal)); 70 } 71 72 void initWithPointer(PointerTy PtrVal) & { 73 Value = Info::updatePointer(0, PtrVal); 74 } 75 76 void setPointerAndInt(PointerTy PtrVal, IntType IntVal) & { 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 94 void setFromOpaqueValue(void *Val) & { 95 Value = reinterpret_cast<intptr_t>(Val); 96 } 97 98 static PointerIntPair getFromOpaqueValue(void *V) { 99 PointerIntPair P; 100 P.setFromOpaqueValue(V); 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 template <typename PointerT, unsigned IntBits, typename PtrTraits> 132 struct PointerIntPairInfo { 133 static_assert(PtrTraits::NumLowBitsAvailable < 134 std::numeric_limits<uintptr_t>::digits, 135 "cannot use a pointer type that has all bits free"); 136 static_assert(IntBits <= PtrTraits::NumLowBitsAvailable, 137 "PointerIntPair with integer size too large for pointer"); 138 enum MaskAndShiftConstants : uintptr_t { 139 /// PointerBitMask - The bits that come from the pointer. 140 PointerBitMask = 141 ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable) - 1), 142 143 /// IntShift - The number of low bits that we reserve for other uses, and 144 /// keep zero. 145 IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable - IntBits, 146 147 /// IntMask - This is the unshifted mask for valid bits of the int type. 148 IntMask = (uintptr_t)(((intptr_t)1 << IntBits) - 1), 149 150 // ShiftedIntMask - This is the bits for the integer shifted in place. 151 ShiftedIntMask = (uintptr_t)(IntMask << IntShift) 152 }; 153 154 static PointerT getPointer(intptr_t Value) { 155 return PtrTraits::getFromVoidPointer( 156 reinterpret_cast<void *>(Value & PointerBitMask)); 157 } 158 159 static intptr_t getInt(intptr_t Value) { 160 return (Value >> IntShift) & IntMask; 161 } 162 163 static intptr_t updatePointer(intptr_t OrigValue, PointerT Ptr) { 164 intptr_t PtrWord = 165 reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr)); 166 assert((PtrWord & ~PointerBitMask) == 0 && 167 "Pointer is not sufficiently aligned"); 168 // Preserve all low bits, just update the pointer. 169 return PtrWord | (OrigValue & ~PointerBitMask); 170 } 171 172 static intptr_t updateInt(intptr_t OrigValue, intptr_t Int) { 173 intptr_t IntWord = static_cast<intptr_t>(Int); 174 assert((IntWord & ~IntMask) == 0 && "Integer too large for field"); 175 176 // Preserve all bits other than the ones we are updating. 177 return (OrigValue & ~ShiftedIntMask) | IntWord << IntShift; 178 } 179 }; 180 181 // Provide specialization of DenseMapInfo for PointerIntPair. 182 template <typename PointerTy, unsigned IntBits, typename IntType> 183 struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>, void> { 184 using Ty = PointerIntPair<PointerTy, IntBits, IntType>; 185 186 static Ty getEmptyKey() { 187 uintptr_t Val = static_cast<uintptr_t>(-1); 188 Val <<= PointerLikeTypeTraits<Ty>::NumLowBitsAvailable; 189 return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val)); 190 } 191 192 static Ty getTombstoneKey() { 193 uintptr_t Val = static_cast<uintptr_t>(-2); 194 Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable; 195 return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val)); 196 } 197 198 static unsigned getHashValue(Ty V) { 199 uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue()); 200 return unsigned(IV) ^ unsigned(IV >> 9); 201 } 202 203 static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; } 204 }; 205 206 // Teach SmallPtrSet that PointerIntPair is "basically a pointer". 207 template <typename PointerTy, unsigned IntBits, typename IntType, 208 typename PtrTraits> 209 struct PointerLikeTypeTraits< 210 PointerIntPair<PointerTy, IntBits, IntType, PtrTraits>> { 211 static inline void * 212 getAsVoidPointer(const PointerIntPair<PointerTy, IntBits, IntType> &P) { 213 return P.getOpaqueValue(); 214 } 215 216 static inline PointerIntPair<PointerTy, IntBits, IntType> 217 getFromVoidPointer(void *P) { 218 return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P); 219 } 220 221 static inline PointerIntPair<PointerTy, IntBits, IntType> 222 getFromVoidPointer(const void *P) { 223 return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P); 224 } 225 226 static constexpr int NumLowBitsAvailable = 227 PtrTraits::NumLowBitsAvailable - IntBits; 228 }; 229 230 // Allow structured bindings on PointerIntPair. 231 template <std::size_t I, typename PointerTy, unsigned IntBits, typename IntType, 232 typename PtrTraits, typename Info> 233 decltype(auto) 234 get(const PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info> &Pair) { 235 static_assert(I < 2); 236 if constexpr (I == 0) 237 return Pair.getPointer(); 238 else 239 return Pair.getInt(); 240 } 241 242 } // end namespace llvm 243 244 namespace std { 245 template <typename PointerTy, unsigned IntBits, typename IntType, 246 typename PtrTraits, typename Info> 247 struct tuple_size< 248 llvm::PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>> 249 : std::integral_constant<std::size_t, 2> {}; 250 251 template <std::size_t I, typename PointerTy, unsigned IntBits, typename IntType, 252 typename PtrTraits, typename Info> 253 struct tuple_element< 254 I, llvm::PointerIntPair<PointerTy, IntBits, IntType, PtrTraits, Info>> 255 : std::conditional<I == 0, PointerTy, IntType> {}; 256 } // namespace std 257 258 #endif // LLVM_ADT_POINTERINTPAIR_H 259