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