Skip to content

Commit

Permalink
Bug 1721686 - wasm: Generate intrinsics boilerplate code via yaml. r=…
Browse files Browse the repository at this point in the history
…rhunt

Differential Revision: https://phabricator.services.mozilla.com/D120724
  • Loading branch information
yurydelendik committed Aug 30, 2021
1 parent 3aa3d28 commit ad2ffab
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 39 deletions.
1 change: 1 addition & 0 deletions config/check_spidermonkey_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
"unicode/utypes.h", # ICU
"unicode/uversion.h", # ICU
"vtune/VTuneWrapper.h", # VTune
"wasm/WasmIntrinsicGenerated.h", # generated in $OBJDIR"
"zydis/ZydisAPI.h", # Zydis
]
)
Expand Down
85 changes: 85 additions & 0 deletions js/src/wasm/GenerateIntrinsics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import buildconfig
import yaml
import six
from collections import OrderedDict
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/GenerateInstrinsic.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()

# Load into an OrderedDict to ensure order is preserved. Note: Python 3.7+
# also preserves ordering for normal dictionaries.
# Code based on https://stackoverflow.com/a/21912744.
class OrderedLoader(yaml.Loader):
pass

def construct_mapping(loader, node):
loader.flatten_mapping(node)
return OrderedDict(loader.construct_pairs(node))

tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG
OrderedLoader.add_constructor(tag, construct_mapping)
return yaml.load(contents, OrderedLoader)


def main(c_out, yaml_path):
data = load_yaml(yaml_path)

# Interate for all defined intrinsics
contents = "#define FOR_EACH_INTRINSIC(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']}, {i})\\\n"
)
contents += "\n"

for op in data:
# Define DECLARE_INTRINSIC_SAS_PARAM_VALTYPES_<op> as:
# `{ValType::I32, ValType::I32, ...}`.
contents += (
f"#define DECLARE_INTRINSIC_SAS_PARAM_VALTYPES_{op['op']} "
f"{{ValType::{', ValType::'.join(op['params'])}}}\n"
)
# Define DECLARE_INTRINSIC_PARAM_TYPES_<op> as:
# `<num_types>, {_PTR, _I32, ..., _PTR, _END}`.
sas_types = f"{{_PTR{''.join(', _' + p for p in op['params'])}, _PTR, _END}}"
num_types = len(op["params"]) + 2
contents += f"#define DECLARE_INTRINSIC_PARAM_TYPES_{op['op']} {num_types}, {sas_types}\n"

generate_header(c_out, "wasm_WasmIntrinsicGenerated_h", contents)
30 changes: 17 additions & 13 deletions js/src/wasm/WasmBuiltins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,13 @@ const SymbolicAddressSignature SASigRefTest = {
SymbolicAddress::RefTest, _I32, _Infallible, 3, {_PTR, _RoN, _RoN, _END}};
const SymbolicAddressSignature SASigRttSub = {
SymbolicAddress::RttSub, _RoN, _FailOnNullPtr, 3, {_PTR, _RoN, _RoN, _END}};
const SymbolicAddressSignature SASigIntrI8VecMul = {
SymbolicAddress::IntrI8VecMul,
_VOID,
_FailOnNegI32,
6,
{_PTR, _I32, _I32, _I32, _I32, _PTR, _END}};
#define DECL_SAS_FOR_INTRINSIC(op, export, sa_name, abitype, entry, idx) \
const SymbolicAddressSignature SASig##sa_name = { \
SymbolicAddress::sa_name, _VOID, _FailOnNegI32, \
DECLARE_INTRINSIC_PARAM_TYPES_##op};

FOR_EACH_INTRINSIC(DECL_SAS_FOR_INTRINSIC)
#undef DECL_SAS_FOR_INTRINSIC

} // namespace wasm
} // namespace js
Expand Down Expand Up @@ -1277,12 +1278,12 @@ void* wasm::AddressOf(SymbolicAddress imm, ABIFunctionType* abiType) {
*abiType = Args_General1;
return FuncCast(PrintText, *abiType);
#endif
case SymbolicAddress::IntrI8VecMul:
*abiType = MakeABIFunctionType(
ArgType_Int32, {ArgType_General, ArgType_Int32, ArgType_Int32,
ArgType_Int32, ArgType_Int32, ArgType_General});
MOZ_ASSERT(*abiType == ToABIType(SASigIntrI8VecMul));
return FuncCast(Instance::intrI8VecMul, *abiType);
#define DECL_SAS_TYPE_AND_FN(op, export, sa_name, abitype, entry, idx) \
case SymbolicAddress::sa_name: \
*abiType = abitype; \
return FuncCast(entry, *abiType);
FOR_EACH_INTRINSIC(DECL_SAS_TYPE_AND_FN)
#undef DECL_SAS_TYPE_AND_FN
case SymbolicAddress::Limit:
break;
}
Expand Down Expand Up @@ -1409,7 +1410,10 @@ bool wasm::NeedsBuiltinThunk(SymbolicAddress sym) {
case SymbolicAddress::ArrayNew:
case SymbolicAddress::RefTest:
case SymbolicAddress::RttSub:
case SymbolicAddress::IntrI8VecMul:
#define OP(op, export, sa_name, abitype, entry, idx) \
case SymbolicAddress::sa_name:
FOR_EACH_INTRINSIC(OP)
#undef OP
return true;
case SymbolicAddress::Limit:
break;
Expand Down
7 changes: 5 additions & 2 deletions js/src/wasm/WasmBuiltins.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define wasm_builtins_h

#include "jit/IonTypes.h"
#include "wasm/WasmIntrinsicGenerated.h"

namespace js {
namespace jit {
Expand Down Expand Up @@ -123,9 +124,11 @@ enum class SymbolicAddress {
#if defined(JS_CODEGEN_MIPS32)
js_jit_gAtomic64Lock,
#endif
IntrI8VecMul,
#define DECL_INTRINSIC_SA(op, export, sa_name, abitype, entry, idx) sa_name,
FOR_EACH_INTRINSIC(DECL_INTRINSIC_SA)
#undef DECL_INTRINSIC_SA
#ifdef WASM_CODEGEN_DEBUG
PrintI32,
PrintI32,
PrintPtr,
PrintF32,
PrintF64,
Expand Down
23 changes: 12 additions & 11 deletions js/src/wasm/WasmConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

#include <stdint.h>

#include "wasm/WasmIntrinsicGenerated.h"

namespace js {
namespace wasm {

Expand Down Expand Up @@ -939,17 +941,16 @@ enum class ThreadOp {
};

enum class IntrinsicOp {
// ------------------------------------------------------------------------
// These operators are emitted internally when compiling intrinsic modules
// and are rejected by wasm validation. They are prefixed by
// IntrinsicPrefix.

// i8vecmul(dest: i32, src1: i32, src2: i32, len: i32)
// Performs pairwise multiplication of two i8 vectors of 'len' specified at
// 'src1' and 'src2'. Output is written to 'dest'. This is used as a
// basic self-test for intrinsics.
I8VecMul = 0x0,

// ------------------------------------------------------------------------
// These operators are emitted internally when compiling intrinsic modules
// and are rejected by wasm validation. They are prefixed by
// IntrinsicPrefix. See wasm/WasmIntrinsic.yaml for the list.
#define DECL_INTRINSIC_OP(op, export, sa_name, abitype, entry, idx) \
op = idx, // NOLINT
FOR_EACH_INTRINSIC(DECL_INTRINSIC_OP)
#undef DECL_INTRINSIC_OP

// Op limit.
Limit
};

Expand Down
8 changes: 6 additions & 2 deletions js/src/wasm/WasmFrameIter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "vm/JSContext.h"
#include "wasm/WasmDebugFrame.h"
#include "wasm/WasmInstance.h"
#include "wasm/WasmIntrinsicGenerated.h"
#include "wasm/WasmStubs.h"
#include "wasm/WasmTlsData.h"

Expand Down Expand Up @@ -1527,8 +1528,11 @@ static const char* ThunkedNativeToDescription(SymbolicAddress func) {
case SymbolicAddress::js_jit_gAtomic64Lock:
MOZ_CRASH();
#endif
case SymbolicAddress::IntrI8VecMul:
return "call to native i8 vector multiplication intrinsic (in wasm)";
#define OP(op, export, sa_name, abitype, entry, idx) \
case SymbolicAddress::sa_name: \
return "call to native " #op " intrinsic (in wasm)";
FOR_EACH_INTRINSIC(OP)
#undef OP
#ifdef WASM_CODEGEN_DEBUG
case SymbolicAddress::PrintI32:
case SymbolicAddress::PrintPtr:
Expand Down
31 changes: 20 additions & 11 deletions js/src/wasm/WasmIntrinsic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "vm/GlobalObject.h"

#include "wasm/WasmGenerator.h"
#include "wasm/WasmIntrinsicGenerated.h"
#include "wasm/WasmJS.h"
#include "wasm/WasmModule.h"
#include "wasm/WasmOpIter.h"
Expand All @@ -30,13 +31,18 @@
using namespace js;
using namespace js::wasm;

static const ValType IntrinsicI8VecMul_Params[] = {ValType::I32, ValType::I32,
ValType::I32, ValType::I32};
const Intrinsic IntrinsicI8VecMul = {
"i8vecmul",
mozilla::Span<const ValType>(IntrinsicI8VecMul_Params),
SASigIntrI8VecMul,
};
#define INTR_DECL(op, export, sa_name, abitype, entry, idx) \
static const ValType Intrinsic##op##_Params[] = \
DECLARE_INTRINSIC_SAS_PARAM_VALTYPES_##op; \
\
const Intrinsic Intrinsic##op = { \
export, \
mozilla::Span<const ValType>(Intrinsic##op##_Params), \
SASig##sa_name, \
};

FOR_EACH_INTRINSIC(INTR_DECL)
#undef INTR_DECL

bool Intrinsic::funcType(FuncType* type) const {
ValTypeVector paramVec;
Expand All @@ -50,8 +56,11 @@ bool Intrinsic::funcType(FuncType* type) const {
/* static */
const Intrinsic& Intrinsic::getFromOp(IntrinsicOp op) {
switch (op) {
case IntrinsicOp::I8VecMul:
return IntrinsicI8VecMul;
#define OP(op, export, sa_name, abitype, entry, idx) \
case IntrinsicOp::op: \
return Intrinsic##op;
FOR_EACH_INTRINSIC(OP)
#undef OP
default:
MOZ_CRASH("unexpected intrinsic");
}
Expand Down Expand Up @@ -113,8 +122,8 @@ bool wasm::CompileIntrinsicModule(JSContext* cx,

// Add (type (func (params ...))) for each intrinsic. The function types will
// be deduplicated by the runtime
for (uint32_t funcIndex = 0; funcIndex < ops.size(); funcIndex++) {
const Intrinsic& intrinsic = Intrinsic::getFromOp(ops[funcIndex]);
for (const IntrinsicOp& op : ops) {
const Intrinsic& intrinsic = Intrinsic::getFromOp(op);

FuncType type;
if (!intrinsic.funcType(&type) ||
Expand Down
17 changes: 17 additions & 0 deletions js/src/wasm/WasmIntrinsic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# The file contains information need to define wasm intrinsic operations.

# i8vecmul(dest: i32, src1: i32, src2: i32, len: i32)
# Performs pairwise multiplication of two i8 vectors of 'len' specified at
# 'src1' and 'src2'. Output is written to 'dest'. This is used as a
# basic self-test for intrinsics.
- op: I8VecMul
symbolic_address:
name: IntrI8VecMul
type: Args_Int32_GeneralInt32Int32Int32Int32General
entry: Instance::intrI8VecMul
export: i8vecmul
params:
- I32
- I32
- I32
- I32
7 changes: 7 additions & 0 deletions js/src/wasm/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ UNIFIED_SOURCES += [
"WasmValue.cpp",
]

# Generate wasm/WasmIntrinsicGenerated.h from wasm/WasmIntrinsic.yaml
GeneratedFile(
"WasmIntrinsicGenerated.h",
script="GenerateIntrinsics.py",
inputs=["WasmIntrinsic.yaml"],
)

# We don't support signals for wasi yet.
if CONFIG["OS_ARCH"] != "WASI":
UNIFIED_SOURCES += ["WasmSignalHandlers.cpp"]
Expand Down

0 comments on commit ad2ffab

Please sign in to comment.