Debug Info: use module flag to set up Dwarf version.
[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/Support/Compiler.h"
19 #include "llvm/ADT/PointerIntPair.h"
20
21 namespace llvm {
22
23   template <typename T>
24   struct PointerUnionTypeSelectorReturn {
25     typedef T Return;
26   };
27
28   /// \brief Get a type based on whether two types are the same or not. For:
29   /// @code
30   /// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
31   /// @endcode
32   /// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
33   template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
34   struct PointerUnionTypeSelector {
35     typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return;
36   };
37
38   template <typename T, typename RET_EQ, typename RET_NE>
39   struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
40     typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return;
41   };
42
43   template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
44   struct PointerUnionTypeSelectorReturn<
45                             PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > {
46     typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return
47         Return;
48   };
49
50   /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
51   /// for the two template arguments.
52   template <typename PT1, typename PT2>
53   class PointerUnionUIntTraits {
54   public:
55     static inline void *getAsVoidPointer(void *P) { return P; }
56     static inline void *getFromVoidPointer(void *P) { return P; }
57     enum {
58       PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable),
59       PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable),
60       NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
61     };
62   };
63   
64   /// PointerUnion - This implements a discriminated union of two pointer types,
65   /// and keeps the discriminator bit-mangled into the low bits of the pointer.
66   /// This allows the implementation to be extremely efficient in space, but
67   /// permits a very natural and type-safe API.
68   ///
69   /// Common use patterns would be something like this:
70   ///    PointerUnion<int*, float*> P;
71   ///    P = (int*)0;
72   ///    printf("%d %d", P.is<int*>(), P.is<float*>());  // prints "1 0"
73   ///    X = P.get<int*>();     // ok.
74   ///    Y = P.get<float*>();   // runtime assertion failure.
75   ///    Z = P.get<double*>();  // runtime assertion failure (regardless of tag)
76   ///    P = (float*)0;
77   ///    Y = P.get<float*>();   // ok.
78   ///    X = P.get<int*>();     // runtime assertion failure.
79   template <typename PT1, typename PT2>
80   class PointerUnion {
81   public:
82     typedef PointerIntPair<void*, 1, bool, 
83                            PointerUnionUIntTraits<PT1,PT2> > ValTy;
84   private:
85     ValTy Val;
86
87     struct IsPT1 {
88       static const int Num = 0;
89     };
90     struct IsPT2 {
91       static const int Num = 1;
92     };
93     template <typename T>
94     struct UNION_DOESNT_CONTAIN_TYPE { };
95
96   public:
97     PointerUnion() {}
98     
99     PointerUnion(PT1 V) : Val(
100       const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
101     }
102     PointerUnion(PT2 V) : Val(
103       const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
104     }
105     
106     /// isNull - Return true if the pointer held in the union is null,
107     /// regardless of which type it is.
108     bool isNull() const {
109       // Convert from the void* to one of the pointer types, to make sure that
110       // we recursively strip off low bits if we have a nested PointerUnion.
111       return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
112     }
113     LLVM_EXPLICIT operator bool() const { return !isNull(); }
114
115     /// is<T>() return true if the Union currently holds the type matching T.
116     template<typename T>
117     int is() const {
118       typedef typename
119         ::llvm::PointerUnionTypeSelector<PT1, T, IsPT1,
120           ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2,
121                                     UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty;
122       int TyNo = Ty::Num;
123       return static_cast<int>(Val.getInt()) == TyNo;
124     }
125     
126     /// get<T>() - Return the value of the specified pointer type. If the
127     /// specified pointer type is incorrect, assert.
128     template<typename T>
129     T get() const {
130       assert(is<T>() && "Invalid accessor called");
131       return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
132     }
133     
134     /// dyn_cast<T>() - If the current value is of the specified pointer type,
135     /// return it, otherwise return null.
136     template<typename T>
137     T dyn_cast() const {
138       if (is<T>()) return get<T>();
139       return T();
140     }
141
142     /// \brief If the union is set to the first pointer type get an address
143     /// pointing to it.
144     PT1 const *getAddrOfPtr1() const {
145       return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
146     }
147
148     /// \brief If the union is set to the first pointer type get an address
149     /// pointing to it.
150     PT1 *getAddrOfPtr1() {
151       assert(is<PT1>() && "Val is not the first pointer");
152       assert(get<PT1>() == Val.getPointer() &&
153          "Can't get the address because PointerLikeTypeTraits changes the ptr");
154       return (PT1 *)Val.getAddrOfPointer();
155     }
156     
157     /// Assignment operators - Allow assigning into this union from either
158     /// pointer type, setting the discriminator to remember what it came from.
159     const PointerUnion &operator=(const PT1 &RHS) {
160       Val.initWithPointer(
161          const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
162       return *this;
163     }
164     const PointerUnion &operator=(const PT2 &RHS) {
165       Val.setPointerAndInt(
166         const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
167         1);
168       return *this;
169     }
170     
171     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
172     static inline PointerUnion getFromOpaqueValue(void *VP) {
173       PointerUnion V;
174       V.Val = ValTy::getFromOpaqueValue(VP);
175       return V;
176     }
177   };
178
179   template<typename PT1, typename PT2>
180   bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
181     return lhs.getOpaqueValue() == rhs.getOpaqueValue();
182   }
183   
184   // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
185   // # low bits available = min(PT1bits,PT2bits)-1.
186   template<typename PT1, typename PT2>
187   class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
188   public:
189     static inline void *
190     getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
191       return P.getOpaqueValue();
192     }
193     static inline PointerUnion<PT1, PT2>
194     getFromVoidPointer(void *P) {
195       return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
196     }
197     
198     // The number of bits available are the min of the two pointer types.
199     enum {
200       NumLowBitsAvailable = 
201         PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
202           ::NumLowBitsAvailable
203     };
204   };
205   
206   
207   /// PointerUnion3 - This is a pointer union of three pointer types.  See
208   /// documentation for PointerUnion for usage.
209   template <typename PT1, typename PT2, typename PT3>
210   class PointerUnion3 {
211   public:
212     typedef PointerUnion<PT1, PT2> InnerUnion;
213     typedef PointerUnion<InnerUnion, PT3> ValTy;
214   private:
215     ValTy Val;
216
217     struct IsInnerUnion {
218       ValTy Val;
219       IsInnerUnion(ValTy val) : Val(val) { }
220       template<typename T>
221       int is() const {
222         return Val.template is<InnerUnion>() && 
223                Val.template get<InnerUnion>().template is<T>();
224       }
225       template<typename T>
226       T get() const {
227         return Val.template get<InnerUnion>().template get<T>();
228       }
229     };
230
231     struct IsPT3 {
232       ValTy Val;
233       IsPT3(ValTy val) : Val(val) { }
234       template<typename T>
235       int is() const {
236         return Val.template is<T>();
237       }
238       template<typename T>
239       T get() const {
240         return Val.template get<T>();
241       }
242     };
243
244   public:
245     PointerUnion3() {}
246     
247     PointerUnion3(PT1 V) {
248       Val = InnerUnion(V);
249     }
250     PointerUnion3(PT2 V) {
251       Val = InnerUnion(V);
252     }
253     PointerUnion3(PT3 V) {
254       Val = V;
255     }
256     
257     /// isNull - Return true if the pointer held in the union is null,
258     /// regardless of which type it is.
259     bool isNull() const { return Val.isNull(); }
260     LLVM_EXPLICIT operator bool() const { return !isNull(); }
261     
262     /// is<T>() return true if the Union currently holds the type matching T.
263     template<typename T>
264     int is() const {
265       // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
266       typedef typename
267         ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
268           ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
269                                                                    >::Return Ty;
270       return Ty(Val).template is<T>();
271     }
272     
273     /// get<T>() - Return the value of the specified pointer type. If the
274     /// specified pointer type is incorrect, assert.
275     template<typename T>
276     T get() const {
277       assert(is<T>() && "Invalid accessor called");
278       // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
279       typedef typename
280         ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
281           ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
282                                                                    >::Return Ty;
283       return Ty(Val).template get<T>();
284     }
285     
286     /// dyn_cast<T>() - If the current value is of the specified pointer type,
287     /// return it, otherwise return null.
288     template<typename T>
289     T dyn_cast() const {
290       if (is<T>()) return get<T>();
291       return T();
292     }
293     
294     /// Assignment operators - Allow assigning into this union from either
295     /// pointer type, setting the discriminator to remember what it came from.
296     const PointerUnion3 &operator=(const PT1 &RHS) {
297       Val = InnerUnion(RHS);
298       return *this;
299     }
300     const PointerUnion3 &operator=(const PT2 &RHS) {
301       Val = InnerUnion(RHS);
302       return *this;
303     }
304     const PointerUnion3 &operator=(const PT3 &RHS) {
305       Val = RHS;
306       return *this;
307     }
308     
309     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
310     static inline PointerUnion3 getFromOpaqueValue(void *VP) {
311       PointerUnion3 V;
312       V.Val = ValTy::getFromOpaqueValue(VP);
313       return V;
314     }
315   };
316  
317   // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
318   // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
319   template<typename PT1, typename PT2, typename PT3>
320   class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
321   public:
322     static inline void *
323     getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
324       return P.getOpaqueValue();
325     }
326     static inline PointerUnion3<PT1, PT2, PT3>
327     getFromVoidPointer(void *P) {
328       return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
329     }
330     
331     // The number of bits available are the min of the two pointer types.
332     enum {
333       NumLowBitsAvailable = 
334         PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
335           ::NumLowBitsAvailable
336     };
337   };
338
339   /// PointerUnion4 - This is a pointer union of four pointer types.  See
340   /// documentation for PointerUnion for usage.
341   template <typename PT1, typename PT2, typename PT3, typename PT4>
342   class PointerUnion4 {
343   public:
344     typedef PointerUnion<PT1, PT2> InnerUnion1;
345     typedef PointerUnion<PT3, PT4> InnerUnion2;
346     typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
347   private:
348     ValTy Val;
349   public:
350     PointerUnion4() {}
351     
352     PointerUnion4(PT1 V) {
353       Val = InnerUnion1(V);
354     }
355     PointerUnion4(PT2 V) {
356       Val = InnerUnion1(V);
357     }
358     PointerUnion4(PT3 V) {
359       Val = InnerUnion2(V);
360     }
361     PointerUnion4(PT4 V) {
362       Val = InnerUnion2(V);
363     }
364     
365     /// isNull - Return true if the pointer held in the union is null,
366     /// regardless of which type it is.
367     bool isNull() const { return Val.isNull(); }
368     LLVM_EXPLICIT operator bool() const { return !isNull(); }
369     
370     /// is<T>() return true if the Union currently holds the type matching T.
371     template<typename T>
372     int is() const {
373       // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
374       typedef typename
375         ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
376           ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
377                                                                    >::Return Ty;
378       return Val.template is<Ty>() && 
379              Val.template get<Ty>().template is<T>();
380     }
381     
382     /// get<T>() - Return the value of the specified pointer type. If the
383     /// specified pointer type is incorrect, assert.
384     template<typename T>
385     T get() const {
386       assert(is<T>() && "Invalid accessor called");
387       // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
388       typedef typename
389         ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
390           ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
391                                                                    >::Return Ty;
392       return Val.template get<Ty>().template get<T>();
393     }
394     
395     /// dyn_cast<T>() - If the current value is of the specified pointer type,
396     /// return it, otherwise return null.
397     template<typename T>
398     T dyn_cast() const {
399       if (is<T>()) return get<T>();
400       return T();
401     }
402     
403     /// Assignment operators - Allow assigning into this union from either
404     /// pointer type, setting the discriminator to remember what it came from.
405     const PointerUnion4 &operator=(const PT1 &RHS) {
406       Val = InnerUnion1(RHS);
407       return *this;
408     }
409     const PointerUnion4 &operator=(const PT2 &RHS) {
410       Val = InnerUnion1(RHS);
411       return *this;
412     }
413     const PointerUnion4 &operator=(const PT3 &RHS) {
414       Val = InnerUnion2(RHS);
415       return *this;
416     }
417     const PointerUnion4 &operator=(const PT4 &RHS) {
418       Val = InnerUnion2(RHS);
419       return *this;
420     }
421     
422     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
423     static inline PointerUnion4 getFromOpaqueValue(void *VP) {
424       PointerUnion4 V;
425       V.Val = ValTy::getFromOpaqueValue(VP);
426       return V;
427     }
428   };
429   
430   // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
431   // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
432   template<typename PT1, typename PT2, typename PT3, typename PT4>
433   class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
434   public:
435     static inline void *
436     getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
437       return P.getOpaqueValue();
438     }
439     static inline PointerUnion4<PT1, PT2, PT3, PT4>
440     getFromVoidPointer(void *P) {
441       return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
442     }
443     
444     // The number of bits available are the min of the two pointer types.
445     enum {
446       NumLowBitsAvailable = 
447         PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
448           ::NumLowBitsAvailable
449     };
450   };
451 }
452
453 #endif