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