diff options
-rw-r--r-- | src/asm2wasm.h | 43 | ||||
-rw-r--r-- | test/unit.asm.js | 8 | ||||
-rw-r--r-- | test/unit.fromasm | 16 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise | 16 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise.no-opts | 18 | ||||
-rw-r--r-- | test/unit.fromasm.no-opts | 18 |
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) ) |