diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 7b3283c96d2..999b802ffca 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -15,50 +15,77 @@ #define LLVM_ADT_POINTERINTPAIR_H #include "llvm/Support/DataTypes.h" +#include "llvm/Support/PointerLikeTypeTraits.h" #include namespace llvm { template struct DenseMapInfo; -template -class PointerLikeTypeTraits; /// PointerIntPair - This class implements a pair of a pointer and small /// integer. It is designed to represent this in the space required by one /// pointer by bitmangling the integer into the low part of the pointer. This /// can only be done for small integers: typically up to 3 bits, but it depends -/// on the alignment returned by the allocator in use. +/// on the number of bits available according to PointerLikeTypeTraits for the +/// type. +/// +/// Note that PointerIntPair always puts the Int part in the highest bits +/// possible. For example, PointerIntPair will put the bit for +/// the bool into bit #2, not bit #0, which allows the low two bits to be used +/// for something else. For example, this allows: +/// PointerIntPair, 1, bool> +/// ... and the two bools will land in different bits. /// template class PointerIntPair { intptr_t Value; + typedef PointerLikeTypeTraits PtrTraits; + enum { + /// PointerBitMask - The bits that come from the pointer. + PointerBitMask = ~(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + /// IntShift - The number of low bits that we reserve for other uses, and + /// keep zero. + IntShift = PtrTraits::NumLowBitsAvailable-IntBits, + + /// IntMask - This is the unshifted mask for valid bits of the int type. + IntMask = ((intptr_t)1 << IntBits)-1, + + // ShiftedIntMask - This is the bits for the integer shifted in place. + ShiftedIntMask = IntMask << IntShift + }; public: PointerIntPair() : Value(0) {} PointerIntPair(PointerTy Ptr, IntType Int) : Value(0) { + assert(IntBits <= PtrTraits::NumLowBitsAvailable && + "PointerIntPair formed with integer size too large for pointer"); setPointer(Ptr); setInt(Int); } PointerTy getPointer() const { - return reinterpret_cast(Value & ~((1 << IntBits)-1)); + return reinterpret_cast(Value & PointerBitMask); } IntType getInt() const { - return (IntType)(Value & ((1 << IntBits)-1)); + return (IntType)((Value >> IntShift) & IntMask); } void setPointer(PointerTy Ptr) { intptr_t PtrVal = reinterpret_cast(Ptr); - assert((PtrVal & ((1 << IntBits)-1)) == 0 && + assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && "Pointer is not sufficiently aligned"); - Value = PtrVal | (intptr_t)getInt(); + // Preserve all low bits, just update the pointer. + Value = PtrVal | (Value & ~PointerBitMask); } void setInt(IntType Int) { intptr_t IntVal = Int; assert(IntVal < (1 << IntBits) && "Integer too large for field"); - Value = reinterpret_cast(getPointer()) | IntVal; + + // Preserve all bits other than the ones we are updating. + Value &= ~ShiftedIntMask; // Remove integer field. + Value |= IntVal << IntShift; // Set new integer. } void *getOpaqueValue() const { return reinterpret_cast(Value); } @@ -107,7 +134,10 @@ public: getFromVoidPointer(void *P) { return PointerIntPair::getFromOpaqueValue(P); } - static inline unsigned getNumLowBitsAvailable() { return 0; } + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits::NumLowBitsAvailable - IntBits + }; }; } // end namespace llvm diff --git a/include/llvm/Instruction.h b/include/llvm/Instruction.h index a9cc000a25e..856531c9068 100644 --- a/include/llvm/Instruction.h +++ b/include/llvm/Instruction.h @@ -227,6 +227,18 @@ public: }; }; +// Instruction* is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { + typedef Instruction* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + } // End llvm namespace #endif diff --git a/include/llvm/Support/PointerLikeTypeTraits.h b/include/llvm/Support/PointerLikeTypeTraits.h index 41b2302381f..000919ca109 100644 --- a/include/llvm/Support/PointerLikeTypeTraits.h +++ b/include/llvm/Support/PointerLikeTypeTraits.h @@ -42,7 +42,7 @@ public: /// /// All clients should use assertions to do a run-time check to ensure that /// this is actually true. - static inline unsigned getNumLowBitsAvailable() { return 3; } + enum { NumLowBitsAvailable = 3 }; }; // Provide PointerLikeTypeTraits for const pointers. @@ -53,7 +53,7 @@ public: static inline const T *getFromVoidPointer(const void *P) { return static_cast(P); } - static inline unsigned getNumLowBitsAvailable() { return 3; } + enum { NumLowBitsAvailable = 3 }; }; } // end namespace llvm diff --git a/include/llvm/Use.h b/include/llvm/Use.h index cde4366a5a0..53df699e703 100644 --- a/include/llvm/Use.h +++ b/include/llvm/Use.h @@ -24,11 +24,21 @@ namespace llvm { class Value; class User; - +class Use; /// Tag - generic tag type for (at least 32 bit) pointers enum Tag { noTag, tagOne, tagTwo, tagThree }; +// Use** is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(Use** P) { return P; } + static inline Use **getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; //===----------------------------------------------------------------------===// // Use Class @@ -212,7 +222,7 @@ template<> struct simplify_type > { template<> struct simplify_type > : public simplify_type > {}; - + } // End llvm namespace #endif