make #includes consistent
[hiphop-php.git] / hphp / runtime / vm / translator / physreg.h
blob0a870e6665413272ab6f0d7a177fa1328e7b0801
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #ifndef incl_HPHP_VM_PHYSREG_H_
17 #define incl_HPHP_VM_PHYSREG_H_
19 #include "hphp/util/asm-x64.h"
20 #include "hphp/util/bitops.h"
22 namespace HPHP { namespace Transl {
24 //////////////////////////////////////////////////////////////////////
27 * PhysReg represents a physical machine register. (Currently it only
28 * knows how to do GPRs.)
30 * To make it possible to use it with the assembler conveniently, it
31 * can be implicitly converted to and from Reg64. If you want to use
32 * it as a 32 bit register call r32(physReg).
34 * The implicit conversion to RegNumber is historical: it exists
35 * for backward-compatability with the old-style asm-x64.h api
36 * (e.g. store_reg##_disp_reg##).
38 struct PhysReg {
39 explicit constexpr PhysReg(int n = -1) : n(n) {}
40 constexpr /* implicit */ PhysReg(Reg64 r) : n(int(r)) {}
41 explicit constexpr PhysReg(Reg32 r) : n(int(RegNumber(r))) {}
43 explicit constexpr PhysReg(RegNumber r) : n(int(r)) {}
45 constexpr /* implicit */ operator Reg64() const { return Reg64(n); }
46 constexpr /* implicit */ operator RegNumber() const { return RegNumber(n); }
48 explicit constexpr operator int() const { return n; }
49 constexpr bool operator==(PhysReg r) const { return n == r.n; }
50 constexpr bool operator!=(PhysReg r) const { return n != r.n; }
51 constexpr bool operator==(Reg64 r) const { return Reg64(n) == r; }
52 constexpr bool operator!=(Reg64 r) const { return Reg64(n) != r; }
53 constexpr bool operator==(Reg32 r) const { return Reg32(n) == r; }
54 constexpr bool operator!=(Reg32 r) const { return Reg32(n) != r; }
56 MemoryRef operator[](intptr_t p) const { return *(*this + p); }
57 IndexedMemoryRef operator[](Reg64 i) const { return *(*this + i); }
58 IndexedMemoryRef operator[](ScaledIndex s) const { return *(*this + s); }
59 IndexedMemoryRef operator[](ScaledIndexDisp s) const {
60 return *(*this + s.si + s.disp);
62 IndexedMemoryRef operator[](DispReg dr) const {
63 return *(*this + ScaledIndex(dr.base, 0x1) + dr.disp);
66 private:
67 int n;
70 constexpr PhysReg InvalidReg;
73 * A set of registers.
75 * This type is guaranteed to be a standard layout class with a
76 * trivial destructor. (This makes it usable in classes that are
77 * arena-allocated.)
79 * Zero-initializing this class is guaranteed to produce an empty set.
81 struct RegSet {
82 explicit RegSet() : m_bits(0) {}
83 explicit RegSet(PhysReg pr) : m_bits(1 << int(pr)) {}
85 // Union
86 RegSet operator|(const RegSet& rhs) const {
87 RegSet retval;
88 retval.m_bits = m_bits | rhs.m_bits;
89 return retval;
92 RegSet& operator|=(const RegSet& rhs) {
93 m_bits |= rhs.m_bits;
94 return *this;
97 // Intersection
98 RegSet operator&(const RegSet& rhs) const {
99 RegSet retval;
100 retval.m_bits = m_bits & rhs.m_bits;
101 return retval;
104 RegSet& operator&=(const RegSet& rhs) {
105 m_bits &= rhs.m_bits;
106 return *this;
109 // Equality
110 bool operator==(const RegSet& rhs) const {
111 return m_bits == rhs.m_bits;
114 bool operator!=(const RegSet& rhs) const {
115 return !(*this == rhs);
118 // Difference
119 RegSet operator-(const RegSet& rhs) const {
120 RegSet retval;
121 retval.m_bits = m_bits & ~rhs.m_bits;
122 return retval;
125 RegSet& operator-=(const RegSet& rhs) {
126 *this = *this - rhs;
127 return *this;
130 void clear() {
131 m_bits = 0;
134 int size() const {
135 return __builtin_popcount(m_bits);
138 RegSet& add(PhysReg pr) {
139 if (pr != InvalidReg) {
140 *this |= RegSet(pr);
142 return *this;
145 RegSet& remove(PhysReg pr) {
146 if (pr != InvalidReg) {
147 m_bits = m_bits & ~(1 << int(pr));
149 return *this;
152 bool contains(PhysReg pr) const {
153 return bool(m_bits & (1 << int(pr)));
156 bool empty() const {
157 return m_bits == 0;
161 * Can be used for iterating over present registers, in forward or
162 * backward order:
164 * while (regSet.findFirst(reg)) {
165 * regSet.remove(reg);
166 * foo(reg);
169 * while (regSet.findLast(reg)) {
170 * regSet.remove(reg);
171 * foo(reg);
174 * Consider forEach if you don't want to mutate your register set.
176 bool findFirst(PhysReg& reg) {
177 uint64_t out;
178 bool retval = ffs64(m_bits, out);
179 reg = PhysReg(out);
180 assert(!retval || (int(reg) >= 0 && int(reg) < 64));
181 return retval;
184 bool findLast(PhysReg& reg) {
185 uint64_t out;
186 bool retval = fls64(m_bits, out);
187 reg = PhysReg(out);
188 assert(!retval || (int(reg) >= 0 && int(reg) < 64));
189 return retval;
193 * Do something for each register in the set, in either forward or
194 * reverse order.
197 template<class Fun>
198 void forEach(Fun f) const {
199 RegSet cpy = *this;
200 PhysReg r;
201 while (cpy.findFirst(r)) {
202 cpy.remove(r);
203 f(r);
207 template<class Fun>
208 void forEachR(Fun f) const {
209 RegSet cpy = *this;
210 PhysReg r;
211 while (cpy.findLast(r)) {
212 cpy.remove(r);
213 f(r);
217 private:
218 uint64_t m_bits;
221 static_assert(std::has_trivial_destructor<RegSet>::value,
222 "RegSet must have a trivial destructor");
224 //////////////////////////////////////////////////////////////////////
226 struct PhysRegSaverParity {
227 PhysRegSaverParity(int parity, X64Assembler& as, RegSet regs);
228 ~PhysRegSaverParity();
230 PhysRegSaverParity(const PhysRegSaverParity&) = delete;
231 PhysRegSaverParity(PhysRegSaverParity&&) = default;
232 PhysRegSaverParity& operator=(const PhysRegSaverParity&) = delete;
233 PhysRegSaverParity& operator=(PhysRegSaverParity&&) = default;
235 int rspAdjustment() const;
236 void bytesPushed(int64_t bytes);
238 private:
239 X64Assembler& m_as;
240 RegSet m_regs;
241 int64_t m_adjust;
244 struct PhysRegSaverStub : public PhysRegSaverParity {
245 PhysRegSaverStub(X64Assembler& as, RegSet regs)
246 : PhysRegSaverParity(0, as, regs)
250 struct PhysRegSaver : public PhysRegSaverParity {
251 PhysRegSaver(X64Assembler& as, RegSet regs)
252 : PhysRegSaverParity(1, as, regs)
256 //////////////////////////////////////////////////////////////////////
260 #endif