PointerUnion.h revision 38297f5f760de604258aaa9000e5aadb43c78921
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 /// \brief If the union is set to the first pointer type we can get an 112 /// address pointing to it. 113 template <typename T> 114 PT1 const *getAddrOf() const { 115 assert(is<PT1>() && "Val is not the first pointer"); 116 assert(get<PT1>() == Val.getPointer() && 117 "Can't get the address because PointerLikeTypeTraits changes the ptr"); 118 T const *can_only_get_address_of_first_pointer_type 119 = reinterpret_cast<PT1 const *>(Val.getAddrOfPointer()); 120 return can_only_get_address_of_first_pointer_type; 121 } 122 123 /// Assignment operators - Allow assigning into this union from either 124 /// pointer type, setting the discriminator to remember what it came from. 125 const PointerUnion &operator=(const PT1 &RHS) { 126 Val.setPointer( 127 const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS))); 128 Val.setInt(0); 129 return *this; 130 } 131 const PointerUnion &operator=(const PT2 &RHS) { 132 Val.setPointer( 133 const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS))); 134 Val.setInt(1); 135 return *this; 136 } 137 138 void *getOpaqueValue() const { return Val.getOpaqueValue(); } 139 static inline PointerUnion getFromOpaqueValue(void *VP) { 140 PointerUnion V; 141 V.Val = ValTy::getFromOpaqueValue(VP); 142 return V; 143 } 144 }; 145 146 // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has 147 // # low bits available = min(PT1bits,PT2bits)-1. 148 template<typename PT1, typename PT2> 149 class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > { 150 public: 151 static inline void * 152 getAsVoidPointer(const PointerUnion<PT1, PT2> &P) { 153 return P.getOpaqueValue(); 154 } 155 static inline PointerUnion<PT1, PT2> 156 getFromVoidPointer(void *P) { 157 return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); 158 } 159 160 // The number of bits available are the min of the two pointer types. 161 enum { 162 NumLowBitsAvailable = 163 PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy> 164 ::NumLowBitsAvailable 165 }; 166 }; 167 168 169 /// PointerUnion3 - This is a pointer union of three pointer types. See 170 /// documentation for PointerUnion for usage. 171 template <typename PT1, typename PT2, typename PT3> 172 class PointerUnion3 { 173 public: 174 typedef PointerUnion<PT1, PT2> InnerUnion; 175 typedef PointerUnion<InnerUnion, PT3> ValTy; 176 private: 177 ValTy Val; 178 public: 179 PointerUnion3() {} 180 181 PointerUnion3(PT1 V) { 182 Val = InnerUnion(V); 183 } 184 PointerUnion3(PT2 V) { 185 Val = InnerUnion(V); 186 } 187 PointerUnion3(PT3 V) { 188 Val = V; 189 } 190 191 /// isNull - Return true if the pointer held in the union is null, 192 /// regardless of which type it is. 193 bool isNull() const { return Val.isNull(); } 194 operator bool() const { return !isNull(); } 195 196 /// is<T>() return true if the Union currently holds the type matching T. 197 template<typename T> 198 int is() const { 199 // Is it PT1/PT2? 200 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 201 return Val.template is<InnerUnion>() && 202 Val.template get<InnerUnion>().template is<T>(); 203 return Val.template is<T>(); 204 } 205 206 /// get<T>() - Return the value of the specified pointer type. If the 207 /// specified pointer type is incorrect, assert. 208 template<typename T> 209 T get() const { 210 assert(is<T>() && "Invalid accessor called"); 211 // Is it PT1/PT2? 212 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 213 return Val.template get<InnerUnion>().template get<T>(); 214 215 return Val.template get<T>(); 216 } 217 218 /// dyn_cast<T>() - If the current value is of the specified pointer type, 219 /// return it, otherwise return null. 220 template<typename T> 221 T dyn_cast() const { 222 if (is<T>()) return get<T>(); 223 return T(); 224 } 225 226 /// Assignment operators - Allow assigning into this union from either 227 /// pointer type, setting the discriminator to remember what it came from. 228 const PointerUnion3 &operator=(const PT1 &RHS) { 229 Val = InnerUnion(RHS); 230 return *this; 231 } 232 const PointerUnion3 &operator=(const PT2 &RHS) { 233 Val = InnerUnion(RHS); 234 return *this; 235 } 236 const PointerUnion3 &operator=(const PT3 &RHS) { 237 Val = RHS; 238 return *this; 239 } 240 241 void *getOpaqueValue() const { return Val.getOpaqueValue(); } 242 static inline PointerUnion3 getFromOpaqueValue(void *VP) { 243 PointerUnion3 V; 244 V.Val = ValTy::getFromOpaqueValue(VP); 245 return V; 246 } 247 }; 248 249 // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has 250 // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 251 template<typename PT1, typename PT2, typename PT3> 252 class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > { 253 public: 254 static inline void * 255 getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) { 256 return P.getOpaqueValue(); 257 } 258 static inline PointerUnion3<PT1, PT2, PT3> 259 getFromVoidPointer(void *P) { 260 return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); 261 } 262 263 // The number of bits available are the min of the two pointer types. 264 enum { 265 NumLowBitsAvailable = 266 PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy> 267 ::NumLowBitsAvailable 268 }; 269 }; 270 271 /// PointerUnion4 - This is a pointer union of four pointer types. See 272 /// documentation for PointerUnion for usage. 273 template <typename PT1, typename PT2, typename PT3, typename PT4> 274 class PointerUnion4 { 275 public: 276 typedef PointerUnion<PT1, PT2> InnerUnion1; 277 typedef PointerUnion<PT3, PT4> InnerUnion2; 278 typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy; 279 private: 280 ValTy Val; 281 public: 282 PointerUnion4() {} 283 284 PointerUnion4(PT1 V) { 285 Val = InnerUnion1(V); 286 } 287 PointerUnion4(PT2 V) { 288 Val = InnerUnion1(V); 289 } 290 PointerUnion4(PT3 V) { 291 Val = InnerUnion2(V); 292 } 293 PointerUnion4(PT4 V) { 294 Val = InnerUnion2(V); 295 } 296 297 /// isNull - Return true if the pointer held in the union is null, 298 /// regardless of which type it is. 299 bool isNull() const { return Val.isNull(); } 300 operator bool() const { return !isNull(); } 301 302 /// is<T>() return true if the Union currently holds the type matching T. 303 template<typename T> 304 int is() const { 305 // Is it PT1/PT2? 306 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 307 return Val.template is<InnerUnion1>() && 308 Val.template get<InnerUnion1>().template is<T>(); 309 return Val.template is<InnerUnion2>() && 310 Val.template get<InnerUnion2>().template is<T>(); 311 } 312 313 /// get<T>() - Return the value of the specified pointer type. If the 314 /// specified pointer type is incorrect, assert. 315 template<typename T> 316 T get() const { 317 assert(is<T>() && "Invalid accessor called"); 318 // Is it PT1/PT2? 319 if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 320 return Val.template get<InnerUnion1>().template get<T>(); 321 322 return Val.template get<InnerUnion2>().template get<T>(); 323 } 324 325 /// dyn_cast<T>() - If the current value is of the specified pointer type, 326 /// return it, otherwise return null. 327 template<typename T> 328 T dyn_cast() const { 329 if (is<T>()) return get<T>(); 330 return T(); 331 } 332 333 /// Assignment operators - Allow assigning into this union from either 334 /// pointer type, setting the discriminator to remember what it came from. 335 const PointerUnion4 &operator=(const PT1 &RHS) { 336 Val = InnerUnion1(RHS); 337 return *this; 338 } 339 const PointerUnion4 &operator=(const PT2 &RHS) { 340 Val = InnerUnion1(RHS); 341 return *this; 342 } 343 const PointerUnion4 &operator=(const PT3 &RHS) { 344 Val = InnerUnion2(RHS); 345 return *this; 346 } 347 const PointerUnion4 &operator=(const PT4 &RHS) { 348 Val = InnerUnion2(RHS); 349 return *this; 350 } 351 352 void *getOpaqueValue() const { return Val.getOpaqueValue(); } 353 static inline PointerUnion4 getFromOpaqueValue(void *VP) { 354 PointerUnion4 V; 355 V.Val = ValTy::getFromOpaqueValue(VP); 356 return V; 357 } 358 }; 359 360 // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has 361 // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 362 template<typename PT1, typename PT2, typename PT3, typename PT4> 363 class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > { 364 public: 365 static inline void * 366 getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) { 367 return P.getOpaqueValue(); 368 } 369 static inline PointerUnion4<PT1, PT2, PT3, PT4> 370 getFromVoidPointer(void *P) { 371 return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P); 372 } 373 374 // The number of bits available are the min of the two pointer types. 375 enum { 376 NumLowBitsAvailable = 377 PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy> 378 ::NumLowBitsAvailable 379 }; 380 }; 381} 382 383#endif 384