Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/asmjs/asm_v_wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
10 changes: 8 additions & 2 deletions src/emscripten-optimizer/optimizer-shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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;
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/emscripten-optimizer/optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum JsType {
JS_INT16X8,
JS_INT32X4,
JS_INT64,
JS_REF,
JS_NONE // number of types
};

Expand All @@ -51,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);

Expand Down
30 changes: 15 additions & 15 deletions src/wasm2js.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -2219,21 +2221,19 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
visit(curr->value, EXPRESSION_RESULT),
visit(curr->size, EXPRESSION_RESULT));
}
Ref visitRefNull(RefNull* curr) {
unimplemented(curr);
WASM_UNREACHABLE("unimp");
}
Ref visitRefNull(RefNull* curr) { return ValueBuilder::makeName("null"); }
Ref visitRefIsNull(RefIsNull* curr) {
unimplemented(curr);
WASM_UNREACHABLE("unimp");
return ValueBuilder::makeBinary(visit(curr->value, EXPRESSION_RESULT),
EQ,
ValueBuilder::makeName("null"));
}
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);
Expand Down
44 changes: 44 additions & 0 deletions test/wasm2js/refs.2asm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

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) {
return ref == null | 0;
}

function ref_func() {
var ref_func_1 = 0;
ref_func_1 = ref_func_1 + 1 | 0;
return ref_func;
}

function ref_eq(x, 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;
42 changes: 42 additions & 0 deletions test/wasm2js/refs.2asm.js.opt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

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) {
return $0 == null | 0;
}

function ref_func() {
return ref_func;
}

function ref_eq($0, $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;
33 changes: 33 additions & 0 deletions test/wasm2js/refs.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
(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)
;; 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)
)

(func $ref.eq (export "ref.eq") (param $x eqref) (param $y eqref) (result i32)
(ref.eq
(local.get $x)
(local.get $y)
)
)
)