3579b08a24e473bcf3db1b1e3103ce48485ce919
[WebKit-https.git] / Source / JavaScriptCore / jit / RegisterSet.cpp
1 /*
2  * Copyright (C) 2013-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 #include "config.h"
27 #include "RegisterSet.h"
28
29 #if ENABLE(JIT)
30
31 #include "GPRInfo.h"
32 #include "MacroAssembler.h"
33 #include "JSCInlines.h"
34 #include <wtf/CommaPrinter.h>
35
36 namespace JSC {
37
38 RegisterSet RegisterSet::stackRegisters()
39 {
40     return RegisterSet(
41         MacroAssembler::stackPointerRegister,
42         MacroAssembler::framePointerRegister);
43 }
44
45 RegisterSet RegisterSet::reservedHardwareRegisters()
46 {
47 #if CPU(ARM64)
48 #if PLATFORM(IOS)
49     return RegisterSet(ARM64Registers::x18, ARM64Registers::lr);
50 #else
51     return RegisterSet(ARM64Registers::lr);
52 #endif // PLATFORM(IOS)
53 #else
54     return RegisterSet();
55 #endif
56 }
57
58 RegisterSet RegisterSet::runtimeRegisters()
59 {
60 #if USE(JSVALUE64)
61     return RegisterSet(GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
62 #else
63     return RegisterSet();
64 #endif
65 }
66
67 RegisterSet RegisterSet::specialRegisters()
68 {
69     return RegisterSet(
70         stackRegisters(), reservedHardwareRegisters(), runtimeRegisters());
71 }
72
73 RegisterSet RegisterSet::volatileRegistersForJSCall()
74 {
75     RegisterSet volatileRegisters = allRegisters();
76     volatileRegisters.exclude(RegisterSet::stackRegisters());
77     volatileRegisters.exclude(RegisterSet::reservedHardwareRegisters());
78     volatileRegisters.exclude(RegisterSet::vmCalleeSaveRegisters());
79     return volatileRegisters;
80 }
81
82 RegisterSet RegisterSet::stubUnavailableRegisters()
83 {
84     return RegisterSet(specialRegisters(), vmCalleeSaveRegisters());
85 }
86
87 RegisterSet RegisterSet::macroScratchRegisters()
88 {
89 #if CPU(X86_64)
90     return RegisterSet(MacroAssembler::s_scratchRegister);
91 #elif CPU(ARM64)
92     return RegisterSet(MacroAssembler::dataTempRegister, MacroAssembler::memoryTempRegister);
93 #elif CPU(MIPS)
94     RegisterSet result;
95     result.set(MacroAssembler::immTempRegister);
96     result.set(MacroAssembler::dataTempRegister);
97     result.set(MacroAssembler::addrTempRegister);
98     result.set(MacroAssembler::cmpTempRegister);
99     return result;
100 #else
101     return RegisterSet();
102 #endif
103 }
104
105 RegisterSet RegisterSet::calleeSaveRegisters()
106 {
107     RegisterSet result;
108 #if CPU(X86)
109     result.set(X86Registers::ebx);
110     result.set(X86Registers::ebp);
111     result.set(X86Registers::edi);
112     result.set(X86Registers::esi);
113 #elif CPU(X86_64)
114     result.set(X86Registers::ebx);
115     result.set(X86Registers::ebp);
116     result.set(X86Registers::r12);
117     result.set(X86Registers::r13);
118     result.set(X86Registers::r14);
119     result.set(X86Registers::r15);
120 #elif CPU(ARM_THUMB2)
121     result.set(ARMRegisters::r4);
122     result.set(ARMRegisters::r5);
123     result.set(ARMRegisters::r6);
124     result.set(ARMRegisters::r8);
125 #if !PLATFORM(IOS)
126     result.set(ARMRegisters::r9);
127 #endif
128     result.set(ARMRegisters::r10);
129     result.set(ARMRegisters::r11);
130 #elif CPU(ARM_TRADITIONAL)
131     result.set(ARMRegisters::r4);
132     result.set(ARMRegisters::r5);
133     result.set(ARMRegisters::r6);
134     result.set(ARMRegisters::r7);
135     result.set(ARMRegisters::r8);
136     result.set(ARMRegisters::r9);
137     result.set(ARMRegisters::r10);
138     result.set(ARMRegisters::r11);
139 #elif CPU(ARM64)
140     // We don't include LR in the set of callee-save registers even though it technically belongs
141     // there. This is because we use this set to describe the set of registers that need to be saved
142     // beyond what you would save by the platform-agnostic "preserve return address" and "restore
143     // return address" operations in CCallHelpers.
144     for (
145         ARM64Registers::RegisterID reg = ARM64Registers::x19;
146         reg <= ARM64Registers::x28;
147         reg = static_cast<ARM64Registers::RegisterID>(reg + 1))
148         result.set(reg);
149     result.set(ARM64Registers::fp);
150     for (
151         ARM64Registers::FPRegisterID reg = ARM64Registers::q8;
152         reg <= ARM64Registers::q15;
153         reg = static_cast<ARM64Registers::FPRegisterID>(reg + 1))
154         result.set(reg);
155 #elif CPU(MIPS)
156 #else
157     UNREACHABLE_FOR_PLATFORM();
158 #endif
159     return result;
160 }
161
162 RegisterSet RegisterSet::vmCalleeSaveRegisters()
163 {
164     RegisterSet result;
165 #if CPU(X86_64)
166     result.set(GPRInfo::regCS0);
167     result.set(GPRInfo::regCS1);
168     result.set(GPRInfo::regCS2);
169     result.set(GPRInfo::regCS3);
170     result.set(GPRInfo::regCS4);
171 #if OS(WINDOWS)
172     result.set(GPRInfo::regCS5);
173     result.set(GPRInfo::regCS6);
174 #endif
175 #elif CPU(ARM64)
176     result.set(GPRInfo::regCS0);
177     result.set(GPRInfo::regCS1);
178     result.set(GPRInfo::regCS2);
179     result.set(GPRInfo::regCS3);
180     result.set(GPRInfo::regCS4);
181     result.set(GPRInfo::regCS5);
182     result.set(GPRInfo::regCS6);
183     result.set(GPRInfo::regCS7);
184     result.set(GPRInfo::regCS8);
185     result.set(GPRInfo::regCS9);
186     result.set(FPRInfo::fpRegCS0);
187     result.set(FPRInfo::fpRegCS1);
188     result.set(FPRInfo::fpRegCS2);
189     result.set(FPRInfo::fpRegCS3);
190     result.set(FPRInfo::fpRegCS4);
191     result.set(FPRInfo::fpRegCS5);
192     result.set(FPRInfo::fpRegCS6);
193     result.set(FPRInfo::fpRegCS7);
194 #endif
195     return result;
196 }
197
198 RegisterSet RegisterSet::llintBaselineCalleeSaveRegisters()
199 {
200     RegisterSet result;
201 #if CPU(X86)
202 #elif CPU(X86_64)
203 #if !OS(WINDOWS)
204     result.set(GPRInfo::regCS2);
205     ASSERT(GPRInfo::regCS3 == GPRInfo::tagTypeNumberRegister);
206     ASSERT(GPRInfo::regCS4 == GPRInfo::tagMaskRegister);
207     result.set(GPRInfo::regCS3);
208     result.set(GPRInfo::regCS4);
209 #else
210     result.set(GPRInfo::regCS4);
211     ASSERT(GPRInfo::regCS5 == GPRInfo::tagTypeNumberRegister);
212     ASSERT(GPRInfo::regCS6 == GPRInfo::tagMaskRegister);
213     result.set(GPRInfo::regCS5);
214     result.set(GPRInfo::regCS6);
215 #endif
216 #elif CPU(ARM_THUMB2)
217 #elif CPU(ARM_TRADITIONAL)
218 #elif CPU(ARM64)
219     result.set(GPRInfo::regCS7);
220     ASSERT(GPRInfo::regCS8 == GPRInfo::tagTypeNumberRegister);
221     ASSERT(GPRInfo::regCS9 == GPRInfo::tagMaskRegister);
222     result.set(GPRInfo::regCS8);
223     result.set(GPRInfo::regCS9);
224 #elif CPU(MIPS)
225 #elif CPU(SH4)
226 #else
227     UNREACHABLE_FOR_PLATFORM();
228 #endif
229     return result;
230 }
231
232 RegisterSet RegisterSet::dfgCalleeSaveRegisters()
233 {
234     RegisterSet result;
235 #if CPU(X86)
236 #elif CPU(X86_64)
237     result.set(GPRInfo::regCS0);
238     result.set(GPRInfo::regCS1);
239     result.set(GPRInfo::regCS2);
240 #if !OS(WINDOWS)
241     ASSERT(GPRInfo::regCS3 == GPRInfo::tagTypeNumberRegister);
242     ASSERT(GPRInfo::regCS4 == GPRInfo::tagMaskRegister);
243     result.set(GPRInfo::regCS3);
244     result.set(GPRInfo::regCS4);
245 #else
246     result.set(GPRInfo::regCS3);
247     result.set(GPRInfo::regCS4);
248     ASSERT(GPRInfo::regCS5 == GPRInfo::tagTypeNumberRegister);
249     ASSERT(GPRInfo::regCS6 == GPRInfo::tagMaskRegister);
250     result.set(GPRInfo::regCS5);
251     result.set(GPRInfo::regCS6);
252 #endif
253 #elif CPU(ARM_THUMB2)
254 #elif CPU(ARM_TRADITIONAL)
255 #elif CPU(ARM64)
256     ASSERT(GPRInfo::regCS8 == GPRInfo::tagTypeNumberRegister);
257     ASSERT(GPRInfo::regCS9 == GPRInfo::tagMaskRegister);
258     result.set(GPRInfo::regCS8);
259     result.set(GPRInfo::regCS9);
260 #elif CPU(MIPS)
261 #elif CPU(SH4)
262 #else
263     UNREACHABLE_FOR_PLATFORM();
264 #endif
265     return result;
266 }
267
268 RegisterSet RegisterSet::ftlCalleeSaveRegisters()
269 {
270     RegisterSet result;
271 #if ENABLE(FTL_JIT)
272 #if CPU(X86_64) && !OS(WINDOWS)
273     result.set(GPRInfo::regCS0);
274     result.set(GPRInfo::regCS1);
275     result.set(GPRInfo::regCS2);
276     ASSERT(GPRInfo::regCS3 == GPRInfo::tagTypeNumberRegister);
277     ASSERT(GPRInfo::regCS4 == GPRInfo::tagMaskRegister);
278     result.set(GPRInfo::regCS3);
279     result.set(GPRInfo::regCS4);
280 #elif CPU(ARM64)
281     // LLVM might save and use all ARM64 callee saves specified in the ABI.
282     result.set(GPRInfo::regCS0);
283     result.set(GPRInfo::regCS1);
284     result.set(GPRInfo::regCS2);
285     result.set(GPRInfo::regCS3);
286     result.set(GPRInfo::regCS4);
287     result.set(GPRInfo::regCS5);
288     result.set(GPRInfo::regCS6);
289     result.set(GPRInfo::regCS7);
290     ASSERT(GPRInfo::regCS8 == GPRInfo::tagTypeNumberRegister);
291     ASSERT(GPRInfo::regCS9 == GPRInfo::tagMaskRegister);
292     result.set(GPRInfo::regCS8);
293     result.set(GPRInfo::regCS9);
294     result.set(FPRInfo::fpRegCS0);
295     result.set(FPRInfo::fpRegCS1);
296     result.set(FPRInfo::fpRegCS2);
297     result.set(FPRInfo::fpRegCS3);
298     result.set(FPRInfo::fpRegCS4);
299     result.set(FPRInfo::fpRegCS5);
300     result.set(FPRInfo::fpRegCS6);
301     result.set(FPRInfo::fpRegCS7);
302 #else
303     UNREACHABLE_FOR_PLATFORM();
304 #endif
305 #endif
306     return result;
307 }
308
309 #if ENABLE(WEBASSEMBLY)
310 RegisterSet RegisterSet::webAssemblyCalleeSaveRegisters()
311 {
312     RegisterSet result;
313 #if CPU(X86)
314 #elif CPU(X86_64)
315 #if !OS(WINDOWS)
316     ASSERT(GPRInfo::regCS3 == GPRInfo::tagTypeNumberRegister);
317     ASSERT(GPRInfo::regCS4 == GPRInfo::tagMaskRegister);
318     result.set(GPRInfo::regCS3);
319     result.set(GPRInfo::regCS4);
320 #else
321     ASSERT(GPRInfo::regCS5 == GPRInfo::tagTypeNumberRegister);
322     ASSERT(GPRInfo::regCS6 == GPRInfo::tagMaskRegister);
323     result.set(GPRInfo::regCS5);
324     result.set(GPRInfo::regCS6);
325 #endif
326 #elif CPU(ARM_THUMB2)
327 #elif CPU(ARM_TRADITIONAL)
328 #elif CPU(ARM64)
329     ASSERT(GPRInfo::regCS8 == GPRInfo::tagTypeNumberRegister);
330     ASSERT(GPRInfo::regCS9 == GPRInfo::tagMaskRegister);
331     result.set(GPRInfo::regCS8);
332     result.set(GPRInfo::regCS9);
333 #elif CPU(MIPS)
334 #elif CPU(SH4)
335 #else
336     UNREACHABLE_FOR_PLATFORM();
337 #endif
338     return result;
339 }
340 #endif
341
342 RegisterSet RegisterSet::registersToNotSaveForJSCall()
343 {
344     return RegisterSet(RegisterSet::vmCalleeSaveRegisters(), RegisterSet::stackRegisters(), RegisterSet::reservedHardwareRegisters());
345 }
346
347 RegisterSet RegisterSet::registersToNotSaveForCCall()
348 {
349     return RegisterSet(RegisterSet::calleeSaveRegisters(), RegisterSet::stackRegisters(), RegisterSet::reservedHardwareRegisters());
350 }
351
352 RegisterSet RegisterSet::allGPRs()
353 {
354     RegisterSet result;
355     for (MacroAssembler::RegisterID reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = static_cast<MacroAssembler::RegisterID>(reg + 1))
356         result.set(reg);
357     return result;
358 }
359
360 RegisterSet RegisterSet::allFPRs()
361 {
362     RegisterSet result;
363     for (MacroAssembler::FPRegisterID reg = MacroAssembler::firstFPRegister(); reg <= MacroAssembler::lastFPRegister(); reg = static_cast<MacroAssembler::FPRegisterID>(reg + 1))
364         result.set(reg);
365     return result;
366 }
367
368 RegisterSet RegisterSet::allRegisters()
369 {
370     RegisterSet result;
371     result.merge(allGPRs());
372     result.merge(allFPRs());
373     return result;
374 }
375
376 size_t RegisterSet::numberOfSetGPRs() const
377 {
378     RegisterSet temp = *this;
379     temp.filter(allGPRs());
380     return temp.numberOfSetRegisters();
381 }
382
383 size_t RegisterSet::numberOfSetFPRs() const
384 {
385     RegisterSet temp = *this;
386     temp.filter(allFPRs());
387     return temp.numberOfSetRegisters();
388 }
389
390 void RegisterSet::dump(PrintStream& out) const
391 {
392     CommaPrinter comma;
393     out.print("[");
394     for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
395         if (get(reg))
396             out.print(comma, reg);
397     }
398     out.print("]");
399 }
400
401 } // namespace JSC
402
403 #endif // ENABLE(JIT)
404