LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PointerUnion.h
Go to the documentation of this file.
1 //===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
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 
18 #include "llvm/Support/Compiler.h"
20 
21 namespace llvm {
22 
23  template <typename T>
25  typedef T Return;
26  };
27 
28  /// \brief Get a type based on whether two types are the same or not. For:
29  /// @code
30  /// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
31  /// @endcode
32  /// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
33  template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
36  };
37 
38  template <typename T, typename RET_EQ, typename RET_NE>
39  struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
41  };
42 
43  template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
45  PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > {
48  };
49 
50  /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
51  /// for the two template arguments.
52  template <typename PT1, typename PT2>
54  public:
55  static inline void *getAsVoidPointer(void *P) { return P; }
56  static inline void *getFromVoidPointer(void *P) { return P; }
57  enum {
60  NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
61  };
62  };
63 
64  /// PointerUnion - This implements a discriminated union of two pointer types,
65  /// and keeps the discriminator bit-mangled into the low bits of the pointer.
66  /// This allows the implementation to be extremely efficient in space, but
67  /// permits a very natural and type-safe API.
68  ///
69  /// Common use patterns would be something like this:
70  /// PointerUnion<int*, float*> P;
71  /// P = (int*)0;
72  /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0"
73  /// X = P.get<int*>(); // ok.
74  /// Y = P.get<float*>(); // runtime assertion failure.
75  /// Z = P.get<double*>(); // compile time failure.
76  /// P = (float*)0;
77  /// Y = P.get<float*>(); // ok.
78  /// X = P.get<int*>(); // runtime assertion failure.
79  template <typename PT1, typename PT2>
80  class PointerUnion {
81  public:
82  typedef PointerIntPair<void*, 1, bool,
84  private:
85  ValTy Val;
86 
87  struct IsPT1 {
88  static const int Num = 0;
89  };
90  struct IsPT2 {
91  static const int Num = 1;
92  };
93  template <typename T>
94  struct UNION_DOESNT_CONTAIN_TYPE { };
95 
96  public:
98 
99  PointerUnion(PT1 V) : Val(
100  const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
101  }
102  PointerUnion(PT2 V) : Val(
103  const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
104  }
105 
106  /// isNull - Return true if the pointer held in the union is null,
107  /// regardless of which type it is.
108  bool isNull() const {
109  // Convert from the void* to one of the pointer types, to make sure that
110  // we recursively strip off low bits if we have a nested PointerUnion.
112  }
113  LLVM_EXPLICIT operator bool() const { return !isNull(); }
114 
115  /// is<T>() return true if the Union currently holds the type matching T.
116  template<typename T>
117  int is() const {
118  typedef typename
119  ::llvm::PointerUnionTypeSelector<PT1, T, IsPT1,
121  UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty;
122  int TyNo = Ty::Num;
123  return static_cast<int>(Val.getInt()) == TyNo;
124  }
125 
126  /// get<T>() - Return the value of the specified pointer type. If the
127  /// specified pointer type is incorrect, assert.
128  template<typename T>
129  T get() const {
130  assert(is<T>() && "Invalid accessor called");
132  }
133 
134  /// dyn_cast<T>() - If the current value is of the specified pointer type,
135  /// return it, otherwise return null.
136  template<typename T>
137  T dyn_cast() const {
138  if (is<T>()) return get<T>();
139  return T();
140  }
141 
142  /// \brief If the union is set to the first pointer type get an address
143  /// pointing to it.
144  PT1 const *getAddrOfPtr1() const {
145  return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
146  }
147 
148  /// \brief If the union is set to the first pointer type get an address
149  /// pointing to it.
150  PT1 *getAddrOfPtr1() {
151  assert(is<PT1>() && "Val is not the first pointer");
152  assert(get<PT1>() == Val.getPointer() &&
153  "Can't get the address because PointerLikeTypeTraits changes the ptr");
154  return (PT1 *)Val.getAddrOfPointer();
155  }
156 
157  /// Assignment operators - Allow assigning into this union from either
158  /// pointer type, setting the discriminator to remember what it came from.
159  const PointerUnion &operator=(const PT1 &RHS) {
160  Val.initWithPointer(
161  const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
162  return *this;
163  }
164  const PointerUnion &operator=(const PT2 &RHS) {
165  Val.setPointerAndInt(
166  const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
167  1);
168  return *this;
169  }
170 
171  void *getOpaqueValue() const { return Val.getOpaqueValue(); }
172  static inline PointerUnion getFromOpaqueValue(void *VP) {
173  PointerUnion V;
174  V.Val = ValTy::getFromOpaqueValue(VP);
175  return V;
176  }
177  };
178 
179  template<typename PT1, typename PT2>
182  return lhs.getOpaqueValue() == rhs.getOpaqueValue();
183  }
184 
185  template<typename PT1, typename PT2>
188  return lhs.getOpaqueValue() != rhs.getOpaqueValue();
189  }
190 
191  // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
192  // # low bits available = min(PT1bits,PT2bits)-1.
193  template<typename PT1, typename PT2>
195  public:
196  static inline void *
198  return P.getOpaqueValue();
199  }
200  static inline PointerUnion<PT1, PT2>
203  }
204 
205  // The number of bits available are the min of the two pointer types.
206  enum {
207  NumLowBitsAvailable =
209  ::NumLowBitsAvailable
210  };
211  };
212 
213 
214  /// PointerUnion3 - This is a pointer union of three pointer types. See
215  /// documentation for PointerUnion for usage.
216  template <typename PT1, typename PT2, typename PT3>
218  public:
221  private:
222  ValTy Val;
223 
224  struct IsInnerUnion {
225  ValTy Val;
226  IsInnerUnion(ValTy val) : Val(val) { }
227  template<typename T>
228  int is() const {
229  return Val.template is<InnerUnion>() &&
230  Val.template get<InnerUnion>().template is<T>();
231  }
232  template<typename T>
233  T get() const {
234  return Val.template get<InnerUnion>().template get<T>();
235  }
236  };
237 
238  struct IsPT3 {
239  ValTy Val;
240  IsPT3(ValTy val) : Val(val) { }
241  template<typename T>
242  int is() const {
243  return Val.template is<T>();
244  }
245  template<typename T>
246  T get() const {
247  return Val.template get<T>();
248  }
249  };
250 
251  public:
253 
254  PointerUnion3(PT1 V) {
255  Val = InnerUnion(V);
256  }
257  PointerUnion3(PT2 V) {
258  Val = InnerUnion(V);
259  }
260  PointerUnion3(PT3 V) {
261  Val = V;
262  }
263 
264  /// isNull - Return true if the pointer held in the union is null,
265  /// regardless of which type it is.
266  bool isNull() const { return Val.isNull(); }
267  LLVM_EXPLICIT operator bool() const { return !isNull(); }
268 
269  /// is<T>() return true if the Union currently holds the type matching T.
270  template<typename T>
271  int is() const {
272  // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
273  typedef typename
274  ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
276  >::Return Ty;
277  return Ty(Val).template is<T>();
278  }
279 
280  /// get<T>() - Return the value of the specified pointer type. If the
281  /// specified pointer type is incorrect, assert.
282  template<typename T>
283  T get() const {
284  assert(is<T>() && "Invalid accessor called");
285  // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
286  typedef typename
287  ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
289  >::Return Ty;
290  return Ty(Val).template get<T>();
291  }
292 
293  /// dyn_cast<T>() - If the current value is of the specified pointer type,
294  /// return it, otherwise return null.
295  template<typename T>
296  T dyn_cast() const {
297  if (is<T>()) return get<T>();
298  return T();
299  }
300 
301  /// Assignment operators - Allow assigning into this union from either
302  /// pointer type, setting the discriminator to remember what it came from.
303  const PointerUnion3 &operator=(const PT1 &RHS) {
304  Val = InnerUnion(RHS);
305  return *this;
306  }
307  const PointerUnion3 &operator=(const PT2 &RHS) {
308  Val = InnerUnion(RHS);
309  return *this;
310  }
311  const PointerUnion3 &operator=(const PT3 &RHS) {
312  Val = RHS;
313  return *this;
314  }
315 
316  void *getOpaqueValue() const { return Val.getOpaqueValue(); }
317  static inline PointerUnion3 getFromOpaqueValue(void *VP) {
318  PointerUnion3 V;
319  V.Val = ValTy::getFromOpaqueValue(VP);
320  return V;
321  }
322  };
323 
324  // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
325  // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
326  template<typename PT1, typename PT2, typename PT3>
327  class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
328  public:
329  static inline void *
331  return P.getOpaqueValue();
332  }
333  static inline PointerUnion3<PT1, PT2, PT3>
336  }
337 
338  // The number of bits available are the min of the two pointer types.
339  enum {
340  NumLowBitsAvailable =
342  ::NumLowBitsAvailable
343  };
344  };
345 
346  /// PointerUnion4 - This is a pointer union of four pointer types. See
347  /// documentation for PointerUnion for usage.
348  template <typename PT1, typename PT2, typename PT3, typename PT4>
350  public:
354  private:
355  ValTy Val;
356  public:
358 
359  PointerUnion4(PT1 V) {
360  Val = InnerUnion1(V);
361  }
362  PointerUnion4(PT2 V) {
363  Val = InnerUnion1(V);
364  }
365  PointerUnion4(PT3 V) {
366  Val = InnerUnion2(V);
367  }
368  PointerUnion4(PT4 V) {
369  Val = InnerUnion2(V);
370  }
371 
372  /// isNull - Return true if the pointer held in the union is null,
373  /// regardless of which type it is.
374  bool isNull() const { return Val.isNull(); }
375  LLVM_EXPLICIT operator bool() const { return !isNull(); }
376 
377  /// is<T>() return true if the Union currently holds the type matching T.
378  template<typename T>
379  int is() const {
380  // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
381  typedef typename
382  ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
384  >::Return Ty;
385  return Val.template is<Ty>() &&
386  Val.template get<Ty>().template is<T>();
387  }
388 
389  /// get<T>() - Return the value of the specified pointer type. If the
390  /// specified pointer type is incorrect, assert.
391  template<typename T>
392  T get() const {
393  assert(is<T>() && "Invalid accessor called");
394  // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
395  typedef typename
396  ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
398  >::Return Ty;
399  return Val.template get<Ty>().template get<T>();
400  }
401 
402  /// dyn_cast<T>() - If the current value is of the specified pointer type,
403  /// return it, otherwise return null.
404  template<typename T>
405  T dyn_cast() const {
406  if (is<T>()) return get<T>();
407  return T();
408  }
409 
410  /// Assignment operators - Allow assigning into this union from either
411  /// pointer type, setting the discriminator to remember what it came from.
412  const PointerUnion4 &operator=(const PT1 &RHS) {
413  Val = InnerUnion1(RHS);
414  return *this;
415  }
416  const PointerUnion4 &operator=(const PT2 &RHS) {
417  Val = InnerUnion1(RHS);
418  return *this;
419  }
420  const PointerUnion4 &operator=(const PT3 &RHS) {
421  Val = InnerUnion2(RHS);
422  return *this;
423  }
424  const PointerUnion4 &operator=(const PT4 &RHS) {
425  Val = InnerUnion2(RHS);
426  return *this;
427  }
428 
429  void *getOpaqueValue() const { return Val.getOpaqueValue(); }
430  static inline PointerUnion4 getFromOpaqueValue(void *VP) {
431  PointerUnion4 V;
432  V.Val = ValTy::getFromOpaqueValue(VP);
433  return V;
434  }
435  };
436 
437  // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
438  // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
439  template<typename PT1, typename PT2, typename PT3, typename PT4>
440  class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
441  public:
442  static inline void *
444  return P.getOpaqueValue();
445  }
449  }
450 
451  // The number of bits available are the min of the two pointer types.
452  enum {
453  NumLowBitsAvailable =
455  ::NumLowBitsAvailable
456  };
457  };
458 }
459 
460 #endif
const PointerUnion4 & operator=(const PT3 &RHS)
Definition: PointerUnion.h:420
void * getOpaqueValue() const
Definition: PointerUnion.h:316
PointerUnionTypeSelectorReturn< RET_NE >::Return Return
Definition: PointerUnion.h:35
const PointerUnion4 & operator=(const PT1 &RHS)
Definition: PointerUnion.h:412
const PointerUnion & operator=(const PT1 &RHS)
Definition: PointerUnion.h:159
PT1 * getAddrOfPtr1()
If the union is set to the first pointer type get an address pointing to it.
Definition: PointerUnion.h:150
static PointerUnion4 getFromOpaqueValue(void *VP)
Definition: PointerUnion.h:430
T dyn_cast() const
Definition: PointerUnion.h:137
const PointerUnion & operator=(const PT2 &RHS)
Definition: PointerUnion.h:164
PointerUnion< InnerUnion, PT3 > ValTy
Definition: PointerUnion.h:220
int is() const
is<T>() return true if the Union currently holds the type matching T.
Definition: PointerUnion.h:379
PointerUnion< InnerUnion1, InnerUnion2 > ValTy
Definition: PointerUnion.h:353
static PointerUnion< PT1, PT2 > getFromVoidPointer(void *P)
Definition: PointerUnion.h:201
static PointerUnion getFromOpaqueValue(void *VP)
Definition: PointerUnion.h:172
void * getOpaqueValue() const
Definition: PointerUnion.h:171
PointerUnionTypeSelector< T1, T2, RET_EQ, RET_NE >::Return Return
Definition: PointerUnion.h:47
static void * getAsVoidPointer(void *P)
Definition: PointerUnion.h:55
static void * getAsVoidPointer(const PointerUnion3< PT1, PT2, PT3 > &P)
Definition: PointerUnion.h:330
void setPointerAndInt(PointerTy PtrVal, IntType IntVal)
void initWithPointer(PointerTy PtrVal)
Get a type based on whether two types are the same or not. For:
Definition: PointerUnion.h:34
static PointerUnion4< PT1, PT2, PT3, PT4 > getFromVoidPointer(void *P)
Definition: PointerUnion.h:447
#define T
const PointerUnion3 & operator=(const PT3 &RHS)
Definition: PointerUnion.h:311
static void * getAsVoidPointer(const PointerUnion< PT1, PT2 > &P)
Definition: PointerUnion.h:197
const PointerUnion4 & operator=(const PT2 &RHS)
Definition: PointerUnion.h:416
bool isNull() const
Definition: PointerUnion.h:266
#define P(N)
const PointerUnion3 & operator=(const PT1 &RHS)
Definition: PointerUnion.h:303
PT1 const * getAddrOfPtr1() const
If the union is set to the first pointer type get an address pointing to it.
Definition: PointerUnion.h:144
const PointerUnion4 & operator=(const PT4 &RHS)
Definition: PointerUnion.h:424
int is() const
is<T>() return true if the Union currently holds the type matching T.
Definition: PointerUnion.h:271
bool isNull() const
Definition: PointerUnion.h:374
IntType getInt() const
static PointerUnion3< PT1, PT2, PT3 > getFromVoidPointer(void *P)
Definition: PointerUnion.h:334
PointerUnionTypeSelectorReturn< RET_EQ >::Return Return
Definition: PointerUnion.h:40
bool isNull() const
Definition: PointerUnion.h:108
static PointerUnion3 getFromOpaqueValue(void *VP)
Definition: PointerUnion.h:317
static void * getAsVoidPointer(const PointerUnion4< PT1, PT2, PT3, PT4 > &P)
Definition: PointerUnion.h:443
PointerIntPair< void *, 1, bool, PointerUnionUIntTraits< PT1, PT2 > > ValTy
Definition: PointerUnion.h:83
PointerTy getPointer() const
PointerUnion< PT1, PT2 > InnerUnion
Definition: PointerUnion.h:219
Instr is a return instruction.
Definition: GCMetadata.h:52
void * getOpaqueValue() const
bool operator!=(uint64_t V1, const APInt &V2)
Definition: APInt.h:1686
void * getOpaqueValue() const
Definition: PointerUnion.h:429
#define LLVM_EXPLICIT
Expands to explicit on compilers which support explicit conversion operators. Otherwise expands to no...
Definition: Compiler.h:381
const PointerUnion3 & operator=(const PT2 &RHS)
Definition: PointerUnion.h:307
PointerUnion< PT1, PT2 > InnerUnion1
Definition: PointerUnion.h:351
bool operator==(uint64_t V1, const APInt &V2)
Definition: APInt.h:1684
int is() const
is<T>() return true if the Union currently holds the type matching T.
Definition: PointerUnion.h:117
static void * getFromVoidPointer(void *P)
Definition: PointerUnion.h:56
PointerUnion< PT3, PT4 > InnerUnion2
Definition: PointerUnion.h:352
PointerTy const * getAddrOfPointer() const
#define T1