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