summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm2js.h17
-rw-r--r--test/wasm2js/emscripten.2asm.js2
-rw-r--r--test/wasm2js/func-ptr-offset.2asm.js2
-rw-r--r--test/wasm2js/func-ptr-offset.2asm.js.opt2
-rw-r--r--test/wasm2js/func_ptrs.2asm.js6
-rw-r--r--test/wasm2js/indirect-select.2asm.js43
-rw-r--r--test/wasm2js/indirect-select.2asm.js.opt43
-rw-r--r--test/wasm2js/indirect-select.wast22
-rw-r--r--test/wasm2js/left-to-right.2asm.js8
-rw-r--r--test/wasm2js/ordering.2asm.js8
10 files changed, 135 insertions, 18 deletions
diff --git a/src/wasm2js.h b/src/wasm2js.h
index 3accfad75..33f70a4fc 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -1146,6 +1146,14 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
}
}
}
+ // Ensure the function pointer is a number. In general in wasm2js we are
+ // ok with true/false being present, as they are immediately cast to a
+ // number anyhow on their use. However, FUNCTION_TABLE[true] is *not* the
+ // same as FUNCTION_TABLE[1], so we must cast. This is a rare exception
+ // because FUNCTION_TABLE is just a normal JS object, not a typed array
+ // or a mathematical operation (all of which coerce to a number for us).
+ auto target = visit(curr->target, EXPRESSION_RESULT);
+ target = makeAsmCoercion(target, ASM_INT);
if (mustReorder) {
Ref ret;
ScopedTemp idx(Type::i32, parent, func);
@@ -1155,7 +1163,9 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
IString temp = temps.back()->temp;
sequenceAppend(ret, visitAndAssign(operand, temp));
}
- sequenceAppend(ret, visitAndAssign(curr->target, idx));
+ sequenceAppend(ret,
+ ValueBuilder::makeBinary(
+ ValueBuilder::makeName(idx.getName()), SET, target));
Ref theCall = ValueBuilder::makeCall(ValueBuilder::makeSub(
ValueBuilder::makeName(FUNCTION_TABLE), idx.getAstName()));
for (size_t i = 0; i < temps.size(); i++) {
@@ -1172,9 +1182,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
return ret;
} else {
// Target has no side effects, emit simple code
- Ref theCall = ValueBuilder::makeCall(
- ValueBuilder::makeSub(ValueBuilder::makeName(FUNCTION_TABLE),
- visit(curr->target, EXPRESSION_RESULT)));
+ Ref theCall = ValueBuilder::makeCall(ValueBuilder::makeSub(
+ ValueBuilder::makeName(FUNCTION_TABLE), target));
for (auto* operand : curr->operands) {
theCall[2]->push_back(visit(operand, EXPRESSION_RESULT));
}
diff --git a/test/wasm2js/emscripten.2asm.js b/test/wasm2js/emscripten.2asm.js
index a595eb151..6f1d19bce 100644
--- a/test/wasm2js/emscripten.2asm.js
+++ b/test/wasm2js/emscripten.2asm.js
@@ -30,7 +30,7 @@ function asmFunc(global, env, buffer) {
function main() {
syscall$6(1 | 0, 2 | 0) | 0;
syscall$54(3 | 0, 4 | 0) | 0;
- FUNCTION_TABLE[HEAP32[(0 + 1030 | 0) >> 2] | 0]();
+ FUNCTION_TABLE[HEAP32[(0 + 1030 | 0) >> 2] | 0 | 0]();
internal(1 | 0) | 0;
tabled(1 | 0) | 0;
exported(1 | 0) | 0;
diff --git a/test/wasm2js/func-ptr-offset.2asm.js b/test/wasm2js/func-ptr-offset.2asm.js
index 98d5f7281..ac436c6d6 100644
--- a/test/wasm2js/func-ptr-offset.2asm.js
+++ b/test/wasm2js/func-ptr-offset.2asm.js
@@ -34,7 +34,7 @@ function asmFunc(global, env, buffer) {
function $3($0) {
$0 = $0 | 0;
- return FUNCTION_TABLE[$0]() | 0 | 0;
+ return FUNCTION_TABLE[$0 | 0]() | 0 | 0;
}
var FUNCTION_TABLE = [null, t1, t2, t3];
diff --git a/test/wasm2js/func-ptr-offset.2asm.js.opt b/test/wasm2js/func-ptr-offset.2asm.js.opt
index 1c2457fc9..b1198607d 100644
--- a/test/wasm2js/func-ptr-offset.2asm.js.opt
+++ b/test/wasm2js/func-ptr-offset.2asm.js.opt
@@ -34,7 +34,7 @@ function asmFunc(global, env, buffer) {
function $3($0) {
$0 = $0 | 0;
- return FUNCTION_TABLE[$0]() | 0;
+ return FUNCTION_TABLE[$0 | 0]() | 0;
}
var FUNCTION_TABLE = [null, t1, t2, t3];
diff --git a/test/wasm2js/func_ptrs.2asm.js b/test/wasm2js/func_ptrs.2asm.js
index 45e0a8697..97ebf3cb3 100644
--- a/test/wasm2js/func_ptrs.2asm.js
+++ b/test/wasm2js/func_ptrs.2asm.js
@@ -100,12 +100,12 @@ function asmFunc(global, env, buffer) {
function $5(i) {
i = i | 0;
- return FUNCTION_TABLE[i]() | 0 | 0;
+ return FUNCTION_TABLE[i | 0]() | 0 | 0;
}
function $6(i) {
i = i | 0;
- return FUNCTION_TABLE[i]() | 0 | 0;
+ return FUNCTION_TABLE[i | 0]() | 0 | 0;
}
var FUNCTION_TABLE = [t1, t2, t3, u1, u2, t1, t3];
@@ -151,7 +151,7 @@ function asmFunc(global, env, buffer) {
function $2(i) {
i = i | 0;
- return FUNCTION_TABLE[i]() | 0 | 0;
+ return FUNCTION_TABLE[i | 0]() | 0 | 0;
}
var FUNCTION_TABLE = [t1, t2];
diff --git a/test/wasm2js/indirect-select.2asm.js b/test/wasm2js/indirect-select.2asm.js
new file mode 100644
index 000000000..d190bb082
--- /dev/null
+++ b/test/wasm2js/indirect-select.2asm.js
@@ -0,0 +1,43 @@
+import { FUNCTION_TABLE } from 'env';
+
+function asmFunc(global, env, buffer) {
+ var HEAP8 = new global.Int8Array(buffer);
+ var HEAP16 = new global.Int16Array(buffer);
+ var HEAP32 = new global.Int32Array(buffer);
+ var HEAPU8 = new global.Uint8Array(buffer);
+ var HEAPU16 = new global.Uint16Array(buffer);
+ var HEAPU32 = new global.Uint32Array(buffer);
+ var HEAPF32 = new global.Float32Array(buffer);
+ var HEAPF64 = new global.Float64Array(buffer);
+ var Math_imul = global.Math.imul;
+ var Math_fround = global.Math.fround;
+ var Math_abs = global.Math.abs;
+ var Math_clz32 = global.Math.clz32;
+ var Math_min = global.Math.min;
+ var Math_max = global.Math.max;
+ var Math_floor = global.Math.floor;
+ var Math_ceil = global.Math.ceil;
+ var Math_sqrt = global.Math.sqrt;
+ var abort = env.abort;
+ var nan = global.NaN;
+ var infinity = global.Infinity;
+ function $0(x) {
+ x = x | 0;
+ return FUNCTION_TABLE[(x ? 1 : 0) | 0]() | 0 | 0;
+ }
+
+ function $1(x) {
+ x = x | 0;
+ return FUNCTION_TABLE[(x ? 0 : 1) | 0]() | 0 | 0;
+ }
+
+ return {
+ "foo_true": $0,
+ "foo_false": $1
+ };
+}
+
+var memasmFunc = new ArrayBuffer(65536);
+var retasmFunc = asmFunc({Math,Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,NaN,Infinity}, {abort:function() { throw new Error('abort'); }},memasmFunc);
+export var foo_true = retasmFunc.foo_true;
+export var foo_false = retasmFunc.foo_false;
diff --git a/test/wasm2js/indirect-select.2asm.js.opt b/test/wasm2js/indirect-select.2asm.js.opt
new file mode 100644
index 000000000..424b91d4a
--- /dev/null
+++ b/test/wasm2js/indirect-select.2asm.js.opt
@@ -0,0 +1,43 @@
+import { FUNCTION_TABLE } from 'env';
+
+function asmFunc(global, env, buffer) {
+ var HEAP8 = new global.Int8Array(buffer);
+ var HEAP16 = new global.Int16Array(buffer);
+ var HEAP32 = new global.Int32Array(buffer);
+ var HEAPU8 = new global.Uint8Array(buffer);
+ var HEAPU16 = new global.Uint16Array(buffer);
+ var HEAPU32 = new global.Uint32Array(buffer);
+ var HEAPF32 = new global.Float32Array(buffer);
+ var HEAPF64 = new global.Float64Array(buffer);
+ var Math_imul = global.Math.imul;
+ var Math_fround = global.Math.fround;
+ var Math_abs = global.Math.abs;
+ var Math_clz32 = global.Math.clz32;
+ var Math_min = global.Math.min;
+ var Math_max = global.Math.max;
+ var Math_floor = global.Math.floor;
+ var Math_ceil = global.Math.ceil;
+ var Math_sqrt = global.Math.sqrt;
+ var abort = env.abort;
+ var nan = global.NaN;
+ var infinity = global.Infinity;
+ function $0($0_1) {
+ $0_1 = $0_1 | 0;
+ return FUNCTION_TABLE[!!$0_1 | 0]() | 0;
+ }
+
+ function $1($0_1) {
+ $0_1 = $0_1 | 0;
+ return FUNCTION_TABLE[!$0_1 | 0]() | 0;
+ }
+
+ return {
+ "foo_true": $0,
+ "foo_false": $1
+ };
+}
+
+var memasmFunc = new ArrayBuffer(65536);
+var retasmFunc = asmFunc({Math,Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,NaN,Infinity}, {abort:function() { throw new Error('abort'); }},memasmFunc);
+export var foo_true = retasmFunc.foo_true;
+export var foo_false = retasmFunc.foo_false;
diff --git a/test/wasm2js/indirect-select.wast b/test/wasm2js/indirect-select.wast
new file mode 100644
index 000000000..fc6f4c470
--- /dev/null
+++ b/test/wasm2js/indirect-select.wast
@@ -0,0 +1,22 @@
+(module
+ (type $none_=>_i32 (func (result i32)))
+ (import "env" "table" (table $timport 6 funcref))
+ (func "foo-true" (param $x i32) (result i32)
+ (call_indirect (type $none_=>_i32)
+ (select
+ (i32.const 1)
+ (i32.const 0)
+ (local.get $x)
+ )
+ )
+ )
+ (func "foo-false" (param $x i32) (result i32)
+ (call_indirect (type $none_=>_i32)
+ (select
+ (i32.const 0)
+ (i32.const 1)
+ (local.get $x)
+ )
+ )
+ )
+)
diff --git a/test/wasm2js/left-to-right.2asm.js b/test/wasm2js/left-to-right.2asm.js
index f5f19a1cd..4c595c3b0 100644
--- a/test/wasm2js/left-to-right.2asm.js
+++ b/test/wasm2js/left-to-right.2asm.js
@@ -408,7 +408,7 @@ function asmFunc(global, env, buffer) {
function $62() {
var wasm2js_i32$0 = 0, wasm2js_i32$1 = 0, wasm2js_i32$2 = 0;
reset();
- ((wasm2js_i32$1 = i32_left() | 0, wasm2js_i32$2 = i32_right() | 0), wasm2js_i32$0 = i32_callee() | 0), FUNCTION_TABLE[wasm2js_i32$0](wasm2js_i32$1 | 0, wasm2js_i32$2 | 0) | 0;
+ ((wasm2js_i32$1 = i32_left() | 0, wasm2js_i32$2 = i32_right() | 0), wasm2js_i32$0 = i32_callee() | 0 | 0), FUNCTION_TABLE[wasm2js_i32$0](wasm2js_i32$1 | 0, wasm2js_i32$2 | 0) | 0;
return get() | 0 | 0;
}
@@ -972,7 +972,7 @@ function asmFunc(global, env, buffer) {
$1$hi = i64toi32_i32$0;
i64toi32_i32$0 = $0$hi;
i64toi32_i32$1 = $1$hi;
- FUNCTION_TABLE[i64_callee() | 0]($0, i64toi32_i32$0, $1, i64toi32_i32$1) | 0;
+ FUNCTION_TABLE[i64_callee() | 0 | 0]($0, i64toi32_i32$0, $1, i64toi32_i32$1) | 0;
return get() | 0 | 0;
}
@@ -1087,7 +1087,7 @@ function asmFunc(global, env, buffer) {
function $109() {
var wasm2js_i32$0 = 0, wasm2js_f32$0 = Math_fround(0), wasm2js_f32$1 = Math_fround(0);
reset();
- ((wasm2js_f32$0 = Math_fround(f32_left()), wasm2js_f32$1 = Math_fround(f32_right())), wasm2js_i32$0 = f32_callee() | 0), FUNCTION_TABLE[wasm2js_i32$0](Math_fround(wasm2js_f32$0), Math_fround(wasm2js_f32$1)) | 0;
+ ((wasm2js_f32$0 = Math_fround(f32_left()), wasm2js_f32$1 = Math_fround(f32_right())), wasm2js_i32$0 = f32_callee() | 0 | 0), FUNCTION_TABLE[wasm2js_i32$0](Math_fround(wasm2js_f32$0), Math_fround(wasm2js_f32$1)) | 0;
return get() | 0 | 0;
}
@@ -1216,7 +1216,7 @@ function asmFunc(global, env, buffer) {
function $126() {
var wasm2js_i32$0 = 0, wasm2js_f64$0 = 0.0, wasm2js_f64$1 = 0.0;
reset();
- ((wasm2js_f64$0 = +f64_left(), wasm2js_f64$1 = +f64_right()), wasm2js_i32$0 = f64_callee() | 0), FUNCTION_TABLE[wasm2js_i32$0](+wasm2js_f64$0, +wasm2js_f64$1) | 0;
+ ((wasm2js_f64$0 = +f64_left(), wasm2js_f64$1 = +f64_right()), wasm2js_i32$0 = f64_callee() | 0 | 0), FUNCTION_TABLE[wasm2js_i32$0](+wasm2js_f64$0, +wasm2js_f64$1) | 0;
return get() | 0 | 0;
}
diff --git a/test/wasm2js/ordering.2asm.js b/test/wasm2js/ordering.2asm.js
index 1fbfd0c03..f3d879a99 100644
--- a/test/wasm2js/ordering.2asm.js
+++ b/test/wasm2js/ordering.2asm.js
@@ -23,10 +23,10 @@ function asmFunc(global, env, buffer) {
var infinity = global.Infinity;
function main() {
var wasm2js_i32$0 = 0, wasm2js_i32$1 = 0, wasm2js_i32$2 = 0;
- FUNCTION_TABLE[foo(2 | 0) | 0](1) | 0;
- FUNCTION_TABLE[4](foo(3 | 0) | 0) | 0;
- (wasm2js_i32$1 = foo(5 | 0) | 0, wasm2js_i32$0 = bar(6 | 0) | 0), FUNCTION_TABLE[wasm2js_i32$0](wasm2js_i32$1 | 0) | 0;
- FUNCTION_TABLE[8](7) | 0;
+ FUNCTION_TABLE[foo(2 | 0) | 0 | 0](1) | 0;
+ FUNCTION_TABLE[4 | 0](foo(3 | 0) | 0) | 0;
+ (wasm2js_i32$1 = foo(5 | 0) | 0, wasm2js_i32$0 = bar(6 | 0) | 0 | 0), FUNCTION_TABLE[wasm2js_i32$0](wasm2js_i32$1 | 0) | 0;
+ FUNCTION_TABLE[8 | 0](7) | 0;
baz((11 ? 9 : 10) | 0) | 0;
baz((wasm2js_i32$0 = foo(12 | 0) | 0, wasm2js_i32$1 = 13, wasm2js_i32$2 = 14, wasm2js_i32$2 ? wasm2js_i32$0 : wasm2js_i32$1) | 0) | 0;
baz((wasm2js_i32$0 = 15, wasm2js_i32$1 = foo(16 | 0) | 0, wasm2js_i32$2 = 17, wasm2js_i32$2 ? wasm2js_i32$0 : wasm2js_i32$1) | 0) | 0;