Bug 1867190 - Add prefs for PHC probablities r=glandium
[gecko.git] / js / src / jit / GenerateABIFunctionType.py
blob58478bf0bc2f91fb57803393fcd2b7ff152f19a4
1 import buildconfig
2 import six
3 import yaml
4 from mozbuild.preprocessor import Preprocessor
6 HEADER_TEMPLATE = """\
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! */
16 %(contents)s
18 #endif // %(includeguard)s
19 """
22 def generate_header(c_out, includeguard, contents):
23 c_out.write(
24 HEADER_TEMPLATE
25 % {
26 "includeguard": includeguard,
27 "contents": contents,
32 def load_yaml(yaml_path):
33 # First invoke preprocessor.py so that we can use #ifdef JS_SIMULATOR in
34 # the YAML file.
35 pp = Preprocessor()
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":
46 return "intptr_t"
47 elif arg_type == "Int32":
48 return "int32_t"
49 elif arg_type == "Int64":
50 return "int64_t"
51 elif arg_type == "Float32":
52 return "float"
53 elif arg_type == "Float64":
54 return "double"
55 else:
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":
70 return True
71 return False
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
77 contents = ""
78 numIntArgRegs = 4
79 intRegIndex = 0
80 stackOffset = 0
81 for i, arg in enumerate(func_type["args"]):
82 if i != 0:
83 contents += ", "
85 if arg == "General":
86 if intRegIndex == numIntArgRegs:
87 contents += f"stack_pointer[{stackOffset}]"
88 stackOffset += 1
89 else:
90 contents += f"a{intRegIndex}"
91 intRegIndex += 1
92 elif arg == "Int32":
93 if intRegIndex == numIntArgRegs:
94 contents += f"stack_pointer[{stackOffset}]"
95 stackOffset += 1
96 else:
97 contents += f"a{intRegIndex}"
98 intRegIndex += 1
99 elif arg == "Int64":
100 intRegIndex += intRegIndex % 2
101 if intRegIndex == numIntArgRegs:
102 stackOffset += stackOffset % 2
103 contents += f"MakeInt64(stack_pointer[{stackOffset}], stack_pointer[{stackOffset + 1}])"
104 stackOffset += 2
105 else:
106 contents += f"MakeInt64(a{intRegIndex}, a{intRegIndex+1})"
107 intRegIndex += 2
108 elif arg == "Float32":
109 if intRegIndex == numIntArgRegs:
110 contents += f"mozilla::BitwiseCast<float>(stack_pointer[{stackOffset}])"
111 stackOffset += 1
112 else:
113 contents += f"mozilla::BitwiseCast<float>(a{intRegIndex})"
114 intRegIndex += 1
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}]))"
120 stackOffset += 2
121 else:
122 contents += f"mozilla::BitwiseCast<double>(MakeInt64(a{intRegIndex}, a{intRegIndex + 1}))"
123 intRegIndex += 2
124 assert intRegIndex <= numIntArgRegs
125 return contents
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
131 contents = ""
132 numIntArgRegs = 4
133 numFloatArgRegs = 16
134 intRegIndex = 0
135 floatRegIndex = 0
136 stackOffset = 0
137 for i, arg in enumerate(func_type["args"]):
138 if i != 0:
139 contents += ", "
141 if arg == "General":
142 if intRegIndex == numIntArgRegs:
143 contents += f"stack_pointer[{stackOffset}]"
144 stackOffset += 1
145 else:
146 contents += f"a{intRegIndex}"
147 intRegIndex += 1
148 elif arg == "Int32":
149 if intRegIndex == numIntArgRegs:
150 contents += f"stack_pointer[{stackOffset}]"
151 stackOffset += 1
152 else:
153 contents += f"a{intRegIndex}"
154 intRegIndex += 1
155 elif arg == "Int64":
156 intRegIndex += intRegIndex % 2
157 if intRegIndex == numIntArgRegs:
158 stackOffset += stackOffset % 2
159 contents += f"MakeInt64(stack_pointer[{stackOffset}], stack_pointer[{stackOffset + 1}])"
160 stackOffset += 2
161 else:
162 contents += f"MakeInt64(a{intRegIndex}, a{intRegIndex+1})"
163 intRegIndex += 2
164 elif arg == "Float32":
165 if floatRegIndex == numFloatArgRegs:
166 contents += f"mozilla::BitwiseCast<float>(stack_pointer[{stackOffset}])"
167 stackOffset += 1
168 else:
169 contents += f"s{floatRegIndex}"
170 floatRegIndex += 1
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}]))"
176 stackOffset += 2
177 else:
178 contents += f"d{round(floatRegIndex / 2)}"
179 floatRegIndex += 2
180 assert intRegIndex <= numIntArgRegs
181 assert floatRegIndex <= numFloatArgRegs
182 return contents
185 def arm32_simulator_dispatch(func_types):
186 contents = ""
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"
200 contents += " }\\\n"
201 else:
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"
213 contents += "}\\\n"
214 return contents
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
220 contents = ""
221 numIntArgRegs = 8
222 numFloatArgRegs = 8
223 intRegIndex = 0
224 floatRegIndex = 0
225 stackOffset = 0
226 for i, arg in enumerate(func_type["args"]):
227 if i != 0:
228 contents += ", "
230 if arg == "General":
231 if intRegIndex == numIntArgRegs:
232 contents += f"sp[{stackOffset}]"
233 stackOffset += 1
234 else:
235 contents += f"x{intRegIndex}"
236 intRegIndex += 1
237 elif arg == "Int32":
238 if intRegIndex == numIntArgRegs:
239 contents += f"sp[{stackOffset}]"
240 stackOffset += 1
241 else:
242 contents += f"x{intRegIndex}"
243 intRegIndex += 1
244 elif arg == "Int64":
245 if intRegIndex == numIntArgRegs:
246 contents += f"sp[{stackOffset}]"
247 stackOffset += 1
248 else:
249 contents += f"x{intRegIndex}"
250 intRegIndex += 1
251 elif arg == "Float32":
252 if floatRegIndex == numFloatArgRegs:
253 contents += f"mozilla::BitwiseCast<float>(sp[{stackOffset}])"
254 stackOffset += 1
255 else:
256 contents += f"s{floatRegIndex}"
257 floatRegIndex += 1
258 elif arg == "Float64":
259 if floatRegIndex == numFloatArgRegs:
260 contents += f"mozilla::BitwiseCast<double>(sp[{stackOffset}])"
261 stackOffset += 1
262 else:
263 contents += f"d{floatRegIndex}"
264 floatRegIndex += 1
265 assert intRegIndex <= numIntArgRegs
266 assert floatRegIndex <= numFloatArgRegs
267 return contents
270 def arm64_simulator_dispatch(func_types):
271 contents = ""
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"]
278 if ret == "General":
279 contents += " setGPR64Result(ret);\\\n"
280 elif ret == "Int32":
281 contents += " setGPR32Result(ret);\\\n"
282 elif ret == "Int64":
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"
289 contents += "}\\\n"
290 return contents
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
296 contents = ""
297 numIntArgRegs = 8
298 numFloatArgRegs = 8
299 intRegIndex = 0
300 floatRegIndex = 0
301 stackOffset = 0
302 for i, arg in enumerate(func_type["args"]):
303 if i != 0:
304 contents += ", "
306 if arg == "General":
307 if intRegIndex == numIntArgRegs:
308 contents += f"sp_[{stackOffset}]"
309 stackOffset += 1
310 else:
311 contents += f"a{intRegIndex}_"
312 intRegIndex += 1
313 elif arg == "Int32":
314 if intRegIndex == numIntArgRegs:
315 contents += f"I32(sp_[{stackOffset}])"
316 stackOffset += 1
317 else:
318 contents += f"I32(a{intRegIndex}_)"
319 intRegIndex += 1
320 elif arg == "Int64":
321 if intRegIndex == numIntArgRegs:
322 contents += f"sp_[{stackOffset}]"
323 stackOffset += 1
324 else:
325 contents += f"a{intRegIndex}_"
326 intRegIndex += 1
327 elif arg == "Float32":
328 if floatRegIndex == numFloatArgRegs:
329 contents += f"*mozilla::BitwiseCast<float*>(sp_[{stackOffset}])"
330 stackOffset += 1
331 else:
332 contents += f"f{floatRegIndex}_s"
333 floatRegIndex += 1
334 elif arg == "Float64":
335 if floatRegIndex == numFloatArgRegs:
336 contents += f"mozilla::BitwiseCast<double>(sp_[{stackOffset}])"
337 stackOffset += 1
338 else:
339 contents += f"f{floatRegIndex}_d"
340 floatRegIndex += 1
341 assert intRegIndex <= numIntArgRegs
342 assert floatRegIndex <= numFloatArgRegs
343 return contents
346 def loongarch64_simulator_dispatch(func_types):
347 contents = ""
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"]
354 if ret == "General":
355 contents += " setCallResult(ret);\\\n"
356 elif ret == "Int32":
357 contents += " setCallResult(I64(ret));\\\n"
358 elif ret == "Int64":
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"
365 contents += "}\\\n"
366 return contents
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
372 contents = ""
373 numIntArgRegs = 8
374 numFloatArgRegs = 8
375 regIndex = 0
376 stackOffset = 0
377 for i, arg in enumerate(func_type["args"]):
378 if i != 0:
379 contents += ", "
381 if arg == "General":
382 if regIndex == numIntArgRegs:
383 contents += f"sp_[{stackOffset}]"
384 stackOffset += 1
385 else:
386 contents += f"a{regIndex}_"
387 regIndex += 1
388 elif arg == "Int32":
389 if regIndex == numIntArgRegs:
390 contents += f"I32(sp_[{stackOffset}])"
391 stackOffset += 1
392 else:
393 contents += f"I32(a{regIndex}_)"
394 regIndex += 1
395 elif arg == "Int64":
396 if regIndex == numIntArgRegs:
397 contents += f"sp_[{stackOffset}]"
398 stackOffset += 1
399 else:
400 contents += f"a{regIndex}_"
401 regIndex += 1
402 elif arg == "Float32":
403 if regIndex == numFloatArgRegs:
404 contents += f"*mozilla::BitwiseCast<float*>(sp_[{stackOffset}])"
405 stackOffset += 1
406 else:
407 contents += f"f{regIndex + 12}_s"
408 regIndex += 1
409 elif arg == "Float64":
410 if regIndex == numFloatArgRegs:
411 contents += f"mozilla::BitwiseCast<double>(sp_[{stackOffset}])"
412 stackOffset += 1
413 else:
414 contents += f"f{regIndex + 12}_d"
415 regIndex += 1
416 assert regIndex <= numIntArgRegs
417 assert numIntArgRegs == numFloatArgRegs
418 return contents
421 def mips64_simulator_dispatch(func_types):
422 contents = ""
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"]
429 if ret == "General":
430 contents += " setCallResult(ret);\\\n"
431 elif ret == "Int32":
432 contents += " setCallResult(I64(ret));\\\n"
433 elif ret == "Int64":
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"
440 contents += "}\\\n"
441 return contents
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"
455 contents += "\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"
465 contents += "\n"
467 contents += "#define ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH \\\n"
468 contents += arm64_simulator_dispatch(func_types)
469 contents += "\n"
471 contents += "#define ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH \\\n"
472 contents += arm32_simulator_dispatch(func_types)
473 contents += "\n"
475 contents += "#define ABI_FUNCTION_TYPE_LOONGARCH64_SIM_DISPATCH \\\n"
476 contents += loongarch64_simulator_dispatch(func_types)
477 contents += "\n"
479 contents += "#define ABI_FUNCTION_TYPE_MIPS64_SIM_DISPATCH \\\n"
480 contents += mips64_simulator_dispatch(func_types)
481 contents += "\n"
483 generate_header(c_out, "jit_ABIFunctionTypeGenerated_h", contents)