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 == 0 ? 0 : llvm::bit_width_constexpr(n - 1);
35 }
36
37 template <typename... Ts> constexpr int lowBitsAvailable() {
38 return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...});
39 }
40
41 /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
42 /// for the template arguments.
43 template <typename ...PTs> class PointerUnionUIntTraits {
44 public:
45 static inline void *getAsVoidPointer(void *P) { return P; }
46 static inline void *getFromVoidPointer(void *P) { return P; }
47 static constexpr int NumLowBitsAvailable = lowBitsAvailable<PTs...>();
48 };
49
50 template <typename Derived, typename ValTy, int I, typename ...Types>
52
53 template <typename Derived, typename ValTy, int I>
54 class PointerUnionMembers<Derived, ValTy, I> {
55 protected:
56 ValTy Val;
59
60 friend struct PointerLikeTypeTraits<Derived>;
61 };
62
63 template <typename Derived, typename ValTy, int I, typename Type,
64 typename ...Types>
65 class PointerUnionMembers<Derived, ValTy, I, Type, Types...>
66 : public PointerUnionMembers<Derived, ValTy, I + 1, Types...> {
67 using Base = PointerUnionMembers<Derived, ValTy, I + 1, Types...>;
68 public:
69 using Base::Base;
72 : Base(ValTy(const_cast<void *>(
73 PointerLikeTypeTraits<Type>::getAsVoidPointer(V)),
74 I)) {}
75
76 using Base::operator=;
77 Derived &operator=(Type V) {
78 this->Val = ValTy(
80 I);
81 return static_cast<Derived &>(*this);
82 };
83 };
84}
85
86/// A discriminated union of two or more pointer types, with the discriminator
87/// in the low bit of the pointer.
88///
89/// This implementation is extremely efficient in space due to leveraging the
90/// low bits of the pointer, while exposing a natural and type-safe API.
91///
92/// Common use patterns would be something like this:
93/// PointerUnion<int*, float*> P;
94/// P = (int*)0;
95/// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0"
96/// X = P.get<int*>(); // ok.
97/// Y = P.get<float*>(); // runtime assertion failure.
98/// Z = P.get<double*>(); // compile time failure.
99/// P = (float*)0;
100/// Y = P.get<float*>(); // ok.
101/// X = P.get<int*>(); // runtime assertion failure.
102/// PointerUnion<int*, int*> Q; // compile time failure.
103template <typename... PTs>
106 PointerUnion<PTs...>,
107 PointerIntPair<
108 void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int,
109 pointer_union_detail::PointerUnionUIntTraits<PTs...>>,
110 0, PTs...> {
111 static_assert(TypesAreDistinct<PTs...>::value,
112 "PointerUnion alternative types cannot be repeated");
113 // The first type is special because we want to directly cast a pointer to a
114 // default-initialized union to a pointer to the first type. But we don't
115 // want PointerUnion to be a 'template <typename First, typename ...Rest>'
116 // because it's much more convenient to have a name for the whole pack. So
117 // split off the first type here.
118 using First = TypeAtIndex<0, PTs...>;
119 using Base = typename PointerUnion::PointerUnionMembers;
120
121 // Give the CastInfo specialization below access to protected members.
122 //
123 // This makes all of CastInfo a friend, which is more than strictly
124 // necessary. It's a workaround for C++'s inability to friend a
125 // partial template specialization.
126 template <typename To, typename From, typename Enable> friend struct CastInfo;
127
128public:
129 PointerUnion() = default;
130
131 PointerUnion(std::nullptr_t) : PointerUnion() {}
132 using Base::Base;
133
134 /// Test if the pointer held in the union is null, regardless of
135 /// which type it is.
136 bool isNull() const { return !this->Val.getPointer(); }
137
138 explicit operator bool() const { return !isNull(); }
139
140 // FIXME: Replace the uses of is(), get() and dyn_cast() with
141 // isa<T>, cast<T> and the llvm::dyn_cast<T>
142
143 /// Test if the Union currently holds the type matching T.
144 template <typename T>
145 [[deprecated("Use isa instead")]]
146 inline bool is() const {
147 return isa<T>(*this);
148 }
149
150 /// Returns the value of the specified pointer type.
151 ///
152 /// If the specified pointer type is incorrect, assert.
153 template <typename T>
154 [[deprecated("Use cast instead")]]
155 inline T get() const {
156 assert(isa<T>(*this) && "Invalid accessor called");
157 return cast<T>(*this);
158 }
159
160 /// Returns the current pointer if it is of the specified pointer type,
161 /// otherwise returns null.
162 template <typename T> inline T dyn_cast() const {
163 return llvm::dyn_cast_if_present<T>(*this);
164 }
165
166 /// If the union is set to the first pointer type get an address pointing to
167 /// it.
168 First const *getAddrOfPtr1() const {
169 return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
170 }
171
172 /// If the union is set to the first pointer type get an address pointing to
173 /// it.
174 First *getAddrOfPtr1() {
175 assert(isa<First>(*this) && "Val is not the first pointer");
176 assert(
178 this->Val.getPointer() &&
179 "Can't get the address because PointerLikeTypeTraits changes the ptr");
180 return const_cast<First *>(
181 reinterpret_cast<const First *>(this->Val.getAddrOfPointer()));
182 }
183
184 /// Assignment from nullptr which just clears the union.
185 const PointerUnion &operator=(std::nullptr_t) {
186 this->Val.initWithPointer(nullptr);
187 return *this;
188 }
189
190 /// Assignment from elements of the union.
191 using Base::operator=;
192
193 void *getOpaqueValue() const { return this->Val.getOpaqueValue(); }
194 static inline PointerUnion getFromOpaqueValue(void *VP) {
195 PointerUnion V;
196 V.Val = decltype(V.Val)::getFromOpaqueValue(VP);
197 return V;
198 }
199};
200
201template <typename ...PTs>
205
206template <typename ...PTs>
210
211template <typename ...PTs>
215
216// Specialization of CastInfo for PointerUnion
217template <typename To, typename... PTs>
218struct CastInfo<To, PointerUnion<PTs...>>
219 : public DefaultDoCastIfPossible<To, PointerUnion<PTs...>,
220 CastInfo<To, PointerUnion<PTs...>>> {
221 using From = PointerUnion<PTs...>;
222
223 static inline bool isPossible(From &f) {
224 return f.Val.getInt() == FirstIndexOfType<To, PTs...>::value;
225 }
226
227 static To doCast(From &f) {
228 assert(isPossible(f) && "cast to an incompatible type!");
229 return PointerLikeTypeTraits<To>::getFromVoidPointer(f.Val.getPointer());
230 }
231
232 static inline To castFailed() { return To(); }
233};
234
235template <typename To, typename... PTs>
236struct CastInfo<To, const PointerUnion<PTs...>>
237 : public ConstStrippingForwardingCast<To, const PointerUnion<PTs...>,
238 CastInfo<To, PointerUnion<PTs...>>> {
239};
240
241// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
242// # low bits available = min(PT1bits,PT2bits)-1.
243template <typename ...PTs>
245 static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) {
246 return P.getOpaqueValue();
247 }
248
249 static inline PointerUnion<PTs...> getFromVoidPointer(void *P) {
251 }
252
253 // The number of bits available are the min of the pointer types minus the
254 // bits needed for the discriminator.
255 static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<decltype(
257};
258
259// Teach DenseMap how to use PointerUnions as keys.
260template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> {
261 using Union = PointerUnion<PTs...>;
262 using FirstInfo = DenseMapInfo<TypeAtIndex<0, PTs...>>;
263
264 static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); }
265
266 static inline Union getTombstoneKey() {
267 return Union(FirstInfo::getTombstoneKey());
268 }
269
270 static unsigned getHashValue(const Union &UnionVal) {
271 intptr_t key = (intptr_t)UnionVal.getOpaqueValue();
273 }
274
275 static bool isEqual(const Union &LHS, const Union &RHS) {
276 return LHS == RHS;
277 }
278};
279
280} // end namespace llvm
281
282#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:733
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:560
std::tuple_element_t< I, std::tuple< Ts... > > TypeAtIndex
Find the type at a given index in a list of types.
Definition STLExtras.h:159
constexpr int bit_width_constexpr(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
Definition bit.h:301
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< TypeAtIndex< 0, PTs... > > 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:148
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:131