diff options
-rw-r--r-- | src/asm2wasm.h | 34 | ||||
-rw-r--r-- | src/ast_utils.h | 28 | ||||
-rw-r--r-- | test/unit.asm.js | 6 | ||||
-rw-r--r-- | test/unit.fromasm | 64 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise | 64 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise.no-opts | 66 | ||||
-rw-r--r-- | test/unit.fromasm.no-opts | 66 |
7 files changed, 263 insertions, 65 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 059e51c59..53fa78db4 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -224,12 +224,6 @@ private: // if we already saw this signature, verify it's the same (or else handle that) if (importedFunctionTypes.find(importName) != importedFunctionTypes.end()) { FunctionType* previous = importedFunctionTypes[importName].get(); -#if 0 - std::cout << "compare " << importName.str << "\nfirst: "; - type.print(std::cout, 0); - std::cout << "\nsecond: "; - previous.print(std::cout, 0) << ".\n"; -#endif if (*type != *previous) { // merge it in. we'll add on extra 0 parameters for ones not actually used, and upgrade types to // double where there is a conflict (which is ok since in JS, double can contain everything @@ -247,6 +241,8 @@ private: } if (previous->result == none) { previous->result = type->result; // use a more concrete type + } else if (previous->result != type->result) { + previous->result = f64; // overloaded return type, make it a double } } } else { @@ -752,7 +748,10 @@ void Asm2WasmBuilder::processAsm(Ref ast) { void visitCall(Call* curr) { assert(getModule()->checkFunction(curr->target) ? true : (std::cerr << curr->target << '\n', false)); - curr->type = getModule()->getFunction(curr->target)->result; + auto result = getModule()->getFunction(curr->target)->result; + if (curr->type != result) { + curr->type = result; + } } void visitCallImport(CallImport* curr) { @@ -776,9 +775,25 @@ void Asm2WasmBuilder::processAsm(Ref ast) { } } } - - curr->type = getModule()->getImport(curr->target)->functionType->result; + auto importResult = getModule()->getImport(curr->target)->functionType->result; + if (curr->type != importResult) { + if (importResult == f64) { + // we use a JS f64 value which is the most general, and convert to it + switch (curr->type) { + case i32: replaceCurrent(parent->builder.makeUnary(TruncSFloat64ToInt32, curr)); break; + case f32: replaceCurrent(parent->builder.makeUnary(DemoteFloat64, curr)); break; + case none: replaceCurrent(parent->builder.makeDrop(curr)); break; + default: WASM_UNREACHABLE(); + } + } else { + assert(curr->type == none); + // we don't want a return value here, but the import does provide one + replaceCurrent(parent->builder.makeDrop(curr)); + } + curr->type = importResult; + } } + 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>(); @@ -789,6 +804,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) { }; PassRunner passRunner(&wasm); passRunner.add<FinalizeCalls>(this); + passRunner.add<ReFinalize>(); // FinalizeCalls changes call types, need to percolate passRunner.add<AutoDrop>(); // FinalizeCalls may cause us to require additional drops if (optimize) { passRunner.add("vacuum"); // autodrop can add some garbage diff --git a/src/ast_utils.h b/src/ast_utils.h index 0bb0a821e..9b2ff10cd 100644 --- a/src/ast_utils.h +++ b/src/ast_utils.h @@ -821,6 +821,34 @@ struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop, Visitor<Auto } }; +// Finalizes a node + +struct ReFinalize : public WalkerPass<PostWalker<ReFinalize, Visitor<ReFinalize>>> { + void visitBlock(Block *curr) { curr->finalize(); } + void visitIf(If *curr) { curr->finalize(); } + void visitLoop(Loop *curr) { curr->finalize(); } + void visitBreak(Break *curr) { curr->finalize(); } + void visitSwitch(Switch *curr) { curr->finalize(); } + void visitCall(Call *curr) { curr->finalize(); } + void visitCallImport(CallImport *curr) { curr->finalize(); } + void visitCallIndirect(CallIndirect *curr) { curr->finalize(); } + void visitGetLocal(GetLocal *curr) { curr->finalize(); } + void visitSetLocal(SetLocal *curr) { curr->finalize(); } + void visitGetGlobal(GetGlobal *curr) { curr->finalize(); } + void visitSetGlobal(SetGlobal *curr) { curr->finalize(); } + void visitLoad(Load *curr) { curr->finalize(); } + void visitStore(Store *curr) { curr->finalize(); } + void visitConst(Const *curr) { curr->finalize(); } + void visitUnary(Unary *curr) { curr->finalize(); } + void visitBinary(Binary *curr) { curr->finalize(); } + void visitSelect(Select *curr) { curr->finalize(); } + void visitDrop(Drop *curr) { curr->finalize(); } + void visitReturn(Return *curr) { curr->finalize(); } + void visitHost(Host *curr) { curr->finalize(); } + void visitNop(Nop *curr) { curr->finalize(); } + void visitUnreachable(Unreachable *curr) { curr->finalize(); } +}; + } // namespace wasm #endif // wasm_ast_utils_h diff --git a/test/unit.asm.js b/test/unit.asm.js index 25aed0834..e76ae1ef9 100644 --- a/test/unit.asm.js +++ b/test/unit.asm.js @@ -324,6 +324,12 @@ function asm(global, env, buffer) { return HEAP8[x | 0] | 0; } + function conditionalTypeFun() { + var x = 0, y = +0; + x = 1 ? abort(5) | 0 : 2; + y = 3 ? +abort(7) : 4.5; + } + function z() { } function w() { diff --git a/test/unit.fromasm b/test/unit.fromasm index 98202a4ec..a3fbf0add 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -7,13 +7,13 @@ (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) - (type $FUNCSIG$vd (func (param f64))) + (type $FUNCSIG$dd (func (param f64) (result f64))) (import $t global "global" "NaN" f64) (import $u global "global" "Infinity" f64) (import $tempDoublePtr global "env" "tempDoublePtr" i32) (import $n global "env" "gb" i32) (import $setTempRet0 "env" "setTempRet0" (param i32) (result i32)) - (import $abort "env" "abort" (param f64)) + (import $abort "env" "abort" (param f64) (result f64)) (import $print "env" "print" (param i32)) (import $h "env" "h" (param i32)) (import $f64-to-int "asm2wasm" "f64-to-int" (param f64) (result i32)) @@ -319,23 +319,33 @@ (nop) ) (func $aborts - (call_import $abort - (f64.const 0) + (drop + (call_import $abort + (f64.const 0) + ) ) - (call_import $abort - (f64.convert_s/i32 - (i32.const 55) + (drop + (call_import $abort + (f64.convert_s/i32 + (i32.const 55) + ) ) ) - (call_import $abort - (f64.const 0) + (drop + (call_import $abort + (f64.const 0) + ) ) - (call_import $abort - (f64.const 12.34) + (drop + (call_import $abort + (f64.const 12.34) + ) ) - (call_import $abort - (f64.promote/f32 - (f32.const 56.779998779296875) + (drop + (call_import $abort + (f64.promote/f32 + (f32.const 56.779998779296875) + ) ) ) ) @@ -580,4 +590,30 @@ (get_local $0) ) ) + (func $conditionalTypeFun + (drop + (if + (i32.const 1) + (i32.trunc_s/f64 + (call_import $abort + (f64.convert_s/i32 + (i32.const 5) + ) + ) + ) + (i32.const 2) + ) + ) + (drop + (if + (i32.const 3) + (call_import $abort + (f64.convert_s/i32 + (i32.const 7) + ) + ) + (f64.const 4.5) + ) + ) + ) ) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index 493ebb67e..46de1092f 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -4,13 +4,13 @@ (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) - (type $FUNCSIG$vd (func (param f64))) + (type $FUNCSIG$dd (func (param f64) (result f64))) (import $t global "global" "NaN" f64) (import $u global "global" "Infinity" f64) (import $tempDoublePtr global "env" "tempDoublePtr" i32) (import $n global "env" "gb" i32) (import $setTempRet0 "env" "setTempRet0" (param i32) (result i32)) - (import $abort "env" "abort" (param f64)) + (import $abort "env" "abort" (param f64) (result f64)) (import $print "env" "print" (param i32)) (import $h "env" "h" (param i32)) (import $f64-rem "asm2wasm" "f64-rem" (param f64 f64) (result f64)) @@ -300,23 +300,33 @@ (nop) ) (func $aborts - (call_import $abort - (f64.const 0) + (drop + (call_import $abort + (f64.const 0) + ) ) - (call_import $abort - (f64.convert_s/i32 - (i32.const 55) + (drop + (call_import $abort + (f64.convert_s/i32 + (i32.const 55) + ) ) ) - (call_import $abort - (f64.const 0) + (drop + (call_import $abort + (f64.const 0) + ) ) - (call_import $abort - (f64.const 12.34) + (drop + (call_import $abort + (f64.const 12.34) + ) ) - (call_import $abort - (f64.promote/f32 - (f32.const 56.779998779296875) + (drop + (call_import $abort + (f64.promote/f32 + (f32.const 56.779998779296875) + ) ) ) ) @@ -561,4 +571,30 @@ (get_local $0) ) ) + (func $conditionalTypeFun + (drop + (if + (i32.const 1) + (i32.trunc_s/f64 + (call_import $abort + (f64.convert_s/i32 + (i32.const 5) + ) + ) + ) + (i32.const 2) + ) + ) + (drop + (if + (i32.const 3) + (call_import $abort + (f64.convert_s/i32 + (i32.const 7) + ) + ) + (f64.const 4.5) + ) + ) + ) ) diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts index 89a448a82..3f82776e5 100644 --- a/test/unit.fromasm.imprecise.no-opts +++ b/test/unit.fromasm.imprecise.no-opts @@ -4,13 +4,13 @@ (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) - (type $FUNCSIG$vd (func (param f64))) + (type $FUNCSIG$dd (func (param f64) (result f64))) (import $t global "global" "NaN" f64) (import $u global "global" "Infinity" f64) (import $tempDoublePtr global "env" "tempDoublePtr" i32) (import $n global "env" "gb" i32) (import $setTempRet0 "env" "setTempRet0" (param i32) (result i32)) - (import $abort "env" "abort" (param f64)) + (import $abort "env" "abort" (param f64) (result f64)) (import $print "env" "print" (param i32)) (import $h "env" "h" (param i32)) (import $f64-rem "asm2wasm" "f64-rem" (param f64 f64) (result f64)) @@ -543,23 +543,33 @@ ) ) (func $aborts - (call_import $abort - (f64.const 0) + (drop + (call_import $abort + (f64.const 0) + ) ) - (call_import $abort - (f64.convert_s/i32 - (i32.const 55) + (drop + (call_import $abort + (f64.convert_s/i32 + (i32.const 55) + ) ) ) - (call_import $abort - (f64.const 0) + (drop + (call_import $abort + (f64.const 0) + ) ) - (call_import $abort - (f64.const 12.34) + (drop + (call_import $abort + (f64.const 12.34) + ) ) - (call_import $abort - (f64.promote/f32 - (f32.const 56.779998779296875) + (drop + (call_import $abort + (f64.promote/f32 + (f32.const 56.779998779296875) + ) ) ) ) @@ -963,6 +973,34 @@ ) ) ) + (func $conditionalTypeFun + (local $x i32) + (local $y f64) + (set_local $x + (if + (i32.const 1) + (i32.trunc_s/f64 + (call_import $abort + (f64.convert_s/i32 + (i32.const 5) + ) + ) + ) + (i32.const 2) + ) + ) + (set_local $y + (if + (i32.const 3) + (call_import $abort + (f64.convert_s/i32 + (i32.const 7) + ) + ) + (f64.const 4.5) + ) + ) + ) (func $z (nop) ) diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts index f1253c849..c55a309e6 100644 --- a/test/unit.fromasm.no-opts +++ b/test/unit.fromasm.no-opts @@ -6,13 +6,13 @@ (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) - (type $FUNCSIG$vd (func (param f64))) + (type $FUNCSIG$dd (func (param f64) (result f64))) (import $t global "global" "NaN" f64) (import $u global "global" "Infinity" f64) (import $tempDoublePtr global "env" "tempDoublePtr" i32) (import $n global "env" "gb" i32) (import $setTempRet0 "env" "setTempRet0" (param i32) (result i32)) - (import $abort "env" "abort" (param f64)) + (import $abort "env" "abort" (param f64) (result f64)) (import $print "env" "print" (param i32)) (import $h "env" "h" (param i32)) (import $f64-to-int "asm2wasm" "f64-to-int" (param f64) (result i32)) @@ -549,23 +549,33 @@ ) ) (func $aborts - (call_import $abort - (f64.const 0) + (drop + (call_import $abort + (f64.const 0) + ) ) - (call_import $abort - (f64.convert_s/i32 - (i32.const 55) + (drop + (call_import $abort + (f64.convert_s/i32 + (i32.const 55) + ) ) ) - (call_import $abort - (f64.const 0) + (drop + (call_import $abort + (f64.const 0) + ) ) - (call_import $abort - (f64.const 12.34) + (drop + (call_import $abort + (f64.const 12.34) + ) ) - (call_import $abort - (f64.promote/f32 - (f32.const 56.779998779296875) + (drop + (call_import $abort + (f64.promote/f32 + (f32.const 56.779998779296875) + ) ) ) ) @@ -969,6 +979,34 @@ ) ) ) + (func $conditionalTypeFun + (local $x i32) + (local $y f64) + (set_local $x + (if + (i32.const 1) + (i32.trunc_s/f64 + (call_import $abort + (f64.convert_s/i32 + (i32.const 5) + ) + ) + ) + (i32.const 2) + ) + ) + (set_local $y + (if + (i32.const 3) + (call_import $abort + (f64.convert_s/i32 + (i32.const 7) + ) + ) + (f64.const 4.5) + ) + ) + ) (func $z (nop) ) |