GenerateCacheIRFiles.py (23347B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 # This script generates jit/CacheIROpsGenerated.h from CacheIROps.yaml 6 7 import io 8 import os 9 import os.path 10 11 import buildconfig 12 import yaml 13 from mozbuild.preprocessor import Preprocessor 14 15 HEADER_TEMPLATE = """\ 16 /* This Source Code Form is subject to the terms of the Mozilla Public 17 * License, v. 2.0. If a copy of the MPL was not distributed with this 18 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 19 20 #ifndef %(includeguard)s 21 #define %(includeguard)s 22 23 /* This file is generated by jit/GenerateCacheIRFiles.py. Do not edit! */ 24 25 %(contents)s 26 27 #endif // %(includeguard)s 28 """ 29 30 31 def generate_header(c_out, includeguard, contents): 32 c_out.write( 33 HEADER_TEMPLATE 34 % { 35 "includeguard": includeguard, 36 "contents": contents, 37 } 38 ) 39 40 41 def load_yaml(yaml_path): 42 # First invoke preprocessor.py so that we can use #ifdef JS_SIMULATOR in 43 # the YAML file. 44 pp = Preprocessor() 45 pp.context.update(buildconfig.defines["ALLDEFINES"]) 46 pp.out = io.StringIO() 47 pp.do_filter("substitution") 48 pp.do_include(yaml_path) 49 contents = pp.out.getvalue() 50 return yaml.safe_load(contents) 51 52 53 # Information for generating CacheIRWriter code for a single argument. Tuple 54 # stores the C++ argument type and the CacheIRWriter method to call. 55 arg_writer_info = { 56 "ValId": ("ValOperandId", "writeOperandId"), 57 "ObjId": ("ObjOperandId", "writeOperandId"), 58 "StringId": ("StringOperandId", "writeOperandId"), 59 "SymbolId": ("SymbolOperandId", "writeOperandId"), 60 "BooleanId": ("BooleanOperandId", "writeOperandId"), 61 "Int32Id": ("Int32OperandId", "writeOperandId"), 62 "NumberId": ("NumberOperandId", "writeOperandId"), 63 "BigIntId": ("BigIntOperandId", "writeOperandId"), 64 "ValueTagId": ("ValueTagOperandId", "writeOperandId"), 65 "IntPtrId": ("IntPtrOperandId", "writeOperandId"), 66 "RawId": ("OperandId", "writeOperandId"), 67 "ShapeField": ("Shape*", "writeShapeField"), 68 "WeakShapeField": ("Shape*", "writeWeakShapeField"), 69 "ObjectField": ("JSObject*", "writeObjectField"), 70 "WeakObjectField": ("JSObject*", "writeWeakObjectField"), 71 "StringField": ("JSString*", "writeStringField"), 72 "AtomField": ("JSAtom*", "writeStringField"), 73 "SymbolField": ("JS::Symbol*", "writeSymbolField"), 74 "WeakBaseScriptField": ("BaseScript*", "writeWeakBaseScriptField"), 75 "JitCodeField": ("JitCode*", "writeJitCodeField"), 76 "RawInt32Field": ("uint32_t", "writeRawInt32Field"), 77 "RawPointerField": ("const void*", "writeRawPointerField"), 78 "IdField": ("jsid", "writeIdField"), 79 "ValueField": ("const Value&", "writeValueField"), 80 "WeakValueField": ("const Value&", "writeWeakValueField"), 81 "RawInt64Field": ("uint64_t", "writeRawInt64Field"), 82 "DoubleField": ("double", "writeDoubleField"), 83 "AllocSiteField": ("gc::AllocSite*", "writeAllocSiteField"), 84 "JSOpImm": ("JSOp", "writeJSOpImm"), 85 "JSTypeImm": ("JSType", "writeJSTypeImm"), 86 "TypeofEqOperandImm": ("TypeofEqOperand", "writeTypeofEqOperandImm"), 87 "BoolImm": ("bool", "writeBoolImm"), 88 "ByteImm": ("uint32_t", "writeByteImm"), # uint32_t to enable fits-in-byte asserts. 89 "GuardClassKindImm": ("GuardClassKind", "writeGuardClassKindImm"), 90 "ArrayBufferViewKindImm": ("ArrayBufferViewKind", "writeArrayBufferViewKindImm"), 91 "ValueTypeImm": ("ValueType", "writeValueTypeImm"), 92 "JSWhyMagicImm": ("JSWhyMagic", "writeJSWhyMagicImm"), 93 "CallFlagsImm": ("CallFlags", "writeCallFlagsImm"), 94 "ScalarTypeImm": ("Scalar::Type", "writeScalarTypeImm"), 95 "UnaryMathFunctionImm": ("UnaryMathFunction", "writeUnaryMathFunctionImm"), 96 "WasmValTypeImm": ("wasm::ValType::Kind", "writeWasmValTypeImm"), 97 "Int32Imm": ("int32_t", "writeInt32Imm"), 98 "UInt32Imm": ("uint32_t", "writeUInt32Imm"), 99 "JSNativeImm": ("JSNative", "writeJSNativeImm"), 100 "StaticStringImm": ("const char*", "writeStaticStringImm"), 101 "AllocKindImm": ("gc::AllocKind", "writeAllocKindImm"), 102 "CompletionKindImm": ("CompletionKind", "writeCompletionKindImm"), 103 "RealmFuseIndexImm": ("RealmFuses::FuseIndex", "writeRealmFuseIndexImm"), 104 "RuntimeFuseIndexImm": ("RuntimeFuses::FuseIndex", "writeRuntimeFuseIndexImm"), 105 } 106 107 108 def gen_writer_method(name, args, custom_writer): 109 """Generates a CacheIRWRiter method for a single opcode.""" 110 111 # Generate a single method that writes the opcode and each argument. 112 # For example: 113 # 114 # void guardShape(ObjOperandId obj, Shape* shape) { 115 # writeOp(CacheOp::GuardShape); 116 # writeOperandId(obj); 117 # writeShapeField(shape); 118 # assertLengthMatches(); 119 # } 120 # 121 # The assertLengthMatches() call is to assert the information in the 122 # arg_length dictionary below matches what's written. 123 124 # Method names start with a lowercase letter. 125 method_name = name[0].lower() + name[1:] 126 if custom_writer: 127 method_name += "_" 128 129 method_args = [] 130 ret_type = "void" 131 args_code = "" 132 if args: 133 for arg_name, arg_type in args.items(): 134 cpp_type, write_method = arg_writer_info[arg_type] 135 if arg_name == "result": 136 ret_type = cpp_type 137 args_code += f" {cpp_type} result(newOperandId());\\\n" 138 args_code += " writeOperandId(result);\\\n" 139 else: 140 method_args.append(f"{cpp_type} {arg_name}") 141 args_code += f" {write_method}({arg_name});\\\n" 142 143 code = "" 144 if custom_writer: 145 code += "private:\\\n" 146 code += "{} {}({}) {{\\\n".format(ret_type, method_name, ", ".join(method_args)) 147 code += f" writeOp(CacheOp::{name});\\\n" 148 code += args_code 149 code += " assertLengthMatches();\\\n" 150 if ret_type != "void": 151 code += " return result;\\\n" 152 code += "}" 153 if custom_writer: 154 code += "\\\npublic:" 155 return code 156 157 158 # Information for generating code using CacheIRReader for a single argument. 159 # Tuple stores the C++ type, the suffix used for arguments/variables of this 160 # type, and the expression to read this type from CacheIRReader. 161 arg_reader_info = { 162 "ValId": ("ValOperandId", "Id", "reader.valOperandId()"), 163 "ObjId": ("ObjOperandId", "Id", "reader.objOperandId()"), 164 "StringId": ("StringOperandId", "Id", "reader.stringOperandId()"), 165 "SymbolId": ("SymbolOperandId", "Id", "reader.symbolOperandId()"), 166 "BooleanId": ("BooleanOperandId", "Id", "reader.booleanOperandId()"), 167 "Int32Id": ("Int32OperandId", "Id", "reader.int32OperandId()"), 168 "NumberId": ("NumberOperandId", "Id", "reader.numberOperandId()"), 169 "BigIntId": ("BigIntOperandId", "Id", "reader.bigIntOperandId()"), 170 "ValueTagId": ("ValueTagOperandId", "Id", "reader.valueTagOperandId()"), 171 "IntPtrId": ("IntPtrOperandId", "Id", "reader.intPtrOperandId()"), 172 "RawId": ("uint32_t", "Id", "reader.rawOperandId()"), 173 "ShapeField": ("uint32_t", "Offset", "reader.stubOffset()"), 174 "WeakShapeField": ("uint32_t", "Offset", "reader.stubOffset()"), 175 "ObjectField": ("uint32_t", "Offset", "reader.stubOffset()"), 176 "WeakObjectField": ("uint32_t", "Offset", "reader.stubOffset()"), 177 "StringField": ("uint32_t", "Offset", "reader.stubOffset()"), 178 "AtomField": ("uint32_t", "Offset", "reader.stubOffset()"), 179 "SymbolField": ("uint32_t", "Offset", "reader.stubOffset()"), 180 "WeakBaseScriptField": ("uint32_t", "Offset", "reader.stubOffset()"), 181 "JitCodeField": ("uint32_t", "Offset", "reader.stubOffset()"), 182 "RawInt32Field": ("uint32_t", "Offset", "reader.stubOffset()"), 183 "RawPointerField": ("uint32_t", "Offset", "reader.stubOffset()"), 184 "IdField": ("uint32_t", "Offset", "reader.stubOffset()"), 185 "ValueField": ("uint32_t", "Offset", "reader.stubOffset()"), 186 "WeakValueField": ("uint32_t", "Offset", "reader.stubOffset()"), 187 "RawInt64Field": ("uint32_t", "Offset", "reader.stubOffset()"), 188 "DoubleField": ("uint32_t", "Offset", "reader.stubOffset()"), 189 "AllocSiteField": ("uint32_t", "Offset", "reader.stubOffset()"), 190 "JSOpImm": ("JSOp", "", "reader.jsop()"), 191 "JSTypeImm": ("JSType", "", "reader.jstype()"), 192 "TypeofEqOperandImm": ("TypeofEqOperand", "", "reader.typeofEqOperand()"), 193 "BoolImm": ("bool", "", "reader.readBool()"), 194 "ByteImm": ("uint8_t", "", "reader.readByte()"), 195 "GuardClassKindImm": ("GuardClassKind", "", "reader.guardClassKind()"), 196 "ArrayBufferViewKindImm": ( 197 "ArrayBufferViewKind", 198 "", 199 "reader.arrayBufferViewKind()", 200 ), 201 "ValueTypeImm": ("ValueType", "", "reader.valueType()"), 202 "JSWhyMagicImm": ("JSWhyMagic", "", "reader.whyMagic()"), 203 "CallFlagsImm": ("CallFlags", "", "reader.callFlags()"), 204 "ScalarTypeImm": ("Scalar::Type", "", "reader.scalarType()"), 205 "UnaryMathFunctionImm": ("UnaryMathFunction", "", "reader.unaryMathFunction()"), 206 "WasmValTypeImm": ("wasm::ValType::Kind", "", "reader.wasmValType()"), 207 "Int32Imm": ("int32_t", "", "reader.int32Immediate()"), 208 "UInt32Imm": ("uint32_t", "", "reader.uint32Immediate()"), 209 "JSNativeImm": ("JSNative", "", "reinterpret_cast<JSNative>(reader.pointer())"), 210 "StaticStringImm": ("const char*", "", "reinterpret_cast<char*>(reader.pointer())"), 211 "AllocKindImm": ("gc::AllocKind", "", "reader.allocKind()"), 212 "CompletionKindImm": ("CompletionKind", "", "reader.completionKind()"), 213 "RealmFuseIndexImm": ("RealmFuses::FuseIndex", "", "reader.realmFuseIndex()"), 214 "RuntimeFuseIndexImm": ("RuntimeFuses::FuseIndex", "", "reader.runtimeFuseIndex()"), 215 } 216 217 218 def gen_compiler_method(name, args): 219 """Generates CacheIRCompiler or WarpCacheIRTranspiler header code for a 220 single opcode.""" 221 222 method_name = "emit" + name 223 224 # We generate the signature of the method that needs to be implemented and a 225 # separate function forwarding to it. For example: 226 # 227 # [[nodiscard]] bool emitGuardShape(ObjOperandId objId, uint32_t shapeOffset); 228 # [[nodiscard]] bool emitGuardShape(CacheIRReader& reader) { 229 # ObjOperandId objId = reader.objOperandId(); 230 # uint32_t shapeOffset = reader.stubOffset(); 231 # return emitGuardShape(objId, shapeOffset); 232 # } 233 cpp_args = [] 234 method_args = [] 235 args_code = "" 236 if args: 237 for arg_name, arg_type in args.items(): 238 cpp_type, suffix, readexpr = arg_reader_info[arg_type] 239 cpp_name = arg_name + suffix 240 cpp_args.append(cpp_name) 241 method_args.append(f"{cpp_type} {cpp_name}") 242 args_code += f" {cpp_type} {cpp_name} = {readexpr};\\\n" 243 244 # Generate signature. 245 code = "[[nodiscard]] bool {}({});\\\n".format(method_name, ", ".join(method_args)) 246 247 # Generate the method forwarding to it. 248 code += f"[[nodiscard]] bool {method_name}(CacheIRReader& reader) {{\\\n" 249 code += args_code 250 code += " return {}({});\\\n".format(method_name, ", ".join(cpp_args)) 251 code += "}\\\n" 252 253 return code 254 255 256 def gen_reader_method(name, args): 257 """Generates CacheIRReader code for a single opcode.""" 258 259 # Generate a struct that holds the opcode's arguments and a CacheIRReader 260 # method that returns this struct. For example for GuardShape: 261 # 262 # struct GuardShapeArgs final { ObjOperandId objId; uint32_t shapeOffset; }; 263 # 264 # GuardShapeArgs argsForGuardShape() { 265 # MOZ_ASSERT(*lastOp_ == CacheOp::GuardShape); 266 # ObjOperandId objId_ = this->objOperandId(); 267 # uint32_t shapeOffset_ = this->stubOffset(); 268 # return { objId_, shapeOffset_ }; 269 # } 270 # 271 # Note that we use a trailing underscore for the variables to ensure variable 272 # names don't conflict with class methods. 273 274 struct_name = f"{name}Args" 275 method_name = f"argsFor{name}" 276 277 read_args_code = "" 278 method_vars = [] 279 struct_fields = [] 280 281 if args: 282 for arg_name, arg_type in args.items(): 283 cpp_type, suffix, readexpr = arg_reader_info[arg_type] 284 readexpr = readexpr.replace("reader.", "this->") 285 cpp_field_name = arg_name + suffix 286 cpp_var_name = cpp_field_name + "_" 287 method_vars.append(cpp_var_name) 288 struct_fields.append(f"{cpp_type} {cpp_field_name};") 289 read_args_code += f" {cpp_type} {cpp_var_name} = {readexpr};\\\n" 290 291 # Generate struct. 292 code = f"struct {struct_name} final {{ {' '.join(struct_fields)} }};\\\n" 293 294 # Generate reader method. 295 code += f"{struct_name} {method_name}() {{\\\n" 296 code += f" MOZ_ASSERT(*lastOp_ == CacheOp::{name});\\\n" 297 code += read_args_code 298 vars_list = ", ".join(method_vars) 299 code += f" return {{ {vars_list} }};\\\n" 300 code += "}\\\n" 301 302 return code 303 304 305 # For each argument type, the method name for printing it. 306 arg_spewer_method = { 307 "ValId": "spewOperandId", 308 "ObjId": "spewOperandId", 309 "StringId": "spewOperandId", 310 "SymbolId": "spewOperandId", 311 "BooleanId": "spewOperandId", 312 "Int32Id": "spewOperandId", 313 "NumberId": "spewOperandId", 314 "BigIntId": "spewOperandId", 315 "ValueTagId": "spewOperandId", 316 "IntPtrId": "spewOperandId", 317 "RawId": "spewRawOperandId", 318 "ShapeField": "spewField", 319 "WeakShapeField": "spewField", 320 "ObjectField": "spewField", 321 "WeakObjectField": "spewField", 322 "StringField": "spewField", 323 "AtomField": "spewField", 324 "SymbolField": "spewField", 325 "WeakBaseScriptField": "spewField", 326 "JitCodeField": "spewField", 327 "RawInt32Field": "spewField", 328 "RawPointerField": "spewField", 329 "IdField": "spewField", 330 "ValueField": "spewField", 331 "WeakValueField": "spewField", 332 "RawInt64Field": "spewField", 333 "DoubleField": "spewField", 334 "AllocSiteField": "spewField", 335 "JSOpImm": "spewJSOpImm", 336 "JSTypeImm": "spewJSTypeImm", 337 "TypeofEqOperandImm": "spewTypeofEqOperandImm", 338 "BoolImm": "spewBoolImm", 339 "ByteImm": "spewByteImm", 340 "GuardClassKindImm": "spewGuardClassKindImm", 341 "ArrayBufferViewKindImm": "spewArrayBufferViewKindImm", 342 "ValueTypeImm": "spewValueTypeImm", 343 "JSWhyMagicImm": "spewJSWhyMagicImm", 344 "CallFlagsImm": "spewCallFlagsImm", 345 "ScalarTypeImm": "spewScalarTypeImm", 346 "UnaryMathFunctionImm": "spewUnaryMathFunctionImm", 347 "WasmValTypeImm": "spewWasmValTypeImm", 348 "Int32Imm": "spewInt32Imm", 349 "UInt32Imm": "spewUInt32Imm", 350 "JSNativeImm": "spewJSNativeImm", 351 "StaticStringImm": "spewStaticStringImm", 352 "AllocKindImm": "spewAllocKindImm", 353 "CompletionKindImm": "spewCompletionKindImm", 354 "RealmFuseIndexImm": "spewRealmFuseIndexImm", 355 "RuntimeFuseIndexImm": "spewRuntimeFuseIndexImm", 356 } 357 358 359 def gen_spewer_method(name, args): 360 """Generates spewer code for a single opcode.""" 361 362 method_name = "spew" + name 363 364 # Generate code like this: 365 # 366 # void spewGuardShape(CacheIRReader& reader) { 367 # spewOp(CacheOp::GuardShape); 368 # spewOperandId("objId", reader.objOperandId()); 369 # spewOperandSeparator(); 370 # spewField("shapeOffset", reader.stubOffset()); 371 # spewOpEnd(); 372 # } 373 args_code = "" 374 if args: 375 is_first = True 376 for arg_name, arg_type in args.items(): 377 _, suffix, readexpr = arg_reader_info[arg_type] 378 arg_name += suffix 379 spew_method = arg_spewer_method[arg_type] 380 if not is_first: 381 args_code += " spewArgSeparator();\\\n" 382 args_code += f' {spew_method}("{arg_name}", {readexpr});\\\n' 383 is_first = False 384 385 code = f"void {method_name}(CacheIRReader& reader) {{\\\n" 386 code += f" spewOp(CacheOp::{name});\\\n" 387 code += args_code 388 code += " spewOpEnd();\\\n" 389 code += "}\\\n" 390 391 return code 392 393 394 def gen_clone_method(name, args): 395 """Generates code for cloning a single opcode.""" 396 397 method_name = "clone" + name 398 399 # Generate code like this: 400 # 401 # void cloneGuardShape(CacheIRReader& reader, CacheIRWriter& writer) { 402 # writer.writeOp(CacheOp::GuardShape); 403 # ObjOperandId objId = reader.objOperandId(); 404 # writer.writeOperandId(objId); 405 # uint32_t shapeOffset = reader.stubOffset(); 406 # Shape* shape = getShapeField(shapeOffset); 407 # writer.writeShapeField(shape); 408 # writer.assertLengthMatches(); 409 # } 410 411 args_code = "" 412 if args: 413 for arg_name, arg_type in args.items(): 414 if arg_type == "RawId": 415 arg_type = "ValId" 416 417 read_type, suffix, readexpr = arg_reader_info[arg_type] 418 read_name = arg_name + suffix 419 value_name = read_name 420 args_code += f" {read_type} {read_name} = {readexpr};\\\n" 421 422 write_type, write_method = arg_writer_info[arg_type] 423 if arg_name == "result": 424 args_code += " writer.newOperandId();\\\n" 425 if suffix == "Offset": 426 # If the write function takes T&, the intermediate variable 427 # should be of type T. 428 if write_type.endswith("&"): 429 write_type = write_type[:-1] 430 value_name = arg_name 431 args_code += ( 432 f" {write_type} {value_name} = get{arg_type}({read_name});\\\n" 433 ) 434 args_code += f" writer.{write_method}({value_name});\\\n" 435 436 code = f"void {method_name}" 437 code += "(CacheIRReader& reader, CacheIRWriter& writer) {{\\\n" 438 code += f" writer.writeOp(CacheOp::{name});\\\n" 439 code += args_code 440 code += " writer.assertLengthMatches();\\\n" 441 code += "}}\\\n" 442 443 return code 444 445 446 # Length in bytes for each argument type, either an integer or a C++ expression. 447 # This is used to generate the CacheIROpArgLengths array. CacheIRWriter asserts 448 # the number of bytes written matches the value in that array. 449 arg_length = { 450 "ValId": 1, 451 "ObjId": 1, 452 "StringId": 1, 453 "SymbolId": 1, 454 "BooleanId": 1, 455 "Int32Id": 1, 456 "NumberId": 1, 457 "BigIntId": 1, 458 "ValueTagId": 1, 459 "IntPtrId": 1, 460 "RawId": 1, 461 "ShapeField": 1, 462 "WeakShapeField": 1, 463 "ObjectField": 1, 464 "WeakObjectField": 1, 465 "StringField": 1, 466 "AtomField": 1, 467 "SymbolField": 1, 468 "WeakBaseScriptField": 1, 469 "JitCodeField": 1, 470 "RawInt32Field": 1, 471 "RawPointerField": 1, 472 "RawInt64Field": 1, 473 "DoubleField": 1, 474 "IdField": 1, 475 "ValueField": 1, 476 "WeakValueField": 1, 477 "AllocSiteField": 1, 478 "ByteImm": 1, 479 "BoolImm": 1, 480 "CallFlagsImm": 1, 481 "ScalarTypeImm": 1, 482 "UnaryMathFunctionImm": 1, 483 "JSOpImm": 1, 484 "JSTypeImm": 1, 485 "TypeofEqOperandImm": 1, 486 "ValueTypeImm": 1, 487 "GuardClassKindImm": 1, 488 "ArrayBufferViewKindImm": 1, 489 "JSWhyMagicImm": 1, 490 "WasmValTypeImm": 1, 491 "Int32Imm": 4, 492 "UInt32Imm": 4, 493 "JSNativeImm": "sizeof(uintptr_t)", 494 "StaticStringImm": "sizeof(uintptr_t)", 495 "AllocKindImm": 1, 496 "CompletionKindImm": 1, 497 "RealmFuseIndexImm": 1, 498 "RuntimeFuseIndexImm": 1, 499 } 500 501 502 def generate_cacheirops_header(c_out, yaml_path): 503 """Generate CacheIROpsGenerated.h from CacheIROps.yaml. The generated file 504 contains a list of all CacheIR ops and generated source code for 505 CacheIRWriter and CacheIRCompiler.""" 506 507 data = load_yaml(yaml_path) 508 509 # CACHE_IR_OPS items. Each item stores an opcode name and arguments length 510 # expression. For example: _(GuardShape, 1 + 1) 511 ops_items = [] 512 513 # Generated CacheIRWriter methods. 514 writer_methods = [] 515 516 # Generated CacheIRReader methods. 517 reader_methods = [] 518 519 # Generated CacheIRCompiler methods. 520 compiler_shared_methods = [] 521 compiler_unshared_methods = [] 522 523 # Generated WarpCacheIRTranspiler methods. 524 transpiler_methods = [] 525 526 # List of ops supported by WarpCacheIRTranspiler. 527 transpiler_ops = [] 528 529 # Generated methods for spewers. 530 spewer_methods = [] 531 532 # Generated methods for cloning IC stubs 533 clone_methods = [] 534 535 for op in data: 536 name = op["name"] 537 538 args = op["args"] 539 assert args is None or isinstance(args, dict) 540 541 shared = op["shared"] 542 assert isinstance(shared, bool) 543 544 transpile = op["transpile"] 545 assert isinstance(transpile, bool) 546 547 # Unscored Ops default to UINT32_MAX 548 cost_estimate = op.get("cost_estimate", 0xFFFFFFFF) 549 assert isinstance(cost_estimate, int) 550 551 custom_writer = op.get("custom_writer", False) 552 assert isinstance(custom_writer, bool) 553 554 if args: 555 args_length = " + ".join([str(arg_length[v]) for v in args.values()]) 556 else: 557 args_length = "0" 558 559 transpile_str = "true" if transpile else "false" 560 ops_items.append(f"_({name}, {args_length}, {transpile_str}, {cost_estimate})") 561 562 writer_methods.append(gen_writer_method(name, args, custom_writer)) 563 reader_methods.append(gen_reader_method(name, args)) 564 565 if shared: 566 compiler_shared_methods.append(gen_compiler_method(name, args)) 567 else: 568 compiler_unshared_methods.append(gen_compiler_method(name, args)) 569 570 if transpile: 571 transpiler_methods.append(gen_compiler_method(name, args)) 572 transpiler_ops.append(f"_({name})") 573 574 spewer_methods.append(gen_spewer_method(name, args)) 575 576 clone_methods.append(gen_clone_method(name, args)) 577 578 contents = "#define CACHE_IR_OPS(_)\\\n" 579 contents += "\\\n".join(ops_items) 580 contents += "\n\n" 581 582 contents += "#define CACHE_IR_WRITER_GENERATED \\\n" 583 contents += "\\\n".join(writer_methods) 584 contents += "\n\n" 585 586 contents += "#define CACHE_IR_READER_GENERATED \\\n" 587 contents += "\\\n".join(reader_methods) 588 contents += "\n\n" 589 590 contents += "#define CACHE_IR_COMPILER_SHARED_GENERATED \\\n" 591 contents += "\\\n".join(compiler_shared_methods) 592 contents += "\n\n" 593 594 contents += "#define CACHE_IR_COMPILER_UNSHARED_GENERATED \\\n" 595 contents += "\\\n".join(compiler_unshared_methods) 596 contents += "\n\n" 597 598 contents += "#define CACHE_IR_TRANSPILER_GENERATED \\\n" 599 contents += "\\\n".join(transpiler_methods) 600 contents += "\n\n" 601 602 contents += "#define CACHE_IR_TRANSPILER_OPS(_)\\\n" 603 contents += "\\\n".join(transpiler_ops) 604 contents += "\n\n" 605 606 contents += "#define CACHE_IR_SPEWER_GENERATED \\\n" 607 contents += "\\\n".join(spewer_methods) 608 contents += "\n\n" 609 610 contents += "#define CACHE_IR_CLONE_GENERATED \\\n" 611 contents += "\\\n".join(clone_methods) 612 contents += "\n\n" 613 614 generate_header(c_out, "jit_CacheIROpsGenerated_h", contents) 615 616 617 def read_aot_ics(ic_path): 618 ics = "" 619 idx = 0 620 for entry in os.scandir(ic_path): 621 if entry.is_file() and os.path.basename(entry.path).startswith("IC-"): 622 with open(entry.path) as f: 623 content = f.read().strip() 624 ics += " _(%d, %s) \\\n" % (idx, content) 625 idx += 1 626 return ics 627 628 629 def generate_aot_ics_header(c_out, ic_path): 630 """Generate CacheIROpsGenerated.h from AOT IC corpus.""" 631 632 # Read in all ICs from js/src/ics/IC-*. 633 ics = read_aot_ics(ic_path) 634 635 contents = "#define JS_AOT_IC_DATA(_) \\\n" 636 contents += ics 637 contents += "\n" 638 639 generate_header(c_out, "jit_CacheIRAOTGenerated_h", contents)