PointerUnion.h revision 8260ea5c6c15345e00ced1398b03e6886145e45c
12491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===// 22491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// 32491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// The LLVM Compiler Infrastructure 42491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// 52491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// This file is distributed under the University of Illinois Open Source 62491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// License. See LICENSE.TXT for details. 72491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// 82491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//===----------------------------------------------------------------------===// 92491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// 102491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// This file defines the PointerUnion class, which is a discriminated union of 112491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// pointer types. 122491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// 132491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//===----------------------------------------------------------------------===// 142491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 152491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#ifndef LLVM_ADT_POINTERUNION_H 162491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#define LLVM_ADT_POINTERUNION_H 172491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 182491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#include "llvm/ADT/PointerIntPair.h" 192491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 202491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattnernamespace llvm { 212491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 222491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// getPointerUnionTypeNum - If the argument has type PT1* or PT2* return 232491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// false or true respectively. 242491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 25e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline int getPointerUnionTypeNum(PT1 *P) { return 0; } 262491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 27e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline int getPointerUnionTypeNum(PT2 *P) { return 1; } 28e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template <typename PT1, typename PT2> 29e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline int getPointerUnionTypeNum(...) { return -1; } 302491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 322491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion 332491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// for the two template arguments. 342491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 352491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerUnionUIntTraits { 362491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 372491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void *getAsVoidPointer(void *P) { return P; } 382491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void *getFromVoidPointer(void *P) { return P; } 392491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner enum { 402491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PT1BitsAv = PointerLikeTypeTraits<PT1>::NumLowBitsAvailable, 412491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PT2BitsAv = PointerLikeTypeTraits<PT2>::NumLowBitsAvailable, 422491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv 432491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 442491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 452491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 462491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// PointerUnion - This implements a discriminated union of two pointer types, 472491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// and keeps the discriminator bit-mangled into the low bits of the pointer. 482491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// This allows the implementation to be extremely efficient in space, but 492491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// permits a very natural and type-safe API. 502491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// 512491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Common use patterns would be something like this: 522491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// PointerUnion<int*, float*> P; 532491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// P = (int*)0; 542491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" 552491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// X = P.get<int*>(); // ok. 562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Y = P.get<float*>(); // runtime assertion failure. 57f54229192c22559389b0ef47e731fd628db963c5Chris Lattner /// Z = P.get<double*>(); // runtime assertion failure (regardless of tag) 582491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// P = (float*)0; 592491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Y = P.get<float*>(); // ok. 602491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// X = P.get<int*>(); // runtime assertion failure. 612491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 622491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerUnion { 632491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 642491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner typedef PointerIntPair<void*, 1, bool, 652491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnionUIntTraits<PT1,PT2> > ValTy; 662491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner private: 672491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner ValTy Val; 682491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion() {} 702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion(PT1 V) { 7241222823db11107834414a378525bb21493d3a1fDouglas Gregor Val.setPointer( 7341222823db11107834414a378525bb21493d3a1fDouglas Gregor const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))); 742491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(0); 752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 762491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion(PT2 V) { 7741222823db11107834414a378525bb21493d3a1fDouglas Gregor Val.setPointer( 7841222823db11107834414a378525bb21493d3a1fDouglas Gregor const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V))); 792491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(1); 802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 8226ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 833a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// regardless of which type it is. 84ba315c1ee7bef78c6824441fe6c1761596ec9880Chris Lattner bool isNull() const { return Val.getPointer() == 0; } 85e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner operator bool() const { return !isNull(); } 86e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 873a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// is<T>() return true if the Union currently holds the type matching T. 882491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename T> 892491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner int is() const { 90e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner int TyNo = ::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0); 91e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner assert(TyNo != -1 && "Type query could never succeed on PointerUnion!"); 9237c286c18128cce7f52654876a5a104150be4b79Sebastian Redl return static_cast<int>(Val.getInt()) == TyNo; 932491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 943a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner 953a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// get<T>() - Return the value of the specified pointer type. If the 963a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// specified pointer type is incorrect, assert. 972491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename T> 982491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner T get() const { 992491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner assert(is<T>() && "Invalid accessor called"); 100e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer()); 1012491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1022491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1033a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// dyn_cast<T>() - If the current value is of the specified pointer type, 1043a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// return it, otherwise return null. 1053a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner template<typename T> 1063a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner T dyn_cast() const { 107e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner if (is<T>()) return get<T>(); 1083a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner return T(); 1093a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner } 1103a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner 1113a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// Assignment operators - Allow assigning into this union from either 1123a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// pointer type, setting the discriminator to remember what it came from. 1132491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner const PointerUnion &operator=(const PT1 &RHS) { 11441222823db11107834414a378525bb21493d3a1fDouglas Gregor Val.setPointer( 11541222823db11107834414a378525bb21493d3a1fDouglas Gregor const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS))); 1162491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(0); 1172491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return *this; 1182491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1192491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner const PointerUnion &operator=(const PT2 &RHS) { 12041222823db11107834414a378525bb21493d3a1fDouglas Gregor Val.setPointer( 12141222823db11107834414a378525bb21493d3a1fDouglas Gregor const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS))); 1222491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(1); 1232491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return *this; 1242491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1252491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1262491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner void *getOpaqueValue() const { return Val.getOpaqueValue(); } 1278260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion getFromOpaqueValue(void *VP) { 1282491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion V; 1292491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner V.Val = ValTy::getFromOpaqueValue(VP); 1302491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return V; 1312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1322491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 1332491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 134e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has 1352491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // # low bits available = min(PT1bits,PT2bits)-1. 1362491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename PT1, typename PT2> 1372491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > { 1382491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 1392491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void * 1402491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner getAsVoidPointer(const PointerUnion<PT1, PT2> &P) { 1412491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return P.getOpaqueValue(); 1422491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1432491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline PointerUnion<PT1, PT2> 1442491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner getFromVoidPointer(void *P) { 1452491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); 1462491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1472491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1482491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // The number of bits available are the min of the two pointer types. 1492491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner enum { 1502491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner NumLowBitsAvailable = 151e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy> 152e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ::NumLowBitsAvailable 153e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 154e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 155e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 156e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 157e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// PointerUnion3 - This is a pointer union of three pointer types. See 158e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// documentation for PointerUnion for usage. 159e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template <typename PT1, typename PT2, typename PT3> 160e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner class PointerUnion3 { 161e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 162e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner typedef PointerUnion<PT1, PT2> InnerUnion; 163e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner typedef PointerUnion<InnerUnion, PT3> ValTy; 164e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner private: 165e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ValTy Val; 166e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 167e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3() {} 168e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 169e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT1 V) { 170e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(V); 171e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 172e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT2 V) { 173e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(V); 174e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 175e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT3 V) { 176e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = V; 177e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 178e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 17926ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 180e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// regardless of which type it is. 181e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner bool isNull() const { return Val.isNull(); } 182e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner operator bool() const { return !isNull(); } 183e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 184e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// is<T>() return true if the Union currently holds the type matching T. 185e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 186e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner int is() const { 187e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // Is it PT1/PT2? 188e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 1896a66b388469f045c9fcff839595900c9f1512177Douglas Gregor return Val.template is<InnerUnion>() && 1906a66b388469f045c9fcff839595900c9f1512177Douglas Gregor Val.template get<InnerUnion>().template is<T>(); 1916a66b388469f045c9fcff839595900c9f1512177Douglas Gregor return Val.template is<T>(); 192e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 193e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 194e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// get<T>() - Return the value of the specified pointer type. If the 195e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// specified pointer type is incorrect, assert. 196e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 197e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner T get() const { 198e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner assert(is<T>() && "Invalid accessor called"); 1992048cdb08ef6ad04bd1baf52886605d455236eb7Douglas Gregor // Is it PT1/PT2? 2002048cdb08ef6ad04bd1baf52886605d455236eb7Douglas Gregor if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 2016a66b388469f045c9fcff839595900c9f1512177Douglas Gregor return Val.template get<InnerUnion>().template get<T>(); 2022048cdb08ef6ad04bd1baf52886605d455236eb7Douglas Gregor 2036a66b388469f045c9fcff839595900c9f1512177Douglas Gregor return Val.template get<T>(); 204e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 205e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 206e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// dyn_cast<T>() - If the current value is of the specified pointer type, 207e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// return it, otherwise return null. 208e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 209e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner T dyn_cast() const { 210e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner if (is<T>()) return get<T>(); 211e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return T(); 212e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 213e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 214e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// Assignment operators - Allow assigning into this union from either 215e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// pointer type, setting the discriminator to remember what it came from. 216e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT1 &RHS) { 217e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(RHS); 218e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 219e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 220e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT2 &RHS) { 221e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(RHS); 222e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 223e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 224e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT3 &RHS) { 225e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = RHS; 226e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 227e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 228e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 229e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner void *getOpaqueValue() const { return Val.getOpaqueValue(); } 2308260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion3 getFromOpaqueValue(void *VP) { 231e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3 V; 232e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner V.Val = ValTy::getFromOpaqueValue(VP); 233e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return V; 234e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 235e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 236e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 237e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has 238e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 239e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename PT1, typename PT2, typename PT3> 240e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > { 241e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 242e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline void * 243e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) { 244e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return P.getOpaqueValue(); 245e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 246e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline PointerUnion3<PT1, PT2, PT3> 247e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner getFromVoidPointer(void *P) { 248e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); 249e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 250e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 251e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // The number of bits available are the min of the two pointer types. 252e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner enum { 253e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner NumLowBitsAvailable = 254e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy> 255e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ::NumLowBitsAvailable 2562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 2572491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 258e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 259e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// PointerUnion4 - This is a pointer union of four pointer types. See 260e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// documentation for PointerUnion for usage. 261e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template <typename PT1, typename PT2, typename PT3, typename PT4> 262e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor class PointerUnion4 { 263e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 264e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<PT1, PT2> InnerUnion1; 265e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<PT3, PT4> InnerUnion2; 266e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy; 267e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor private: 268e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor ValTy Val; 269e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 270e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4() {} 271e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 272e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT1 V) { 273e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(V); 274e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 275e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT2 V) { 276e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(V); 277e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 278e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT3 V) { 279e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(V); 280e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 281e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT4 V) { 282e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(V); 283e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 284e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 28526ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 286e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// regardless of which type it is. 287e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor bool isNull() const { return Val.isNull(); } 288e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor operator bool() const { return !isNull(); } 289e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 290e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// is<T>() return true if the Union currently holds the type matching T. 291e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 292e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor int is() const { 293e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // Is it PT1/PT2? 294e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 2956a66b388469f045c9fcff839595900c9f1512177Douglas Gregor return Val.template is<InnerUnion1>() && 2966a66b388469f045c9fcff839595900c9f1512177Douglas Gregor Val.template get<InnerUnion1>().template is<T>(); 2976a66b388469f045c9fcff839595900c9f1512177Douglas Gregor return Val.template is<InnerUnion2>() && 2986a66b388469f045c9fcff839595900c9f1512177Douglas Gregor Val.template get<InnerUnion2>().template is<T>(); 299e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 300e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 301e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// get<T>() - Return the value of the specified pointer type. If the 302e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// specified pointer type is incorrect, assert. 303e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 304e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor T get() const { 305e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor assert(is<T>() && "Invalid accessor called"); 306e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // Is it PT1/PT2? 307e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) 3086a66b388469f045c9fcff839595900c9f1512177Douglas Gregor return Val.template get<InnerUnion1>().template get<T>(); 309e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 3106a66b388469f045c9fcff839595900c9f1512177Douglas Gregor return Val.template get<InnerUnion2>().template get<T>(); 311e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 312e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 313e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// dyn_cast<T>() - If the current value is of the specified pointer type, 314e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// return it, otherwise return null. 315e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 316e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor T dyn_cast() const { 317e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor if (is<T>()) return get<T>(); 318e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return T(); 319e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 320e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 321e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// Assignment operators - Allow assigning into this union from either 322e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// pointer type, setting the discriminator to remember what it came from. 323e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT1 &RHS) { 324e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(RHS); 325e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 326e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 327e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT2 &RHS) { 328e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(RHS); 329e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 330e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 331e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT3 &RHS) { 332e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(RHS); 333e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 334e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 335e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT4 &RHS) { 336e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(RHS); 337e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 338e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 339e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 340e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor void *getOpaqueValue() const { return Val.getOpaqueValue(); } 3418260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion4 getFromOpaqueValue(void *VP) { 342e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4 V; 343e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor V.Val = ValTy::getFromOpaqueValue(VP); 344e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return V; 345e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 346e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 347e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 348e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has 349e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 350e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename PT1, typename PT2, typename PT3, typename PT4> 351e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > { 352e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 353e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor static inline void * 354e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) { 355e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return P.getOpaqueValue(); 356e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 357e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor static inline PointerUnion4<PT1, PT2, PT3, PT4> 358e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor getFromVoidPointer(void *P) { 359e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P); 360e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 361e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 362e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // The number of bits available are the min of the two pointer types. 363e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor enum { 364e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor NumLowBitsAvailable = 365e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy> 366e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor ::NumLowBitsAvailable 367e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 368e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 3692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner} 3702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 3712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#endif 372