From 9d27d6818f83308c4853e3d8870d5b88a374453f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 7 Aug 2016 10:38:34 -0700 Subject: add drop and tee expressions --- test/unit.asm.js | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'test/unit.asm.js') diff --git a/test/unit.asm.js b/test/unit.asm.js index 380c97b41..5eb48f776 100644 --- a/test/unit.asm.js +++ b/test/unit.asm.js @@ -261,6 +261,16 @@ function asm(global, env, buffer) { return x | 0; } + function smallIf() { + do { + if (2) { + lb(3) | 0; + } else { + break; + } + } while (0); + } + function z() { } function w() { -- cgit v1.2.3 From db5ee8d83eb32fc7fd007f9e3d9b46d748161ae7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Aug 2016 12:05:20 -0700 Subject: set type of calls to their target, instead of the previous behavior where the asm.js context informed us. this lets us add drops where necessary --- src/asm2wasm.h | 14 ++++++++++---- test/unit.asm.js | 10 ++++++++++ test/unit.fromasm | 23 +++++++++++++++++++++++ test/unit.fromasm.imprecise | 23 +++++++++++++++++++++++ test/unit.fromasm.imprecise.no-opts | 25 +++++++++++++++++++++++++ test/unit.fromasm.no-opts | 25 +++++++++++++++++++++++++ 6 files changed, 116 insertions(+), 4 deletions(-) (limited to 'test/unit.asm.js') diff --git a/src/asm2wasm.h b/src/asm2wasm.h index a85fd4676..5167ad70f 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -401,9 +401,9 @@ private: } void fixCallType(Expression* call, WasmType type) { - if (call->is()) call->type = type; - if (call->is()) call->type = type; - else if (call->is()) call->type = type; + if (call->is()) call->cast()->type = type; + if (call->is()) call->cast()->type = type; + else if (call->is()) call->cast()->type = type; } FunctionType* getBuiltinFunctionType(Name module, Name base, ExpressionList* operands = nullptr) { @@ -736,7 +736,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) { wasm.removeImport(curr); } - // Finalize indirect calls and import calls + // Finalize calls now that everything is known and generated struct FinalizeCalls : public WalkerPass>> { bool isFunctionParallel() override { return true; } @@ -747,6 +747,10 @@ void Asm2WasmBuilder::processAsm(Ref ast) { FinalizeCalls(Asm2WasmBuilder* parent) : parent(parent) {} + void visitCall(Call* curr) { + curr->type = getModule()->getFunction(curr->target)->result; + } + void visitCallImport(CallImport* curr) { // fill out call_import - add extra params as needed, etc. asm tolerates ffi overloading, wasm does not auto iter = parent->importedFunctionTypes.find(curr->target); @@ -768,6 +772,8 @@ void Asm2WasmBuilder::processAsm(Ref ast) { } } } + + curr->type = getModule()->getImport(curr->target)->functionType->result; } 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 diff --git a/test/unit.asm.js b/test/unit.asm.js index 5eb48f776..d6d0a27e8 100644 --- a/test/unit.asm.js +++ b/test/unit.asm.js @@ -9,6 +9,7 @@ function asm(global, env, buffer) { var Math_ceil = global.Math.ceil; var tempDoublePtr = env.tempDoublePtr | 0; var n = env.gb | 0; + var setTempRet0=env.setTempRet0; var abort = env.abort; var print = env.print; @@ -271,6 +272,15 @@ function asm(global, env, buffer) { } while (0); } + function dropCall() { + if (0) { + phi(); // drop this + setTempRet0(10); // this too + zeroInit(setTempRet0(10) | 0); + } + return phi() | 0; + } + function z() { } function w() { diff --git a/test/unit.fromasm b/test/unit.fromasm index 78a97a9d7..daaf1359d 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -5,11 +5,13 @@ (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (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))) (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 $print "env" "print" (param i32)) (import $h "env" "h" (param i32)) @@ -496,4 +498,25 @@ ) ) ) + (func $dropCall (result i32) + (if + (i32.const 0) + (block + (drop + (call $phi) + ) + (drop + (call_import $setTempRet0 + (i32.const 10) + ) + ) + (call $zeroInit + (call_import $setTempRet0 + (i32.const 10) + ) + ) + ) + ) + (call $phi) + ) ) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index a18e1f436..b2c79ff79 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -3,11 +3,13 @@ (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) (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))) (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 $print "env" "print" (param i32)) (import $h "env" "h" (param i32)) @@ -478,4 +480,25 @@ ) ) ) + (func $dropCall (result i32) + (if + (i32.const 0) + (block + (drop + (call $phi) + ) + (drop + (call_import $setTempRet0 + (i32.const 10) + ) + ) + (call $zeroInit + (call_import $setTempRet0 + (i32.const 10) + ) + ) + ) + ) + (call $phi) + ) ) diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts index 46d746946..06ab8089b 100644 --- a/test/unit.fromasm.imprecise.no-opts +++ b/test/unit.fromasm.imprecise.no-opts @@ -3,11 +3,13 @@ (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) (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))) (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 $print "env" "print" (param i32)) (import $h "env" "h" (param i32)) @@ -861,6 +863,29 @@ (nop) ) ) + (func $dropCall (result i32) + (if + (i32.const 0) + (block + (drop + (call $phi) + ) + (drop + (call_import $setTempRet0 + (i32.const 10) + ) + ) + (call $zeroInit + (call_import $setTempRet0 + (i32.const 10) + ) + ) + ) + ) + (return + (call $phi) + ) + ) (func $z (nop) ) diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts index 56a1d4085..169d4fe5b 100644 --- a/test/unit.fromasm.no-opts +++ b/test/unit.fromasm.no-opts @@ -5,11 +5,13 @@ (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (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))) (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 $print "env" "print" (param i32)) (import $h "env" "h" (param i32)) @@ -867,6 +869,29 @@ (nop) ) ) + (func $dropCall (result i32) + (if + (i32.const 0) + (block + (drop + (call $phi) + ) + (drop + (call_import $setTempRet0 + (i32.const 10) + ) + ) + (call $zeroInit + (call_import $setTempRet0 + (i32.const 10) + ) + ) + ) + ) + (return + (call $phi) + ) + ) (func $z (nop) ) -- cgit v1.2.3 From f3bb9debe6af0576d76bda1580df2570e749bd36 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Aug 2016 16:01:10 -0700 Subject: handle asm.js globals that are set and the return value used --- src/asm2wasm.h | 5 ++++- test/unit.asm.js | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'test/unit.asm.js') diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 52598ad0b..321d5275e 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -1014,7 +1014,10 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { } // global var assert(mappedGlobals.find(name) != mappedGlobals.end()); - return builder.makeSetGlobal(name, process(ast[3])); + auto* ret = builder.makeSetGlobal(name, process(ast[3])); + // set_global does not return; if our value is trivially not used, don't emit a load (if nontrivially not used, opts get it later) + if (astStackHelper.getParent()[0] == STAT) return ret; + return builder.makeSequence(ret, builder.makeGetGlobal(name, ret->value->type)); } else if (ast[2][0] == SUB) { Ref target = ast[2]; assert(target[1][0] == NAME); diff --git a/test/unit.asm.js b/test/unit.asm.js index d6d0a27e8..cf2060030 100644 --- a/test/unit.asm.js +++ b/test/unit.asm.js @@ -281,6 +281,17 @@ function asm(global, env, buffer) { return phi() | 0; } + function useSetGlobal() { + var x = 0; + x = (Int = 10); + Int = 20; + return (Int = 30) | 0; + } + + function usesSetGlobal2() { + return (Int = 40, 50) | 0; + } + function z() { } function w() { -- cgit v1.2.3 From c05ac6a217cb7657c7aa4e248bcc76d47e65983d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Aug 2016 21:35:04 -0700 Subject: add a test for loop finalization --- test/unit.asm.js | 16 ++++++++++++++++ test/unit.fromasm | 21 +++++++++++++++++++++ test/unit.fromasm.imprecise | 21 +++++++++++++++++++++ test/unit.fromasm.imprecise.no-opts | 25 +++++++++++++++++++++++++ test/unit.fromasm.no-opts | 25 +++++++++++++++++++++++++ 5 files changed, 108 insertions(+) (limited to 'test/unit.asm.js') diff --git a/test/unit.asm.js b/test/unit.asm.js index cf2060030..b4c10b1d2 100644 --- a/test/unit.asm.js +++ b/test/unit.asm.js @@ -292,6 +292,22 @@ function asm(global, env, buffer) { return (Int = 40, 50) | 0; } + function breakThroughMany($s) { + $s = $s|0; + L1: do { + if ($s) { + while(1) { + if (!($s)) { + break L1; + } + zeroInit(0); + } + } else { + 1337; + } + } while(0); + } + function z() { } function w() { diff --git a/test/unit.fromasm b/test/unit.fromasm index 31c1d5b3d..cecbeef22 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -537,4 +537,25 @@ ) (i32.const 50) ) + (func $breakThroughMany (param $0 i32) + (block $label$break$L1 + (drop + (if + (get_local $0) + (loop $while-in$2 + (br_if $label$break$L1 + (i32.eqz + (get_local $0) + ) + ) + (call $zeroInit + (i32.const 0) + ) + (br $while-in$2) + ) + (i32.const 1337) + ) + ) + ) + ) ) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index 2e9ea8243..ba1af7916 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -519,4 +519,25 @@ ) (i32.const 50) ) + (func $breakThroughMany (param $0 i32) + (block $label$break$L1 + (drop + (if + (get_local $0) + (loop $while-in$2 + (br_if $label$break$L1 + (i32.eqz + (get_local $0) + ) + ) + (call $zeroInit + (i32.const 0) + ) + (br $while-in$2) + ) + (i32.const 1337) + ) + ) + ) + ) ) diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts index bec8a4f58..0c02680da 100644 --- a/test/unit.fromasm.imprecise.no-opts +++ b/test/unit.fromasm.imprecise.no-opts @@ -907,6 +907,31 @@ ) ) ) + (func $breakThroughMany (param $$s i32) + (block $label$break$L1 + (drop + (if + (get_local $$s) + (loop $while-in$2 + (block $while-out$1 + (if + (i32.eqz + (get_local $$s) + ) + (br $label$break$L1) + ) + (call $zeroInit + (i32.const 0) + ) + (br $while-in$2) + ) + ) + (i32.const 1337) + ) + ) + (nop) + ) + ) (func $z (nop) ) diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts index 936601995..fbbc6e7ff 100644 --- a/test/unit.fromasm.no-opts +++ b/test/unit.fromasm.no-opts @@ -913,6 +913,31 @@ ) ) ) + (func $breakThroughMany (param $$s i32) + (block $label$break$L1 + (drop + (if + (get_local $$s) + (loop $while-in$2 + (block $while-out$1 + (if + (i32.eqz + (get_local $$s) + ) + (br $label$break$L1) + ) + (call $zeroInit + (i32.const 0) + ) + (br $while-in$2) + ) + ) + (i32.const 1337) + ) + ) + (nop) + ) + ) (func $z (nop) ) -- cgit v1.2.3 From 14fe75e4d6e670d2e7f3e171d3d96c340b574eab Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 23 Aug 2016 11:39:58 -0700 Subject: when replacing an if with its condition (when it has no body), we must drop it --- src/passes/Vacuum.cpp | 2 +- test/unit.asm.js | 11 +++++++++++ test/unit.fromasm | 12 ++++++++++++ test/unit.fromasm.imprecise | 12 ++++++++++++ test/unit.fromasm.imprecise.no-opts | 21 +++++++++++++++++++++ test/unit.fromasm.no-opts | 21 +++++++++++++++++++++ 6 files changed, 78 insertions(+), 1 deletion(-) (limited to 'test/unit.asm.js') diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp index 150593713..89ef7359e 100644 --- a/src/passes/Vacuum.cpp +++ b/src/passes/Vacuum.cpp @@ -190,7 +190,7 @@ struct Vacuum : public WalkerPass> // no else if (curr->ifTrue->is()) { // no nothing - replaceCurrent(curr->condition); + replaceCurrent(Builder(*getModule()).makeDrop(curr->condition)); } } } diff --git a/test/unit.asm.js b/test/unit.asm.js index b4c10b1d2..8f0812e29 100644 --- a/test/unit.asm.js +++ b/test/unit.asm.js @@ -308,6 +308,17 @@ function asm(global, env, buffer) { } while(0); } + function ifChainEmpty(label) { + label = label | 0; + if ((label|0) == 4) { + return 0; + } + else if ((label|0) == 7) { + // unreachable; + } + return 0; + } + function z() { } function w() { diff --git a/test/unit.fromasm b/test/unit.fromasm index cecbeef22..bc5281ed5 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -558,4 +558,16 @@ ) ) ) + (func $ifChainEmpty (param $0 i32) (result i32) + (if + (i32.eq + (get_local $0) + (i32.const 4) + ) + (return + (i32.const 0) + ) + ) + (i32.const 0) + ) ) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index ba1af7916..945d6cc8e 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -540,4 +540,16 @@ ) ) ) + (func $ifChainEmpty (param $0 i32) (result i32) + (if + (i32.eq + (get_local $0) + (i32.const 4) + ) + (return + (i32.const 0) + ) + ) + (i32.const 0) + ) ) diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts index 0c02680da..f06912d08 100644 --- a/test/unit.fromasm.imprecise.no-opts +++ b/test/unit.fromasm.imprecise.no-opts @@ -932,6 +932,27 @@ (nop) ) ) + (func $ifChainEmpty (param $label i32) (result i32) + (if + (i32.eq + (get_local $label) + (i32.const 4) + ) + (return + (i32.const 0) + ) + (if + (i32.eq + (get_local $label) + (i32.const 7) + ) + (nop) + ) + ) + (return + (i32.const 0) + ) + ) (func $z (nop) ) diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts index fbbc6e7ff..222e0fa65 100644 --- a/test/unit.fromasm.no-opts +++ b/test/unit.fromasm.no-opts @@ -938,6 +938,27 @@ (nop) ) ) + (func $ifChainEmpty (param $label i32) (result i32) + (if + (i32.eq + (get_local $label) + (i32.const 4) + ) + (return + (i32.const 0) + ) + (if + (i32.eq + (get_local $label) + (i32.const 7) + ) + (nop) + ) + ) + (return + (i32.const 0) + ) + ) (func $z (nop) ) -- cgit v1.2.3 From d58adf43956c65615c9cd8d6c2f4c2a3cceff8bb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 28 Aug 2016 18:15:33 -0700 Subject: support HEAP8[x | 0| notation in asm2wasm --- src/asm2wasm.h | 4 +++- test/unit.asm.js | 5 +++++ test/unit.fromasm | 5 +++++ test/unit.fromasm.imprecise | 5 +++++ test/unit.fromasm.imprecise.no-opts | 7 +++++++ test/unit.fromasm.no-opts | 7 +++++++ 6 files changed, 32 insertions(+), 1 deletion(-) (limited to 'test/unit.asm.js') diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 0cb9b8dbe..059e51c59 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -1819,7 +1819,9 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { // if there is a shift, we can just look through it, etc. processUnshifted = [&](Ref ptr, unsigned bytes) { auto shifts = bytesToShift(bytes); - if (ptr[0] == BINARY && ptr[1] == RSHIFT && ptr[3][0] == NUM && ptr[3][1]->getInteger() == shifts) { + // HEAP?[addr >> ?], or HEAP8[x | 0] + if ((ptr[0] == BINARY && ptr[1] == RSHIFT && ptr[3][0] == NUM && ptr[3][1]->getInteger() == shifts) || + (bytes == 1 && ptr[0] == BINARY && ptr[1] == OR && ptr[3][0] == NUM && ptr[3][1]->getInteger() == 0)) { return process(ptr[2]); // look through it } else if (ptr[0] == NUM) { // constant, apply a shift (e.g. HEAP32[1] is address 4) diff --git a/test/unit.asm.js b/test/unit.asm.js index 8f0812e29..25aed0834 100644 --- a/test/unit.asm.js +++ b/test/unit.asm.js @@ -319,6 +319,11 @@ function asm(global, env, buffer) { return 0; } + function heap8NoShift(x) { + x = x | 0; + return HEAP8[x | 0] | 0; + } + function z() { } function w() { diff --git a/test/unit.fromasm b/test/unit.fromasm index 0260adb81..98202a4ec 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -575,4 +575,9 @@ ) (i32.const 0) ) + (func $heap8NoShift (param $0 i32) (result i32) + (i32.load8_s + (get_local $0) + ) + ) ) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index 5ebe88c6f..493ebb67e 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -556,4 +556,9 @@ ) (i32.const 0) ) + (func $heap8NoShift (param $0 i32) (result i32) + (i32.load8_s + (get_local $0) + ) + ) ) diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts index 7fdd01aaa..89a448a82 100644 --- a/test/unit.fromasm.imprecise.no-opts +++ b/test/unit.fromasm.imprecise.no-opts @@ -956,6 +956,13 @@ (i32.const 0) ) ) + (func $heap8NoShift (param $x i32) (result i32) + (return + (i32.load8_s + (get_local $x) + ) + ) + ) (func $z (nop) ) diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts index 14c4d6615..f1253c849 100644 --- a/test/unit.fromasm.no-opts +++ b/test/unit.fromasm.no-opts @@ -962,6 +962,13 @@ (i32.const 0) ) ) + (func $heap8NoShift (param $x i32) (result i32) + (return + (i32.load8_s + (get_local $x) + ) + ) + ) (func $z (nop) ) -- cgit v1.2.3 From 0793f2f87ca023e1769c7e7d4c64fa16d7fec1a2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 28 Aug 2016 19:20:53 -0700 Subject: Add a ReFinalize helper, and use that to properly handle asm.js imports whose return value is polymorphic --- src/asm2wasm.h | 34 ++++++++++++++----- src/ast_utils.h | 28 ++++++++++++++++ test/unit.asm.js | 6 ++++ test/unit.fromasm | 64 +++++++++++++++++++++++++++-------- test/unit.fromasm.imprecise | 64 +++++++++++++++++++++++++++-------- test/unit.fromasm.imprecise.no-opts | 66 +++++++++++++++++++++++++++++-------- test/unit.fromasm.no-opts | 66 +++++++++++++++++++++++++++++-------- 7 files changed, 263 insertions(+), 65 deletions(-) (limited to 'test/unit.asm.js') 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(); @@ -789,6 +804,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) { }; PassRunner passRunner(&wasm); passRunner.add(this); + passRunner.add(); // FinalizeCalls changes call types, need to percolate passRunner.add(); // 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>> { + 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) ) -- cgit v1.2.3