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