summaryrefslogtreecommitdiffstats
path: root/include/llvm/ADT/PointerIntPair.h
blob: 0aa478b1ff61cd7117d06ce780d319f11e7959e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PointerIntPair class.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_ADT_POINTERINTPAIR_H
#define LLVM_ADT_POINTERINTPAIR_H

#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>

namespace llvm {

template<typename T>
struct DenseMapInfo;

/// 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 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,
          typename PtrTraits = PointerLikeTypeTraits<PointerTy> >
class PointerIntPair {
  intptr_t Value;
  enum {
    /// PointerBitMask - The bits that come from the pointer.
    PointerBitMask =
      ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1),

    /// IntShift - The number of low bits that we reserve for other uses, and
    /// keep zero.
    IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable-IntBits,
    
    /// IntMask - This is the unshifted mask for valid bits of the int type.
    IntMask = (uintptr_t)(((intptr_t)1 << IntBits)-1),
    
    // ShiftedIntMask - This is the bits for the integer shifted in place.
    ShiftedIntMask = (uintptr_t)(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 & PointerBitMask);
  }

  IntType getInt() const {
    return (IntType)((Value >> IntShift) & IntMask);
  }

  void setPointer(PointerTy Ptr) {
    intptr_t PtrVal = reinterpret_cast<intptr_t>(Ptr);
    assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
           "Pointer is not sufficiently aligned");
    // 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");
    
    // 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); }
  void setFromOpaqueValue(void *Val) { Value = reinterpret_cast<intptr_t>(Val);}

  static PointerIntPair getFromOpaqueValue(void *V) {
    PointerIntPair P; P.setFromOpaqueValue(V); return P; 
  }
  
  bool operator==(const PointerIntPair &RHS) const {return Value == RHS.Value;}
  bool operator!=(const PointerIntPair &RHS) const {return Value != RHS.Value;}
  bool operator<(const PointerIntPair &RHS) const {return Value < RHS.Value;}
  bool operator>(const PointerIntPair &RHS) const {return Value > RHS.Value;}
  bool operator<=(const PointerIntPair &RHS) const {return Value <= RHS.Value;}
  bool operator>=(const PointerIntPair &RHS) const {return Value >= RHS.Value;}
};

// Provide specialization of DenseMapInfo for PointerIntPair.
template<typename PointerTy, unsigned IntBits, typename IntType>
struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType> > {
  typedef PointerIntPair<PointerTy, IntBits, IntType> Ty;
  static Ty getEmptyKey() {
    intptr_t Val = -1;
    Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
    return Ty(reinterpret_cast<PointerTy>(Val), IntType((1 << IntBits)-1));
  }
  static Ty getTombstoneKey() {
    intptr_t Val = -2;
    Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
    return Ty(reinterpret_cast<PointerTy>(Val), IntType(0));
  }
  static unsigned getHashValue(Ty V) {
    uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue());
    return unsigned(IV) ^ unsigned(IV >> 9);
  }
  static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; }
  static bool isPod() { return true; }
};

// Teach SmallPtrSet that PointerIntPair is "basically a pointer".
template<typename PointerTy, unsigned IntBits, typename IntType,
         typename PtrTraits>
class PointerLikeTypeTraits<PointerIntPair<PointerTy, IntBits, IntType,
                                           PtrTraits> > {
public:
  static inline void *
  getAsVoidPointer(const PointerIntPair<PointerTy, IntBits, IntType> &P) {
    return P.getOpaqueValue();
  }
  static inline PointerIntPair<PointerTy, IntBits, IntType>
  getFromVoidPointer(void *P) {
    return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
  }
  enum {
    NumLowBitsAvailable = 
           PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable - IntBits
  };
};

} // end namespace llvm
#endif
OpenPOWER on IntegriCloud