Do a compiler check that we use one of the types from PointerUnion[N], instead of...
[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/ADT/PointerIntPair.h"
19
20 namespace llvm {
21
22   /// \brief Statically get an integer for a type. For:
23   /// @code
24   /// PointerUnionTypeNum<PT1, PT2>::template NumFor<T>::Result
25   /// @endcode
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 {
29   private:
30     struct IsNeither { char x; };
31     struct IsPT1 { char x[2]; };
32     struct IsPT2 { char x[3]; };
33
34     static IsPT1 determine(PT1 *P);
35     static IsPT2 determine(PT2 *P);
36     static IsNeither determine(...);
37
38   public:
39     template <typename T>
40     struct NumFor {
41       static const int Result = (int)sizeof(determine((T*)0)) - 2;
42     };
43   };
44
45   template <typename T>
46   struct PointerUnionTypeSelectorReturn {
47     typedef T Return;
48   };
49
50   /// \brief Get a type based on whether two types are the same or not. For:
51   /// @code
52   /// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
53   /// @endcode
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;
58   };
59
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;
63   };
64
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
69         Return;
70   };
71
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 {
76   public:
77     static inline void *getAsVoidPointer(void *P) { return P; }
78     static inline void *getFromVoidPointer(void *P) { return P; }
79     enum {
80       PT1BitsAv = PointerLikeTypeTraits<PT1>::NumLowBitsAvailable,
81       PT2BitsAv = PointerLikeTypeTraits<PT2>::NumLowBitsAvailable,
82       NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
83     };
84   };
85   
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.
90   ///
91   /// Common use patterns would be something like this:
92   ///    PointerUnion<int*, float*> P;
93   ///    P = (int*)0;
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)
98   ///    P = (float*)0;
99   ///    Y = P.get<float*>();   // ok.
100   ///    X = P.get<int*>();     // runtime assertion failure.
101   template <typename PT1, typename PT2>
102   class PointerUnion {
103   public:
104     typedef PointerIntPair<void*, 1, bool, 
105                            PointerUnionUIntTraits<PT1,PT2> > ValTy;
106   private:
107     ValTy Val;
108   public:
109     PointerUnion() {}
110     
111     PointerUnion(PT1 V) {
112       Val.setPointer(
113          const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V)));
114       Val.setInt(0);
115     }
116     PointerUnion(PT2 V) {
117       Val.setPointer(
118          const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)));
119       Val.setInt(1);
120     }
121     
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(); }
126
127     /// is<T>() return true if the Union currently holds the type matching T.
128     template<typename T>
129     int is() const {
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;
135     }
136     
137     /// get<T>() - Return the value of the specified pointer type. If the
138     /// specified pointer type is incorrect, assert.
139     template<typename T>
140     T get() const {
141       assert(is<T>() && "Invalid accessor called");
142       return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
143     }
144     
145     /// dyn_cast<T>() - If the current value is of the specified pointer type,
146     /// return it, otherwise return null.
147     template<typename T>
148     T dyn_cast() const {
149       if (is<T>()) return get<T>();
150       return T();
151     }
152
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;
163     }
164     
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) {
168       Val.setPointer(
169          const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
170       Val.setInt(0);
171       return *this;
172     }
173     const PointerUnion &operator=(const PT2 &RHS) {
174       Val.setPointer(
175         const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)));
176       Val.setInt(1);
177       return *this;
178     }
179     
180     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
181     static inline PointerUnion getFromOpaqueValue(void *VP) {
182       PointerUnion V;
183       V.Val = ValTy::getFromOpaqueValue(VP);
184       return V;
185     }
186   };
187   
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> > {
192   public:
193     static inline void *
194     getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
195       return P.getOpaqueValue();
196     }
197     static inline PointerUnion<PT1, PT2>
198     getFromVoidPointer(void *P) {
199       return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
200     }
201     
202     // The number of bits available are the min of the two pointer types.
203     enum {
204       NumLowBitsAvailable = 
205         PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
206           ::NumLowBitsAvailable
207     };
208   };
209   
210   
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 {
215   public:
216     typedef PointerUnion<PT1, PT2> InnerUnion;
217     typedef PointerUnion<InnerUnion, PT3> ValTy;
218   private:
219     ValTy Val;
220
221     struct IsInnerUnion {
222       ValTy Val;
223       IsInnerUnion(ValTy val) : Val(val) { }
224       template<typename T>
225       int is() const {
226         return Val.template is<InnerUnion>() && 
227                Val.template get<InnerUnion>().template is<T>();
228       }
229       template<typename T>
230       T get() const {
231         return Val.template get<InnerUnion>().template get<T>();
232       }
233     };
234
235     struct IsPT3 {
236       ValTy Val;
237       IsPT3(ValTy val) : Val(val) { }
238       template<typename T>
239       int is() const {
240         return Val.template is<T>();
241       }
242       template<typename T>
243       T get() const {
244         return Val.template get<T>();
245       }
246     };
247
248   public:
249     PointerUnion3() {}
250     
251     PointerUnion3(PT1 V) {
252       Val = InnerUnion(V);
253     }
254     PointerUnion3(PT2 V) {
255       Val = InnerUnion(V);
256     }
257     PointerUnion3(PT3 V) {
258       Val = V;
259     }
260     
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(); }
265     
266     /// is<T>() return true if the Union currently holds the type matching T.
267     template<typename T>
268     int is() const {
269       // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
270       typedef typename
271         ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
272           ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
273                                                                    >::Return Ty;
274       return Ty(Val).is<T>();
275     }
276     
277     /// get<T>() - Return the value of the specified pointer type. If the
278     /// specified pointer type is incorrect, assert.
279     template<typename T>
280     T get() const {
281       assert(is<T>() && "Invalid accessor called");
282       // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
283       typedef typename
284         ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
285           ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
286                                                                    >::Return Ty;
287       return Ty(Val).get<T>();
288     }
289     
290     /// dyn_cast<T>() - If the current value is of the specified pointer type,
291     /// return it, otherwise return null.
292     template<typename T>
293     T dyn_cast() const {
294       if (is<T>()) return get<T>();
295       return T();
296     }
297     
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);
302       return *this;
303     }
304     const PointerUnion3 &operator=(const PT2 &RHS) {
305       Val = InnerUnion(RHS);
306       return *this;
307     }
308     const PointerUnion3 &operator=(const PT3 &RHS) {
309       Val = RHS;
310       return *this;
311     }
312     
313     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
314     static inline PointerUnion3 getFromOpaqueValue(void *VP) {
315       PointerUnion3 V;
316       V.Val = ValTy::getFromOpaqueValue(VP);
317       return V;
318     }
319   };
320  
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> > {
325   public:
326     static inline void *
327     getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
328       return P.getOpaqueValue();
329     }
330     static inline PointerUnion3<PT1, PT2, PT3>
331     getFromVoidPointer(void *P) {
332       return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
333     }
334     
335     // The number of bits available are the min of the two pointer types.
336     enum {
337       NumLowBitsAvailable = 
338         PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
339           ::NumLowBitsAvailable
340     };
341   };
342
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 {
347   public:
348     typedef PointerUnion<PT1, PT2> InnerUnion1;
349     typedef PointerUnion<PT3, PT4> InnerUnion2;
350     typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
351   private:
352     ValTy Val;
353   public:
354     PointerUnion4() {}
355     
356     PointerUnion4(PT1 V) {
357       Val = InnerUnion1(V);
358     }
359     PointerUnion4(PT2 V) {
360       Val = InnerUnion1(V);
361     }
362     PointerUnion4(PT3 V) {
363       Val = InnerUnion2(V);
364     }
365     PointerUnion4(PT4 V) {
366       Val = InnerUnion2(V);
367     }
368     
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(); }
373     
374     /// is<T>() return true if the Union currently holds the type matching T.
375     template<typename T>
376     int is() const {
377       // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
378       typedef typename
379         ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
380           ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
381                                                                    >::Return Ty;
382       return Val.template is<Ty>() && 
383              Val.template get<Ty>().template is<T>();
384     }
385     
386     /// get<T>() - Return the value of the specified pointer type. If the
387     /// specified pointer type is incorrect, assert.
388     template<typename T>
389     T get() const {
390       assert(is<T>() && "Invalid accessor called");
391       // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
392       typedef typename
393         ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
394           ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
395                                                                    >::Return Ty;
396       return Val.template get<Ty>().template get<T>();
397     }
398     
399     /// dyn_cast<T>() - If the current value is of the specified pointer type,
400     /// return it, otherwise return null.
401     template<typename T>
402     T dyn_cast() const {
403       if (is<T>()) return get<T>();
404       return T();
405     }
406     
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);
411       return *this;
412     }
413     const PointerUnion4 &operator=(const PT2 &RHS) {
414       Val = InnerUnion1(RHS);
415       return *this;
416     }
417     const PointerUnion4 &operator=(const PT3 &RHS) {
418       Val = InnerUnion2(RHS);
419       return *this;
420     }
421     const PointerUnion4 &operator=(const PT4 &RHS) {
422       Val = InnerUnion2(RHS);
423       return *this;
424     }
425     
426     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
427     static inline PointerUnion4 getFromOpaqueValue(void *VP) {
428       PointerUnion4 V;
429       V.Val = ValTy::getFromOpaqueValue(VP);
430       return V;
431     }
432   };
433   
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> > {
438   public:
439     static inline void *
440     getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
441       return P.getOpaqueValue();
442     }
443     static inline PointerUnion4<PT1, PT2, PT3, PT4>
444     getFromVoidPointer(void *P) {
445       return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
446     }
447     
448     // The number of bits available are the min of the two pointer types.
449     enum {
450       NumLowBitsAvailable = 
451         PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
452           ::NumLowBitsAvailable
453     };
454   };
455 }
456
457 #endif