From 1b43915a939169dd914b127f0da6d368ed7c79db Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 10 Jun 2024 12:58:48 -0700 Subject: [PATCH 1/6] start --- src/emscripten-optimizer/simple_ast.h | 2 +- src/wasm2js.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h index aed6499d5a6..2b145eb569a 100644 --- a/src/emscripten-optimizer/simple_ast.h +++ b/src/emscripten-optimizer/simple_ast.h @@ -1521,9 +1521,9 @@ class ValueBuilder { return &arena.alloc()->setString(s); } +public: static Ref makeNull() { return &arena.alloc()->setNull(); } -public: static Ref makeRawArray(int size_hint = 0) { return &arena.alloc()->setArray(size_hint); } diff --git a/src/wasm2js.h b/src/wasm2js.h index 7540bd71ac2..5e239b79a83 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2220,20 +2220,20 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, visit(curr->size, EXPRESSION_RESULT)); } Ref visitRefNull(RefNull* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); + return ValueBuilder::makeNull(); } Ref visitRefIsNull(RefIsNull* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); + return ValueBuilder::makeBinary(visit(curr->value, EXPRESSION_RESULT), + EQ, + ValueBuilder::makeNull()); } Ref visitRefFunc(RefFunc* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); + return ValueBuilder::makeName(fromName(curr->func, NameScope::Top)); } Ref visitRefEq(RefEq* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); + return ValueBuilder::makeBinary(visit(curr->left, EXPRESSION_RESULT), + EQ, + visit(curr->right, EXPRESSION_RESULT)); } Ref visitTableGet(TableGet* curr) { unimplemented(curr); From f7492f3f30a3d6f0b060d9a64d80133e16a609dd Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 10 Jun 2024 13:05:58 -0700 Subject: [PATCH 2/6] work --- src/asmjs/asm_v_wasm.cpp | 4 ++++ src/emscripten-optimizer/optimizer.h | 1 + test/wasm2js/refs.wast | 22 ++++++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 test/wasm2js/refs.wast diff --git a/src/asmjs/asm_v_wasm.cpp b/src/asmjs/asm_v_wasm.cpp index 314c2494ff6..bbbaad5bc59 100644 --- a/src/asmjs/asm_v_wasm.cpp +++ b/src/asmjs/asm_v_wasm.cpp @@ -21,6 +21,10 @@ namespace wasm { JsType wasmToJsType(Type type) { + if (type.isRef()) { + return JS_REF; + } + TODO_SINGLE_COMPOUND(type); switch (type.getBasic()) { case Type::i32: diff --git a/src/emscripten-optimizer/optimizer.h b/src/emscripten-optimizer/optimizer.h index a27fe25ebff..1494797dfca 100644 --- a/src/emscripten-optimizer/optimizer.h +++ b/src/emscripten-optimizer/optimizer.h @@ -39,6 +39,7 @@ enum JsType { JS_INT16X8, JS_INT32X4, JS_INT64, + JS_REF, JS_NONE // number of types }; diff --git a/test/wasm2js/refs.wast b/test/wasm2js/refs.wast new file mode 100644 index 00000000000..2db4feffd73 --- /dev/null +++ b/test/wasm2js/refs.wast @@ -0,0 +1,22 @@ +(module + (func $null (export "null") (result anyref) + (ref.null any) + ) + + (func $is_null (export "is_null") (param $ref anyref) (result i32) + (ref.is_null + (local.get $ref) + ) + ) + + (func $ref.func (export "ref.func") (result funcref) + (ref.func $ref.func) + ) + + (func $ref.eq (export "ref.eq") (param $x eqref) (param $y eqref) (result i32) + (ref.eq + (local.get $x) + (local.get $y) + ) + ) +) From d17bf8a9f255273fdc47db49426f6e410093e53e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 10 Jun 2024 13:20:20 -0700 Subject: [PATCH 3/6] more --- src/emscripten-optimizer/simple_ast.h | 2 +- src/wasm2js.h | 4 +-- test/wasm2js/refs.2asm.js | 45 +++++++++++++++++++++++++++ test/wasm2js/refs.2asm.js.opt | 45 +++++++++++++++++++++++++++ test/wasm2js/refs.wast | 1 + 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 test/wasm2js/refs.2asm.js create mode 100644 test/wasm2js/refs.2asm.js.opt diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h index 2b145eb569a..aed6499d5a6 100644 --- a/src/emscripten-optimizer/simple_ast.h +++ b/src/emscripten-optimizer/simple_ast.h @@ -1521,9 +1521,9 @@ class ValueBuilder { return &arena.alloc()->setString(s); } -public: static Ref makeNull() { return &arena.alloc()->setNull(); } +public: static Ref makeRawArray(int size_hint = 0) { return &arena.alloc()->setArray(size_hint); } diff --git a/src/wasm2js.h b/src/wasm2js.h index 5e239b79a83..669f89729f4 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2220,12 +2220,12 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, visit(curr->size, EXPRESSION_RESULT)); } Ref visitRefNull(RefNull* curr) { - return ValueBuilder::makeNull(); + return ValueBuilder::makeName("null"); } Ref visitRefIsNull(RefIsNull* curr) { return ValueBuilder::makeBinary(visit(curr->value, EXPRESSION_RESULT), EQ, - ValueBuilder::makeNull()); + ValueBuilder::makeName("null")); } Ref visitRefFunc(RefFunc* curr) { return ValueBuilder::makeName(fromName(curr->func, NameScope::Top)); diff --git a/test/wasm2js/refs.2asm.js b/test/wasm2js/refs.2asm.js new file mode 100644 index 00000000000..5185979282c --- /dev/null +++ b/test/wasm2js/refs.2asm.js @@ -0,0 +1,45 @@ + +function asmFunc(imports) { + var Math_imul = Math.imul; + var Math_fround = Math.fround; + var Math_abs = Math.abs; + var Math_clz32 = Math.clz32; + var Math_min = Math.min; + var Math_max = Math.max; + var Math_floor = Math.floor; + var Math_ceil = Math.ceil; + var Math_trunc = Math.trunc; + var Math_sqrt = Math.sqrt; + function null_() { + return null; + } + + function is_null(ref) { + ref = ref; + return ref == null | 0; + } + + function ref_func() { + return ref_func; + } + + function ref_eq(x, y) { + x = x; + y = y; + return x == y | 0; + } + + return { + "null_": null_, + "is_null": is_null, + "ref_func": ref_func, + "ref_eq": ref_eq + }; +} + +var retasmFunc = asmFunc({ +}); +export var null_ = retasmFunc.null_; +export var is_null = retasmFunc.is_null; +export var ref_func = retasmFunc.ref_func; +export var ref_eq = retasmFunc.ref_eq; diff --git a/test/wasm2js/refs.2asm.js.opt b/test/wasm2js/refs.2asm.js.opt new file mode 100644 index 00000000000..d5072095584 --- /dev/null +++ b/test/wasm2js/refs.2asm.js.opt @@ -0,0 +1,45 @@ + +function asmFunc(imports) { + var Math_imul = Math.imul; + var Math_fround = Math.fround; + var Math_abs = Math.abs; + var Math_clz32 = Math.clz32; + var Math_min = Math.min; + var Math_max = Math.max; + var Math_floor = Math.floor; + var Math_ceil = Math.ceil; + var Math_trunc = Math.trunc; + var Math_sqrt = Math.sqrt; + function null_() { + return null; + } + + function is_null($0) { + $0 = $0; + return $0 == null | 0; + } + + function ref_func() { + return ref_func; + } + + function ref_eq($0, $1) { + $0 = $0; + $1 = $1; + return $0 == $1 | 0; + } + + return { + "null_": null_, + "is_null": is_null, + "ref_func": ref_func, + "ref_eq": ref_eq + }; +} + +var retasmFunc = asmFunc({ +}); +export var null_ = retasmFunc.null_; +export var is_null = retasmFunc.is_null; +export var ref_func = retasmFunc.ref_func; +export var ref_eq = retasmFunc.ref_eq; diff --git a/test/wasm2js/refs.wast b/test/wasm2js/refs.wast index 2db4feffd73..9eacbb0df8f 100644 --- a/test/wasm2js/refs.wast +++ b/test/wasm2js/refs.wast @@ -10,6 +10,7 @@ ) (func $ref.func (export "ref.func") (result funcref) + (local $ref.func i32) ;; test for scope confusion (ref.func $ref.func) ) From d194ec7d65f370f67be0f3e3b833e5a51cf488a5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 10 Jun 2024 13:23:43 -0700 Subject: [PATCH 4/6] work --- test/wasm2js/refs.2asm.js | 2 ++ test/wasm2js/refs.wast | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/test/wasm2js/refs.2asm.js b/test/wasm2js/refs.2asm.js index 5185979282c..d904f8a8b2d 100644 --- a/test/wasm2js/refs.2asm.js +++ b/test/wasm2js/refs.2asm.js @@ -20,6 +20,8 @@ function asmFunc(imports) { } function ref_func() { + var ref_func_1 = 0; + ref_func_1 = ref_func_1 + 1 | 0; return ref_func; } diff --git a/test/wasm2js/refs.wast b/test/wasm2js/refs.wast index 9eacbb0df8f..4e133c03efe 100644 --- a/test/wasm2js/refs.wast +++ b/test/wasm2js/refs.wast @@ -10,7 +10,17 @@ ) (func $ref.func (export "ref.func") (result funcref) - (local $ref.func i32) ;; test for scope confusion + ;; Test that we are aware that "$ref.func" below refers to the function and + ;; not the local. This code will keep the local around (at least in an + ;; unoptimized build), and it should use a different name than the function. + (local $ref.func i32) + (local.set $ref.func + (i32.add + (local.get $ref.func) + (i32.const 1) + ) + ) + (ref.func $ref.func) ) From 78be2771587c5feed49629f24d79114ebe1f915e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 10 Jun 2024 13:29:14 -0700 Subject: [PATCH 5/6] work --- src/emscripten-optimizer/optimizer-shared.cpp | 10 ++++++++-- src/emscripten-optimizer/optimizer.h | 1 + src/wasm2js.h | 12 +++++++----- test/wasm2js/refs.2asm.js | 3 --- test/wasm2js/refs.2asm.js.opt | 3 --- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/emscripten-optimizer/optimizer-shared.cpp b/src/emscripten-optimizer/optimizer-shared.cpp index 8208f6f47ed..773c5d9fc27 100644 --- a/src/emscripten-optimizer/optimizer-shared.cpp +++ b/src/emscripten-optimizer/optimizer-shared.cpp @@ -104,6 +104,11 @@ Ref makeJsCoercedZero(JsType type) { abort(); } +bool needsJsCoercion(JsType type) { + // References need no coercion, but everything else does. + return type != JS_REF; +} + Ref makeJsCoercion(Ref node, JsType type) { switch (type) { case JS_INT: @@ -122,10 +127,11 @@ Ref makeJsCoercion(Ref node, JsType type) { return ValueBuilder::makeCall(SIMD_INT16X8_CHECK, node); case JS_INT32X4: return ValueBuilder::makeCall(SIMD_INT32X4_CHECK, node); + case JS_REF: case JS_NONE: default: - // non-validating code, emit nothing XXX this is dangerous, we should only - // allow this when we know we are not validating + // No coercion is needed. + // TODO see if JS_NONE is actually used here. return node; } } diff --git a/src/emscripten-optimizer/optimizer.h b/src/emscripten-optimizer/optimizer.h index 1494797dfca..6347c194c06 100644 --- a/src/emscripten-optimizer/optimizer.h +++ b/src/emscripten-optimizer/optimizer.h @@ -52,6 +52,7 @@ enum JsSign { }; cashew::Ref makeJsCoercedZero(JsType type); +bool needsJsCoercion(JsType type); cashew::Ref makeJsCoercion(cashew::Ref node, JsType type); cashew::Ref makeSigning(cashew::Ref node, JsSign sign); diff --git a/src/wasm2js.h b/src/wasm2js.h index 669f89729f4..43e7c52f7f8 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -921,11 +921,13 @@ Ref Wasm2JSBuilder::processFunction(Module* m, IString name = fromName(func->getLocalNameOrGeneric(i), NameScope::Local); ValueBuilder::appendArgumentToFunction(ret, name); if (needCoercions) { - ret[3]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeBinary( - ValueBuilder::makeName(name), - SET, - makeJsCoercion(ValueBuilder::makeName(name), - wasmToJsType(func->getLocalType(i)))))); + auto jsType = wasmToJsType(func->getLocalType(i)); + if (needsJsCoercion(jsType)) { + ret[3]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeBinary( + ValueBuilder::makeName(name), + SET, + makeJsCoercion(ValueBuilder::makeName(name), jsType)))); + } } } Ref theVar = ValueBuilder::makeVar(); diff --git a/test/wasm2js/refs.2asm.js b/test/wasm2js/refs.2asm.js index d904f8a8b2d..0133159b9e9 100644 --- a/test/wasm2js/refs.2asm.js +++ b/test/wasm2js/refs.2asm.js @@ -15,7 +15,6 @@ function asmFunc(imports) { } function is_null(ref) { - ref = ref; return ref == null | 0; } @@ -26,8 +25,6 @@ function asmFunc(imports) { } function ref_eq(x, y) { - x = x; - y = y; return x == y | 0; } diff --git a/test/wasm2js/refs.2asm.js.opt b/test/wasm2js/refs.2asm.js.opt index d5072095584..e38afe1cf6f 100644 --- a/test/wasm2js/refs.2asm.js.opt +++ b/test/wasm2js/refs.2asm.js.opt @@ -15,7 +15,6 @@ function asmFunc(imports) { } function is_null($0) { - $0 = $0; return $0 == null | 0; } @@ -24,8 +23,6 @@ function asmFunc(imports) { } function ref_eq($0, $1) { - $0 = $0; - $1 = $1; return $0 == $1 | 0; } From 1ead8cf12d5ef0eb6391769bb83b67607eda6f59 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 10 Jun 2024 13:29:29 -0700 Subject: [PATCH 6/6] format --- src/wasm2js.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/wasm2js.h b/src/wasm2js.h index 43e7c52f7f8..2084c04537c 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2221,9 +2221,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, visit(curr->value, EXPRESSION_RESULT), visit(curr->size, EXPRESSION_RESULT)); } - Ref visitRefNull(RefNull* curr) { - return ValueBuilder::makeName("null"); - } + Ref visitRefNull(RefNull* curr) { return ValueBuilder::makeName("null"); } Ref visitRefIsNull(RefIsNull* curr) { return ValueBuilder::makeBinary(visit(curr->value, EXPRESSION_RESULT), EQ,