PointerUnion.h revision 2491e4657d95f7ff61fb2a741ba9996e492df515
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> 252491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline bool getPointerUnionTypeNum(PT1 *P) { return false; } 262491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 272491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline bool getPointerUnionTypeNum(PT2 *P) { return true; } 282491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // Enable, if we could use static_assert. 292491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner //template <typename PT1, typename PT2> 302491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner //static inline bool getPointerUnionTypeNum(...) { abort() } 312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 322491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 332491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion 342491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// for the two template arguments. 352491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 362491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerUnionUIntTraits { 372491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 382491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void *getAsVoidPointer(void *P) { return P; } 392491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void *getFromVoidPointer(void *P) { return P; } 402491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner enum { 412491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PT1BitsAv = PointerLikeTypeTraits<PT1>::NumLowBitsAvailable, 422491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PT2BitsAv = PointerLikeTypeTraits<PT2>::NumLowBitsAvailable, 432491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv 442491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 452491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 462491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 472491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// PointerUnion - This implements a discriminated union of two pointer types, 482491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// and keeps the discriminator bit-mangled into the low bits of the pointer. 492491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// This allows the implementation to be extremely efficient in space, but 502491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// permits a very natural and type-safe API. 512491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// 522491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Common use patterns would be something like this: 532491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// PointerUnion<int*, float*> P; 542491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// P = (int*)0; 552491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" 562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// X = P.get<int*>(); // ok. 572491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Y = P.get<float*>(); // runtime assertion failure. 582491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Z = P.get<double*>(); // does not compile. 592491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// P = (float*)0; 602491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Y = P.get<float*>(); // ok. 612491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// X = P.get<int*>(); // runtime assertion failure. 622491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 632491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerUnion { 642491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 652491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner typedef PointerIntPair<void*, 1, bool, 662491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnionUIntTraits<PT1,PT2> > ValTy; 672491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner private: 682491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner ValTy Val; 692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion() {} 712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 722491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion(PT1 V) { 732491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setPointer(V); 742491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(0); 752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 762491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion(PT2 V) { 772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setPointer(V); 782491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(1); 792491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename T> 822491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner int is() const { 832491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return Val.getInt() == ::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0); 842491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 852491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename T> 862491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner T get() const { 872491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner assert(is<T>() && "Invalid accessor called"); 882491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return static_cast<T>(Val.getPointer()); 892491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 902491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 912491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner const PointerUnion &operator=(const PT1 &RHS) { 922491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setPointer(RHS); 932491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(0); 942491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return *this; 952491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 962491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner const PointerUnion &operator=(const PT2 &RHS) { 972491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setPointer(RHS); 982491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(1); 992491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return *this; 1002491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1012491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1022491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner void *getOpaqueValue() const { return Val.getOpaqueValue(); } 1032491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static PointerUnion getFromOpaqueValue(void *VP) { 1042491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion V; 1052491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner V.Val = ValTy::getFromOpaqueValue(VP); 1062491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return V; 1072491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1082491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 1092491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1102491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // Teach SmallPtrSet that PointerIntPair is "basically a pointer", that has 1112491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // # low bits available = min(PT1bits,PT2bits)-1. 1122491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename PT1, typename PT2> 1132491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > { 1142491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 1152491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void * 1162491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner getAsVoidPointer(const PointerUnion<PT1, PT2> &P) { 1172491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return P.getOpaqueValue(); 1182491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1192491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline PointerUnion<PT1, PT2> 1202491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner getFromVoidPointer(void *P) { 1212491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); 1222491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1232491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1242491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // The number of bits available are the min of the two pointer types. 1252491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner enum { 1262491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner NumLowBitsAvailable = 1272491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion<PT1,PT2>::ValTy::NumLowBitsAvailable 1282491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 1292491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 1302491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner} 1312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1322491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#endif 133