1075711ec0c93d686aa8146236eb801ba63093c8
[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       return Val.is<T>();
187     }
188     
189     /// get<T>() - Return the value of the specified pointer type. If the
190     /// specified pointer type is incorrect, assert.
191     template<typename T>
192     T get() const {
193       assert(is<T>() && "Invalid accessor called");
194       // Is it PT1/PT2?
195       if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
196         return Val.get<InnerUnion>().get<T>();
197       
198       return Val.get<T>();
199     }
200     
201     /// dyn_cast<T>() - If the current value is of the specified pointer type,
202     /// return it, otherwise return null.
203     template<typename T>
204     T dyn_cast() const {
205       if (is<T>()) return get<T>();
206       return T();
207     }
208     
209     /// Assignment operators - Allow assigning into this union from either
210     /// pointer type, setting the discriminator to remember what it came from.
211     const PointerUnion3 &operator=(const PT1 &RHS) {
212       Val = InnerUnion(RHS);
213       return *this;
214     }
215     const PointerUnion3 &operator=(const PT2 &RHS) {
216       Val = InnerUnion(RHS);
217       return *this;
218     }
219     const PointerUnion3 &operator=(const PT3 &RHS) {
220       Val = RHS;
221       return *this;
222     }
223     
224     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
225     static PointerUnion3 getFromOpaqueValue(void *VP) {
226       PointerUnion3 V;
227       V.Val = ValTy::getFromOpaqueValue(VP);
228       return V;
229     }
230   };
231  
232   // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
233   // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
234   template<typename PT1, typename PT2, typename PT3>
235   class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
236   public:
237     static inline void *
238     getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
239       return P.getOpaqueValue();
240     }
241     static inline PointerUnion3<PT1, PT2, PT3>
242     getFromVoidPointer(void *P) {
243       return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
244     }
245     
246     // The number of bits available are the min of the two pointer types.
247     enum {
248       NumLowBitsAvailable = 
249         PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
250           ::NumLowBitsAvailable
251     };
252   };
253 }
254
255 #endif