Skip to content

Commit 0a1a59a

Browse files
authored
wasm2js: Add basic reference operations (#6648)
This adds ref.eq, ref.null, ref.is_null, ref.func.
1 parent 76d1ac3 commit 0a1a59a

7 files changed

Lines changed: 148 additions & 17 deletions

File tree

src/asmjs/asm_v_wasm.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
namespace wasm {
2222

2323
JsType wasmToJsType(Type type) {
24+
if (type.isRef()) {
25+
return JS_REF;
26+
}
27+
2428
TODO_SINGLE_COMPOUND(type);
2529
switch (type.getBasic()) {
2630
case Type::i32:

src/emscripten-optimizer/optimizer-shared.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ Ref makeJsCoercedZero(JsType type) {
104104
abort();
105105
}
106106

107+
bool needsJsCoercion(JsType type) {
108+
// References need no coercion, but everything else does.
109+
return type != JS_REF;
110+
}
111+
107112
Ref makeJsCoercion(Ref node, JsType type) {
108113
switch (type) {
109114
case JS_INT:
@@ -122,10 +127,11 @@ Ref makeJsCoercion(Ref node, JsType type) {
122127
return ValueBuilder::makeCall(SIMD_INT16X8_CHECK, node);
123128
case JS_INT32X4:
124129
return ValueBuilder::makeCall(SIMD_INT32X4_CHECK, node);
130+
case JS_REF:
125131
case JS_NONE:
126132
default:
127-
// non-validating code, emit nothing XXX this is dangerous, we should only
128-
// allow this when we know we are not validating
133+
// No coercion is needed.
134+
// TODO see if JS_NONE is actually used here.
129135
return node;
130136
}
131137
}

src/emscripten-optimizer/optimizer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ enum JsType {
3939
JS_INT16X8,
4040
JS_INT32X4,
4141
JS_INT64,
42+
JS_REF,
4243
JS_NONE // number of types
4344
};
4445

@@ -51,6 +52,7 @@ enum JsSign {
5152
};
5253

5354
cashew::Ref makeJsCoercedZero(JsType type);
55+
bool needsJsCoercion(JsType type);
5456
cashew::Ref makeJsCoercion(cashew::Ref node, JsType type);
5557
cashew::Ref makeSigning(cashew::Ref node, JsSign sign);
5658

src/wasm2js.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -921,11 +921,13 @@ Ref Wasm2JSBuilder::processFunction(Module* m,
921921
IString name = fromName(func->getLocalNameOrGeneric(i), NameScope::Local);
922922
ValueBuilder::appendArgumentToFunction(ret, name);
923923
if (needCoercions) {
924-
ret[3]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeBinary(
925-
ValueBuilder::makeName(name),
926-
SET,
927-
makeJsCoercion(ValueBuilder::makeName(name),
928-
wasmToJsType(func->getLocalType(i))))));
924+
auto jsType = wasmToJsType(func->getLocalType(i));
925+
if (needsJsCoercion(jsType)) {
926+
ret[3]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeBinary(
927+
ValueBuilder::makeName(name),
928+
SET,
929+
makeJsCoercion(ValueBuilder::makeName(name), jsType))));
930+
}
929931
}
930932
}
931933
Ref theVar = ValueBuilder::makeVar();
@@ -2219,21 +2221,19 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
22192221
visit(curr->value, EXPRESSION_RESULT),
22202222
visit(curr->size, EXPRESSION_RESULT));
22212223
}
2222-
Ref visitRefNull(RefNull* curr) {
2223-
unimplemented(curr);
2224-
WASM_UNREACHABLE("unimp");
2225-
}
2224+
Ref visitRefNull(RefNull* curr) { return ValueBuilder::makeName("null"); }
22262225
Ref visitRefIsNull(RefIsNull* curr) {
2227-
unimplemented(curr);
2228-
WASM_UNREACHABLE("unimp");
2226+
return ValueBuilder::makeBinary(visit(curr->value, EXPRESSION_RESULT),
2227+
EQ,
2228+
ValueBuilder::makeName("null"));
22292229
}
22302230
Ref visitRefFunc(RefFunc* curr) {
2231-
unimplemented(curr);
2232-
WASM_UNREACHABLE("unimp");
2231+
return ValueBuilder::makeName(fromName(curr->func, NameScope::Top));
22332232
}
22342233
Ref visitRefEq(RefEq* curr) {
2235-
unimplemented(curr);
2236-
WASM_UNREACHABLE("unimp");
2234+
return ValueBuilder::makeBinary(visit(curr->left, EXPRESSION_RESULT),
2235+
EQ,
2236+
visit(curr->right, EXPRESSION_RESULT));
22372237
}
22382238
Ref visitTableGet(TableGet* curr) {
22392239
unimplemented(curr);

test/wasm2js/refs.2asm.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
function asmFunc(imports) {
3+
var Math_imul = Math.imul;
4+
var Math_fround = Math.fround;
5+
var Math_abs = Math.abs;
6+
var Math_clz32 = Math.clz32;
7+
var Math_min = Math.min;
8+
var Math_max = Math.max;
9+
var Math_floor = Math.floor;
10+
var Math_ceil = Math.ceil;
11+
var Math_trunc = Math.trunc;
12+
var Math_sqrt = Math.sqrt;
13+
function null_() {
14+
return null;
15+
}
16+
17+
function is_null(ref) {
18+
return ref == null | 0;
19+
}
20+
21+
function ref_func() {
22+
var ref_func_1 = 0;
23+
ref_func_1 = ref_func_1 + 1 | 0;
24+
return ref_func;
25+
}
26+
27+
function ref_eq(x, y) {
28+
return x == y | 0;
29+
}
30+
31+
return {
32+
"null_": null_,
33+
"is_null": is_null,
34+
"ref_func": ref_func,
35+
"ref_eq": ref_eq
36+
};
37+
}
38+
39+
var retasmFunc = asmFunc({
40+
});
41+
export var null_ = retasmFunc.null_;
42+
export var is_null = retasmFunc.is_null;
43+
export var ref_func = retasmFunc.ref_func;
44+
export var ref_eq = retasmFunc.ref_eq;

test/wasm2js/refs.2asm.js.opt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
function asmFunc(imports) {
3+
var Math_imul = Math.imul;
4+
var Math_fround = Math.fround;
5+
var Math_abs = Math.abs;
6+
var Math_clz32 = Math.clz32;
7+
var Math_min = Math.min;
8+
var Math_max = Math.max;
9+
var Math_floor = Math.floor;
10+
var Math_ceil = Math.ceil;
11+
var Math_trunc = Math.trunc;
12+
var Math_sqrt = Math.sqrt;
13+
function null_() {
14+
return null;
15+
}
16+
17+
function is_null($0) {
18+
return $0 == null | 0;
19+
}
20+
21+
function ref_func() {
22+
return ref_func;
23+
}
24+
25+
function ref_eq($0, $1) {
26+
return $0 == $1 | 0;
27+
}
28+
29+
return {
30+
"null_": null_,
31+
"is_null": is_null,
32+
"ref_func": ref_func,
33+
"ref_eq": ref_eq
34+
};
35+
}
36+
37+
var retasmFunc = asmFunc({
38+
});
39+
export var null_ = retasmFunc.null_;
40+
export var is_null = retasmFunc.is_null;
41+
export var ref_func = retasmFunc.ref_func;
42+
export var ref_eq = retasmFunc.ref_eq;

test/wasm2js/refs.wast

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
(module
2+
(func $null (export "null") (result anyref)
3+
(ref.null any)
4+
)
5+
6+
(func $is_null (export "is_null") (param $ref anyref) (result i32)
7+
(ref.is_null
8+
(local.get $ref)
9+
)
10+
)
11+
12+
(func $ref.func (export "ref.func") (result funcref)
13+
;; Test that we are aware that "$ref.func" below refers to the function and
14+
;; not the local. This code will keep the local around (at least in an
15+
;; unoptimized build), and it should use a different name than the function.
16+
(local $ref.func i32)
17+
(local.set $ref.func
18+
(i32.add
19+
(local.get $ref.func)
20+
(i32.const 1)
21+
)
22+
)
23+
24+
(ref.func $ref.func)
25+
)
26+
27+
(func $ref.eq (export "ref.eq") (param $x eqref) (param $y eqref) (result i32)
28+
(ref.eq
29+
(local.get $x)
30+
(local.get $y)
31+
)
32+
)
33+
)

0 commit comments

Comments
 (0)