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