import buildconfig import six import yaml from mozbuild.preprocessor import Preprocessor HEADER_TEMPLATE = """\ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef %(includeguard)s #define %(includeguard)s /* This file is generated by wasm/GenerateBuiltinModules.py. Do not edit! */ %(contents)s #endif // %(includeguard)s """ def generate_header(c_out, includeguard, contents): c_out.write( HEADER_TEMPLATE % { "includeguard": includeguard, "contents": contents, } ) def load_yaml(yaml_path): # First invoke preprocessor.py so that we can use #ifdef JS_SIMULATOR in # the YAML file. pp = Preprocessor() pp.context.update(buildconfig.defines["ALLDEFINES"]) pp.out = six.StringIO() pp.do_filter("substitution") pp.do_include(yaml_path) contents = pp.out.getvalue() return yaml.safe_load(contents) def cppBool(v): if v: return "true" return "false" def specTypeToMIRType(specType): if specType == "i32" or specType == "i64" or specType == "f32" or specType == "f64": return f"ValType::{specType}().toMIRType()" if ( specType == "externref" or specType == "anyref" or specType == "funcref" or isinstance(specType, dict) ): return "MIRType::WasmAnyRef" raise ValueError() def specHeapTypeToTypeCode(specHeapType): if specHeapType == "func": return "Func" if specHeapType == "any": return "Any" if specHeapType == "extern": return "Extern" if specHeapType == "array": return "Array" if specHeapType == "struct": return "Struct" raise ValueError() def specTypeToValType(specType): if specType == "i32" or specType == "i64" or specType == "f32" or specType == "f64": return f"ValType::{specType}()" if specType == "externref": return "ValType(RefType::extern_())" if specType == "anyref": return "ValType(RefType::any())" if specType == "funcref": return "ValType(RefType::func())" if isinstance(specType, dict): nullable = cppBool(specType["nullable"]) if "type" in specType: ref = specType["type"] return f"ValType(RefType::fromTypeDef({ref}, {nullable}))" else: code = specType["code"] return f"ValType(RefType::fromTypeCode(TypeCode(RefType::{specHeapTypeToTypeCode(code)}), {nullable}))" raise ValueError() def main(c_out, yaml_path): data = load_yaml(yaml_path) # Iterate for all defined builtin methods contents = "#define FOR_EACH_BUILTIN_MODULE_FUNC(M) \\\n" for i in range(len(data)): op = data[i] sa = op["symbolic_address"] contents += ( f" M({op['op']}, \"{op['export']}\", " f"{sa['name']}, {sa['type']}, {op['entry']}, {cppBool(op['uses_memory'])}, {i})\\\n" ) contents += "\n" for op in data: # Define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_ as: # `{ValType::I32, ValType::I32, ...}`. valTypes = ", ".join(specTypeToValType(p) for p in op["params"]) contents += ( f"#define DECLARE_BUILTIN_MODULE_FUNC_PARAM_VALTYPES_{op['op']} " f"{{{valTypes}}}\n" ) # Define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_ as: # `, {MIRType::Pointer, _I32, ..., MIRType::Pointer, _END}`. num_types = len(op["params"]) + 1 mir_types = "{MIRType::Pointer" mir_types += "".join(", " + specTypeToMIRType(p) for p in op["params"]) if op["uses_memory"]: mir_types += ", MIRType::Pointer" num_types += 1 # Add the end marker mir_types += ", MIRType::None}" contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_PARAM_MIRTYPES_{op['op']} {num_types}, {mir_types}\n" # Define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_ as: # `Some(X)` if present, or else `Nothing()`. result_valtype = "" if "result" in op: result_valtype = f"Some({specTypeToValType(op['result'])})\n" else: result_valtype = "Nothing()" contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_VALTYPE_{op['op']} {result_valtype}\n" # Define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_ as: # `X` if present, or else `MIRType::None`. result_mirtype = "" if "result" in op: result_mirtype = specTypeToMIRType(op["result"]) + "\n" else: result_mirtype = "MIRType::None" contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_RESULT_MIRTYPE_{op['op']} {result_mirtype}\n" # Define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_ as: # `FailureMode::X`. contents += f"#define DECLARE_BUILTIN_MODULE_FUNC_FAILMODE_{op['op']} FailureMode::{op['fail_mode']}\n" generate_header(c_out, "wasm_WasmBuiltinModuleGenerated_h", contents)