Use constexpr instead of const in symbol definitions that are obviously constexpr.
[WebKit-https.git] / Source / JavaScriptCore / b3 / air / AirTmp.h
1 /*
2  * Copyright (C) 2015-2019 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 #pragma once
27
28 #if ENABLE(B3_JIT)
29
30 #include "B3Bank.h"
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 class Code;
40
41 // A Tmp is a generalization of a register. It can be used to refer to any GPR or FPR. It can also
42 // be used to refer to an unallocated register (i.e. a temporary). Like many Air classes, we use
43 // deliberately terse naming since we will have to use this name a lot.
44
45 class Tmp {
46 public:
47     constexpr Tmp()
48         : m_value(0)
49     {
50     }
51
52     explicit Tmp(Reg reg)
53     {
54         if (reg) {
55             if (reg.isGPR())
56                 m_value = encodeGPR(reg.gpr());
57             else
58                 m_value = encodeFPR(reg.fpr());
59         } else
60             m_value = 0;
61     }
62
63     explicit Tmp(const Arg&);
64
65     static Tmp gpTmpForIndex(unsigned index)
66     {
67         Tmp result;
68         result.m_value = encodeGPTmp(index);
69         return result;
70     }
71
72     static Tmp fpTmpForIndex(unsigned index)
73     {
74         Tmp result;
75         result.m_value = encodeFPTmp(index);
76         return result;
77     }
78     
79     static Tmp tmpForIndex(Bank bank, unsigned index)
80     {
81         if (bank == GP)
82             return gpTmpForIndex(index);
83         ASSERT(bank == FP);
84         return fpTmpForIndex(index);
85     }
86
87     explicit operator bool() const { return !!m_value; }
88     
89     bool isGP() const
90     {
91         return isEncodedGP(m_value);
92     }
93
94     bool isFP() const
95     {
96         return isEncodedFP(m_value);
97     }
98
99     // For null tmps, returns GP.
100     Bank bank() const
101     {
102         return isFP() ? FP : GP;
103     }
104
105     bool isGPR() const
106     {
107         return isEncodedGPR(m_value);
108     }
109
110     bool isFPR() const
111     {
112         return isEncodedFPR(m_value);
113     }
114
115     bool isReg() const
116     {
117         return isGPR() || isFPR();
118     }
119
120     GPRReg gpr() const
121     {
122         return decodeGPR(m_value);
123     }
124
125     FPRReg fpr() const
126     {
127         return decodeFPR(m_value);
128     }
129
130     Reg reg() const
131     {
132         if (isGP())
133             return gpr();
134         return fpr();
135     }
136
137     bool hasTmpIndex() const
138     {
139         return !isReg();
140     }
141
142     unsigned gpTmpIndex() const
143     {
144         return decodeGPTmp(m_value);
145     }
146
147     unsigned fpTmpIndex() const
148     {
149         return decodeFPTmp(m_value);
150     }
151     
152     unsigned tmpIndex(Bank bank) const
153     {
154         if (bank == GP)
155             return gpTmpIndex();
156         ASSERT(bank == FP);
157         return fpTmpIndex();
158     }
159
160     unsigned tmpIndex() const
161     {
162         if (isGP())
163             return gpTmpIndex();
164         return fpTmpIndex();
165     }
166     
167     template<Bank bank> class Indexed;
168     template<Bank bank> class AbsolutelyIndexed;
169     class LinearlyIndexed;
170     
171     template<Bank bank>
172     Indexed<bank> indexed() const;
173     
174     template<Bank bank>
175     AbsolutelyIndexed<bank> absolutelyIndexed() const;
176     
177     LinearlyIndexed linearlyIndexed(Code&) const;
178
179     static unsigned indexEnd(Code&, Bank);
180     static unsigned absoluteIndexEnd(Code&, Bank);
181     static unsigned linearIndexEnd(Code&);
182     
183     bool isAlive() const
184     {
185         return !!*this;
186     }
187
188     bool operator==(const Tmp& other) const
189     {
190         return m_value == other.m_value;
191     }
192
193     bool operator!=(const Tmp& other) const
194     {
195         return !(*this == other);
196     }
197
198     void dump(PrintStream& out) const;
199
200     Tmp(WTF::HashTableDeletedValueType)
201         : m_value(std::numeric_limits<int>::max())
202     {
203     }
204
205     bool isHashTableDeletedValue() const
206     {
207         return *this == Tmp(WTF::HashTableDeletedValue);
208     }
209
210     unsigned hash() const
211     {
212         return WTF::IntHash<int>::hash(m_value);
213     }
214
215     unsigned internalValue() const { return static_cast<unsigned>(m_value); }
216
217     static Tmp tmpForInternalValue(unsigned index)
218     {
219         Tmp result;
220         result.m_value = static_cast<int>(index);
221         return result;
222     }
223     
224     static Tmp tmpForAbsoluteIndex(Bank, unsigned);
225     
226     static Tmp tmpForLinearIndex(Code&, unsigned);
227     
228 private:
229     static int encodeGP(unsigned index)
230     {
231         return 1 + index;
232     }
233
234     static int encodeFP(unsigned index)
235     {
236         return -1 - index;
237     }
238
239     static int encodeGPR(GPRReg gpr)
240     {
241         return encodeGP(gpr - MacroAssembler::firstRegister());
242     }
243
244     static int encodeFPR(FPRReg fpr)
245     {
246         return encodeFP(fpr - MacroAssembler::firstFPRegister());
247     }
248
249     static int encodeGPTmp(unsigned index)
250     {
251         return encodeGPR(MacroAssembler::lastRegister()) + 1 + index;
252     }
253
254     static int encodeFPTmp(unsigned index)
255     {
256         return encodeFPR(MacroAssembler::lastFPRegister()) - 1 - index;
257     }
258
259     static bool isEncodedGP(int value)
260     {
261         return value > 0;
262     }
263
264     static bool isEncodedFP(int value)
265     {
266         return value < 0;
267     }
268
269     static bool isEncodedGPR(int value)
270     {
271         return isEncodedGP(value) && value <= encodeGPR(MacroAssembler::lastRegister());
272     }
273
274     static bool isEncodedFPR(int value)
275     {
276         return isEncodedFP(value) && value >= encodeFPR(MacroAssembler::lastFPRegister());
277     }
278
279     static bool isEncodedGPTmp(int value)
280     {
281         return isEncodedGP(value) && !isEncodedGPR(value);
282     }
283
284     static bool isEncodedFPTmp(int value)
285     {
286         return isEncodedFP(value) && !isEncodedFPR(value);
287     }
288
289     static GPRReg decodeGPR(int value)
290     {
291         ASSERT(isEncodedGPR(value));
292         return static_cast<GPRReg>(
293             (value - encodeGPR(MacroAssembler::firstRegister())) + MacroAssembler::firstRegister());
294     }
295
296     static FPRReg decodeFPR(int value)
297     {
298         ASSERT(isEncodedFPR(value));
299         return static_cast<FPRReg>(
300             (encodeFPR(MacroAssembler::firstFPRegister()) - value) +
301             MacroAssembler::firstFPRegister());
302     }
303
304     static unsigned decodeGPTmp(int value)
305     {
306         ASSERT(isEncodedGPTmp(value));
307         return value - (encodeGPR(MacroAssembler::lastRegister()) + 1);
308     }
309
310     static unsigned decodeFPTmp(int value)
311     {
312         ASSERT(isEncodedFPTmp(value));
313         return (encodeFPR(MacroAssembler::lastFPRegister()) - 1) - value;
314     }
315
316     // 0: empty Tmp
317     // positive: GPRs and then GP temps.
318     // negative: FPRs and then FP temps.
319     int m_value;
320 };
321
322 struct TmpHash {
323     static unsigned hash(const Tmp& key) { return key.hash(); }
324     static bool equal(const Tmp& a, const Tmp& b) { return a == b; }
325     static constexpr bool safeToCompareToEmptyOrDeleted = true;
326 };
327
328 } } } // namespace JSC::B3::Air
329
330 namespace WTF {
331
332 template<typename T> struct DefaultHash;
333 template<> struct DefaultHash<JSC::B3::Air::Tmp> {
334     typedef JSC::B3::Air::TmpHash Hash;
335 };
336
337 template<typename T> struct HashTraits;
338 template<> struct HashTraits<JSC::B3::Air::Tmp> : SimpleClassHashTraits<JSC::B3::Air::Tmp> { };
339
340 } // namespace WTF
341
342 #endif // ENABLE(B3_JIT)