LLVM API Documentation

PointerIntPair.h
Go to the documentation of this file.
00001 //===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines the PointerIntPair class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_ADT_POINTERINTPAIR_H
00015 #define LLVM_ADT_POINTERINTPAIR_H
00016 
00017 #include "llvm/Support/PointerLikeTypeTraits.h"
00018 #include <cassert>
00019 
00020 namespace llvm {
00021 
00022 template<typename T>
00023 struct DenseMapInfo;
00024 
00025 /// PointerIntPair - This class implements a pair of a pointer and small
00026 /// integer.  It is designed to represent this in the space required by one
00027 /// pointer by bitmangling the integer into the low part of the pointer.  This
00028 /// can only be done for small integers: typically up to 3 bits, but it depends
00029 /// on the number of bits available according to PointerLikeTypeTraits for the
00030 /// type.
00031 ///
00032 /// Note that PointerIntPair always puts the IntVal part in the highest bits
00033 /// possible.  For example, PointerIntPair<void*, 1, bool> will put the bit for
00034 /// the bool into bit #2, not bit #0, which allows the low two bits to be used
00035 /// for something else.  For example, this allows:
00036 ///   PointerIntPair<PointerIntPair<void*, 1, bool>, 1, bool>
00037 /// ... and the two bools will land in different bits.
00038 ///
00039 template <typename PointerTy, unsigned IntBits, typename IntType=unsigned,
00040           typename PtrTraits = PointerLikeTypeTraits<PointerTy> >
00041 class PointerIntPair {
00042   intptr_t Value;
00043   enum {
00044     /// PointerBitMask - The bits that come from the pointer.
00045     PointerBitMask =
00046       ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1),
00047 
00048     /// IntShift - The number of low bits that we reserve for other uses, and
00049     /// keep zero.
00050     IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable-IntBits,
00051     
00052     /// IntMask - This is the unshifted mask for valid bits of the int type.
00053     IntMask = (uintptr_t)(((intptr_t)1 << IntBits)-1),
00054     
00055     // ShiftedIntMask - This is the bits for the integer shifted in place.
00056     ShiftedIntMask = (uintptr_t)(IntMask << IntShift)
00057   };
00058 public:
00059   PointerIntPair() : Value(0) {}
00060   PointerIntPair(PointerTy PtrVal, IntType IntVal) {
00061     assert(IntBits <= PtrTraits::NumLowBitsAvailable &&
00062            "PointerIntPair formed with integer size too large for pointer");
00063     setPointerAndInt(PtrVal, IntVal);
00064   }
00065   explicit PointerIntPair(PointerTy PtrVal) {
00066     initWithPointer(PtrVal);
00067   }
00068 
00069   PointerTy getPointer() const {
00070     return PtrTraits::getFromVoidPointer(
00071                          reinterpret_cast<void*>(Value & PointerBitMask));
00072   }
00073 
00074   IntType getInt() const {
00075     return (IntType)((Value >> IntShift) & IntMask);
00076   }
00077 
00078   void setPointer(PointerTy PtrVal) {
00079     intptr_t PtrWord
00080       = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
00081     assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
00082            "Pointer is not sufficiently aligned");
00083     // Preserve all low bits, just update the pointer.
00084     Value = PtrWord | (Value & ~PointerBitMask);
00085   }
00086 
00087   void setInt(IntType IntVal) {
00088     intptr_t IntWord = static_cast<intptr_t>(IntVal);
00089     assert(IntWord < (1 << IntBits) && "Integer too large for field");
00090     
00091     // Preserve all bits other than the ones we are updating.
00092     Value &= ~ShiftedIntMask;     // Remove integer field.
00093     Value |= IntWord << IntShift;  // Set new integer.
00094   }
00095 
00096   void initWithPointer(PointerTy PtrVal) {
00097     intptr_t PtrWord
00098       = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
00099     assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
00100            "Pointer is not sufficiently aligned");
00101     Value = PtrWord;
00102   }
00103 
00104   void setPointerAndInt(PointerTy PtrVal, IntType IntVal) {
00105     intptr_t PtrWord
00106       = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
00107     assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
00108            "Pointer is not sufficiently aligned");
00109     intptr_t IntWord = static_cast<intptr_t>(IntVal);
00110     assert(IntWord < (1 << IntBits) && "Integer too large for field");
00111 
00112     Value = PtrWord | (IntWord << IntShift);
00113   }
00114 
00115   PointerTy const *getAddrOfPointer() const {
00116     return const_cast<PointerIntPair *>(this)->getAddrOfPointer();
00117   }
00118 
00119   PointerTy *getAddrOfPointer() {
00120     assert(Value == reinterpret_cast<intptr_t>(getPointer()) &&
00121            "Can only return the address if IntBits is cleared and "
00122            "PtrTraits doesn't change the pointer");
00123     return reinterpret_cast<PointerTy *>(&Value);
00124   }
00125 
00126   void *getOpaqueValue() const { return reinterpret_cast<void*>(Value); }
00127   void setFromOpaqueValue(void *Val) { Value = reinterpret_cast<intptr_t>(Val);}
00128 
00129   static PointerIntPair getFromOpaqueValue(void *V) {
00130     PointerIntPair P; P.setFromOpaqueValue(V); return P; 
00131   }
00132 
00133   // Allow PointerIntPairs to be created from const void * if and only if the
00134   // pointer type could be created from a const void *.
00135   static PointerIntPair getFromOpaqueValue(const void *V) {
00136     (void)PtrTraits::getFromVoidPointer(V);
00137     return getFromOpaqueValue(const_cast<void *>(V));
00138   }
00139 
00140   bool operator==(const PointerIntPair &RHS) const {return Value == RHS.Value;}
00141   bool operator!=(const PointerIntPair &RHS) const {return Value != RHS.Value;}
00142   bool operator<(const PointerIntPair &RHS) const {return Value < RHS.Value;}
00143   bool operator>(const PointerIntPair &RHS) const {return Value > RHS.Value;}
00144   bool operator<=(const PointerIntPair &RHS) const {return Value <= RHS.Value;}
00145   bool operator>=(const PointerIntPair &RHS) const {return Value >= RHS.Value;}
00146 };
00147 
00148 template <typename T> struct isPodLike;
00149 template<typename PointerTy, unsigned IntBits, typename IntType>
00150 struct isPodLike<PointerIntPair<PointerTy, IntBits, IntType> > {
00151    static const bool value = true;
00152 };
00153   
00154 // Provide specialization of DenseMapInfo for PointerIntPair.
00155 template<typename PointerTy, unsigned IntBits, typename IntType>
00156 struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType> > {
00157   typedef PointerIntPair<PointerTy, IntBits, IntType> Ty;
00158   static Ty getEmptyKey() {
00159     uintptr_t Val = static_cast<uintptr_t>(-1);
00160     Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
00161     return Ty(reinterpret_cast<PointerTy>(Val), IntType((1 << IntBits)-1));
00162   }
00163   static Ty getTombstoneKey() {
00164     uintptr_t Val = static_cast<uintptr_t>(-2);
00165     Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
00166     return Ty(reinterpret_cast<PointerTy>(Val), IntType(0));
00167   }
00168   static unsigned getHashValue(Ty V) {
00169     uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue());
00170     return unsigned(IV) ^ unsigned(IV >> 9);
00171   }
00172   static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; }
00173 };
00174 
00175 // Teach SmallPtrSet that PointerIntPair is "basically a pointer".
00176 template<typename PointerTy, unsigned IntBits, typename IntType,
00177          typename PtrTraits>
00178 class PointerLikeTypeTraits<PointerIntPair<PointerTy, IntBits, IntType,
00179                                            PtrTraits> > {
00180 public:
00181   static inline void *
00182   getAsVoidPointer(const PointerIntPair<PointerTy, IntBits, IntType> &P) {
00183     return P.getOpaqueValue();
00184   }
00185   static inline PointerIntPair<PointerTy, IntBits, IntType>
00186   getFromVoidPointer(void *P) {
00187     return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
00188   }
00189   static inline PointerIntPair<PointerTy, IntBits, IntType>
00190   getFromVoidPointer(const void *P) {
00191     return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
00192   }
00193   enum {
00194     NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits
00195   };
00196 };
00197 
00198 } // end namespace llvm
00199 #endif