summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asm2wasm.h43
-rw-r--r--test/unit.asm.js8
-rw-r--r--test/unit.fromasm16
-rw-r--r--test/unit.fromasm.imprecise16
-rw-r--r--test/unit.fromasm.imprecise.no-opts18
-rw-r--r--test/unit.fromasm.no-opts18
6 files changed, 111 insertions, 8 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 586adaa99..9ac9ef2c4 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -105,7 +105,9 @@ Name I32_CTTZ("i32_cttz"),
STORE4("store4"),
STORE8("store8"),
STOREF("storef"),
- STORED("stored");
+ STORED("stored"),
+ FTCALL("ftCall_"),
+ MFTCALL("mftCall_");
// Utilities
@@ -975,14 +977,19 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
void visitCallIndirect(CallIndirect* curr) {
// we already call into target = something + offset, where offset is a callImport with the name of the table. replace that with the table offset
- auto add = curr->target->cast<Binary>();
+ // note that for an ftCall or mftCall, we have no asm.js mask, so have nothing to do here
+ auto* add = curr->target->dynCast<Binary>();
+ if (!add) return;
if (add->right->is<CallImport>()) {
- auto offset = add->right->cast<CallImport>();
+ auto* offset = add->right->cast<CallImport>();
auto tableName = offset->target;
+ if (parent->functionTableStarts.find(tableName) == parent->functionTableStarts.end()) return;
add->right = parent->builder.makeConst(Literal((int32_t)parent->functionTableStarts[tableName]));
} else {
- auto offset = add->left->cast<CallImport>();
+ auto* offset = add->left->dynCast<CallImport>();
+ if (!offset) return;
auto tableName = offset->target;
+ if (parent->functionTableStarts.find(tableName) == parent->functionTableStarts.end()) return;
add->left = parent->builder.makeConst(Literal((int32_t)parent->functionTableStarts[tableName]));
}
}
@@ -1592,6 +1599,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
}
return ret;
}
+ bool tableCall = false;
if (wasmOnly) {
auto num = ast[2]->size();
switch (name.str[0]) {
@@ -1695,10 +1703,25 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
default: {}
}
}
+ // ftCall_* and mftCall_* represent function table calls, either from the outside, or
+ // from the inside of the module. when compiling to wasm, we can just convert those
+ // into table calls
+ if ((name.str[0] == 'f' && strncmp(name.str, FTCALL.str, 7) == 0) ||
+ (name.str[0] == 'm' && strncmp(name.str, MFTCALL.str, 8) == 0)) {
+ tableCall = true;
+ }
Expression* ret;
ExpressionList* operands;
bool import = false;
- if (wasm.checkImport(name)) {
+ Index firstOperand = 0;
+ Ref args = ast[2];
+ if (tableCall) {
+ auto specific = allocator.alloc<CallIndirect>();
+ specific->target = process(args[0]);
+ firstOperand = 1;
+ operands = &specific->operands;
+ ret = specific;
+ } else if (wasm.checkImport(name)) {
import = true;
auto specific = allocator.alloc<CallImport>();
specific->target = name;
@@ -1710,10 +1733,16 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
operands = &specific->operands;
ret = specific;
}
- Ref args = ast[2];
- for (unsigned i = 0; i < args->size(); i++) {
+ for (unsigned i = firstOperand; i < args->size(); i++) {
operands->push_back(process(args[i]));
}
+ if (tableCall) {
+ auto specific = ret->dynCast<CallIndirect>();
+ // note that we could also get the type from the suffix of the name, e.g., mftCall_vi
+ auto* fullType = getFunctionType(astStackHelper.getParent(), specific->operands);
+ specific->fullType = fullType->name;
+ specific->type = fullType->result;
+ }
if (import) {
Ref parent = astStackHelper.getParent();
WasmType type = !!parent ? detectWasmType(parent, &asmData) : none;
diff --git a/test/unit.asm.js b/test/unit.asm.js
index 51c2fc22a..4ab43b737 100644
--- a/test/unit.asm.js
+++ b/test/unit.asm.js
@@ -652,6 +652,12 @@ function asm(global, env, buffer) {
HEAPF64[10] = Math_fround(x|0);
}
+ function relocatableAndModules() {
+ ftCall_v(10); // function table call
+ mftCall_v(20); // possible inter-module function table call
+ return ftCall_idi(30, 1.5, 200) | 0; // with args
+ }
+
function v() {
}
function vi(x) {
@@ -663,6 +669,6 @@ function asm(global, env, buffer) {
var FUNCTION_TABLE_c = [ z, cneg, z, z, z, z, z, z ];
var FUNCTION_TABLE_vi = [ vi, vi, vi, vi, vi, vi, vi, vi ];
- return { big_negative: big_negative, pick: forgetMe, pick: exportMe, doubleCompares: doubleCompares, intOps: intOps, conversions: conversions, switcher: switcher, frem: frem, big_uint_div_u: big_uint_div_u, fr: fr, negZero: negZero, neg: neg, smallCompare: smallCompare, cneg_nosemicolon: cneg_nosemicolon, forLoop: forLoop, ceiling_32_64: ceiling_32_64, aborts: aborts, continues: continues, bitcasts: bitcasts, recursiveBlockMerging: recursiveBlockMerging, lb: lb, zeroInit: zeroInit, phi: phi, smallIf: smallIf, dropCall: dropCall, useSetGlobal: useSetGlobal, usesSetGlobal2: usesSetGlobal2, breakThroughMany: breakThroughMany, ifChainEmpty: ifChainEmpty, heap8NoShift: heap8NoShift, conditionalTypeFun: conditionalTypeFun, loadSigned: loadSigned, globalOpts: globalOpts, dropCallImport: dropCallImport, loophi: loophi, loophi2: loophi2, relooperJumpThreading: relooperJumpThreading, relooperJumpThreading__ZN4game14preloadweaponsEv: relooperJumpThreading__ZN4game14preloadweaponsEv, __Z12multi_varargiz: __Z12multi_varargiz, jumpThreadDrop: jumpThreadDrop, dropIgnoredImportInIf: dropIgnoredImportInIf, dropIgnoredImportsInIf: dropIgnoredImportsInIf, relooperJumpThreading_irreducible: relooperJumpThreading_irreducible, store_fround: store_fround, exportedNumber: 42 };
+ return { big_negative: big_negative, pick: forgetMe, pick: exportMe, doubleCompares: doubleCompares, intOps: intOps, conversions: conversions, switcher: switcher, frem: frem, big_uint_div_u: big_uint_div_u, fr: fr, negZero: negZero, neg: neg, smallCompare: smallCompare, cneg_nosemicolon: cneg_nosemicolon, forLoop: forLoop, ceiling_32_64: ceiling_32_64, aborts: aborts, continues: continues, bitcasts: bitcasts, recursiveBlockMerging: recursiveBlockMerging, lb: lb, zeroInit: zeroInit, phi: phi, smallIf: smallIf, dropCall: dropCall, useSetGlobal: useSetGlobal, usesSetGlobal2: usesSetGlobal2, breakThroughMany: breakThroughMany, ifChainEmpty: ifChainEmpty, heap8NoShift: heap8NoShift, conditionalTypeFun: conditionalTypeFun, loadSigned: loadSigned, globalOpts: globalOpts, dropCallImport: dropCallImport, loophi: loophi, loophi2: loophi2, relooperJumpThreading: relooperJumpThreading, relooperJumpThreading__ZN4game14preloadweaponsEv: relooperJumpThreading__ZN4game14preloadweaponsEv, __Z12multi_varargiz: __Z12multi_varargiz, jumpThreadDrop: jumpThreadDrop, dropIgnoredImportInIf: dropIgnoredImportInIf, dropIgnoredImportsInIf: dropIgnoredImportsInIf, relooperJumpThreading_irreducible: relooperJumpThreading_irreducible, store_fround: store_fround, exportedNumber: 42, relocatableAndModules: relocatableAndModules };
}
diff --git a/test/unit.fromasm b/test/unit.fromasm
index 15ff3b517..d887aedac 100644
--- a/test/unit.fromasm
+++ b/test/unit.fromasm
@@ -4,6 +4,8 @@
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$vf (func (param f32)))
(type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$v (func))
+ (type $FUNCSIG$idi (func (param f64 i32) (result i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$dd (func (param f64) (result f64)))
(type $FUNCSIG$i (func (result i32)))
@@ -70,6 +72,7 @@
(export "relooperJumpThreading_irreducible" (func $relooperJumpThreading_irreducible))
(export "store_fround" (func $store_fround))
(export "exportedNumber" (global $exportedNumber))
+ (export "relocatableAndModules" (func $relocatableAndModules))
(func $big_negative
(nop)
)
@@ -1130,6 +1133,19 @@
)
)
)
+ (func $relocatableAndModules (result i32)
+ (call_indirect $FUNCSIG$v
+ (i32.const 10)
+ )
+ (call_indirect $FUNCSIG$v
+ (i32.const 20)
+ )
+ (call_indirect $FUNCSIG$idi
+ (f64.const 1.5)
+ (i32.const 200)
+ (i32.const 30)
+ )
+ )
(func $vi (param $0 i32)
(nop)
)
diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise
index d466f8c27..10ea5a01f 100644
--- a/test/unit.fromasm.imprecise
+++ b/test/unit.fromasm.imprecise
@@ -2,6 +2,8 @@
(type $FUNCSIG$ddd (func (param f64 f64) (result f64)))
(type $FUNCSIG$vf (func (param f32)))
(type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$v (func))
+ (type $FUNCSIG$idi (func (param f64 i32) (result i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$dd (func (param f64) (result f64)))
(type $FUNCSIG$i (func (result i32)))
@@ -65,6 +67,7 @@
(export "relooperJumpThreading_irreducible" (func $relooperJumpThreading_irreducible))
(export "store_fround" (func $store_fround))
(export "exportedNumber" (global $exportedNumber))
+ (export "relocatableAndModules" (func $relocatableAndModules))
(func $big_negative
(nop)
)
@@ -1106,6 +1109,19 @@
)
)
)
+ (func $relocatableAndModules (result i32)
+ (call_indirect $FUNCSIG$v
+ (i32.const 10)
+ )
+ (call_indirect $FUNCSIG$v
+ (i32.const 20)
+ )
+ (call_indirect $FUNCSIG$idi
+ (f64.const 1.5)
+ (i32.const 200)
+ (i32.const 30)
+ )
+ )
(func $vi (param $0 i32)
(nop)
)
diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts
index e16dd92f8..7831656f7 100644
--- a/test/unit.fromasm.imprecise.no-opts
+++ b/test/unit.fromasm.imprecise.no-opts
@@ -2,6 +2,8 @@
(type $FUNCSIG$ddd (func (param f64 f64) (result f64)))
(type $FUNCSIG$vf (func (param f32)))
(type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$v (func))
+ (type $FUNCSIG$idi (func (param f64 i32) (result i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$dd (func (param f64) (result f64)))
(type $FUNCSIG$i (func (result i32)))
@@ -73,6 +75,7 @@
(export "relooperJumpThreading_irreducible" (func $relooperJumpThreading_irreducible))
(export "store_fround" (func $store_fround))
(export "exportedNumber" (global $exportedNumber))
+ (export "relocatableAndModules" (func $relocatableAndModules))
(func $big_negative
(local $temp f64)
(set_local $temp
@@ -1800,6 +1803,21 @@
)
)
)
+ (func $relocatableAndModules (result i32)
+ (call_indirect $FUNCSIG$v
+ (i32.const 10)
+ )
+ (call_indirect $FUNCSIG$v
+ (i32.const 20)
+ )
+ (return
+ (call_indirect $FUNCSIG$idi
+ (f64.const 1.5)
+ (i32.const 200)
+ (i32.const 30)
+ )
+ )
+ )
(func $v
(nop)
)
diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts
index 2fef4cae6..dfcf18538 100644
--- a/test/unit.fromasm.no-opts
+++ b/test/unit.fromasm.no-opts
@@ -4,6 +4,8 @@
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$vf (func (param f32)))
(type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$v (func))
+ (type $FUNCSIG$idi (func (param f64 i32) (result i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$dd (func (param f64) (result f64)))
(type $FUNCSIG$i (func (result i32)))
@@ -77,6 +79,7 @@
(export "relooperJumpThreading_irreducible" (func $relooperJumpThreading_irreducible))
(export "store_fround" (func $store_fround))
(export "exportedNumber" (global $exportedNumber))
+ (export "relocatableAndModules" (func $relocatableAndModules))
(func $big_negative
(local $temp f64)
(set_local $temp
@@ -1806,6 +1809,21 @@
)
)
)
+ (func $relocatableAndModules (result i32)
+ (call_indirect $FUNCSIG$v
+ (i32.const 10)
+ )
+ (call_indirect $FUNCSIG$v
+ (i32.const 20)
+ )
+ (return
+ (call_indirect $FUNCSIG$idi
+ (f64.const 1.5)
+ (i32.const 200)
+ (i32.const 30)
+ )
+ )
+ )
(func $v
(nop)
)