summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-06-12 14:25:50 -0700
committerGitHub <noreply@github.com>2024-06-12 21:25:50 +0000
commit34686197f5a05854c0723214f3fdffbc9b19a7d5 (patch)
tree65b0750b174e29bba39b92289135b6887ba5b425
parent0e1187664ebf93bd268ba7d77813441a4874d998 (diff)
downloadbinaryen-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.cpp12
-rw-r--r--src/wasm2js.h46
-rw-r--r--test/wasm2js/refs.2asm.js20
-rw-r--r--test/wasm2js/refs.2asm.js.opt20
-rw-r--r--test/wasm2js/refs.wast19
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)
+ )
)