Really, really fix PointerUnion3::is
[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   /// getPointerUnionTypeNum - If the argument has type PT1* or PT2* return
23   /// false or true respectively.
24   template <typename PT1, typename PT2>
25   static inline int getPointerUnionTypeNum(PT1 *P) { return 0; }
26   template <typename PT1, typename PT2>
27   static inline int getPointerUnionTypeNum(PT2 *P) { return 1; }
28   template <typename PT1, typename PT2>
29   static inline int getPointerUnionTypeNum(...) { return -1; }
30   
31   
32   /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
33   /// for the two template arguments.
34   template <typename PT1, typename PT2>
35   class PointerUnionUIntTraits {
36   public:
37     static inline void *getAsVoidPointer(void *P) { return P; }
38     static inline void *getFromVoidPointer(void *P) { return P; }
39     enum {
40       PT1BitsAv = PointerLikeTypeTraits<PT1>::NumLowBitsAvailable,
41       PT2BitsAv = PointerLikeTypeTraits<PT2>::NumLowBitsAvailable,
42       NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
43     };
44   };
45   
46   /// PointerUnion - This implements a discriminated union of two pointer types,
47   /// and keeps the discriminator bit-mangled into the low bits of the pointer.
48   /// This allows the implementation to be extremely efficient in space, but
49   /// permits a very natural and type-safe API.
50   ///
51   /// Common use patterns would be something like this:
52   ///    PointerUnion<int*, float*> P;
53   ///    P = (int*)0;
54   ///    printf("%d %d", P.is<int*>(), P.is<float*>());  // prints "1 0"
55   ///    X = P.get<int*>();     // ok.
56   ///    Y = P.get<float*>();   // runtime assertion failure.
57   ///    Z = P.get<double*>();  // runtime assertion failure (regardless of tag)
58   ///    P = (float*)0;
59   ///    Y = P.get<float*>();   // ok.
60   ///    X = P.get<int*>();     // runtime assertion failure.
61   template <typename PT1, typename PT2>
62   class PointerUnion {
63   public:
64     typedef PointerIntPair<void*, 1, bool, 
65                            PointerUnionUIntTraits<PT1,PT2> > ValTy;
66   private:
67     ValTy Val;
68   public:
69     PointerUnion() {}
70     
71     PointerUnion(PT1 V) {
72       Val.setPointer(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V));
73       Val.setInt(0);
74     }
75     PointerUnion(PT2 V) {
76       Val.setPointer(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V));
77       Val.setInt(1);
78     }
79     
80     /// isNull - Return true if the pointer help in the union is null,
81     /// regardless of which type it is.
82     bool isNull() const { return Val.getPointer() == 0; }
83     operator bool() const { return !isNull(); }
84
85     /// is<T>() return true if the Union currently holds the type matching T.
86     template<typename T>
87     int is() const {
88       int TyNo = ::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0);
89       assert(TyNo != -1 && "Type query could never succeed on PointerUnion!");
90       return Val.getInt() == TyNo;
91     }
92     
93     /// get<T>() - Return the value of the specified pointer type. If the
94     /// specified pointer type is incorrect, assert.
95     template<typename T>
96     T get() const {
97       assert(is<T>() && "Invalid accessor called");
98       return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
99     }
100     
101     /// dyn_cast<T>() - If the current value is of the specified pointer type,
102     /// return it, otherwise return null.
103     template<typename T>
104     T dyn_cast() const {
105       if (is<T>()) return get<T>();
106       return T();
107     }
108     
109     /// Assignment operators - Allow assigning into this union from either
110     /// pointer type, setting the discriminator to remember what it came from.
111     const PointerUnion &operator=(const PT1 &RHS) {
112       Val.setPointer(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS));
113       Val.setInt(0);
114       return *this;
115     }
116     const PointerUnion &operator=(const PT2 &RHS) {
117       Val.setPointer(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS));
118       Val.setInt(1);
119       return *this;
120     }
121     
122     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
123     static PointerUnion getFromOpaqueValue(void *VP) {
124       PointerUnion V;
125       V.Val = ValTy::getFromOpaqueValue(VP);
126       return V;
127     }
128   };
129   
130   // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
131   // # low bits available = min(PT1bits,PT2bits)-1.
132   template<typename PT1, typename PT2>
133   class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
134   public:
135     static inline void *
136     getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
137       return P.getOpaqueValue();
138     }
139     static inline PointerUnion<PT1, PT2>
140     getFromVoidPointer(void *P) {
141       return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
142     }
143     
144     // The number of bits available are the min of the two pointer types.
145     enum {
146       NumLowBitsAvailable = 
147         PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
148           ::NumLowBitsAvailable
149     };
150   };
151   
152   
153   /// PointerUnion3 - This is a pointer union of three pointer types.  See
154   /// documentation for PointerUnion for usage.
155   template <typename PT1, typename PT2, typename PT3>
156   class PointerUnion3 {
157   public:
158     typedef PointerUnion<PT1, PT2> InnerUnion;
159     typedef PointerUnion<InnerUnion, PT3> ValTy;
160   private:
161     ValTy Val;
162   public:
163     PointerUnion3() {}
164     
165     PointerUnion3(PT1 V) {
166       Val = InnerUnion(V);
167     }
168     PointerUnion3(PT2 V) {
169       Val = InnerUnion(V);
170     }
171     PointerUnion3(PT3 V) {
172       Val = V;
173     }
174     
175     /// isNull - Return true if the pointer help in the union is null,
176     /// regardless of which type it is.
177     bool isNull() const { return Val.isNull(); }
178     operator bool() const { return !isNull(); }
179     
180     /// is<T>() return true if the Union currently holds the type matching T.
181     template<typename T>
182     int is() const {
183       // Is it PT1/PT2?
184       if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
185         return Val.is<InnerUnion>() && Val.get<InnerUnion>().is<T>();
186       // Must be PT3 or statically invalid.
187       assert(Val.is<T>());
188       return true;
189     }
190     
191     /// get<T>() - Return the value of the specified pointer type. If the
192     /// specified pointer type is incorrect, assert.
193     template<typename T>
194     T get() const {
195       assert(is<T>() && "Invalid accessor called");
196       // Is it PT1/PT2?
197       if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
198         return Val.get<InnerUnion>().get<T>();
199       
200       return Val.get<T>();
201     }
202     
203     /// dyn_cast<T>() - If the current value is of the specified pointer type,
204     /// return it, otherwise return null.
205     template<typename T>
206     T dyn_cast() const {
207       if (is<T>()) return get<T>();
208       return T();
209     }
210     
211     /// Assignment operators - Allow assigning into this union from either
212     /// pointer type, setting the discriminator to remember what it came from.
213     const PointerUnion3 &operator=(const PT1 &RHS) {
214       Val = InnerUnion(RHS);
215       return *this;
216     }
217     const PointerUnion3 &operator=(const PT2 &RHS) {
218       Val = InnerUnion(RHS);
219       return *this;
220     }
221     const PointerUnion3 &operator=(const PT3 &RHS) {
222       Val = RHS;
223       return *this;
224     }
225     
226     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
227     static PointerUnion3 getFromOpaqueValue(void *VP) {
228       PointerUnion3 V;
229       V.Val = ValTy::getFromOpaqueValue(VP);
230       return V;
231     }
232   };
233  
234   // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
235   // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
236   template<typename PT1, typename PT2, typename PT3>
237   class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
238   public:
239     static inline void *
240     getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
241       return P.getOpaqueValue();
242     }
243     static inline PointerUnion3<PT1, PT2, PT3>
244     getFromVoidPointer(void *P) {
245       return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
246     }
247     
248     // The number of bits available are the min of the two pointer types.
249     enum {
250       NumLowBitsAvailable = 
251         PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
252           ::NumLowBitsAvailable
253     };
254   };
255 }
256
257 #endif