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/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