GenerateBuiltinModules.py (5752B)
1 import io 2 3 import buildconfig 4 import yaml 5 from mozbuild.preprocessor import Preprocessor 6 7 HEADER_TEMPLATE = """\ 8 /* This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 11 12 #ifndef %(includeguard)s 13 #define %(includeguard)s 14 15 /* This file is generated by wasm/GenerateBuiltinModules.py. Do not edit! */ 16 17 %(contents)s 18 19 #endif // %(includeguard)s 20 """ 21 22 23 def generate_header(c_out, includeguard, contents): 24 c_out.write( 25 HEADER_TEMPLATE 26 % { 27 "includeguard": includeguard, 28 "contents": contents, 29 } 30 ) 31 32 33 def load_yaml(yaml_path): 34 # First invoke preprocessor.py so that we can use #ifdef JS_SIMULATOR in 35 # the YAML file. 36 pp = Preprocessor() 37 pp.context.update(buildconfig.defines["ALLDEFINES"]) 38 pp.out = io.StringIO() 39 pp.do_filter("substitution") 40 pp.do_include(yaml_path) 41 contents = pp.out.getvalue() 42 return yaml.safe_load(contents) 43 44 45 def cppBool(v): 46 if v: 47 return "true" 48 return "false" 49 50 51 def specTypeToMIRType(specType): 52 if isinstance(specType, dict): 53 return "MIRType::WasmAnyRef" 54 if specType in {"i32", "i64", "f32", "f64"}: 55 return f"ValType::{specType}().toMIRType()" 56 if specType in {"externref", "anyref", "funcref", "exnref"}: 57 return "MIRType::WasmAnyRef" 58 raise ValueError() 59 60 61 def specHeapTypeToTypeCode(specHeapType): 62 if specHeapType == "func": 63 return "Func" 64 if specHeapType == "any": 65 return "Any" 66 if specHeapType == "extern": 67 return "Extern" 68 if specHeapType == "exn": 69 return "Exn" 70 if specHeapType == "array": 71 return "Array" 72 if specHeapType == "struct": 73 return "Struct" 74 raise ValueError() 75 76 77 def specTypeToValType(specType): 78 if isinstance(specType, dict): 79 nullable = cppBool(specType["nullable"]) 80 if "type" in specType: 81 ref = specType["type"] 82 return f"ValType(RefType::fromTypeDef({ref}, {nullable}))" 83 else: 84 code = specType["code"] 85 return f"ValType(RefType::fromTypeCode(TypeCode(RefType::{specHeapTypeToTypeCode(code)}), {nullable}))" 86 87 if specType in {"i32", "i64", "f32", "f64"}: 88 return f"ValType::{specType}()" 89 90 if specType == "externref": 91 return "ValType(RefType::extern_())" 92 93 if specType == "exnref": 94 return "ValType(RefType::exn())" 95 96 if specType == "anyref": 97 return "ValType(RefType::any())" 98 99 if specType == "funcref": 100 return "ValType(RefType::func())" 101 102 raise ValueError() 103 104 105 def failureTrap(op): 106 if not "fail_trap" in op: 107 if op["fail_mode"] == "Infallible": 108 return "Limit" 109 return "ThrowReported" 110 return op["fail_trap"] 111 112 113 def main(c_out, yaml_path): 114 data = load_yaml(yaml_path) 115 116 # Iterate for all defined builtin methods 117 contents = "#define FOR_EACH_BUILTIN_MODULE_FUNC(M) \\\n" 118 for i in range(len(data)): 119 op = data[i] 120 sa = op["symbolic_address"] 121 inlineOp = "BuiltinInlineOp::None" 122 if "inline_op" in op: 123 inlineOp = f"BuiltinInlineOp::{op['inline_op']}" 124 contents += ( 125 f' M({op["op"]}, "{op["export"]}", ' 126 f"{sa['name']}, {sa['type']}, {cppBool(sa['needs_thunk'])}, {op['entry']}, {cppBool(op['uses_memory'])}, {inlineOp}, {i})\\\n" 127 ) 128 contents += "\n" 129 130 for op in data: 131 # Define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_<op> as: 132 # `{ValType::I32, ValType::I32, ...}`. 133 valTypes = ", ".join(specTypeToValType(p) for p in op["params"]) 134 contents += ( 135 f"#define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_{op['op']} " 136 f"{{{valTypes}}}\n" 137 ) 138 139 # Define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_<op> as: 140 # `<num_types>, {MIRType::Pointer, _I32, ..., MIRType::Pointer, _END}`. 141 num_types = len(op["params"]) + 1 142 mir_types = "{MIRType::Pointer" 143 mir_types += "".join(", " + specTypeToMIRType(p) for p in op["params"]) 144 if op["uses_memory"]: 145 mir_types += ", MIRType::Pointer" 146 num_types += 1 147 # Add the end marker 148 mir_types += ", MIRType::None}" 149 150 contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_{op['op']} {num_types}, {mir_types}\n" 151 152 # Define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_<op> as: 153 # `Some(X)` if present, or else `Nothing()`. 154 result_valtype = "" 155 if "result" in op: 156 result_valtype = f"mozilla::Some({specTypeToValType(op['result'])})\n" 157 else: 158 result_valtype = "mozilla::Nothing()" 159 contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_{op['op']} {result_valtype}\n" 160 161 # Define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_<op> as: 162 # `X` if present, or else `MIRType::None`. 163 result_mirtype = "" 164 if "result" in op: 165 result_mirtype = specTypeToMIRType(op["result"]) + "\n" 166 else: 167 result_mirtype = "MIRType::None" 168 contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_{op['op']} {result_mirtype}\n" 169 170 # Define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_<op> as: 171 # `FailureMode::X`. 172 contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_{op['op']} FailureMode::{op['fail_mode']}\n" 173 174 # Define DECLARE_BUILTIN_MODULE_FUNC_FAILTRAP_<op> as: 175 # `Trap::X`. 176 contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_FAILTRAP_{op['op']} Trap::{failureTrap(op)}\n" 177 178 generate_header(c_out, "wasm_WasmBuiltinModuleGenerated_h", contents)