LLVM API Documentation

PointerUnion.h
Go to the documentation of this file.
00001 //===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines the PointerUnion class, which is a discriminated union of
00011 // pointer types.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_ADT_POINTERUNION_H
00016 #define LLVM_ADT_POINTERUNION_H
00017 
00018 #include "llvm/Support/Compiler.h"
00019 #include "llvm/ADT/PointerIntPair.h"
00020 
00021 namespace llvm {
00022 
00023   template <typename T>
00024   struct PointerUnionTypeSelectorReturn {
00025     typedef T Return;
00026   };
00027 
00028   /// \brief Get a type based on whether two types are the same or not. For:
00029   /// @code
00030   /// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
00031   /// @endcode
00032   /// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
00033   template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
00034   struct PointerUnionTypeSelector {
00035     typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return;
00036   };
00037 
00038   template <typename T, typename RET_EQ, typename RET_NE>
00039   struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
00040     typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return;
00041   };
00042 
00043   template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
00044   struct PointerUnionTypeSelectorReturn<
00045                             PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > {
00046     typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return
00047         Return;
00048   };
00049 
00050   /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
00051   /// for the two template arguments.
00052   template <typename PT1, typename PT2>
00053   class PointerUnionUIntTraits {
00054   public:
00055     static inline void *getAsVoidPointer(void *P) { return P; }
00056     static inline void *getFromVoidPointer(void *P) { return P; }
00057     enum {
00058       PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable),
00059       PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable),
00060       NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
00061     };
00062   };
00063   
00064   /// PointerUnion - This implements a discriminated union of two pointer types,
00065   /// and keeps the discriminator bit-mangled into the low bits of the pointer.
00066   /// This allows the implementation to be extremely efficient in space, but
00067   /// permits a very natural and type-safe API.
00068   ///
00069   /// Common use patterns would be something like this:
00070   ///    PointerUnion<int*, float*> P;
00071   ///    P = (int*)0;
00072   ///    printf("%d %d", P.is<int*>(), P.is<float*>());  // prints "1 0"
00073   ///    X = P.get<int*>();     // ok.
00074   ///    Y = P.get<float*>();   // runtime assertion failure.
00075   ///    Z = P.get<double*>();  // runtime assertion failure (regardless of tag)
00076   ///    P = (float*)0;
00077   ///    Y = P.get<float*>();   // ok.
00078   ///    X = P.get<int*>();     // runtime assertion failure.
00079   template <typename PT1, typename PT2>
00080   class PointerUnion {
00081   public:
00082     typedef PointerIntPair<void*, 1, bool, 
00083                            PointerUnionUIntTraits<PT1,PT2> > ValTy;
00084   private:
00085     ValTy Val;
00086 
00087     struct IsPT1 {
00088       static const int Num = 0;
00089     };
00090     struct IsPT2 {
00091       static const int Num = 1;
00092     };
00093     template <typename T>
00094     struct UNION_DOESNT_CONTAIN_TYPE { };
00095 
00096   public:
00097     PointerUnion() {}
00098     
00099     PointerUnion(PT1 V) : Val(
00100       const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
00101     }
00102     PointerUnion(PT2 V) : Val(
00103       const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
00104     }
00105     
00106     /// isNull - Return true if the pointer held in the union is null,
00107     /// regardless of which type it is.
00108     bool isNull() const {
00109       // Convert from the void* to one of the pointer types, to make sure that
00110       // we recursively strip off low bits if we have a nested PointerUnion.
00111       return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
00112     }
00113     LLVM_EXPLICIT operator bool() const { return !isNull(); }
00114 
00115     /// is<T>() return true if the Union currently holds the type matching T.
00116     template<typename T>
00117     int is() const {
00118       typedef typename
00119         ::llvm::PointerUnionTypeSelector<PT1, T, IsPT1,
00120           ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2,
00121                                     UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty;
00122       int TyNo = Ty::Num;
00123       return static_cast<int>(Val.getInt()) == TyNo;
00124     }
00125     
00126     /// get<T>() - Return the value of the specified pointer type. If the
00127     /// specified pointer type is incorrect, assert.
00128     template<typename T>
00129     T get() const {
00130       assert(is<T>() && "Invalid accessor called");
00131       return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
00132     }
00133     
00134     /// dyn_cast<T>() - If the current value is of the specified pointer type,
00135     /// return it, otherwise return null.
00136     template<typename T>
00137     T dyn_cast() const {
00138       if (is<T>()) return get<T>();
00139       return T();
00140     }
00141 
00142     /// \brief If the union is set to the first pointer type get an address
00143     /// pointing to it.
00144     PT1 const *getAddrOfPtr1() const {
00145       return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
00146     }
00147 
00148     /// \brief If the union is set to the first pointer type get an address
00149     /// pointing to it.
00150     PT1 *getAddrOfPtr1() {
00151       assert(is<PT1>() && "Val is not the first pointer");
00152       assert(get<PT1>() == Val.getPointer() &&
00153          "Can't get the address because PointerLikeTypeTraits changes the ptr");
00154       return (PT1 *)Val.getAddrOfPointer();
00155     }
00156     
00157     /// Assignment operators - Allow assigning into this union from either
00158     /// pointer type, setting the discriminator to remember what it came from.
00159     const PointerUnion &operator=(const PT1 &RHS) {
00160       Val.initWithPointer(
00161          const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
00162       return *this;
00163     }
00164     const PointerUnion &operator=(const PT2 &RHS) {
00165       Val.setPointerAndInt(
00166         const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
00167         1);
00168       return *this;
00169     }
00170     
00171     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
00172     static inline PointerUnion getFromOpaqueValue(void *VP) {
00173       PointerUnion V;
00174       V.Val = ValTy::getFromOpaqueValue(VP);
00175       return V;
00176     }
00177   };
00178 
00179   template<typename PT1, typename PT2>
00180   bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
00181     return lhs.getOpaqueValue() == rhs.getOpaqueValue();
00182   }
00183   
00184   // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
00185   // # low bits available = min(PT1bits,PT2bits)-1.
00186   template<typename PT1, typename PT2>
00187   class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
00188   public:
00189     static inline void *
00190     getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
00191       return P.getOpaqueValue();
00192     }
00193     static inline PointerUnion<PT1, PT2>
00194     getFromVoidPointer(void *P) {
00195       return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
00196     }
00197     
00198     // The number of bits available are the min of the two pointer types.
00199     enum {
00200       NumLowBitsAvailable = 
00201         PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
00202           ::NumLowBitsAvailable
00203     };
00204   };
00205   
00206   
00207   /// PointerUnion3 - This is a pointer union of three pointer types.  See
00208   /// documentation for PointerUnion for usage.
00209   template <typename PT1, typename PT2, typename PT3>
00210   class PointerUnion3 {
00211   public:
00212     typedef PointerUnion<PT1, PT2> InnerUnion;
00213     typedef PointerUnion<InnerUnion, PT3> ValTy;
00214   private:
00215     ValTy Val;
00216 
00217     struct IsInnerUnion {
00218       ValTy Val;
00219       IsInnerUnion(ValTy val) : Val(val) { }
00220       template<typename T>
00221       int is() const {
00222         return Val.template is<InnerUnion>() && 
00223                Val.template get<InnerUnion>().template is<T>();
00224       }
00225       template<typename T>
00226       T get() const {
00227         return Val.template get<InnerUnion>().template get<T>();
00228       }
00229     };
00230 
00231     struct IsPT3 {
00232       ValTy Val;
00233       IsPT3(ValTy val) : Val(val) { }
00234       template<typename T>
00235       int is() const {
00236         return Val.template is<T>();
00237       }
00238       template<typename T>
00239       T get() const {
00240         return Val.template get<T>();
00241       }
00242     };
00243 
00244   public:
00245     PointerUnion3() {}
00246     
00247     PointerUnion3(PT1 V) {
00248       Val = InnerUnion(V);
00249     }
00250     PointerUnion3(PT2 V) {
00251       Val = InnerUnion(V);
00252     }
00253     PointerUnion3(PT3 V) {
00254       Val = V;
00255     }
00256     
00257     /// isNull - Return true if the pointer held in the union is null,
00258     /// regardless of which type it is.
00259     bool isNull() const { return Val.isNull(); }
00260     LLVM_EXPLICIT operator bool() const { return !isNull(); }
00261     
00262     /// is<T>() return true if the Union currently holds the type matching T.
00263     template<typename T>
00264     int is() const {
00265       // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
00266       typedef typename
00267         ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
00268           ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
00269                                                                    >::Return Ty;
00270       return Ty(Val).template is<T>();
00271     }
00272     
00273     /// get<T>() - Return the value of the specified pointer type. If the
00274     /// specified pointer type is incorrect, assert.
00275     template<typename T>
00276     T get() const {
00277       assert(is<T>() && "Invalid accessor called");
00278       // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
00279       typedef typename
00280         ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
00281           ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
00282                                                                    >::Return Ty;
00283       return Ty(Val).template get<T>();
00284     }
00285     
00286     /// dyn_cast<T>() - If the current value is of the specified pointer type,
00287     /// return it, otherwise return null.
00288     template<typename T>
00289     T dyn_cast() const {
00290       if (is<T>()) return get<T>();
00291       return T();
00292     }
00293     
00294     /// Assignment operators - Allow assigning into this union from either
00295     /// pointer type, setting the discriminator to remember what it came from.
00296     const PointerUnion3 &operator=(const PT1 &RHS) {
00297       Val = InnerUnion(RHS);
00298       return *this;
00299     }
00300     const PointerUnion3 &operator=(const PT2 &RHS) {
00301       Val = InnerUnion(RHS);
00302       return *this;
00303     }
00304     const PointerUnion3 &operator=(const PT3 &RHS) {
00305       Val = RHS;
00306       return *this;
00307     }
00308     
00309     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
00310     static inline PointerUnion3 getFromOpaqueValue(void *VP) {
00311       PointerUnion3 V;
00312       V.Val = ValTy::getFromOpaqueValue(VP);
00313       return V;
00314     }
00315   };
00316  
00317   // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
00318   // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
00319   template<typename PT1, typename PT2, typename PT3>
00320   class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
00321   public:
00322     static inline void *
00323     getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
00324       return P.getOpaqueValue();
00325     }
00326     static inline PointerUnion3<PT1, PT2, PT3>
00327     getFromVoidPointer(void *P) {
00328       return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
00329     }
00330     
00331     // The number of bits available are the min of the two pointer types.
00332     enum {
00333       NumLowBitsAvailable = 
00334         PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
00335           ::NumLowBitsAvailable
00336     };
00337   };
00338 
00339   /// PointerUnion4 - This is a pointer union of four pointer types.  See
00340   /// documentation for PointerUnion for usage.
00341   template <typename PT1, typename PT2, typename PT3, typename PT4>
00342   class PointerUnion4 {
00343   public:
00344     typedef PointerUnion<PT1, PT2> InnerUnion1;
00345     typedef PointerUnion<PT3, PT4> InnerUnion2;
00346     typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
00347   private:
00348     ValTy Val;
00349   public:
00350     PointerUnion4() {}
00351     
00352     PointerUnion4(PT1 V) {
00353       Val = InnerUnion1(V);
00354     }
00355     PointerUnion4(PT2 V) {
00356       Val = InnerUnion1(V);
00357     }
00358     PointerUnion4(PT3 V) {
00359       Val = InnerUnion2(V);
00360     }
00361     PointerUnion4(PT4 V) {
00362       Val = InnerUnion2(V);
00363     }
00364     
00365     /// isNull - Return true if the pointer held in the union is null,
00366     /// regardless of which type it is.
00367     bool isNull() const { return Val.isNull(); }
00368     LLVM_EXPLICIT operator bool() const { return !isNull(); }
00369     
00370     /// is<T>() return true if the Union currently holds the type matching T.
00371     template<typename T>
00372     int is() const {
00373       // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
00374       typedef typename
00375         ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
00376           ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
00377                                                                    >::Return Ty;
00378       return Val.template is<Ty>() && 
00379              Val.template get<Ty>().template is<T>();
00380     }
00381     
00382     /// get<T>() - Return the value of the specified pointer type. If the
00383     /// specified pointer type is incorrect, assert.
00384     template<typename T>
00385     T get() const {
00386       assert(is<T>() && "Invalid accessor called");
00387       // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
00388       typedef typename
00389         ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
00390           ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
00391                                                                    >::Return Ty;
00392       return Val.template get<Ty>().template get<T>();
00393     }
00394     
00395     /// dyn_cast<T>() - If the current value is of the specified pointer type,
00396     /// return it, otherwise return null.
00397     template<typename T>
00398     T dyn_cast() const {
00399       if (is<T>()) return get<T>();
00400       return T();
00401     }
00402     
00403     /// Assignment operators - Allow assigning into this union from either
00404     /// pointer type, setting the discriminator to remember what it came from.
00405     const PointerUnion4 &operator=(const PT1 &RHS) {
00406       Val = InnerUnion1(RHS);
00407       return *this;
00408     }
00409     const PointerUnion4 &operator=(const PT2 &RHS) {
00410       Val = InnerUnion1(RHS);
00411       return *this;
00412     }
00413     const PointerUnion4 &operator=(const PT3 &RHS) {
00414       Val = InnerUnion2(RHS);
00415       return *this;
00416     }
00417     const PointerUnion4 &operator=(const PT4 &RHS) {
00418       Val = InnerUnion2(RHS);
00419       return *this;
00420     }
00421     
00422     void *getOpaqueValue() const { return Val.getOpaqueValue(); }
00423     static inline PointerUnion4 getFromOpaqueValue(void *VP) {
00424       PointerUnion4 V;
00425       V.Val = ValTy::getFromOpaqueValue(VP);
00426       return V;
00427     }
00428   };
00429   
00430   // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
00431   // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
00432   template<typename PT1, typename PT2, typename PT3, typename PT4>
00433   class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
00434   public:
00435     static inline void *
00436     getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
00437       return P.getOpaqueValue();
00438     }
00439     static inline PointerUnion4<PT1, PT2, PT3, PT4>
00440     getFromVoidPointer(void *P) {
00441       return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
00442     }
00443     
00444     // The number of bits available are the min of the two pointer types.
00445     enum {
00446       NumLowBitsAvailable = 
00447         PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
00448           ::NumLowBitsAvailable
00449     };
00450   };
00451 }
00452 
00453 #endif