PointerUnion.h revision 8260ea5c6c15345e00ced1398b03e6886145e45c
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/ADT/PointerIntPair.h" 19 20namespace llvm { 21 22 /// getPointerUnionTypeNum - If the argument has type PT1* or PT2* return 23 /// false or true respectively. 24 template <typename PT1, typename PT2> 25 static inline int getPointerUnionTypeNum(PT1 *P) { return 0; } 26 template <typename PT1, typename PT2> 27 static inline int getPointerUnionTypeNum(PT2 *P) { return 1; } 28 template <typename PT1, typename PT2> 29 static inline int getPointerUnionTypeNum(...) { return -1; } 30 31 32 /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion 33 /// for the two template arguments. 34 template <typename PT1, typename PT2> 35 class PointerUnionUIntTraits { 36 public: 37 static inline void *getAsVoidPointer(void *P) { return P; } 38 static inline void *getFromVoidPointer(void *P) { return P; } 39 enum { 40 PT1BitsAv = PointerLikeTypeTraits<PT1>::NumLowBitsAvailable, 41 PT2BitsAv = PointerLikeTypeTraits<PT2>::NumLowBitsAvailable, 42 NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv 43 }; 44 }; 45 46 /// PointerUnion - This implements a discriminated union of two pointer types, 47 /// and keeps the discriminator bit-mangled into the low bits of the pointer. 48 /// This allows the implementation to be extremely efficient in space, but 49 /// permits a very natural and type-safe API. 50 /// 51 /// Common use patterns would be something like this: 52 /// PointerUnion<int*, float*> P; 53 /// P = (int*)0; 54 /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" 55 /// X = P.get<int*>(); // ok. 56 /// Y = P.get<float*>(); // runtime assertion failure. 57 /// Z = P.get<double*>(); // runtime assertion failure (regardless of tag) 58 /// P = (float*)0; 59 /// Y = P.get<float*>(); // ok. 60 /// X = P.get<int*>(); // runtime assertion failure. 61 template <typename PT1, typename PT2> 62 class PointerUnion { 63 public: 64 typedef PointerIntPair<void*, 1, bool, 65 PointerUnionUIntTraits<PT1,PT2> > ValTy; 66 private: 67 ValTy Val; 68 public: 69 PointerUnion() {} 70 71 PointerUnion(PT1 V) { 72 Val.setPointer( 73 const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))); 74 Val.setInt(0); 75 } 76 PointerUnion(PT2 V) { 77 Val.setPointer( 78 const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V))); 79 Val.setInt(1); 80 } 81 82 /// isNull - Return true if the pointer held in the union is null, 83 /// regardless of which type it is. 84 bool isNull() const { return Val.getPointer() == 0; } 85 operator bool() const { return !isNull(); } 86 87 /// is<T>() return true if the Union currently holds the type matching T. 88 template<typename T> 89 int is() const { 90 int TyNo = ::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0); 91 assert(TyNo != -1 && "Type query could never succeed on PointerUnion!"); 92 return static_cast<int>(Val.getInt()) == TyNo; 93 } 94 95 /// get<T>() - Return the value of the specified pointer type. If the 96 /// specified pointer type is incorrect, assert. 97 template<typename T> 98 T get() const { 99 assert(is<T>() && "Invalid accessor called"); 100 return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer()); 101 } 102 103 /// dyn_cast<T>() - If the current value is of the specified pointer type, 104 /// return it, otherwise return null. 105 template<typename T> 106 T dyn_cast() const { 107 if (is<T>()) return get<T>(); 108 return T(); 109 } 110 111 /// Assignment operators - Allow assigning into this union from either 112 /// pointer type, setting the discriminator to remember what it came from. 113 const PointerUnion &operator=(const PT1 &RHS) { 114 Val.setPointer( 115 const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS))); 116 Val.setInt(0); 117 return *this; 118 } 119 const PointerUnion &operator=(const PT2 &RHS) { 120 Val.setPointer( 121 const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS))); 122 Val.setInt(1); 123 return *this; 124 } 125 126 void *getOpaqueValue() const { return Val.getOpaqueValue(); } 127 static inline PointerUnion getFromOpaqueValue(void *VP) { 128 PointerUnion V; 129 V.Val = ValTy::getFromOpaqueValue(VP); 130 return V; 131 } 132 }; 133 134 // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has 135 // # low bits available = min(PT1bits,PT2bits)-1. 136 template<typename PT1, typename PT2> 137 class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > { 138 public: 139 static inline void * 140 getAsVoidPointer(const PointerUnion<PT1, PT2> &P) { 141 return P.getOpaqueValue(); 142 } 143 static inline PointerUnion<PT1, PT2> 144 getFromVoidPointer(void *P) { 145 return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); 146 } 147 148 // The number of bits available are the min of the two pointer types. 149 enum { 150 NumLowBitsAvailable = 151 PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy> 152 ::NumLowBitsAvailable 153 }; 154 }; 155 156 157 /// PointerUnion3 - This is a pointer union of three pointer types. See 158 /// documentation for PointerUnion for usage. 159 template <typename PT1, typename PT2, typename PT3> 160 class PointerUnion3 { 161 public: 162 typedef PointerUnion<PT1, PT2> InnerUnion; 163 typedef PointerUnion<InnerUnion, PT3> ValTy; 164 private: 165 ValTy Val; 166 public: 167 PointerUnion3() {} 168 169 PointerUnion3(PT1 V) { 170 Val = InnerUnion(V); 171 } 172 PointerUnion3(PT2 V) { 173 Val = InnerUnion(V); 174 } 175 PointerUnion3(PT3 V) { 176 Val = V; 177 } 178 179 /// isNull - Return true if the pointer held in the union is null, 180 /// regardless of which type it is. 181 bool isNull() const { return Val.isNull(); } 182 operator bool() const { return !isNull(); } 183 184 /// is<T>() return true if the Union currently holds the type matching T. 185 template<typename T> 186 int is() const { 187 // Is it PT1/PT2? 188 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 189 return Val.template is<InnerUnion>() && 190 Val.template get<InnerUnion>().template is<T>(); 191 return Val.template is<T>(); 192 } 193 194 /// get<T>() - Return the value of the specified pointer type. If the 195 /// specified pointer type is incorrect, assert. 196 template<typename T> 197 T get() const { 198 assert(is<T>() && "Invalid accessor called"); 199 // Is it PT1/PT2? 200 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 201 return Val.template get<InnerUnion>().template get<T>(); 202 203 return Val.template get<T>(); 204 } 205 206 /// dyn_cast<T>() - If the current value is of the specified pointer type, 207 /// return it, otherwise return null. 208 template<typename T> 209 T dyn_cast() const { 210 if (is<T>()) return get<T>(); 211 return T(); 212 } 213 214 /// Assignment operators - Allow assigning into this union from either 215 /// pointer type, setting the discriminator to remember what it came from. 216 const PointerUnion3 &operator=(const PT1 &RHS) { 217 Val = InnerUnion(RHS); 218 return *this; 219 } 220 const PointerUnion3 &operator=(const PT2 &RHS) { 221 Val = InnerUnion(RHS); 222 return *this; 223 } 224 const PointerUnion3 &operator=(const PT3 &RHS) { 225 Val = RHS; 226 return *this; 227 } 228 229 void *getOpaqueValue() const { return Val.getOpaqueValue(); } 230 static inline PointerUnion3 getFromOpaqueValue(void *VP) { 231 PointerUnion3 V; 232 V.Val = ValTy::getFromOpaqueValue(VP); 233 return V; 234 } 235 }; 236 237 // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has 238 // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 239 template<typename PT1, typename PT2, typename PT3> 240 class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > { 241 public: 242 static inline void * 243 getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) { 244 return P.getOpaqueValue(); 245 } 246 static inline PointerUnion3<PT1, PT2, PT3> 247 getFromVoidPointer(void *P) { 248 return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); 249 } 250 251 // The number of bits available are the min of the two pointer types. 252 enum { 253 NumLowBitsAvailable = 254 PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy> 255 ::NumLowBitsAvailable 256 }; 257 }; 258 259 /// PointerUnion4 - This is a pointer union of four pointer types. See 260 /// documentation for PointerUnion for usage. 261 template <typename PT1, typename PT2, typename PT3, typename PT4> 262 class PointerUnion4 { 263 public: 264 typedef PointerUnion<PT1, PT2> InnerUnion1; 265 typedef PointerUnion<PT3, PT4> InnerUnion2; 266 typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy; 267 private: 268 ValTy Val; 269 public: 270 PointerUnion4() {} 271 272 PointerUnion4(PT1 V) { 273 Val = InnerUnion1(V); 274 } 275 PointerUnion4(PT2 V) { 276 Val = InnerUnion1(V); 277 } 278 PointerUnion4(PT3 V) { 279 Val = InnerUnion2(V); 280 } 281 PointerUnion4(PT4 V) { 282 Val = InnerUnion2(V); 283 } 284 285 /// isNull - Return true if the pointer held in the union is null, 286 /// regardless of which type it is. 287 bool isNull() const { return Val.isNull(); } 288 operator bool() const { return !isNull(); } 289 290 /// is<T>() return true if the Union currently holds the type matching T. 291 template<typename T> 292 int is() const { 293 // Is it PT1/PT2? 294 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 295 return Val.template is<InnerUnion1>() && 296 Val.template get<InnerUnion1>().template is<T>(); 297 return Val.template is<InnerUnion2>() && 298 Val.template get<InnerUnion2>().template is<T>(); 299 } 300 301 /// get<T>() - Return the value of the specified pointer type. If the 302 /// specified pointer type is incorrect, assert. 303 template<typename T> 304 T get() const { 305 assert(is<T>() && "Invalid accessor called"); 306 // Is it PT1/PT2? 307 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 308 return Val.template get<InnerUnion1>().template get<T>(); 309 310 return Val.template get<InnerUnion2>().template get<T>(); 311 } 312 313 /// dyn_cast<T>() - If the current value is of the specified pointer type, 314 /// return it, otherwise return null. 315 template<typename T> 316 T dyn_cast() const { 317 if (is<T>()) return get<T>(); 318 return T(); 319 } 320 321 /// Assignment operators - Allow assigning into this union from either 322 /// pointer type, setting the discriminator to remember what it came from. 323 const PointerUnion4 &operator=(const PT1 &RHS) { 324 Val = InnerUnion1(RHS); 325 return *this; 326 } 327 const PointerUnion4 &operator=(const PT2 &RHS) { 328 Val = InnerUnion1(RHS); 329 return *this; 330 } 331 const PointerUnion4 &operator=(const PT3 &RHS) { 332 Val = InnerUnion2(RHS); 333 return *this; 334 } 335 const PointerUnion4 &operator=(const PT4 &RHS) { 336 Val = InnerUnion2(RHS); 337 return *this; 338 } 339 340 void *getOpaqueValue() const { return Val.getOpaqueValue(); } 341 static inline PointerUnion4 getFromOpaqueValue(void *VP) { 342 PointerUnion4 V; 343 V.Val = ValTy::getFromOpaqueValue(VP); 344 return V; 345 } 346 }; 347 348 // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has 349 // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 350 template<typename PT1, typename PT2, typename PT3, typename PT4> 351 class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > { 352 public: 353 static inline void * 354 getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) { 355 return P.getOpaqueValue(); 356 } 357 static inline PointerUnion4<PT1, PT2, PT3, PT4> 358 getFromVoidPointer(void *P) { 359 return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P); 360 } 361 362 // The number of bits available are the min of the two pointer types. 363 enum { 364 NumLowBitsAvailable = 365 PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy> 366 ::NumLowBitsAvailable 367 }; 368 }; 369} 370 371#endif 372