61de042b0ff2c0923c63a67f67384f080f1698f6
[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(
73          const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V)));
74       Val.setInt(0);
75     }
76     PointerUnion(PT2 V) {
77       Val.setPointer(
78          const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)));
79       Val.setInt(1);
80     }
81     
82     /// isNull - Return true if the pointer held in the union is null,
83     /// regardless of which type it is.
84     bool isNull() const { return Val.getPointer() == 0; }
85     operator bool() const { return !isNull(); }
86
87     /// is<T>() return true if the Union currently holds the type matching T.
88     template<typename T>
89     int is() const {
90       int TyNo = ::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0);
91       assert(TyNo != -1 && "Type query could never succeed on PointerUnion!");
92       return static_cast<int>(Val.getInt()) == TyNo;
93     }
94     
95     /// get<T>() - Return the value of the specified pointer type. If the
96     /// specified pointer type is incorrect, assert.
97     template<typename T>
98     T get() const {
99       assert(is<T>() && "Invalid accessor called");
100       return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
101     }
102     
103     /// dyn_cast<T>() - If the current value is of the specified pointer type,
104     /// return it, otherwise return null.
105     template<typename T>
106     T dyn_cast() const {
107       if (is<T>()) return get<T>();
108       return T();
109     }
110
111     /// \brief If the union is set to the first pointer type we can get an
112     /// address pointing to it.
113     template <typename T>
114     PT1 const *getAddrOf() const {
115       assert(is<PT1>() && "Val is not the first pointer");
116       assert(get<PT1>() == Val.getPointer() &&
117          "Can't get the address because PointerLikeTypeTraits changes the ptr");
118       T const *can_only_get_address_of_first_pointer_type
119                         = reinterpret_cast<PT1 const *>(Val.getAddrOfPointer());
120       return can_only_get_address_of_first_pointer_type;
121     }
122     
123     /// Assignment operators - Allow assigning into this union from either
124     /// pointer type, setting the discriminator to remember what it came from.
125     const PointerUnion &operator=(const PT1 &RHS) {
126       Val.setPointer(
127          const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
128       Val.setInt(0);
129       return *this;
130     }
131     const PointerUnion &operator=(const PT2 &RHS) {
132       Val.setPointer(
133         const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)));
134       Val.setInt(1);
135       return *this;
136     }
137     
138     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
139     static inline PointerUnion getFromOpaqueValue(void *VP) {
140       PointerUnion V;
141       V.Val = ValTy::getFromOpaqueValue(VP);
142       return V;
143     }
144   };
145   
146   // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
147   // # low bits available = min(PT1bits,PT2bits)-1.
148   template<typename PT1, typename PT2>
149   class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
150   public:
151     static inline void *
152     getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
153       return P.getOpaqueValue();
154     }
155     static inline PointerUnion<PT1, PT2>
156     getFromVoidPointer(void *P) {
157       return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
158     }
159     
160     // The number of bits available are the min of the two pointer types.
161     enum {
162       NumLowBitsAvailable = 
163         PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
164           ::NumLowBitsAvailable
165     };
166   };
167   
168   
169   /// PointerUnion3 - This is a pointer union of three pointer types.  See
170   /// documentation for PointerUnion for usage.
171   template <typename PT1, typename PT2, typename PT3>
172   class PointerUnion3 {
173   public:
174     typedef PointerUnion<PT1, PT2> InnerUnion;
175     typedef PointerUnion<InnerUnion, PT3> ValTy;
176   private:
177     ValTy Val;
178   public:
179     PointerUnion3() {}
180     
181     PointerUnion3(PT1 V) {
182       Val = InnerUnion(V);
183     }
184     PointerUnion3(PT2 V) {
185       Val = InnerUnion(V);
186     }
187     PointerUnion3(PT3 V) {
188       Val = V;
189     }
190     
191     /// isNull - Return true if the pointer held in the union is null,
192     /// regardless of which type it is.
193     bool isNull() const { return Val.isNull(); }
194     operator bool() const { return !isNull(); }
195     
196     /// is<T>() return true if the Union currently holds the type matching T.
197     template<typename T>
198     int is() const {
199       // Is it PT1/PT2?
200       if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
201         return Val.template is<InnerUnion>() && 
202                Val.template get<InnerUnion>().template is<T>();
203       return Val.template is<T>();
204     }
205     
206     /// get<T>() - Return the value of the specified pointer type. If the
207     /// specified pointer type is incorrect, assert.
208     template<typename T>
209     T get() const {
210       assert(is<T>() && "Invalid accessor called");
211       // Is it PT1/PT2?
212       if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
213         return Val.template get<InnerUnion>().template get<T>();
214       
215       return Val.template get<T>();
216     }
217     
218     /// dyn_cast<T>() - If the current value is of the specified pointer type,
219     /// return it, otherwise return null.
220     template<typename T>
221     T dyn_cast() const {
222       if (is<T>()) return get<T>();
223       return T();
224     }
225     
226     /// Assignment operators - Allow assigning into this union from either
227     /// pointer type, setting the discriminator to remember what it came from.
228     const PointerUnion3 &operator=(const PT1 &RHS) {
229       Val = InnerUnion(RHS);
230       return *this;
231     }
232     const PointerUnion3 &operator=(const PT2 &RHS) {
233       Val = InnerUnion(RHS);
234       return *this;
235     }
236     const PointerUnion3 &operator=(const PT3 &RHS) {
237       Val = RHS;
238       return *this;
239     }
240     
241     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
242     static inline PointerUnion3 getFromOpaqueValue(void *VP) {
243       PointerUnion3 V;
244       V.Val = ValTy::getFromOpaqueValue(VP);
245       return V;
246     }
247   };
248  
249   // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
250   // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
251   template<typename PT1, typename PT2, typename PT3>
252   class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
253   public:
254     static inline void *
255     getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
256       return P.getOpaqueValue();
257     }
258     static inline PointerUnion3<PT1, PT2, PT3>
259     getFromVoidPointer(void *P) {
260       return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
261     }
262     
263     // The number of bits available are the min of the two pointer types.
264     enum {
265       NumLowBitsAvailable = 
266         PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
267           ::NumLowBitsAvailable
268     };
269   };
270
271   /// PointerUnion4 - This is a pointer union of four pointer types.  See
272   /// documentation for PointerUnion for usage.
273   template <typename PT1, typename PT2, typename PT3, typename PT4>
274   class PointerUnion4 {
275   public:
276     typedef PointerUnion<PT1, PT2> InnerUnion1;
277     typedef PointerUnion<PT3, PT4> InnerUnion2;
278     typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
279   private:
280     ValTy Val;
281   public:
282     PointerUnion4() {}
283     
284     PointerUnion4(PT1 V) {
285       Val = InnerUnion1(V);
286     }
287     PointerUnion4(PT2 V) {
288       Val = InnerUnion1(V);
289     }
290     PointerUnion4(PT3 V) {
291       Val = InnerUnion2(V);
292     }
293     PointerUnion4(PT4 V) {
294       Val = InnerUnion2(V);
295     }
296     
297     /// isNull - Return true if the pointer held in the union is null,
298     /// regardless of which type it is.
299     bool isNull() const { return Val.isNull(); }
300     operator bool() const { return !isNull(); }
301     
302     /// is<T>() return true if the Union currently holds the type matching T.
303     template<typename T>
304     int is() const {
305       // Is it PT1/PT2?
306       if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
307         return Val.template is<InnerUnion1>() && 
308                Val.template get<InnerUnion1>().template is<T>();
309       return Val.template is<InnerUnion2>() && 
310              Val.template get<InnerUnion2>().template is<T>();
311     }
312     
313     /// get<T>() - Return the value of the specified pointer type. If the
314     /// specified pointer type is incorrect, assert.
315     template<typename T>
316     T get() const {
317       assert(is<T>() && "Invalid accessor called");
318       // Is it PT1/PT2?
319       if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
320         return Val.template get<InnerUnion1>().template get<T>();
321       
322       return Val.template get<InnerUnion2>().template get<T>();
323     }
324     
325     /// dyn_cast<T>() - If the current value is of the specified pointer type,
326     /// return it, otherwise return null.
327     template<typename T>
328     T dyn_cast() const {
329       if (is<T>()) return get<T>();
330       return T();
331     }
332     
333     /// Assignment operators - Allow assigning into this union from either
334     /// pointer type, setting the discriminator to remember what it came from.
335     const PointerUnion4 &operator=(const PT1 &RHS) {
336       Val = InnerUnion1(RHS);
337       return *this;
338     }
339     const PointerUnion4 &operator=(const PT2 &RHS) {
340       Val = InnerUnion1(RHS);
341       return *this;
342     }
343     const PointerUnion4 &operator=(const PT3 &RHS) {
344       Val = InnerUnion2(RHS);
345       return *this;
346     }
347     const PointerUnion4 &operator=(const PT4 &RHS) {
348       Val = InnerUnion2(RHS);
349       return *this;
350     }
351     
352     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
353     static inline PointerUnion4 getFromOpaqueValue(void *VP) {
354       PointerUnion4 V;
355       V.Val = ValTy::getFromOpaqueValue(VP);
356       return V;
357     }
358   };
359   
360   // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
361   // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
362   template<typename PT1, typename PT2, typename PT3, typename PT4>
363   class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
364   public:
365     static inline void *
366     getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
367       return P.getOpaqueValue();
368     }
369     static inline PointerUnion4<PT1, PT2, PT3, PT4>
370     getFromVoidPointer(void *P) {
371       return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
372     }
373     
374     // The number of bits available are the min of the two pointer types.
375     enum {
376       NumLowBitsAvailable = 
377         PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
378           ::NumLowBitsAvailable
379     };
380   };
381 }
382
383 #endif