PointerUnion.h revision e657ec6701ee78e70ed7de43a9d98dbd00f330e5
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 help 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 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 help 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.is<InnerUnion>() && Val.get<InnerUnion>().is<T>(); 190 return Val.is<T>(); 191 } 192 193 /// get<T>() - Return the value of the specified pointer type. If the 194 /// specified pointer type is incorrect, assert. 195 template<typename T> 196 T get() const { 197 assert(is<T>() && "Invalid accessor called"); 198 // Is it PT1/PT2? 199 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 200 return Val.get<InnerUnion>().get<T>(); 201 202 return Val.get<T>(); 203 } 204 205 /// dyn_cast<T>() - If the current value is of the specified pointer type, 206 /// return it, otherwise return null. 207 template<typename T> 208 T dyn_cast() const { 209 if (is<T>()) return get<T>(); 210 return T(); 211 } 212 213 /// Assignment operators - Allow assigning into this union from either 214 /// pointer type, setting the discriminator to remember what it came from. 215 const PointerUnion3 &operator=(const PT1 &RHS) { 216 Val = InnerUnion(RHS); 217 return *this; 218 } 219 const PointerUnion3 &operator=(const PT2 &RHS) { 220 Val = InnerUnion(RHS); 221 return *this; 222 } 223 const PointerUnion3 &operator=(const PT3 &RHS) { 224 Val = RHS; 225 return *this; 226 } 227 228 void *getOpaqueValue() const { return Val.getOpaqueValue(); } 229 static PointerUnion3 getFromOpaqueValue(void *VP) { 230 PointerUnion3 V; 231 V.Val = ValTy::getFromOpaqueValue(VP); 232 return V; 233 } 234 }; 235 236 // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has 237 // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 238 template<typename PT1, typename PT2, typename PT3> 239 class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > { 240 public: 241 static inline void * 242 getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) { 243 return P.getOpaqueValue(); 244 } 245 static inline PointerUnion3<PT1, PT2, PT3> 246 getFromVoidPointer(void *P) { 247 return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); 248 } 249 250 // The number of bits available are the min of the two pointer types. 251 enum { 252 NumLowBitsAvailable = 253 PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy> 254 ::NumLowBitsAvailable 255 }; 256 }; 257 258 /// PointerUnion4 - This is a pointer union of four pointer types. See 259 /// documentation for PointerUnion for usage. 260 template <typename PT1, typename PT2, typename PT3, typename PT4> 261 class PointerUnion4 { 262 public: 263 typedef PointerUnion<PT1, PT2> InnerUnion1; 264 typedef PointerUnion<PT3, PT4> InnerUnion2; 265 typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy; 266 private: 267 ValTy Val; 268 public: 269 PointerUnion4() {} 270 271 PointerUnion4(PT1 V) { 272 Val = InnerUnion1(V); 273 } 274 PointerUnion4(PT2 V) { 275 Val = InnerUnion1(V); 276 } 277 PointerUnion4(PT3 V) { 278 Val = InnerUnion2(V); 279 } 280 PointerUnion4(PT4 V) { 281 Val = InnerUnion2(V); 282 } 283 284 /// isNull - Return true if the pointer help in the union is null, 285 /// regardless of which type it is. 286 bool isNull() const { return Val.isNull(); } 287 operator bool() const { return !isNull(); } 288 289 /// is<T>() return true if the Union currently holds the type matching T. 290 template<typename T> 291 int is() const { 292 // Is it PT1/PT2? 293 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 294 return Val.is<InnerUnion1>() && Val.get<InnerUnion1>().is<T>(); 295 return Val.is<InnerUnion2>() && Val.get<InnerUnion2>().is<T>(); 296 } 297 298 /// get<T>() - Return the value of the specified pointer type. If the 299 /// specified pointer type is incorrect, assert. 300 template<typename T> 301 T get() const { 302 assert(is<T>() && "Invalid accessor called"); 303 // Is it PT1/PT2? 304 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 305 return Val.get<InnerUnion1>().get<T>(); 306 307 return Val.get<InnerUnion2>().get<T>(); 308 } 309 310 /// dyn_cast<T>() - If the current value is of the specified pointer type, 311 /// return it, otherwise return null. 312 template<typename T> 313 T dyn_cast() const { 314 if (is<T>()) return get<T>(); 315 return T(); 316 } 317 318 /// Assignment operators - Allow assigning into this union from either 319 /// pointer type, setting the discriminator to remember what it came from. 320 const PointerUnion4 &operator=(const PT1 &RHS) { 321 Val = InnerUnion1(RHS); 322 return *this; 323 } 324 const PointerUnion4 &operator=(const PT2 &RHS) { 325 Val = InnerUnion1(RHS); 326 return *this; 327 } 328 const PointerUnion4 &operator=(const PT3 &RHS) { 329 Val = InnerUnion2(RHS); 330 return *this; 331 } 332 const PointerUnion4 &operator=(const PT4 &RHS) { 333 Val = InnerUnion2(RHS); 334 return *this; 335 } 336 337 void *getOpaqueValue() const { return Val.getOpaqueValue(); } 338 static PointerUnion4 getFromOpaqueValue(void *VP) { 339 PointerUnion4 V; 340 V.Val = ValTy::getFromOpaqueValue(VP); 341 return V; 342 } 343 }; 344 345 // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has 346 // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 347 template<typename PT1, typename PT2, typename PT3, typename PT4> 348 class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > { 349 public: 350 static inline void * 351 getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) { 352 return P.getOpaqueValue(); 353 } 354 static inline PointerUnion4<PT1, PT2, PT3, PT4> 355 getFromVoidPointer(void *P) { 356 return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P); 357 } 358 359 // The number of bits available are the min of the two pointer types. 360 enum { 361 NumLowBitsAvailable = 362 PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy> 363 ::NumLowBitsAvailable 364 }; 365 }; 366} 367 368#endif 369