X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FADT%2FPointerUnion.h;h=a9e86d22002de7f1b5c57b3a039ad2c809d6439e;hb=2430973fb657eb84dfbacb1e8886d3a29190e0b5;hp=3a514b56269734f88ccf9734de65b6ff37045b57;hpb=8260ea5c6c15345e00ced1398b03e6886145e45c;p=oota-llvm.git diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index 3a514b56269..a9e86d22002 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -19,16 +19,33 @@ namespace llvm { - /// getPointerUnionTypeNum - If the argument has type PT1* or PT2* return - /// false or true respectively. - template - static inline int getPointerUnionTypeNum(PT1 *P) { return 0; } - template - static inline int getPointerUnionTypeNum(PT2 *P) { return 1; } - template - static inline int getPointerUnionTypeNum(...) { return -1; } - - + template + struct PointerUnionTypeSelectorReturn { + typedef T Return; + }; + + /// \brief Get a type based on whether two types are the same or not. For: + /// @code + /// typedef typename PointerUnionTypeSelector::Return Ret; + /// @endcode + /// Ret will be EQ type if T1 is same as T2 or NE type otherwise. + template + struct PointerUnionTypeSelector { + typedef typename PointerUnionTypeSelectorReturn::Return Return; + }; + + template + struct PointerUnionTypeSelector { + typedef typename PointerUnionTypeSelectorReturn::Return Return; + }; + + template + struct PointerUnionTypeSelectorReturn< + PointerUnionTypeSelector > { + typedef typename PointerUnionTypeSelector::Return + Return; + }; + /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion /// for the two template arguments. template @@ -37,8 +54,8 @@ namespace llvm { static inline void *getAsVoidPointer(void *P) { return P; } static inline void *getFromVoidPointer(void *P) { return P; } enum { - PT1BitsAv = PointerLikeTypeTraits::NumLowBitsAvailable, - PT2BitsAv = PointerLikeTypeTraits::NumLowBitsAvailable, + PT1BitsAv = (int)(PointerLikeTypeTraits::NumLowBitsAvailable), + PT2BitsAv = (int)(PointerLikeTypeTraits::NumLowBitsAvailable), NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv }; }; @@ -65,6 +82,16 @@ namespace llvm { PointerUnionUIntTraits > ValTy; private: ValTy Val; + + struct IsPT1 { + static const int Num = 0; + }; + struct IsPT2 { + static const int Num = 1; + }; + template + struct UNION_DOESNT_CONTAIN_TYPE { }; + public: PointerUnion() {} @@ -81,14 +108,21 @@ namespace llvm { /// isNull - Return true if the pointer held in the union is null, /// regardless of which type it is. - bool isNull() const { return Val.getPointer() == 0; } + bool isNull() const { + // Convert from the void* to one of the pointer types, to make sure that + // we recursively strip off low bits if we have a nested PointerUnion. + return !PointerLikeTypeTraits::getFromVoidPointer(Val.getPointer()); + } operator bool() const { return !isNull(); } /// is() return true if the Union currently holds the type matching T. template int is() const { - int TyNo = ::llvm::getPointerUnionTypeNum((T*)0); - assert(TyNo != -1 && "Type query could never succeed on PointerUnion!"); + typedef typename + ::llvm::PointerUnionTypeSelector > >::Return Ty; + int TyNo = Ty::Num; return static_cast(Val.getInt()) == TyNo; } @@ -107,6 +141,21 @@ namespace llvm { if (is()) return get(); return T(); } + + /// \brief If the union is set to the first pointer type get an address + /// pointing to it. + PT1 const *getAddrOfPtr1() const { + return const_cast(this)->getAddrOfPtr1(); + } + + /// \brief If the union is set to the first pointer type get an address + /// pointing to it. + PT1 *getAddrOfPtr1() { + assert(is() && "Val is not the first pointer"); + assert(get() == Val.getPointer() && + "Can't get the address because PointerLikeTypeTraits changes the ptr"); + return (PT1 *)Val.getAddrOfPointer(); + } /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. @@ -163,6 +212,34 @@ namespace llvm { typedef PointerUnion ValTy; private: ValTy Val; + + struct IsInnerUnion { + ValTy Val; + IsInnerUnion(ValTy val) : Val(val) { } + template + int is() const { + return Val.template is() && + Val.template get().template is(); + } + template + T get() const { + return Val.template get().template get(); + } + }; + + struct IsPT3 { + ValTy Val; + IsPT3(ValTy val) : Val(val) { } + template + int is() const { + return Val.template is(); + } + template + T get() const { + return Val.template get(); + } + }; + public: PointerUnion3() {} @@ -184,11 +261,12 @@ namespace llvm { /// is() return true if the Union currently holds the type matching T. template int is() const { - // Is it PT1/PT2? - if (::llvm::getPointerUnionTypeNum((T*)0) != -1) - return Val.template is() && - Val.template get().template is(); - return Val.template is(); + // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Ty(Val).template is(); } /// get() - Return the value of the specified pointer type. If the @@ -196,11 +274,12 @@ namespace llvm { template T get() const { assert(is() && "Invalid accessor called"); - // Is it PT1/PT2? - if (::llvm::getPointerUnionTypeNum((T*)0) != -1) - return Val.template get().template get(); - - return Val.template get(); + // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Ty(Val).template get(); } /// dyn_cast() - If the current value is of the specified pointer type, @@ -290,12 +369,13 @@ namespace llvm { /// is() return true if the Union currently holds the type matching T. template int is() const { - // Is it PT1/PT2? - if (::llvm::getPointerUnionTypeNum((T*)0) != -1) - return Val.template is() && - Val.template get().template is(); - return Val.template is() && - Val.template get().template is(); + // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Val.template is() && + Val.template get().template is(); } /// get() - Return the value of the specified pointer type. If the @@ -303,11 +383,12 @@ namespace llvm { template T get() const { assert(is() && "Invalid accessor called"); - // Is it PT1/PT2? - if (::llvm::getPointerUnionTypeNum((T*)0) != -1) - return Val.template get().template get(); - - return Val.template get().template get(); + // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Val.template get().template get(); } /// dyn_cast() - If the current value is of the specified pointer type,