Fix PointerIntPair to be enum class compatible.
[oota-llvm.git] / include / llvm / ADT / PointerIntPair.h
1 //===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the PointerIntPair class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ADT_POINTERINTPAIR_H
15 #define LLVM_ADT_POINTERINTPAIR_H
16
17 #include "llvm/Support/PointerLikeTypeTraits.h"
18 #include <cassert>
19
20 namespace llvm {
21
22 template<typename T>
23 struct DenseMapInfo;
24
25 /// PointerIntPair - This class implements a pair of a pointer and small
26 /// integer.  It is designed to represent this in the space required by one
27 /// pointer by bitmangling the integer into the low part of the pointer.  This
28 /// can only be done for small integers: typically up to 3 bits, but it depends
29 /// on the number of bits available according to PointerLikeTypeTraits for the
30 /// type.
31 ///
32 /// Note that PointerIntPair always puts the IntVal part in the highest bits
33 /// possible.  For example, PointerIntPair<void*, 1, bool> will put the bit for
34 /// the bool into bit #2, not bit #0, which allows the low two bits to be used
35 /// for something else.  For example, this allows:
36 ///   PointerIntPair<PointerIntPair<void*, 1, bool>, 1, bool>
37 /// ... and the two bools will land in different bits.
38 ///
39 template <typename PointerTy, unsigned IntBits, typename IntType=unsigned,
40           typename PtrTraits = PointerLikeTypeTraits<PointerTy> >
41 class PointerIntPair {
42   intptr_t Value;
43   enum {
44     /// PointerBitMask - The bits that come from the pointer.
45     PointerBitMask =
46       ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1),
47
48     /// IntShift - The number of low bits that we reserve for other uses, and
49     /// keep zero.
50     IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable-IntBits,
51     
52     /// IntMask - This is the unshifted mask for valid bits of the int type.
53     IntMask = (uintptr_t)(((intptr_t)1 << IntBits)-1),
54     
55     // ShiftedIntMask - This is the bits for the integer shifted in place.
56     ShiftedIntMask = (uintptr_t)(IntMask << IntShift)
57   };
58 public:
59   PointerIntPair() : Value(0) {}
60   PointerIntPair(PointerTy PtrVal, IntType IntVal) {
61     assert(IntBits <= PtrTraits::NumLowBitsAvailable &&
62            "PointerIntPair formed with integer size too large for pointer");
63     setPointerAndInt(PtrVal, IntVal);
64   }
65   explicit PointerIntPair(PointerTy PtrVal) {
66     initWithPointer(PtrVal);
67   }
68
69   PointerTy getPointer() const {
70     return PtrTraits::getFromVoidPointer(
71                          reinterpret_cast<void*>(Value & PointerBitMask));
72   }
73
74   IntType getInt() const {
75     return (IntType)((Value >> IntShift) & IntMask);
76   }
77
78   void setPointer(PointerTy PtrVal) {
79     intptr_t PtrWord
80       = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
81     assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
82            "Pointer is not sufficiently aligned");
83     // Preserve all low bits, just update the pointer.
84     Value = PtrWord | (Value & ~PointerBitMask);
85   }
86
87   void setInt(IntType IntVal) {
88     intptr_t IntWord = static_cast<intptr_t>(IntVal);
89     assert(IntWord < (1 << IntBits) && "Integer too large for field");
90     
91     // Preserve all bits other than the ones we are updating.
92     Value &= ~ShiftedIntMask;     // Remove integer field.
93     Value |= IntWord << IntShift;  // Set new integer.
94   }
95
96   void initWithPointer(PointerTy PtrVal) {
97     intptr_t PtrWord
98       = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
99     assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
100            "Pointer is not sufficiently aligned");
101     Value = PtrWord;
102   }
103
104   void setPointerAndInt(PointerTy PtrVal, IntType IntVal) {
105     intptr_t PtrWord
106       = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
107     assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
108            "Pointer is not sufficiently aligned");
109     intptr_t IntWord = static_cast<intptr_t>(IntVal);
110     assert(IntWord < (1 << IntBits) && "Integer too large for field");
111
112     Value = PtrWord | (IntWord << IntShift);
113   }
114
115   PointerTy const *getAddrOfPointer() const {
116     return const_cast<PointerIntPair *>(this)->getAddrOfPointer();
117   }
118
119   PointerTy *getAddrOfPointer() {
120     assert(Value == reinterpret_cast<intptr_t>(getPointer()) &&
121            "Can only return the address if IntBits is cleared and "
122            "PtrTraits doesn't change the pointer");
123     return reinterpret_cast<PointerTy *>(&Value);
124   }
125
126   void *getOpaqueValue() const { return reinterpret_cast<void*>(Value); }
127   void setFromOpaqueValue(void *Val) { Value = reinterpret_cast<intptr_t>(Val);}
128
129   static PointerIntPair getFromOpaqueValue(void *V) {
130     PointerIntPair P; P.setFromOpaqueValue(V); return P; 
131   }
132
133   // Allow PointerIntPairs to be created from const void * if and only if the
134   // pointer type could be created from a const void *.
135   static PointerIntPair getFromOpaqueValue(const void *V) {
136     (void)PtrTraits::getFromVoidPointer(V);
137     return getFromOpaqueValue(const_cast<void *>(V));
138   }
139
140   bool operator==(const PointerIntPair &RHS) const {return Value == RHS.Value;}
141   bool operator!=(const PointerIntPair &RHS) const {return Value != RHS.Value;}
142   bool operator<(const PointerIntPair &RHS) const {return Value < RHS.Value;}
143   bool operator>(const PointerIntPair &RHS) const {return Value > RHS.Value;}
144   bool operator<=(const PointerIntPair &RHS) const {return Value <= RHS.Value;}
145   bool operator>=(const PointerIntPair &RHS) const {return Value >= RHS.Value;}
146 };
147
148 template <typename T> struct isPodLike;
149 template<typename PointerTy, unsigned IntBits, typename IntType>
150 struct isPodLike<PointerIntPair<PointerTy, IntBits, IntType> > {
151    static const bool value = true;
152 };
153   
154 // Provide specialization of DenseMapInfo for PointerIntPair.
155 template<typename PointerTy, unsigned IntBits, typename IntType>
156 struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType> > {
157   typedef PointerIntPair<PointerTy, IntBits, IntType> Ty;
158   static Ty getEmptyKey() {
159     uintptr_t Val = static_cast<uintptr_t>(-1);
160     Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
161     return Ty(reinterpret_cast<PointerTy>(Val), IntType((1 << IntBits)-1));
162   }
163   static Ty getTombstoneKey() {
164     uintptr_t Val = static_cast<uintptr_t>(-2);
165     Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
166     return Ty(reinterpret_cast<PointerTy>(Val), IntType(0));
167   }
168   static unsigned getHashValue(Ty V) {
169     uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue());
170     return unsigned(IV) ^ unsigned(IV >> 9);
171   }
172   static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; }
173 };
174
175 // Teach SmallPtrSet that PointerIntPair is "basically a pointer".
176 template<typename PointerTy, unsigned IntBits, typename IntType,
177          typename PtrTraits>
178 class PointerLikeTypeTraits<PointerIntPair<PointerTy, IntBits, IntType,
179                                            PtrTraits> > {
180 public:
181   static inline void *
182   getAsVoidPointer(const PointerIntPair<PointerTy, IntBits, IntType> &P) {
183     return P.getOpaqueValue();
184   }
185   static inline PointerIntPair<PointerTy, IntBits, IntType>
186   getFromVoidPointer(void *P) {
187     return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
188   }
189   static inline PointerIntPair<PointerTy, IntBits, IntType>
190   getFromVoidPointer(const void *P) {
191     return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
192   }
193   enum {
194     NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits
195   };
196 };
197
198 } // end namespace llvm
199 #endif