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 18dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/ADT/DenseMapInfo.h" 192491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#include "llvm/ADT/PointerIntPair.h" 2036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/Compiler.h" 212491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 222491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattnernamespace llvm { 232491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 24128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template <typename T> 25128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct PointerUnionTypeSelectorReturn { 26128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef T Return; 27128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 28128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 29128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis /// \brief Get a type based on whether two types are the same or not. For: 30128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis /// @code 31128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis /// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret; 32128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis /// @endcode 33128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis /// Ret will be EQ type if T1 is same as T2 or NE type otherwise. 34128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template <typename T1, typename T2, typename RET_EQ, typename RET_NE> 35128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct PointerUnionTypeSelector { 36128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return; 37128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 38128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 39128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template <typename T, typename RET_EQ, typename RET_NE> 40128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> { 41128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return; 42128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 43128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 44128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template <typename T1, typename T2, typename RET_EQ, typename RET_NE> 45128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct PointerUnionTypeSelectorReturn< 46128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > { 47128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return 48128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis Return; 49128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 50128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 512491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion 522491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// for the two template arguments. 532491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 542491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerUnionUIntTraits { 552491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void *getAsVoidPointer(void *P) { return P; } 572491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void *getFromVoidPointer(void *P) { return P; } 582491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner enum { 59b76fb96cd66aec709e2a0cfda8c29c53ba5ad98cGalina Kistanova PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable), 60b76fb96cd66aec709e2a0cfda8c29c53ba5ad98cGalina Kistanova PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable), 612491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv 622491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 632491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 642491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 652491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// PointerUnion - This implements a discriminated union of two pointer types, 662491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// and keeps the discriminator bit-mangled into the low bits of the pointer. 672491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// This allows the implementation to be extremely efficient in space, but 682491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// permits a very natural and type-safe API. 692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// 702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Common use patterns would be something like this: 712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// PointerUnion<int*, float*> P; 722491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// P = (int*)0; 732491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" 742491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// X = P.get<int*>(); // ok. 752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Y = P.get<float*>(); // runtime assertion failure. 76296ca41b2d305f4aaf1d0562c7da90dc20cd9e14David Blaikie /// Z = P.get<double*>(); // compile time failure. 772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// P = (float*)0; 782491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Y = P.get<float*>(); // ok. 792491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// X = P.get<int*>(); // runtime assertion failure. 802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerUnion { 822491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 832491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner typedef PointerIntPair<void*, 1, bool, 842491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnionUIntTraits<PT1,PT2> > ValTy; 852491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner private: 862491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner ValTy Val; 87a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis 88a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis struct IsPT1 { 89a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis static const int Num = 0; 90a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis }; 91a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis struct IsPT2 { 92a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis static const int Num = 1; 93a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis }; 94a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis template <typename T> 95a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis struct UNION_DOESNT_CONTAIN_TYPE { }; 96a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis 972491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 982491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion() {} 992491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 100acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis PointerUnion(PT1 V) : Val( 101acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) { 1022491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 103acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis PointerUnion(PT2 V) : Val( 104acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) { 1052491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1062491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 10726ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 1083a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// regardless of which type it is. 109823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner bool isNull() const { 110823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner // Convert from the void* to one of the pointer types, to make sure that 111823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner // we recursively strip off low bits if we have a nested PointerUnion. 112823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer()); 113823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner } 114453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie LLVM_EXPLICIT operator bool() const { return !isNull(); } 115e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 1163a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// is<T>() return true if the Union currently holds the type matching T. 1172491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename T> 1182491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner int is() const { 119a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis typedef typename 120a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, IsPT1, 121a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2, 122a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty; 123a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis int TyNo = Ty::Num; 12437c286c18128cce7f52654876a5a104150be4b79Sebastian Redl return static_cast<int>(Val.getInt()) == TyNo; 1252491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1263a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner 1273a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// get<T>() - Return the value of the specified pointer type. If the 1283a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// specified pointer type is incorrect, assert. 1292491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename T> 1302491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner T get() const { 1312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner assert(is<T>() && "Invalid accessor called"); 132e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer()); 1332491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1342491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1353a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// dyn_cast<T>() - If the current value is of the specified pointer type, 1363a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// return it, otherwise return null. 1373a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner template<typename T> 1383a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner T dyn_cast() const { 139e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner if (is<T>()) return get<T>(); 1403a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner return T(); 1413a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner } 14238297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis 1430db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// \brief If the union is set to the first pointer type get an address 1440db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// pointing to it. 1450db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis PT1 const *getAddrOfPtr1() const { 1460db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis return const_cast<PointerUnion *>(this)->getAddrOfPtr1(); 1470db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis } 1480db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis 1490db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// \brief If the union is set to the first pointer type get an address 1500db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// pointing to it. 1510db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis PT1 *getAddrOfPtr1() { 15238297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis assert(is<PT1>() && "Val is not the first pointer"); 15338297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis assert(get<PT1>() == Val.getPointer() && 15438297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis "Can't get the address because PointerLikeTypeTraits changes the ptr"); 1550db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis return (PT1 *)Val.getAddrOfPointer(); 15638297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis } 157dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 158dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Assignment from nullptr which just clears the union. 159dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const PointerUnion &operator=(std::nullptr_t) { 160dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Val.initWithPointer(nullptr); 161dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 162dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 1633a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner 1643a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// Assignment operators - Allow assigning into this union from either 1653a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// pointer type, setting the discriminator to remember what it came from. 1662491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner const PointerUnion &operator=(const PT1 &RHS) { 167acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis Val.initWithPointer( 16841222823db11107834414a378525bb21493d3a1fDouglas Gregor const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS))); 1692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return *this; 1702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner const PointerUnion &operator=(const PT2 &RHS) { 172acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis Val.setPointerAndInt( 173acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)), 174acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis 1); 1752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return *this; 1762491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1782491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner void *getOpaqueValue() const { return Val.getOpaqueValue(); } 1798260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion getFromOpaqueValue(void *VP) { 1802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion V; 1812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner V.Val = ValTy::getFromOpaqueValue(VP); 1822491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return V; 1832491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1842491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 185453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie 186453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie template<typename PT1, typename PT2> 187b2820859240b8b8ad03384207ce896da60702f98Chris Lattner static bool operator==(PointerUnion<PT1, PT2> lhs, 188b2820859240b8b8ad03384207ce896da60702f98Chris Lattner PointerUnion<PT1, PT2> rhs) { 189453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie return lhs.getOpaqueValue() == rhs.getOpaqueValue(); 190453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie } 191b2820859240b8b8ad03384207ce896da60702f98Chris Lattner 192b2820859240b8b8ad03384207ce896da60702f98Chris Lattner template<typename PT1, typename PT2> 193b2820859240b8b8ad03384207ce896da60702f98Chris Lattner static bool operator!=(PointerUnion<PT1, PT2> lhs, 194b2820859240b8b8ad03384207ce896da60702f98Chris Lattner PointerUnion<PT1, PT2> rhs) { 195586ea17be9fbf2fa1f2341900ebf1675a0924edcChris Lattner return lhs.getOpaqueValue() != rhs.getOpaqueValue(); 196b2820859240b8b8ad03384207ce896da60702f98Chris Lattner } 197b2820859240b8b8ad03384207ce896da60702f98Chris Lattner 198e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has 1992491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // # low bits available = min(PT1bits,PT2bits)-1. 2002491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename PT1, typename PT2> 2012491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > { 2022491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 2032491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void * 2042491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner getAsVoidPointer(const PointerUnion<PT1, PT2> &P) { 2052491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return P.getOpaqueValue(); 2062491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 2072491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline PointerUnion<PT1, PT2> 2082491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner getFromVoidPointer(void *P) { 2092491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); 2102491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 2112491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 2122491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // The number of bits available are the min of the two pointer types. 2132491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner enum { 2142491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner NumLowBitsAvailable = 215e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy> 216e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ::NumLowBitsAvailable 217e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 218e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 219e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 220e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 221e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// PointerUnion3 - This is a pointer union of three pointer types. See 222e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// documentation for PointerUnion for usage. 223e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template <typename PT1, typename PT2, typename PT3> 224e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner class PointerUnion3 { 225e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 226e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner typedef PointerUnion<PT1, PT2> InnerUnion; 227e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner typedef PointerUnion<InnerUnion, PT3> ValTy; 228e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner private: 229e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ValTy Val; 230128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 231128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct IsInnerUnion { 232128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ValTy Val; 233128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis IsInnerUnion(ValTy val) : Val(val) { } 234128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 235128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis int is() const { 236128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template is<InnerUnion>() && 237128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis Val.template get<InnerUnion>().template is<T>(); 238128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 239128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 240128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis T get() const { 241128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template get<InnerUnion>().template get<T>(); 242128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 243128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 244128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 245128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct IsPT3 { 246128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ValTy Val; 247128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis IsPT3(ValTy val) : Val(val) { } 248128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 249128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis int is() const { 250128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template is<T>(); 251128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 252128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 253128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis T get() const { 254128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template get<T>(); 255128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 256128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 257128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 258e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 259e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3() {} 260e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 261e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT1 V) { 262e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(V); 263e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 264e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT2 V) { 265e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(V); 266e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 267e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT3 V) { 268e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = V; 269e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 270e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 27126ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 272e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// regardless of which type it is. 273e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner bool isNull() const { return Val.isNull(); } 274453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie LLVM_EXPLICIT operator bool() const { return !isNull(); } 275e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 276e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// is<T>() return true if the Union currently holds the type matching T. 277e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 278e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner int is() const { 279128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. 280128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 281128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion, 282128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 > 283128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 28487d8e60505b26960956996550c8b805c81e5b02bDouglas Gregor return Ty(Val).template is<T>(); 285e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 286e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 287e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// get<T>() - Return the value of the specified pointer type. If the 288e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// specified pointer type is incorrect, assert. 289e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 290e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner T get() const { 291e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner assert(is<T>() && "Invalid accessor called"); 292128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. 293128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 294128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion, 295128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 > 296128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 29787d8e60505b26960956996550c8b805c81e5b02bDouglas Gregor return Ty(Val).template get<T>(); 298e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 299e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 300e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// dyn_cast<T>() - If the current value is of the specified pointer type, 301e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// return it, otherwise return null. 302e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 303e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner T dyn_cast() const { 304e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner if (is<T>()) return get<T>(); 305e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return T(); 306e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 307dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 308dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Assignment from nullptr which just clears the union. 309dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const PointerUnion3 &operator=(std::nullptr_t) { 310dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Val = nullptr; 311dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 312dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 313e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 314e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// Assignment operators - Allow assigning into this union from either 315e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// pointer type, setting the discriminator to remember what it came from. 316e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT1 &RHS) { 317e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(RHS); 318e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 319e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 320e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT2 &RHS) { 321e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(RHS); 322e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 323e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 324e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT3 &RHS) { 325e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = RHS; 326e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 327e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 328e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 329e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner void *getOpaqueValue() const { return Val.getOpaqueValue(); } 3308260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion3 getFromOpaqueValue(void *VP) { 331e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3 V; 332e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner V.Val = ValTy::getFromOpaqueValue(VP); 333e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return V; 334e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 335e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 336e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 337e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has 338e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 339e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename PT1, typename PT2, typename PT3> 340e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > { 341e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 342e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline void * 343e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) { 344e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return P.getOpaqueValue(); 345e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 346e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline PointerUnion3<PT1, PT2, PT3> 347e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner getFromVoidPointer(void *P) { 348e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); 349e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 350e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 351e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // The number of bits available are the min of the two pointer types. 352e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner enum { 353e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner NumLowBitsAvailable = 354e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy> 355e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ::NumLowBitsAvailable 3562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 3572491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 358e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 359e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// PointerUnion4 - This is a pointer union of four pointer types. See 360e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// documentation for PointerUnion for usage. 361e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template <typename PT1, typename PT2, typename PT3, typename PT4> 362e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor class PointerUnion4 { 363e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 364e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<PT1, PT2> InnerUnion1; 365e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<PT3, PT4> InnerUnion2; 366e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy; 367e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor private: 368e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor ValTy Val; 369e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 370e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4() {} 371e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 372e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT1 V) { 373e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(V); 374e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 375e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT2 V) { 376e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(V); 377e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 378e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT3 V) { 379e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(V); 380e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 381e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT4 V) { 382e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(V); 383e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 384e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 38526ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 386e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// regardless of which type it is. 387e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor bool isNull() const { return Val.isNull(); } 388453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie LLVM_EXPLICIT operator bool() const { return !isNull(); } 389e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 390e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// is<T>() return true if the Union currently holds the type matching T. 391e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 392e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor int is() const { 393128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. 394128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 395128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1, 396128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 > 397128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 398128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template is<Ty>() && 399128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis Val.template get<Ty>().template is<T>(); 400e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 401e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 402e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// get<T>() - Return the value of the specified pointer type. If the 403e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// specified pointer type is incorrect, assert. 404e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 405e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor T get() const { 406e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor assert(is<T>() && "Invalid accessor called"); 407128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. 408128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 409128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1, 410128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 > 411128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 412128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template get<Ty>().template get<T>(); 413e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 414e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 415e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// dyn_cast<T>() - If the current value is of the specified pointer type, 416e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// return it, otherwise return null. 417e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 418e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor T dyn_cast() const { 419e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor if (is<T>()) return get<T>(); 420e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return T(); 421e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 422dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 423dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines /// \brief Assignment from nullptr which just clears the union. 424dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const PointerUnion4 &operator=(std::nullptr_t) { 425dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Val = nullptr; 426dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return *this; 427dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 428e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 429e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// Assignment operators - Allow assigning into this union from either 430e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// pointer type, setting the discriminator to remember what it came from. 431e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT1 &RHS) { 432e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(RHS); 433e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 434e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 435e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT2 &RHS) { 436e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(RHS); 437e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 438e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 439e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT3 &RHS) { 440e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(RHS); 441e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 442e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 443e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT4 &RHS) { 444e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(RHS); 445e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 446e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 447e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 448e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor void *getOpaqueValue() const { return Val.getOpaqueValue(); } 4498260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion4 getFromOpaqueValue(void *VP) { 450e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4 V; 451e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor V.Val = ValTy::getFromOpaqueValue(VP); 452e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return V; 453e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 454e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 455e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 456e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has 457e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 458e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename PT1, typename PT2, typename PT3, typename PT4> 459e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > { 460e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 461e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor static inline void * 462e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) { 463e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return P.getOpaqueValue(); 464e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 465e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor static inline PointerUnion4<PT1, PT2, PT3, PT4> 466e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor getFromVoidPointer(void *P) { 467e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P); 468e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 469e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 470e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // The number of bits available are the min of the two pointer types. 471e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor enum { 472e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor NumLowBitsAvailable = 473e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy> 474e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor ::NumLowBitsAvailable 475e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 476e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 477dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 478dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Teach DenseMap how to use PointerUnions as keys. 479dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines template<typename T, typename U> 480dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines struct DenseMapInfo<PointerUnion<T, U> > { 481dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines typedef PointerUnion<T, U> Pair; 482dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines typedef DenseMapInfo<T> FirstInfo; 483dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines typedef DenseMapInfo<U> SecondInfo; 484dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 485dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static inline Pair getEmptyKey() { 486dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return Pair(FirstInfo::getEmptyKey()); 487dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 488dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static inline Pair getTombstoneKey() { 489dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return Pair(FirstInfo::getTombstoneKey()); 490dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 491dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static unsigned getHashValue(const Pair &PairVal) { 492dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines intptr_t key = (intptr_t)PairVal.getOpaqueValue(); 493dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return DenseMapInfo<intptr_t>::getHashValue(key); 494dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 495dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines static bool isEqual(const Pair &LHS, const Pair &RHS) { 496dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return LHS.template is<T>() == RHS.template is<T>() && 497dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines (LHS.template is<T>() ? 498dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines FirstInfo::isEqual(LHS.template get<T>(), 499dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines RHS.template get<T>()) : 500dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SecondInfo::isEqual(LHS.template get<U>(), 501dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines RHS.template get<U>())); 502dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 503dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines }; 5042491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner} 5052491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 5062491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#endif 507