diff options
author | Alon Zakai <azakai@google.com> | 2024-06-12 14:25:50 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-12 21:25:50 +0000 |
commit | 34686197f5a05854c0723214f3fdffbc9b19a7d5 (patch) | |
tree | 65b0750b174e29bba39b92289135b6887ba5b425 | |
parent | 0e1187664ebf93bd268ba7d77813441a4874d998 (diff) | |
download | binaryen-34686197f5a05854c0723214f3fdffbc9b19a7d5.tar.gz binaryen-34686197f5a05854c0723214f3fdffbc9b19a7d5.tar.bz2 binaryen-34686197f5a05854c0723214f3fdffbc9b19a7d5.zip |
wasm2js: Fix null handling and RefAsNonNull (#6656)
-rw-r--r-- | src/emscripten-optimizer/optimizer-shared.cpp | 12 | ||||
-rw-r--r-- | src/wasm2js.h | 46 | ||||
-rw-r--r-- | test/wasm2js/refs.2asm.js | 20 | ||||
-rw-r--r-- | test/wasm2js/refs.2asm.js.opt | 20 | ||||
-rw-r--r-- | test/wasm2js/refs.wast | 19 |
5 files changed, 88 insertions, 29 deletions
diff --git a/src/emscripten-optimizer/optimizer-shared.cpp b/src/emscripten-optimizer/optimizer-shared.cpp index 773c5d9fc..f4482aa09 100644 --- a/src/emscripten-optimizer/optimizer-shared.cpp +++ b/src/emscripten-optimizer/optimizer-shared.cpp @@ -17,6 +17,7 @@ #include <limits> #include "optimizer.h" +#include "shared-constants.h" #include "support/safe_integer.h" using namespace cashew; @@ -33,17 +34,14 @@ Ref makeJsCoercedZero(JsType type) { switch (type) { case JS_INT: return ValueBuilder::makeNum(0); - break; case JS_DOUBLE: return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeNum(0)); - break; case JS_FLOAT: { if (!JS_FLOAT_ZERO.isNull()) { return ValueBuilder::makeName(JS_FLOAT_ZERO); } else { return ValueBuilder::makeCall(MATH_FROUND, ValueBuilder::makeNum(0)); } - break; } case JS_FLOAT32X4: { return ValueBuilder::makeCall(SIMD_FLOAT32X4, @@ -51,12 +49,10 @@ Ref makeJsCoercedZero(JsType type) { ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); - break; } case JS_FLOAT64X2: { return ValueBuilder::makeCall( SIMD_FLOAT64X2, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); - break; } case JS_INT8X16: { return ValueBuilder::makeCall(SIMD_INT8X16, @@ -76,7 +72,6 @@ Ref makeJsCoercedZero(JsType type) { ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); - break; } case JS_INT16X8: { return ValueBuilder::makeCall(SIMD_INT16X8, @@ -88,7 +83,6 @@ Ref makeJsCoercedZero(JsType type) { ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); - break; } case JS_INT32X4: { return ValueBuilder::makeCall(SIMD_INT32X4, @@ -96,7 +90,9 @@ Ref makeJsCoercedZero(JsType type) { ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); - break; + } + case JS_REF: { + return ValueBuilder::makeName(wasm::NULL_); } default: assert(0); diff --git a/src/wasm2js.h b/src/wasm2js.h index dd4e61a51..034212b79 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -846,44 +846,45 @@ void Wasm2JSBuilder::addExports(Ref ast, Module* wasm) { } void Wasm2JSBuilder::addGlobal(Ref ast, Global* global) { - if (auto* const_ = global->init->dynCast<Const>()) { - Ref theValue; + Ref theVar = ValueBuilder::makeVar(); + ast->push_back(theVar); + + auto* init = global->init; + Ref value; + + if (auto* const_ = init->dynCast<Const>()) { TODO_SINGLE_COMPOUND(const_->type); switch (const_->type.getBasic()) { case Type::i32: { - theValue = ValueBuilder::makeInt(const_->value.geti32()); + value = ValueBuilder::makeInt(const_->value.geti32()); break; } case Type::f32: { - theValue = ValueBuilder::makeCall( + value = ValueBuilder::makeCall( MATH_FROUND, makeJsCoercion(ValueBuilder::makeDouble(const_->value.getf32()), JS_DOUBLE)); break; } case Type::f64: { - theValue = makeJsCoercion( - ValueBuilder::makeDouble(const_->value.getf64()), JS_DOUBLE); + value = makeJsCoercion(ValueBuilder::makeDouble(const_->value.getf64()), + JS_DOUBLE); break; } default: { assert(false && "Top const type not supported"); } } - Ref theVar = ValueBuilder::makeVar(); - ast->push_back(theVar); - ValueBuilder::appendToVar( - theVar, fromName(global->name, NameScope::Top), theValue); - } else if (auto* get = global->init->dynCast<GlobalGet>()) { - Ref theVar = ValueBuilder::makeVar(); - ast->push_back(theVar); - ValueBuilder::appendToVar( - theVar, - fromName(global->name, NameScope::Top), - ValueBuilder::makeName(fromName(get->name, NameScope::Top))); + } else if (auto* get = init->dynCast<GlobalGet>()) { + value = ValueBuilder::makeName(fromName(get->name, NameScope::Top)); + } else if (init->is<RefNull>()) { + value = ValueBuilder::makeName(NULL_); } else { assert(false && "Top init type not supported"); } + + ValueBuilder::appendToVar( + theVar, fromName(global->name, NameScope::Top), value); } Ref Wasm2JSBuilder::processFunction(Module* m, @@ -2415,8 +2416,15 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, WASM_UNREACHABLE("unimp"); } Ref visitRefAs(RefAs* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); + // TODO: support others + assert(curr->op == RefAsNonNull); + + // value || trap() + ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::TRAP); + return ValueBuilder::makeBinary( + visit(curr->value, EXPRESSION_RESULT), + IString("||"), + ValueBuilder::makeCall(ABI::wasm2js::TRAP)); } Ref visitContBind(ContBind* curr) { diff --git a/test/wasm2js/refs.2asm.js b/test/wasm2js/refs.2asm.js index 0133159b9..f538df6d6 100644 --- a/test/wasm2js/refs.2asm.js +++ b/test/wasm2js/refs.2asm.js @@ -1,4 +1,6 @@ +function wasm2js_trap() { throw new Error('abort'); } + function asmFunc(imports) { var Math_imul = Math.imul; var Math_fround = Math.fround; @@ -10,6 +12,7 @@ function asmFunc(imports) { var Math_ceil = Math.ceil; var Math_trunc = Math.trunc; var Math_sqrt = Math.sqrt; + var global = null; function null_() { return null; } @@ -28,11 +31,24 @@ function asmFunc(imports) { return x == y | 0; } + function ref_as(x) { + return x || wasm2js_trap(); + } + + function use_global(x) { + var temp = null; + temp = global; + global = x; + return temp; + } + return { "null_": null_, "is_null": is_null, "ref_func": ref_func, - "ref_eq": ref_eq + "ref_eq": ref_eq, + "ref_as": ref_as, + "use_global": use_global }; } @@ -42,3 +58,5 @@ 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; +export var ref_as = retasmFunc.ref_as; +export var use_global = retasmFunc.use_global; diff --git a/test/wasm2js/refs.2asm.js.opt b/test/wasm2js/refs.2asm.js.opt index e38afe1cf..251e63475 100644 --- a/test/wasm2js/refs.2asm.js.opt +++ b/test/wasm2js/refs.2asm.js.opt @@ -1,4 +1,6 @@ +function wasm2js_trap() { throw new Error('abort'); } + function asmFunc(imports) { var Math_imul = Math.imul; var Math_fround = Math.fround; @@ -10,6 +12,7 @@ function asmFunc(imports) { var Math_ceil = Math.ceil; var Math_trunc = Math.trunc; var Math_sqrt = Math.sqrt; + var global = null; function null_() { return null; } @@ -26,11 +29,24 @@ function asmFunc(imports) { return $0 == $1 | 0; } + function ref_as($0) { + return $0 || wasm2js_trap(); + } + + function use_global($0) { + var $1 = null; + $1 = global; + global = $0; + return $1; + } + return { "null_": null_, "is_null": is_null, "ref_func": ref_func, - "ref_eq": ref_eq + "ref_eq": ref_eq, + "ref_as": ref_as, + "use_global": use_global }; } @@ -40,3 +56,5 @@ 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; +export var ref_as = retasmFunc.ref_as; +export var use_global = retasmFunc.use_global; diff --git a/test/wasm2js/refs.wast b/test/wasm2js/refs.wast index 4e133c03e..964d0a60c 100644 --- a/test/wasm2js/refs.wast +++ b/test/wasm2js/refs.wast @@ -1,4 +1,6 @@ (module + (global $global (mut anyref) (ref.null any)) + (func $null (export "null") (result anyref) (ref.null any) ) @@ -30,4 +32,21 @@ (local.get $y) ) ) + + (func $ref.as (export "ref.as") (param $x anyref) (result anyref) + (ref.as_non_null + (local.get $x) + ) + ) + + (func $use-global (export "use-global") (param $x anyref) (result anyref) + (local $temp anyref) + (local.set $temp + (global.get $global) + ) + (global.set $global + (local.get $x) + ) + (local.get $temp) + ) ) |