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