05d362feab22b4d3d68e95f4ab1b90c112435cd9
[oota-llvm.git] / include / llvm / ADT / PointerUnion.h
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"
19 #include "llvm/ADT/PointerIntPair.h"
20
21 namespace llvm {
22
23   template <typename T>
24   struct PointerUnionTypeSelectorReturn {
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>
34   struct PointerUnionTypeSelector {
35     typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return;
36   };
37
38   template <typename T, typename RET_EQ, typename RET_NE>
39   struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
40     typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return;
41   };
42
43   template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
44   struct PointerUnionTypeSelectorReturn<
45                             PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > {
46     typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return
47         Return;
48   };
49
50   /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
51   /// for the two template arguments.
52   template <typename PT1, typename PT2>
53   class PointerUnionUIntTraits {
54   public:
55     static inline void *getAsVoidPointer(void *P) { return P; }
56     static inline void *getFromVoidPointer(void *P) { return P; }
57     enum {
58       PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable),
59       PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable),
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, 
83                            PointerUnionUIntTraits<PT1,PT2> > ValTy;
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:
97     PointerUnion() {}
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.
111       return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
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,
120           ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2,
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");
131       return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
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>
180   static bool operator==(PointerUnion<PT1, PT2> lhs,
181                          PointerUnion<PT1, PT2> rhs) {
182     return lhs.getOpaqueValue() == rhs.getOpaqueValue();
183   }
184
185   template<typename PT1, typename PT2>
186   static bool operator!=(PointerUnion<PT1, PT2> lhs,
187                          PointerUnion<PT1, PT2> rhs) {
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>
194   class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
195   public:
196     static inline void *
197     getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
198       return P.getOpaqueValue();
199     }
200     static inline PointerUnion<PT1, PT2>
201     getFromVoidPointer(void *P) {
202       return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
203     }
204     
205     // The number of bits available are the min of the two pointer types.
206     enum {
207       NumLowBitsAvailable = 
208         PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
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>
217   class PointerUnion3 {
218   public:
219     typedef PointerUnion<PT1, PT2> InnerUnion;
220     typedef PointerUnion<InnerUnion, PT3> ValTy;
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:
252     PointerUnion3() {}
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,
275           ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
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,
288           ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
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 *
330     getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
331       return P.getOpaqueValue();
332     }
333     static inline PointerUnion3<PT1, PT2, PT3>
334     getFromVoidPointer(void *P) {
335       return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
336     }
337     
338     // The number of bits available are the min of the two pointer types.
339     enum {
340       NumLowBitsAvailable = 
341         PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
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>
349   class PointerUnion4 {
350   public:
351     typedef PointerUnion<PT1, PT2> InnerUnion1;
352     typedef PointerUnion<PT3, PT4> InnerUnion2;
353     typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
354   private:
355     ValTy Val;
356   public:
357     PointerUnion4() {}
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,
383           ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
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,
397           ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
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 *
443     getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
444       return P.getOpaqueValue();
445     }
446     static inline PointerUnion4<PT1, PT2, PT3, PT4>
447     getFromVoidPointer(void *P) {
448       return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
449     }
450     
451     // The number of bits available are the min of the two pointer types.
452     enum {
453       NumLowBitsAvailable = 
454         PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
455           ::NumLowBitsAvailable
456     };
457   };
458 }
459
460 #endif