1 //===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the PointerUnion class, which is a discriminated union of
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_ADT_POINTERUNION_H
16 #define LLVM_ADT_POINTERUNION_H
18 #include "llvm/ADT/PointerIntPair.h"
22 /// \brief Statically get an integer for a type. For:
24 /// PointerUnionTypeNum<PT1, PT2>::template NumFor<T>::Result
26 /// Result will be 0 if T is PT1, 1 if it is PT2, and -1 otherwise.
27 template <typename PT1, typename PT2>
28 struct PointerUnionTypeNum {
30 struct IsNeither { char x; };
31 struct IsPT1 { char x[2]; };
32 struct IsPT2 { char x[3]; };
34 static IsPT1 determine(PT1 *P);
35 static IsPT2 determine(PT2 *P);
36 static IsNeither determine(...);
41 static const int Result = (int)sizeof(determine((T*)0)) - 2;
46 struct PointerUnionTypeSelectorReturn {
50 /// \brief Get a type based on whether two types are the same or not. For:
52 /// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
54 /// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
55 template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
56 struct PointerUnionTypeSelector {
57 typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return;
60 template <typename T, typename RET_EQ, typename RET_NE>
61 struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
62 typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return;
65 template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
66 struct PointerUnionTypeSelectorReturn<
67 PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > {
68 typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return
72 /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
73 /// for the two template arguments.
74 template <typename PT1, typename PT2>
75 class PointerUnionUIntTraits {
77 static inline void *getAsVoidPointer(void *P) { return P; }
78 static inline void *getFromVoidPointer(void *P) { return P; }
80 PT1BitsAv = PointerLikeTypeTraits<PT1>::NumLowBitsAvailable,
81 PT2BitsAv = PointerLikeTypeTraits<PT2>::NumLowBitsAvailable,
82 NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
86 /// PointerUnion - This implements a discriminated union of two pointer types,
87 /// and keeps the discriminator bit-mangled into the low bits of the pointer.
88 /// This allows the implementation to be extremely efficient in space, but
89 /// permits a very natural and type-safe API.
91 /// Common use patterns would be something like this:
92 /// PointerUnion<int*, float*> P;
94 /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0"
95 /// X = P.get<int*>(); // ok.
96 /// Y = P.get<float*>(); // runtime assertion failure.
97 /// Z = P.get<double*>(); // runtime assertion failure (regardless of tag)
99 /// Y = P.get<float*>(); // ok.
100 /// X = P.get<int*>(); // runtime assertion failure.
101 template <typename PT1, typename PT2>
104 typedef PointerIntPair<void*, 1, bool,
105 PointerUnionUIntTraits<PT1,PT2> > ValTy;
111 PointerUnion(PT1 V) {
113 const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V)));
116 PointerUnion(PT2 V) {
118 const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)));
122 /// isNull - Return true if the pointer held in the union is null,
123 /// regardless of which type it is.
124 bool isNull() const { return Val.getPointer() == 0; }
125 operator bool() const { return !isNull(); }
127 /// is<T>() return true if the Union currently holds the type matching T.
130 static const int TyNo =
131 ::llvm::PointerUnionTypeNum<PT1, PT2>::template NumFor<T>::Result;
132 char TYPE_IS_NOT_IN_UNION[TyNo*2+1]; // statically check the type.
133 (void)TYPE_IS_NOT_IN_UNION;
134 return static_cast<int>(Val.getInt()) == TyNo;
137 /// get<T>() - Return the value of the specified pointer type. If the
138 /// specified pointer type is incorrect, assert.
141 assert(is<T>() && "Invalid accessor called");
142 return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
145 /// dyn_cast<T>() - If the current value is of the specified pointer type,
146 /// return it, otherwise return null.
149 if (is<T>()) return get<T>();
153 /// \brief If the union is set to the first pointer type we can get an
154 /// address pointing to it.
155 template <typename T>
156 PT1 const *getAddrOf() const {
157 assert(is<PT1>() && "Val is not the first pointer");
158 assert(get<PT1>() == Val.getPointer() &&
159 "Can't get the address because PointerLikeTypeTraits changes the ptr");
160 T const *can_only_get_address_of_first_pointer_type
161 = reinterpret_cast<PT1 const *>(Val.getAddrOfPointer());
162 return can_only_get_address_of_first_pointer_type;
165 /// Assignment operators - Allow assigning into this union from either
166 /// pointer type, setting the discriminator to remember what it came from.
167 const PointerUnion &operator=(const PT1 &RHS) {
169 const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
173 const PointerUnion &operator=(const PT2 &RHS) {
175 const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)));
180 void *getOpaqueValue() const { return Val.getOpaqueValue(); }
181 static inline PointerUnion getFromOpaqueValue(void *VP) {
183 V.Val = ValTy::getFromOpaqueValue(VP);
188 // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
189 // # low bits available = min(PT1bits,PT2bits)-1.
190 template<typename PT1, typename PT2>
191 class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
194 getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
195 return P.getOpaqueValue();
197 static inline PointerUnion<PT1, PT2>
198 getFromVoidPointer(void *P) {
199 return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
202 // The number of bits available are the min of the two pointer types.
204 NumLowBitsAvailable =
205 PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
206 ::NumLowBitsAvailable
211 /// PointerUnion3 - This is a pointer union of three pointer types. See
212 /// documentation for PointerUnion for usage.
213 template <typename PT1, typename PT2, typename PT3>
214 class PointerUnion3 {
216 typedef PointerUnion<PT1, PT2> InnerUnion;
217 typedef PointerUnion<InnerUnion, PT3> ValTy;
221 struct IsInnerUnion {
223 IsInnerUnion(ValTy val) : Val(val) { }
226 return Val.template is<InnerUnion>() &&
227 Val.template get<InnerUnion>().template is<T>();
231 return Val.template get<InnerUnion>().template get<T>();
237 IsPT3(ValTy val) : Val(val) { }
240 return Val.template is<T>();
244 return Val.template get<T>();
251 PointerUnion3(PT1 V) {
254 PointerUnion3(PT2 V) {
257 PointerUnion3(PT3 V) {
261 /// isNull - Return true if the pointer held in the union is null,
262 /// regardless of which type it is.
263 bool isNull() const { return Val.isNull(); }
264 operator bool() const { return !isNull(); }
266 /// is<T>() return true if the Union currently holds the type matching T.
269 // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
271 ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
272 ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
274 return Ty(Val).is<T>();
277 /// get<T>() - Return the value of the specified pointer type. If the
278 /// specified pointer type is incorrect, assert.
281 assert(is<T>() && "Invalid accessor called");
282 // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
284 ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
285 ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
287 return Ty(Val).get<T>();
290 /// dyn_cast<T>() - If the current value is of the specified pointer type,
291 /// return it, otherwise return null.
294 if (is<T>()) return get<T>();
298 /// Assignment operators - Allow assigning into this union from either
299 /// pointer type, setting the discriminator to remember what it came from.
300 const PointerUnion3 &operator=(const PT1 &RHS) {
301 Val = InnerUnion(RHS);
304 const PointerUnion3 &operator=(const PT2 &RHS) {
305 Val = InnerUnion(RHS);
308 const PointerUnion3 &operator=(const PT3 &RHS) {
313 void *getOpaqueValue() const { return Val.getOpaqueValue(); }
314 static inline PointerUnion3 getFromOpaqueValue(void *VP) {
316 V.Val = ValTy::getFromOpaqueValue(VP);
321 // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
322 // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
323 template<typename PT1, typename PT2, typename PT3>
324 class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
327 getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
328 return P.getOpaqueValue();
330 static inline PointerUnion3<PT1, PT2, PT3>
331 getFromVoidPointer(void *P) {
332 return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
335 // The number of bits available are the min of the two pointer types.
337 NumLowBitsAvailable =
338 PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
339 ::NumLowBitsAvailable
343 /// PointerUnion4 - This is a pointer union of four pointer types. See
344 /// documentation for PointerUnion for usage.
345 template <typename PT1, typename PT2, typename PT3, typename PT4>
346 class PointerUnion4 {
348 typedef PointerUnion<PT1, PT2> InnerUnion1;
349 typedef PointerUnion<PT3, PT4> InnerUnion2;
350 typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
356 PointerUnion4(PT1 V) {
357 Val = InnerUnion1(V);
359 PointerUnion4(PT2 V) {
360 Val = InnerUnion1(V);
362 PointerUnion4(PT3 V) {
363 Val = InnerUnion2(V);
365 PointerUnion4(PT4 V) {
366 Val = InnerUnion2(V);
369 /// isNull - Return true if the pointer held in the union is null,
370 /// regardless of which type it is.
371 bool isNull() const { return Val.isNull(); }
372 operator bool() const { return !isNull(); }
374 /// is<T>() return true if the Union currently holds the type matching T.
377 // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
379 ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
380 ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
382 return Val.template is<Ty>() &&
383 Val.template get<Ty>().template is<T>();
386 /// get<T>() - Return the value of the specified pointer type. If the
387 /// specified pointer type is incorrect, assert.
390 assert(is<T>() && "Invalid accessor called");
391 // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
393 ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
394 ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
396 return Val.template get<Ty>().template get<T>();
399 /// dyn_cast<T>() - If the current value is of the specified pointer type,
400 /// return it, otherwise return null.
403 if (is<T>()) return get<T>();
407 /// Assignment operators - Allow assigning into this union from either
408 /// pointer type, setting the discriminator to remember what it came from.
409 const PointerUnion4 &operator=(const PT1 &RHS) {
410 Val = InnerUnion1(RHS);
413 const PointerUnion4 &operator=(const PT2 &RHS) {
414 Val = InnerUnion1(RHS);
417 const PointerUnion4 &operator=(const PT3 &RHS) {
418 Val = InnerUnion2(RHS);
421 const PointerUnion4 &operator=(const PT4 &RHS) {
422 Val = InnerUnion2(RHS);
426 void *getOpaqueValue() const { return Val.getOpaqueValue(); }
427 static inline PointerUnion4 getFromOpaqueValue(void *VP) {
429 V.Val = ValTy::getFromOpaqueValue(VP);
434 // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
435 // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
436 template<typename PT1, typename PT2, typename PT3, typename PT4>
437 class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
440 getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
441 return P.getOpaqueValue();
443 static inline PointerUnion4<PT1, PT2, PT3, PT4>
444 getFromVoidPointer(void *P) {
445 return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
448 // The number of bits available are the min of the two pointer types.
450 NumLowBitsAvailable =
451 PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
452 ::NumLowBitsAvailable