Create a super rough prototype of B3
[WebKit-https.git] / Source / JavaScriptCore / b3 / air / AirTmp.h
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef AirTmp_h
27 #define AirTmp_h
28
29 #if ENABLE(B3_JIT)
30
31 #include "FPRInfo.h"
32 #include "GPRInfo.h"
33 #include "Reg.h"
34 #include <wtf/HashMap.h>
35
36 namespace JSC { namespace B3 { namespace Air {
37
38 class Arg;
39
40 // A Tmp is a generalization of a register. It can be used to refer to any GPR or FPR. It can also
41 // be used to refer to an unallocated register (i.e. a temporary). Like many Air classes, we use
42 // deliberately terse naming since we will have to use this name a lot.
43
44 class Tmp {
45 public:
46     Tmp()
47         : m_value(0)
48     {
49     }
50
51     explicit Tmp(Reg reg)
52     {
53         if (reg) {
54             if (reg.isGPR())
55                 m_value = encodeGPR(reg.gpr());
56             else
57                 m_value = encodeFPR(reg.fpr());
58         } else
59             m_value = 0;
60     }
61
62     explicit Tmp(const Arg&);
63
64     static Tmp gpTmpForIndex(unsigned index)
65     {
66         Tmp result;
67         result.m_value = encodeGPTmp(index);
68         return result;
69     }
70
71     static Tmp fpTmpForIndex(unsigned index)
72     {
73         Tmp result;
74         result.m_value = encodeFPTmp(index);
75         return result;
76     }
77
78     explicit operator bool() const { return !!m_value; }
79
80     bool isGP() const
81     {
82         return isEncodedGP(m_value);
83     }
84
85     bool isFP() const
86     {
87         return isEncodedFP(m_value);
88     }
89
90     bool isGPR() const
91     {
92         return isEncodedGPR(m_value);
93     }
94
95     bool isFPR() const
96     {
97         return isEncodedFPR(m_value);
98     }
99
100     bool isReg() const
101     {
102         return isGPR() || isFPR();
103     }
104
105     GPRReg gpr() const
106     {
107         return decodeGPR(m_value);
108     }
109
110     FPRReg fpr() const
111     {
112         return decodeFPR(m_value);
113     }
114
115     Reg reg() const
116     {
117         if (isGP())
118             return gpr();
119         return fpr();
120     }
121
122     bool hasTmpIndex() const
123     {
124         return !isReg();
125     }
126
127     unsigned gpTmpIndex() const
128     {
129         return decodeGPTmp(m_value);
130     }
131
132     unsigned fpTmpIndex() const
133     {
134         return decodeFPTmp(m_value);
135     }
136
137     unsigned tmpIndex() const
138     {
139         if (isGP())
140             return gpTmpIndex();
141         return fpTmpIndex();
142     }
143
144     bool isAlive() const
145     {
146         return !!*this;
147     }
148
149     bool operator==(const Tmp& other) const
150     {
151         return m_value == other.m_value;
152     }
153
154     bool operator!=(const Tmp& other) const
155     {
156         return !(*this == other);
157     }
158
159     void dump(PrintStream& out) const;
160
161     Tmp(WTF::HashTableDeletedValueType)
162         : m_value(std::numeric_limits<int>::max())
163     {
164     }
165
166     bool isHashTableDeletedValue() const
167     {
168         return *this == Tmp(WTF::HashTableDeletedValue);
169     }
170
171     unsigned hash() const
172     {
173         return WTF::IntHash<int>::hash(m_value);
174     }
175     
176 private:
177     static int encodeGP(unsigned index)
178     {
179         return 1 + index;
180     }
181
182     static int encodeFP(unsigned index)
183     {
184         return -1 - index;
185     }
186
187     static int encodeGPR(GPRReg gpr)
188     {
189         return encodeGP(gpr - MacroAssembler::firstRegister());
190     }
191
192     static int encodeFPR(FPRReg fpr)
193     {
194         return encodeFP(fpr - MacroAssembler::firstFPRegister());
195     }
196
197     static int encodeGPTmp(unsigned index)
198     {
199         return encodeGPR(MacroAssembler::lastRegister()) + 1 + index;
200     }
201
202     static int encodeFPTmp(unsigned index)
203     {
204         return encodeFPR(MacroAssembler::lastFPRegister()) - 1 - index;
205     }
206
207     static bool isEncodedGP(int value)
208     {
209         return value > 0;
210     }
211
212     static bool isEncodedFP(int value)
213     {
214         return value < 0;
215     }
216
217     static bool isEncodedGPR(int value)
218     {
219         return isEncodedGP(value) && value <= encodeGPR(MacroAssembler::lastRegister());
220     }
221
222     static bool isEncodedFPR(int value)
223     {
224         return isEncodedFP(value) && value >= encodeFPR(MacroAssembler::lastFPRegister());
225     }
226
227     static bool isEncodedGPTmp(int value)
228     {
229         return isEncodedGP(value) && !isEncodedGPR(value);
230     }
231
232     static bool isEncodedFPTmp(int value)
233     {
234         return isEncodedFP(value) && !isEncodedFPR(value);
235     }
236
237     static GPRReg decodeGPR(int value)
238     {
239         ASSERT(isEncodedGPR(value));
240         return static_cast<GPRReg>(
241             (value - encodeGPR(MacroAssembler::firstRegister())) + MacroAssembler::firstRegister());
242     }
243
244     static FPRReg decodeFPR(int value)
245     {
246         ASSERT(isEncodedFPR(value));
247         return static_cast<FPRReg>(
248             (encodeFPR(MacroAssembler::firstFPRegister()) - value) +
249             MacroAssembler::firstFPRegister());
250     }
251
252     static unsigned decodeGPTmp(int value)
253     {
254         ASSERT(isEncodedGPTmp(value));
255         return value - (encodeGPR(MacroAssembler::lastRegister()) + 1);
256     }
257
258     static unsigned decodeFPTmp(int value)
259     {
260         ASSERT(isEncodedFPTmp(value));
261         return (encodeFPR(MacroAssembler::lastFPRegister()) - 1) - value;
262     }
263
264     // 0: empty Tmp
265     // positive: GPRs and then GP temps.
266     // negative: FPRs and then FP temps.
267     int m_value;
268 };
269
270 struct TmpHash {
271     static unsigned hash(const Tmp& key) { return key.hash(); }
272     static bool equal(const Tmp& a, const Tmp& b) { return a == b; }
273     static const bool safeToCompareToEmptyOrDeleted = true;
274 };
275
276 } } } // namespace JSC::B3::Air
277
278 namespace WTF {
279
280 template<typename T> struct DefaultHash;
281 template<> struct DefaultHash<JSC::B3::Air::Tmp> {
282     typedef JSC::B3::Air::TmpHash Hash;
283 };
284
285 template<typename T> struct HashTraits;
286 template<> struct HashTraits<JSC::B3::Air::Tmp> : SimpleClassHashTraits<JSC::B3::Air::Tmp> { };
287
288 } // namespace WTF
289
290 #endif // ENABLE(B3_JIT)
291
292 #endif // AirTmp_h
293