LLVM API Documentation
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