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