Allow the use of pointers to const within PointerUnion.
[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 help 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 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     /// Assignment operators - Allow assigning into this union from either
112     /// pointer type, setting the discriminator to remember what it came from.
113     const PointerUnion &operator=(const PT1 &RHS) {
114       Val.setPointer(
115          const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
116       Val.setInt(0);
117       return *this;
118     }
119     const PointerUnion &operator=(const PT2 &RHS) {
120       Val.setPointer(
121         const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)));
122       Val.setInt(1);
123       return *this;
124     }
125     
126     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
127     static PointerUnion getFromOpaqueValue(void *VP) {
128       PointerUnion V;
129       V.Val = ValTy::getFromOpaqueValue(VP);
130       return V;
131     }
132   };
133   
134   // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
135   // # low bits available = min(PT1bits,PT2bits)-1.
136   template<typename PT1, typename PT2>
137   class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
138   public:
139     static inline void *
140     getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
141       return P.getOpaqueValue();
142     }
143     static inline PointerUnion<PT1, PT2>
144     getFromVoidPointer(void *P) {
145       return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
146     }
147     
148     // The number of bits available are the min of the two pointer types.
149     enum {
150       NumLowBitsAvailable = 
151         PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
152           ::NumLowBitsAvailable
153     };
154   };
155   
156   
157   /// PointerUnion3 - This is a pointer union of three pointer types.  See
158   /// documentation for PointerUnion for usage.
159   template <typename PT1, typename PT2, typename PT3>
160   class PointerUnion3 {
161   public:
162     typedef PointerUnion<PT1, PT2> InnerUnion;
163     typedef PointerUnion<InnerUnion, PT3> ValTy;
164   private:
165     ValTy Val;
166   public:
167     PointerUnion3() {}
168     
169     PointerUnion3(PT1 V) {
170       Val = InnerUnion(V);
171     }
172     PointerUnion3(PT2 V) {
173       Val = InnerUnion(V);
174     }
175     PointerUnion3(PT3 V) {
176       Val = V;
177     }
178     
179     /// isNull - Return true if the pointer help in the union is null,
180     /// regardless of which type it is.
181     bool isNull() const { return Val.isNull(); }
182     operator bool() const { return !isNull(); }
183     
184     /// is<T>() return true if the Union currently holds the type matching T.
185     template<typename T>
186     int is() const {
187       // Is it PT1/PT2?
188       if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
189         return Val.is<InnerUnion>() && Val.get<InnerUnion>().is<T>();
190       return Val.is<T>();
191     }
192     
193     /// get<T>() - Return the value of the specified pointer type. If the
194     /// specified pointer type is incorrect, assert.
195     template<typename T>
196     T get() const {
197       assert(is<T>() && "Invalid accessor called");
198       // Is it PT1/PT2?
199       if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
200         return Val.get<InnerUnion>().get<T>();
201       
202       return Val.get<T>();
203     }
204     
205     /// dyn_cast<T>() - If the current value is of the specified pointer type,
206     /// return it, otherwise return null.
207     template<typename T>
208     T dyn_cast() const {
209       if (is<T>()) return get<T>();
210       return T();
211     }
212     
213     /// Assignment operators - Allow assigning into this union from either
214     /// pointer type, setting the discriminator to remember what it came from.
215     const PointerUnion3 &operator=(const PT1 &RHS) {
216       Val = InnerUnion(RHS);
217       return *this;
218     }
219     const PointerUnion3 &operator=(const PT2 &RHS) {
220       Val = InnerUnion(RHS);
221       return *this;
222     }
223     const PointerUnion3 &operator=(const PT3 &RHS) {
224       Val = RHS;
225       return *this;
226     }
227     
228     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
229     static PointerUnion3 getFromOpaqueValue(void *VP) {
230       PointerUnion3 V;
231       V.Val = ValTy::getFromOpaqueValue(VP);
232       return V;
233     }
234   };
235  
236   // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
237   // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
238   template<typename PT1, typename PT2, typename PT3>
239   class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
240   public:
241     static inline void *
242     getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
243       return P.getOpaqueValue();
244     }
245     static inline PointerUnion3<PT1, PT2, PT3>
246     getFromVoidPointer(void *P) {
247       return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
248     }
249     
250     // The number of bits available are the min of the two pointer types.
251     enum {
252       NumLowBitsAvailable = 
253         PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
254           ::NumLowBitsAvailable
255     };
256   };
257 }
258
259 #endif