diff options
-rw-r--r-- | include/llvm/ADT/PointerIntPair.h | 48 | ||||
-rw-r--r-- | include/llvm/Instruction.h | 12 | ||||
-rw-r--r-- | include/llvm/Support/PointerLikeTypeTraits.h | 4 | ||||
-rw-r--r-- | include/llvm/Use.h | 14 |
4 files changed, 65 insertions, 13 deletions
diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 7b3283c..999b802 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 <cassert> namespace llvm { template<typename T> struct DenseMapInfo; -template<typename> -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<void*, 1,bool> 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<PointerIntPair<void*, 1,bool>, 1, bool> +/// ... and the two bools will land in different bits. /// template <typename PointerTy, unsigned IntBits, typename IntType=unsigned> class PointerIntPair { intptr_t Value; + typedef PointerLikeTypeTraits<PointerTy> 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<PointerTy>(Value & ~((1 << IntBits)-1)); + return reinterpret_cast<PointerTy>(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<intptr_t>(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<intptr_t>(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<void*>(Value); } @@ -107,7 +134,10 @@ public: getFromVoidPointer(void *P) { return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P); } - static inline unsigned getNumLowBitsAvailable() { return 0; } + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable - IntBits + }; }; } // end namespace llvm diff --git a/include/llvm/Instruction.h b/include/llvm/Instruction.h index a9cc000..856531c 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<Instruction*> { + typedef Instruction* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast<PT>(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + } // End llvm namespace #endif diff --git a/include/llvm/Support/PointerLikeTypeTraits.h b/include/llvm/Support/PointerLikeTypeTraits.h index 41b2302..000919c 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<const T*>(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 cde4366..53df699 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<Use**> { +public: + static inline void *getAsVoidPointer(Use** P) { return P; } + static inline Use **getFromVoidPointer(void *P) { + return static_cast<Use**>(P); + } + enum { NumLowBitsAvailable = 2 }; +}; //===----------------------------------------------------------------------===// // Use Class @@ -212,7 +222,7 @@ template<> struct simplify_type<value_use_iterator<const User> > { template<> struct simplify_type<const value_use_iterator<const User> > : public simplify_type<value_use_iterator<const User> > {}; - + } // End llvm namespace #endif |