4 from mozbuild
.preprocessor
import Preprocessor
7 /* This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11 #ifndef %(includeguard)s
12 #define %(includeguard)s
14 /* This file is generated by jit/GenerateABIFunctionType.py. Do not edit! */
18 #endif // %(includeguard)s
22 def generate_header(c_out
, includeguard
, contents
):
26 "includeguard": includeguard
,
32 def load_yaml(yaml_path
):
33 # First invoke preprocessor.py so that we can use #ifdef JS_SIMULATOR in
36 pp
.context
.update(buildconfig
.defines
["ALLDEFINES"])
37 pp
.out
= six
.StringIO()
38 pp
.do_filter("substitution")
39 pp
.do_include(yaml_path
)
40 contents
= pp
.out
.getvalue()
41 return yaml
.safe_load(contents
)
44 def cpp_arg_type(arg_type
):
45 if arg_type
== "General":
47 elif arg_type
== "Int32":
49 elif arg_type
== "Int64":
51 elif arg_type
== "Float32":
53 elif arg_type
== "Float64":
56 raise ValueError(arg_type
)
59 def func_type_name(func_type
):
60 if "name" in func_type
:
61 return func_type
["name"]
63 # Autogenerate a name like `General_GeneralGeneral` if none is specified
64 return f
"{func_type['ret']}_{''.join(func_type['args'])}"
67 def func_type_has_floats(func_type
):
68 for arg
in func_type
["args"]:
69 if arg
== "Float32" or arg
== "Float64":
74 # Generate the ARM32 argument loading for a func type for when soft-FP is enabled
75 def arm32_soft_fp_args(func_type
):
76 # This must match ABIArgGenerator::softNext() in Assembler-arm.cpp
81 for i
, arg
in enumerate(func_type
["args"]):
86 if intRegIndex
== numIntArgRegs
:
87 contents
+= f
"stack_pointer[{stackOffset}]"
90 contents
+= f
"a{intRegIndex}"
93 if intRegIndex
== numIntArgRegs
:
94 contents
+= f
"stack_pointer[{stackOffset}]"
97 contents
+= f
"a{intRegIndex}"
100 intRegIndex
+= intRegIndex
% 2
101 if intRegIndex
== numIntArgRegs
:
102 stackOffset
+= stackOffset
% 2
103 contents
+= f
"MakeInt64(stack_pointer[{stackOffset}], stack_pointer[{stackOffset + 1}])"
106 contents
+= f
"MakeInt64(a{intRegIndex}, a{intRegIndex+1})"
108 elif arg
== "Float32":
109 if intRegIndex
== numIntArgRegs
:
110 contents
+= f
"mozilla::BitwiseCast<float>(stack_pointer[{stackOffset}])"
113 contents
+= f
"mozilla::BitwiseCast<float>(a{intRegIndex})"
115 elif arg
== "Float64":
116 intRegIndex
+= intRegIndex
% 2
117 if intRegIndex
== numIntArgRegs
:
118 stackOffset
+= stackOffset
% 2
119 contents
+= f
"mozilla::BitwiseCast<double>(MakeInt64(stack_pointer[{stackOffset}], stack_pointer[{stackOffset + 1}]))"
122 contents
+= f
"mozilla::BitwiseCast<double>(MakeInt64(a{intRegIndex}, a{intRegIndex + 1}))"
124 assert intRegIndex
<= numIntArgRegs
128 # Generate the ARM32 argument loading for a func type for when hard-FP is enabled
129 def arm32_hard_fp_args(func_type
):
130 # This must match ABIArgGenerator::hardNext() in Assembler-arm.cpp
137 for i
, arg
in enumerate(func_type
["args"]):
142 if intRegIndex
== numIntArgRegs
:
143 contents
+= f
"stack_pointer[{stackOffset}]"
146 contents
+= f
"a{intRegIndex}"
149 if intRegIndex
== numIntArgRegs
:
150 contents
+= f
"stack_pointer[{stackOffset}]"
153 contents
+= f
"a{intRegIndex}"
156 intRegIndex
+= intRegIndex
% 2
157 if intRegIndex
== numIntArgRegs
:
158 stackOffset
+= stackOffset
% 2
159 contents
+= f
"MakeInt64(stack_pointer[{stackOffset}], stack_pointer[{stackOffset + 1}])"
162 contents
+= f
"MakeInt64(a{intRegIndex}, a{intRegIndex+1})"
164 elif arg
== "Float32":
165 if floatRegIndex
== numFloatArgRegs
:
166 contents
+= f
"mozilla::BitwiseCast<float>(stack_pointer[{stackOffset}])"
169 contents
+= f
"s{floatRegIndex}"
171 elif arg
== "Float64":
172 floatRegIndex
+= floatRegIndex
% 2
173 if floatRegIndex
== numFloatArgRegs
:
174 stackOffset
+= stackOffset
% 2
175 contents
+= f
"mozilla::BitwiseCast<double>(MakeInt64(stack_pointer[{stackOffset}], stack_pointer[{stackOffset + 1}]))"
178 contents
+= f
"d{round(floatRegIndex / 2)}"
180 assert intRegIndex
<= numIntArgRegs
181 assert floatRegIndex
<= numFloatArgRegs
185 def arm32_simulator_dispatch(func_types
):
187 for func_type
in func_types
:
188 hard_fp_args
= arm32_hard_fp_args(func_type
)
189 soft_fp_args
= arm32_soft_fp_args(func_type
)
190 ret
= func_type
["ret"]
192 contents
+= f
"case js::jit::Args_{func_type_name(func_type)}: {{\\\n"
193 contents
+= f
" auto target = reinterpret_cast<Prototype_{func_type_name(func_type)}>(external);\\\n"
194 contents
+= f
" {cpp_arg_type(ret)} ret;\\\n"
195 if func_type_has_floats(func_type
):
196 contents
+= " if (UseHardFpABI()) {\\\n"
197 contents
+= f
" ret = target({hard_fp_args});\\\n"
198 contents
+= " } else {\\\n"
199 contents
+= f
" ret = target({soft_fp_args});\\\n"
202 # No float args means we don't need to check the float ABI and
203 # either generated args will do.
204 contents
+= f
" ret = target({soft_fp_args});\\\n"
205 contents
+= " scratchVolatileRegisters((void*)target);\\\n"
206 if ret
== "General" or ret
== "Int32" or ret
== "Int64":
207 contents
+= " setCallResult(ret);\\\n"
208 elif ret
== "Float32":
209 contents
+= " setCallResultFloat(ret);\\\n"
210 elif ret
== "Float64":
211 contents
+= " setCallResultDouble(ret);\\\n"
212 contents
+= " break;\\\n"
217 # Generate the ARM64 argument loading for a func type
218 def arm64_args(func_type
):
219 # This must match ABIArgGenerator::next() in Assembler-arm64.cpp
226 for i
, arg
in enumerate(func_type
["args"]):
231 if intRegIndex
== numIntArgRegs
:
232 contents
+= f
"sp[{stackOffset}]"
235 contents
+= f
"x{intRegIndex}"
238 if intRegIndex
== numIntArgRegs
:
239 contents
+= f
"sp[{stackOffset}]"
242 contents
+= f
"x{intRegIndex}"
245 if intRegIndex
== numIntArgRegs
:
246 contents
+= f
"sp[{stackOffset}]"
249 contents
+= f
"x{intRegIndex}"
251 elif arg
== "Float32":
252 if floatRegIndex
== numFloatArgRegs
:
253 contents
+= f
"mozilla::BitwiseCast<float>(sp[{stackOffset}])"
256 contents
+= f
"s{floatRegIndex}"
258 elif arg
== "Float64":
259 if floatRegIndex
== numFloatArgRegs
:
260 contents
+= f
"mozilla::BitwiseCast<double>(sp[{stackOffset}])"
263 contents
+= f
"d{floatRegIndex}"
265 assert intRegIndex
<= numIntArgRegs
266 assert floatRegIndex
<= numFloatArgRegs
270 def arm64_simulator_dispatch(func_types
):
272 for func_type
in func_types
:
273 args
= arm64_args(func_type
)
274 contents
+= f
"case js::jit::Args_{func_type_name(func_type)}: {{\\\n"
275 contents
+= f
" auto target = reinterpret_cast<Prototype_{func_type_name(func_type)}>(nativeFn);\\\n"
276 contents
+= f
" auto ret = target({args});\\\n"
277 ret
= func_type
["ret"]
279 contents
+= " setGPR64Result(ret);\\\n"
281 contents
+= " setGPR32Result(ret);\\\n"
283 contents
+= " setGPR64Result(ret);\\\n"
284 elif ret
== "Float32":
285 contents
+= " setFP32Result(ret);\\\n"
286 elif ret
== "Float64":
287 contents
+= " setFP64Result(ret);\\\n"
288 contents
+= " break;\\\n"
293 # Generate the LoongArch64 argument loading for a func type
294 def loongarch64_args(func_type
):
295 # This must match ABIArgGenerator::next() in Assembler-loong64.cpp
302 for i
, arg
in enumerate(func_type
["args"]):
307 if intRegIndex
== numIntArgRegs
:
308 contents
+= f
"sp_[{stackOffset}]"
311 contents
+= f
"a{intRegIndex}_"
314 if intRegIndex
== numIntArgRegs
:
315 contents
+= f
"I32(sp_[{stackOffset}])"
318 contents
+= f
"I32(a{intRegIndex}_)"
321 if intRegIndex
== numIntArgRegs
:
322 contents
+= f
"sp_[{stackOffset}]"
325 contents
+= f
"a{intRegIndex}_"
327 elif arg
== "Float32":
328 if floatRegIndex
== numFloatArgRegs
:
329 contents
+= f
"*mozilla::BitwiseCast<float*>(sp_[{stackOffset}])"
332 contents
+= f
"f{floatRegIndex}_s"
334 elif arg
== "Float64":
335 if floatRegIndex
== numFloatArgRegs
:
336 contents
+= f
"mozilla::BitwiseCast<double>(sp_[{stackOffset}])"
339 contents
+= f
"f{floatRegIndex}_d"
341 assert intRegIndex
<= numIntArgRegs
342 assert floatRegIndex
<= numFloatArgRegs
346 def loongarch64_simulator_dispatch(func_types
):
348 for func_type
in func_types
:
349 args
= loongarch64_args(func_type
)
350 contents
+= f
"case js::jit::Args_{func_type_name(func_type)}: {{\\\n"
351 contents
+= f
" auto target = reinterpret_cast<Prototype_{func_type_name(func_type)}>(nativeFn);\\\n"
352 contents
+= f
" auto ret = target({args});\\\n"
353 ret
= func_type
["ret"]
355 contents
+= " setCallResult(ret);\\\n"
357 contents
+= " setCallResult(I64(ret));\\\n"
359 contents
+= " setCallResult(ret);\\\n"
360 elif ret
== "Float32":
361 contents
+= " setCallResultFloat(ret);\\\n"
362 elif ret
== "Float64":
363 contents
+= " setCallResultDouble(ret);\\\n"
364 contents
+= " break;\\\n"
369 # Generate the MIPS64 argument loading for a func type
370 def mips64_args(func_type
):
371 # This must match ABIArgGenerator::next() in Assembler-mips64.cpp
377 for i
, arg
in enumerate(func_type
["args"]):
382 if regIndex
== numIntArgRegs
:
383 contents
+= f
"sp_[{stackOffset}]"
386 contents
+= f
"a{regIndex}_"
389 if regIndex
== numIntArgRegs
:
390 contents
+= f
"I32(sp_[{stackOffset}])"
393 contents
+= f
"I32(a{regIndex}_)"
396 if regIndex
== numIntArgRegs
:
397 contents
+= f
"sp_[{stackOffset}]"
400 contents
+= f
"a{regIndex}_"
402 elif arg
== "Float32":
403 if regIndex
== numFloatArgRegs
:
404 contents
+= f
"*mozilla::BitwiseCast<float*>(sp_[{stackOffset}])"
407 contents
+= f
"f{regIndex + 12}_s"
409 elif arg
== "Float64":
410 if regIndex
== numFloatArgRegs
:
411 contents
+= f
"mozilla::BitwiseCast<double>(sp_[{stackOffset}])"
414 contents
+= f
"f{regIndex + 12}_d"
416 assert regIndex
<= numIntArgRegs
417 assert numIntArgRegs
== numFloatArgRegs
421 def mips64_simulator_dispatch(func_types
):
423 for func_type
in func_types
:
424 args
= mips64_args(func_type
)
425 contents
+= f
"case js::jit::Args_{func_type_name(func_type)}: {{\\\n"
426 contents
+= f
" auto target = reinterpret_cast<Prototype_{func_type_name(func_type)}>(nativeFn);\\\n"
427 contents
+= f
" auto ret = target({args});\\\n"
428 ret
= func_type
["ret"]
430 contents
+= " setCallResult(ret);\\\n"
432 contents
+= " setCallResult(I64(ret));\\\n"
434 contents
+= " setCallResult(ret);\\\n"
435 elif ret
== "Float32":
436 contents
+= " setCallResultFloat(ret);\\\n"
437 elif ret
== "Float64":
438 contents
+= " setCallResultDouble(ret);\\\n"
439 contents
+= " break;\\\n"
444 def main(c_out
, yaml_path
):
445 func_types
= load_yaml(yaml_path
)
447 # Define the ABIFunctionType enum
448 contents
= "#define ABI_FUNCTION_TYPE_ENUM \\\n"
449 for func_type
in func_types
:
450 name
= "Args_" + func_type_name(func_type
)
451 args
= ", ".join(f
"ABIType::{p}" for p
in func_type
["args"])
452 ret
= f
"ABIType::{func_type['ret']}"
454 contents
+= f
" {name} = detail::MakeABIFunctionType({ret}, {{{args}}}),\\\n"
457 # Define the prototypes of the types
458 contents
+= "#define ABI_FUNCTION_TYPE_SIM_PROTOTYPES \\\n"
459 for func_type
in func_types
:
460 name
= "Prototype_" + func_type_name(func_type
)
461 args
= ", ".join(cpp_arg_type(p
) for p
in func_type
["args"])
462 ret
= cpp_arg_type(func_type
["ret"])
464 contents
+= f
" typedef {ret} (*{name})({args});\\\n"
467 contents
+= "#define ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH \\\n"
468 contents
+= arm64_simulator_dispatch(func_types
)
471 contents
+= "#define ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH \\\n"
472 contents
+= arm32_simulator_dispatch(func_types
)
475 contents
+= "#define ABI_FUNCTION_TYPE_LOONGARCH64_SIM_DISPATCH \\\n"
476 contents
+= loongarch64_simulator_dispatch(func_types
)
479 contents
+= "#define ABI_FUNCTION_TYPE_MIPS64_SIM_DISPATCH \\\n"
480 contents
+= mips64_simulator_dispatch(func_types
)
483 generate_header(c_out
, "jit_ABIFunctionTypeGenerated_h", contents
)