LLVM 22.0.0git
PointerUnion.h
Go to the documentation of this file.
1//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- 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 PointerUnion class, which is a discriminated union of
11/// pointer types.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_ADT_POINTERUNION_H
16#define LLVM_ADT_POINTERUNION_H
17
20#include "llvm/ADT/STLExtras.h"
23#include <algorithm>
24#include <cassert>
25#include <cstddef>
26#include <cstdint>
27
28namespace llvm {
29
31 /// Determine the number of bits required to store integers with values < n.
32 /// This is ceil(log2(n)).
33 constexpr int bitsRequired(unsigned n) {
34 return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0;
35 }
36
37 template <typename... Ts> constexpr int lowBitsAvailable() {
38 return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...});
39 }
40
41 /// Find the first type in a list of types.
42 template <typename T, typename...> struct GetFirstType {
43 using type = T;
44 };
45
46 /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
47 /// for the template arguments.
48 template <typename ...PTs> class PointerUnionUIntTraits {
49 public:
50 static inline void *getAsVoidPointer(void *P) { return P; }
51 static inline void *getFromVoidPointer(void *P) { return P; }
52 static constexpr int NumLowBitsAvailable = lowBitsAvailable<PTs...>();
53 };
54
55 template <typename Derived, typename ValTy, int I, typename ...Types>
57
58 template <typename Derived, typename ValTy, int I>
59 class PointerUnionMembers<Derived, ValTy, I> {
60 protected:
61 ValTy Val;
64
65 friend struct PointerLikeTypeTraits<Derived>;
66 };
67
68 template <typename Derived, typename ValTy, int I, typename Type,
69 typename ...Types>
70 class PointerUnionMembers<Derived, ValTy, I, Type, Types...>
71 : public PointerUnionMembers<Derived, ValTy, I + 1, Types...> {
72 using Base = PointerUnionMembers<Derived, ValTy, I + 1, Types...>;
73 public:
74 using Base::Base;
77 : Base(ValTy(const_cast<void *>(
78 PointerLikeTypeTraits<Type>::getAsVoidPointer(V)),
79 I)) {}
80
81 using Base::operator=;
82 Derived &operator=(Type V) {
83 this->Val = ValTy(
85 I);
86 return static_cast<Derived &>(*this);
87 };
88 };
89}
90
91/// A discriminated union of two or more pointer types, with the discriminator
92/// in the low bit of the pointer.
93///
94/// This implementation is extremely efficient in space due to leveraging the
95/// low bits of the pointer, while exposing a natural and type-safe API.
96///
97/// Common use patterns would be something like this:
98/// PointerUnion<int*, float*> P;
99/// P = (int*)0;
100/// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0"
101/// X = P.get<int*>(); // ok.
102/// Y = P.get<float*>(); // runtime assertion failure.
103/// Z = P.get<double*>(); // compile time failure.
104/// P = (float*)0;
105/// Y = P.get<float*>(); // ok.
106/// X = P.get<int*>(); // runtime assertion failure.
107/// PointerUnion<int*, int*> Q; // compile time failure.
108template <typename... PTs>
111 PointerUnion<PTs...>,
112 PointerIntPair<
113 void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int,
114 pointer_union_detail::PointerUnionUIntTraits<PTs...>>,
115 0, PTs...> {
116 static_assert(TypesAreDistinct<PTs...>::value,
117 "PointerUnion alternative types cannot be repeated");
118 // The first type is special because we want to directly cast a pointer to a
119 // default-initialized union to a pointer to the first type. But we don't
120 // want PointerUnion to be a 'template <typename First, typename ...Rest>'
121 // because it's much more convenient to have a name for the whole pack. So
122 // split off the first type here.
123 using First = TypeAtIndex<0, PTs...>;
124 using Base = typename PointerUnion::PointerUnionMembers;
125
126 // Give the CastInfo specialization below access to protected members.
127 //
128 // This makes all of CastInfo a friend, which is more than strictly
129 // necessary. It's a workaround for C++'s inability to friend a
130 // partial template specialization.
131 template <typename To, typename From, typename Enable> friend struct CastInfo;
132
133public:
134 PointerUnion() = default;
135
136 PointerUnion(std::nullptr_t) : PointerUnion() {}
137 using Base::Base;
138
139 /// Test if the pointer held in the union is null, regardless of
140 /// which type it is.
141 bool isNull() const { return !this->Val.getPointer(); }
142
143 explicit operator bool() const { return !isNull(); }
144
145 // FIXME: Replace the uses of is(), get() and dyn_cast() with
146 // isa<T>, cast<T> and the llvm::dyn_cast<T>
147
148 /// Test if the Union currently holds the type matching T.
149 template <typename T>
150 [[deprecated("Use isa instead")]]
151 inline bool is() const {
152 return isa<T>(*this);
153 }
154
155 /// Returns the value of the specified pointer type.
156 ///
157 /// If the specified pointer type is incorrect, assert.
158 template <typename T>
159 [[deprecated("Use cast instead")]]
160 inline T get() const {
161 assert(isa<T>(*this) && "Invalid accessor called");
162 return cast<T>(*this);
163 }
164
165 /// Returns the current pointer if it is of the specified pointer type,
166 /// otherwise returns null.
167 template <typename T> inline T dyn_cast() const {
168 return llvm::dyn_cast_if_present<T>(*this);
169 }
170
171 /// If the union is set to the first pointer type get an address pointing to
172 /// it.
173 First const *getAddrOfPtr1() const {
174 return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
175 }
176
177 /// If the union is set to the first pointer type get an address pointing to
178 /// it.
179 First *getAddrOfPtr1() {
180 assert(isa<First>(*this) && "Val is not the first pointer");
181 assert(
183 this->Val.getPointer() &&
184 "Can't get the address because PointerLikeTypeTraits changes the ptr");
185 return const_cast<First *>(
186 reinterpret_cast<const First *>(this->Val.getAddrOfPointer()));
187 }
188
189 /// Assignment from nullptr which just clears the union.
190 const PointerUnion &operator=(std::nullptr_t) {
191 this->Val.initWithPointer(nullptr);
192 return *this;
193 }
194
195 /// Assignment from elements of the union.
196 using Base::operator=;
197
198 void *getOpaqueValue() const { return this->Val.getOpaqueValue(); }
199 static inline PointerUnion getFromOpaqueValue(void *VP) {
200 PointerUnion V;
201 V.Val = decltype(V.Val)::getFromOpaqueValue(VP);
202 return V;
203 }
204};
205
206template <typename ...PTs>
210
211template <typename ...PTs>
215
216template <typename ...PTs>
220
221// Specialization of CastInfo for PointerUnion
222template <typename To, typename... PTs>
223struct CastInfo<To, PointerUnion<PTs...>>
224 : public DefaultDoCastIfPossible<To, PointerUnion<PTs...>,
225 CastInfo<To, PointerUnion<PTs...>>> {
226 using From = PointerUnion<PTs...>;
227
228 static inline bool isPossible(From &f) {
229 return f.Val.getInt() == FirstIndexOfType<To, PTs...>::value;
230 }
231
232 static To doCast(From &f) {
233 assert(isPossible(f) && "cast to an incompatible type!");
234 return PointerLikeTypeTraits<To>::getFromVoidPointer(f.Val.getPointer());
235 }
236
237 static inline To castFailed() { return To(); }
238};
239
240template <typename To, typename... PTs>
241struct CastInfo<To, const PointerUnion<PTs...>>
242 : public ConstStrippingForwardingCast<To, const PointerUnion<PTs...>,
243 CastInfo<To, PointerUnion<PTs...>>> {
244};
245
246// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
247// # low bits available = min(PT1bits,PT2bits)-1.
248template <typename ...PTs>
250 static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) {
251 return P.getOpaqueValue();
252 }
253
254 static inline PointerUnion<PTs...> getFromVoidPointer(void *P) {
256 }
257
258 // The number of bits available are the min of the pointer types minus the
259 // bits needed for the discriminator.
260 static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<decltype(
262};
263
264// Teach DenseMap how to use PointerUnions as keys.
265template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> {
266 using Union = PointerUnion<PTs...>;
267 using FirstInfo =
268 DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>;
269
270 static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); }
271
272 static inline Union getTombstoneKey() {
273 return Union(FirstInfo::getTombstoneKey());
274 }
275
276 static unsigned getHashValue(const Union &UnionVal) {
277 intptr_t key = (intptr_t)UnionVal.getOpaqueValue();
279 }
280
281 static bool isEqual(const Union &LHS, const Union &RHS) {
282 return LHS == RHS;
283 }
284};
285
286} // end namespace llvm
287
288#endif // LLVM_ADT_POINTERUNION_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
This file defines DenseMapInfo traits for DenseMap.
#define I(x, y, z)
Definition MD5.cpp:58
#define T
#define P(N)
This file defines the PointerIntPair class.
This file contains some templates that are useful if you are working with the STL at all.
Value * RHS
Value * LHS
A discriminated union of two or more pointer types, with the discriminator in the low bit of the poin...
PointerUnion()=default
bool isNull() const
Test if the pointer held in the union is null, regardless of which type it is.
T get() const
Returns the value of the specified pointer type.
T dyn_cast() const
Returns the current pointer if it is of the specified pointer type, otherwise returns null.
First const * getAddrOfPtr1() const
If the union is set to the first pointer type get an address pointing to it.
bool is() const
Test if the Union currently holds the type matching T.
void * getOpaqueValue() const
PointerUnion(std::nullptr_t)
const PointerUnion & operator=(std::nullptr_t)
Assignment from nullptr which just clears the union.
First * getAddrOfPtr1()
If the union is set to the first pointer type get an address pointing to it.
static PointerUnion getFromOpaqueValue(void *VP)
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
Provide PointerLikeTypeTraits for void* that is used by PointerUnion for the template arguments.
constexpr int bitsRequired(unsigned n)
Determine the number of bits required to store integers with values < n.
constexpr int lowBitsAvailable()
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:362
bool operator!=(uint64_t V1, const APInt &V2)
Definition APInt.h:2113
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:738
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
std::tuple_element_t< I, std::tuple< Ts... > > TypeAtIndex
Find the type at a given index in a list of types.
Definition STLExtras.h:171
This struct provides a method for customizing the way a cast is performed.
Definition Casting.h:476
static bool isPossible(const From &f)
Definition Casting.h:254
Provides a cast trait that strips const from types to make it easier to implement a const-version of ...
Definition Casting.h:388
This cast trait just provides the default implementation of doCastIfPossible to make CastInfo special...
Definition Casting.h:309
static unsigned getHashValue(const Union &UnionVal)
static bool isEqual(const Union &LHS, const Union &RHS)
DenseMapInfo< typename pointer_union_detail::GetFirstType< PTs... >::type > FirstInfo
An information struct used to provide DenseMap with the various necessary components for a given valu...
Find the first index where a type appears in a list of types.
Definition STLExtras.h:160
static PointerUnion< PTs... > getFromVoidPointer(void *P)
static void * getAsVoidPointer(const PointerUnion< PTs... > &P)
A traits type that is used to handle pointer types and things that are just wrappers for pointers as ...
Determine if all types in Ts are distinct.
Definition STLExtras.h:143
Find the first type in a list of types.