1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_CODEGEN_ARM_INTERFACE_DESCRIPTORS_ARM_INL_H_
6 #define V8_CODEGEN_ARM_INTERFACE_DESCRIPTORS_ARM_INL_H_
7 
8 #if V8_TARGET_ARCH_ARM
9 
10 #include "src/codegen/interface-descriptors.h"
11 #include "src/execution/frames.h"
12 
13 namespace v8 {
14 namespace internal {
15 
DefaultRegisterArray()16 constexpr auto CallInterfaceDescriptor::DefaultRegisterArray() {
17   auto registers = RegisterArray(r0, r1, r2, r3, r4);
18   STATIC_ASSERT(registers.size() == kMaxBuiltinRegisterParams);
19   return registers;
20 }
21 
22 #if DEBUG
23 template <typename DerivedDescriptor>
24 void StaticCallInterfaceDescriptor<DerivedDescriptor>::
VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc)25     VerifyArgumentRegisterCount(CallInterfaceDescriptorData* data, int argc) {
26   RegList allocatable_regs = data->allocatable_registers();
27   if (argc >= 1) DCHECK(allocatable_regs.has(r0));
28   if (argc >= 2) DCHECK(allocatable_regs.has(r1));
29   if (argc >= 3) DCHECK(allocatable_regs.has(r2));
30   if (argc >= 4) DCHECK(allocatable_regs.has(r3));
31   if (argc >= 5) DCHECK(allocatable_regs.has(r4));
32   if (argc >= 6) DCHECK(allocatable_regs.has(r5));
33   if (argc >= 7) DCHECK(allocatable_regs.has(r6));
34   if (argc >= 8) DCHECK(allocatable_regs.has(r7));
35   // Additional arguments are passed on the stack.
36 }
37 #endif  // DEBUG
38 
39 // static
registers()40 constexpr auto WriteBarrierDescriptor::registers() {
41   return RegisterArray(r1, r5, r4, r2, r0, r3, kContextRegister);
42 }
43 
44 // static
ReceiverRegister()45 constexpr Register LoadDescriptor::ReceiverRegister() { return r1; }
46 // static
NameRegister()47 constexpr Register LoadDescriptor::NameRegister() { return r2; }
48 // static
SlotRegister()49 constexpr Register LoadDescriptor::SlotRegister() { return r0; }
50 
51 // static
VectorRegister()52 constexpr Register LoadWithVectorDescriptor::VectorRegister() { return r3; }
53 
54 // static
ReceiverRegister()55 constexpr Register KeyedLoadBaselineDescriptor::ReceiverRegister() {
56   return r1;
57 }
58 // static
NameRegister()59 constexpr Register KeyedLoadBaselineDescriptor::NameRegister() {
60   return kInterpreterAccumulatorRegister;
61 }
62 // static
SlotRegister()63 constexpr Register KeyedLoadBaselineDescriptor::SlotRegister() { return r2; }
64 
65 // static
VectorRegister()66 constexpr Register KeyedLoadWithVectorDescriptor::VectorRegister() {
67   return r3;
68 }
69 
70 // static
ReceiverRegister()71 constexpr Register KeyedHasICBaselineDescriptor::ReceiverRegister() {
72   return kInterpreterAccumulatorRegister;
73 }
74 // static
NameRegister()75 constexpr Register KeyedHasICBaselineDescriptor::NameRegister() { return r1; }
76 // static
SlotRegister()77 constexpr Register KeyedHasICBaselineDescriptor::SlotRegister() { return r2; }
78 
79 // static
VectorRegister()80 constexpr Register KeyedHasICWithVectorDescriptor::VectorRegister() {
81   return r3;
82 }
83 
84 // static
85 constexpr Register
LookupStartObjectRegister()86 LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
87   return r4;
88 }
89 
90 // static
ReceiverRegister()91 constexpr Register StoreDescriptor::ReceiverRegister() { return r1; }
92 // static
NameRegister()93 constexpr Register StoreDescriptor::NameRegister() { return r2; }
94 // static
ValueRegister()95 constexpr Register StoreDescriptor::ValueRegister() { return r0; }
96 // static
SlotRegister()97 constexpr Register StoreDescriptor::SlotRegister() { return r4; }
98 
99 // static
VectorRegister()100 constexpr Register StoreWithVectorDescriptor::VectorRegister() { return r3; }
101 
102 // static
MapRegister()103 constexpr Register StoreTransitionDescriptor::MapRegister() { return r5; }
104 
105 // static
HolderRegister()106 constexpr Register ApiGetterDescriptor::HolderRegister() { return r0; }
107 // static
CallbackRegister()108 constexpr Register ApiGetterDescriptor::CallbackRegister() { return r3; }
109 
110 // static
ObjectRegister()111 constexpr Register GrowArrayElementsDescriptor::ObjectRegister() { return r0; }
112 // static
KeyRegister()113 constexpr Register GrowArrayElementsDescriptor::KeyRegister() { return r3; }
114 
115 // static
ParamsSizeRegister()116 constexpr Register BaselineLeaveFrameDescriptor::ParamsSizeRegister() {
117   return r3;
118 }
119 // static
WeightRegister()120 constexpr Register BaselineLeaveFrameDescriptor::WeightRegister() { return r4; }
121 
122 // static
123 // static
ArgumentRegister()124 constexpr Register TypeConversionDescriptor::ArgumentRegister() { return r0; }
125 
126 // static
registers()127 constexpr auto TypeofDescriptor::registers() { return RegisterArray(r0); }
128 
129 // static
registers()130 constexpr auto CallTrampolineDescriptor::registers() {
131   // r0 : number of arguments
132   // r1 : the target to call
133   return RegisterArray(r1, r0);
134 }
135 
136 // static
registers()137 constexpr auto CopyDataPropertiesWithExcludedPropertiesDescriptor::registers() {
138   // r0 : the source
139   // r1 : the excluded property count
140   return RegisterArray(r1, r0);
141 }
142 
143 // static
144 constexpr auto
registers()145 CopyDataPropertiesWithExcludedPropertiesOnStackDescriptor::registers() {
146   // r0 : the source
147   // r1 : the excluded property count
148   // r2 : the excluded property base
149   return RegisterArray(r1, r0, r2);
150 }
151 
152 // static
registers()153 constexpr auto CallVarargsDescriptor::registers() {
154   // r0 : number of arguments (on the stack)
155   // r1 : the target to call
156   // r4 : arguments list length (untagged)
157   // r2 : arguments list (FixedArray)
158   return RegisterArray(r1, r0, r4, r2);
159 }
160 
161 // static
registers()162 constexpr auto CallForwardVarargsDescriptor::registers() {
163   // r0 : number of arguments
164   // r2 : start index (to support rest parameters)
165   // r1 : the target to call
166   return RegisterArray(r1, r0, r2);
167 }
168 
169 // static
registers()170 constexpr auto CallFunctionTemplateDescriptor::registers() {
171   // r1 : function template info
172   // r2 : number of arguments (on the stack)
173   return RegisterArray(r1, r2);
174 }
175 
176 // static
registers()177 constexpr auto CallWithSpreadDescriptor::registers() {
178   // r0 : number of arguments (on the stack)
179   // r1 : the target to call
180   // r2 : the object to spread
181   return RegisterArray(r1, r0, r2);
182 }
183 
184 // static
registers()185 constexpr auto CallWithArrayLikeDescriptor::registers() {
186   // r1 : the target to call
187   // r2 : the arguments list
188   return RegisterArray(r1, r2);
189 }
190 
191 // static
registers()192 constexpr auto ConstructVarargsDescriptor::registers() {
193   // r0 : number of arguments (on the stack)
194   // r1 : the target to call
195   // r3 : the new target
196   // r4 : arguments list length (untagged)
197   // r2 : arguments list (FixedArray)
198   return RegisterArray(r1, r3, r0, r4, r2);
199 }
200 
201 // static
registers()202 constexpr auto ConstructForwardVarargsDescriptor::registers() {
203   // r0 : number of arguments
204   // r3 : the new target
205   // r2 : start index (to support rest parameters)
206   // r1 : the target to call
207   return RegisterArray(r1, r3, r0, r2);
208 }
209 
210 // static
registers()211 constexpr auto ConstructWithSpreadDescriptor::registers() {
212   // r0 : number of arguments (on the stack)
213   // r1 : the target to call
214   // r3 : the new target
215   // r2 : the object to spread
216   return RegisterArray(r1, r3, r0, r2);
217 }
218 
219 // static
registers()220 constexpr auto ConstructWithArrayLikeDescriptor::registers() {
221   // r1 : the target to call
222   // r3 : the new target
223   // r2 : the arguments list
224   return RegisterArray(r1, r3, r2);
225 }
226 
227 // static
registers()228 constexpr auto ConstructStubDescriptor::registers() {
229   // r0 : number of arguments
230   // r1 : the target to call
231   // r3 : the new target
232   // r2 : allocation site or undefined
233   return RegisterArray(r1, r3, r0, r2);
234 }
235 
236 // static
registers()237 constexpr auto AbortDescriptor::registers() { return RegisterArray(r1); }
238 
239 // static
registers()240 constexpr auto CompareDescriptor::registers() { return RegisterArray(r1, r0); }
241 
242 // static
registers()243 constexpr auto Compare_BaselineDescriptor::registers() {
244   // r1: left operand
245   // r0: right operand
246   // r2: feedback slot
247   return RegisterArray(r1, r0, r2);
248 }
249 
250 // static
registers()251 constexpr auto BinaryOpDescriptor::registers() { return RegisterArray(r1, r0); }
252 
253 // static
registers()254 constexpr auto BinaryOp_BaselineDescriptor::registers() {
255   // r1: left operand
256   // r0: right operand
257   // r2: feedback slot
258   return RegisterArray(r1, r0, r2);
259 }
260 
261 // static
registers()262 constexpr auto BinarySmiOp_BaselineDescriptor::registers() {
263   // r0: left operand
264   // r1: right operand
265   // r2: feedback slot
266   return RegisterArray(r0, r1, r2);
267 }
268 
269 // static
registers()270 constexpr auto ApiCallbackDescriptor::registers() {
271   return RegisterArray(r1,   // kApiFunctionAddress
272                        r2,   // kArgc
273                        r3,   // kCallData
274                        r0);  // kHolder
275 }
276 
277 // static
registers()278 constexpr auto InterpreterDispatchDescriptor::registers() {
279   return RegisterArray(
280       kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
281       kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister);
282 }
283 
284 // static
registers()285 constexpr auto InterpreterPushArgsThenCallDescriptor::registers() {
286   return RegisterArray(r0,   // argument count
287                        r2,   // address of first argument
288                        r1);  // the target callable to be call
289 }
290 
291 // static
registers()292 constexpr auto InterpreterPushArgsThenConstructDescriptor::registers() {
293   return RegisterArray(
294       r0,   // argument count
295       r4,   // address of the first argument
296       r1,   // constructor to call
297       r3,   // new target
298       r2);  // allocation site feedback if available, undefined otherwise
299 }
300 
301 // static
registers()302 constexpr auto ResumeGeneratorDescriptor::registers() {
303   return RegisterArray(r0,   // the value to pass to the generator
304                        r1);  // the JSGeneratorObject to resume
305 }
306 
307 // static
registers()308 constexpr auto RunMicrotasksEntryDescriptor::registers() {
309   return RegisterArray(r0, r1);
310 }
311 
312 }  // namespace internal
313 }  // namespace v8
314 
315 #endif  // V8_TARGET_ARCH_ARM
316 
317 #endif  // V8_CODEGEN_ARM_INTERFACE_DESCRIPTORS_ARM_INL_H_
318