diff options
-rw-r--r-- | src/asm2wasm.h | 25 | ||||
-rw-r--r-- | src/asmjs/shared-constants.cpp | 4 | ||||
-rw-r--r-- | src/asmjs/shared-constants.h | 4 | ||||
-rw-r--r-- | src/js/wasm.js-post.js | 12 | ||||
-rw-r--r-- | test/emcc_O2_hello_world.fromasm | 5 | ||||
-rw-r--r-- | test/emcc_O2_hello_world.fromasm.no-opts | 5 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm | 65 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm.no-opts | 38 | ||||
-rw-r--r-- | test/memorygrowth.fromasm | 5 | ||||
-rw-r--r-- | test/memorygrowth.fromasm.no-opts | 5 | ||||
-rw-r--r-- | test/unit.fromasm | 10 | ||||
-rw-r--r-- | test/unit.fromasm.no-opts | 4 |
12 files changed, 129 insertions, 53 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 994342b4e..c0f13ff8f 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -1075,6 +1075,31 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { wasm.addImport(import); } return call; + } else if (!imprecise && (ret->op == BinaryOp::RemSInt32 || ret->op == BinaryOp::RemUInt32 || + ret->op == BinaryOp::DivSInt32 || ret->op == BinaryOp::DivUInt32)) { + // we are precise, and the wasm operation might trap if done over 0, so generate a safe call + CallImport *call = allocator.alloc<CallImport>(); + switch (ret->op) { + case BinaryOp::RemSInt32: call->target = I32S_REM; break; + case BinaryOp::RemUInt32: call->target = I32U_REM; break; + case BinaryOp::DivSInt32: call->target = I32S_DIV; break; + case BinaryOp::DivUInt32: call->target = I32U_DIV; break; + default: WASM_UNREACHABLE(); + } + call->operands.push_back(ret->left); + call->operands.push_back(ret->right); + call->type = i32; + static std::set<Name> addedImport; + if (addedImport.count(call->target) == 0) { + addedImport.insert(call->target); + auto import = new Import; + import->name = call->target; + import->module = ASM2WASM; + import->base = call->target; + import->type = ensureFunctionType("iii", &wasm); + wasm.addImport(import); + } + return call; } return ret; } else if (what == NUM) { diff --git a/src/asmjs/shared-constants.cpp b/src/asmjs/shared-constants.cpp index b2321a209..e30fd939c 100644 --- a/src/asmjs/shared-constants.cpp +++ b/src/asmjs/shared-constants.cpp @@ -40,6 +40,10 @@ cashew::IString GLOBAL("global"), ASM2WASM("asm2wasm"), F64_REM("f64-rem"), F64_TO_INT("f64-to-int"), + I32S_DIV("i32s-div"), + I32U_DIV("i32u-div"), + I32S_REM("i32s-rem"), + I32U_REM("i32u-rem"), GLOBAL_MATH("global.Math"), ABS("abs"), FLOOR("floor"), diff --git a/src/asmjs/shared-constants.h b/src/asmjs/shared-constants.h index fb32340ab..e0c627511 100644 --- a/src/asmjs/shared-constants.h +++ b/src/asmjs/shared-constants.h @@ -43,6 +43,10 @@ extern cashew::IString GLOBAL, ASM2WASM, F64_REM, F64_TO_INT, + I32S_DIV, + I32U_DIV, + I32S_REM, + I32U_REM, GLOBAL_MATH, ABS, FLOOR, diff --git a/src/js/wasm.js-post.js b/src/js/wasm.js-post.js index 6d73981f1..ae42ef175 100644 --- a/src/js/wasm.js-post.js +++ b/src/js/wasm.js-post.js @@ -45,6 +45,18 @@ function integrateWasmJS(Module) { "f64-to-int": function(x) { return x | 0; }, + "i32s-div": function(x, y) { + return ((x | 0) / (y | 0)) | 0; + }, + "i32u-div": function(x, y) { + return ((x >>> 0) / (y >>> 0)) >>> 0; + }, + "i32s-rem": function(x, y) { + return ((x | 0) % (y | 0)) | 0; + }, + "i32u-rem": function(x, y) { + return ((x >>> 0) % (y >>> 0)) >>> 0; + }, "debugger": function() { debugger; }, diff --git a/test/emcc_O2_hello_world.fromasm b/test/emcc_O2_hello_world.fromasm index be4324f2c..628abd77d 100644 --- a/test/emcc_O2_hello_world.fromasm +++ b/test/emcc_O2_hello_world.fromasm @@ -2,10 +2,10 @@ (memory 256 256) (export "memory" memory) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$i (func (result i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$v (func)) (type $FUNCSIG$vii (func (param i32 i32))) (import $abort "env" "abort" (param i32)) @@ -23,6 +23,7 @@ (import $___unlock "env" "___unlock" (param i32)) (import $___syscall140 "env" "___syscall140" (param i32 i32) (result i32)) (import $___syscall146 "env" "___syscall146" (param i32 i32) (result i32)) + (import $i32u-div "asm2wasm" "i32u-div" (param i32 i32) (result i32)) (export "_free" $_free) (export "_main" $_main) (export "_memset" $_memset) @@ -9618,7 +9619,7 @@ (get_local $4) ) (get_local $2) - (i32.div_u + (call_import $i32u-div (get_local $0) (get_local $1) ) diff --git a/test/emcc_O2_hello_world.fromasm.no-opts b/test/emcc_O2_hello_world.fromasm.no-opts index d34022a9e..f850b8306 100644 --- a/test/emcc_O2_hello_world.fromasm.no-opts +++ b/test/emcc_O2_hello_world.fromasm.no-opts @@ -2,10 +2,10 @@ (memory 256 256) (export "memory" memory) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$i (func (result i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$v (func)) (type $FUNCSIG$vii (func (param i32 i32))) (import $abort "env" "abort" (param i32)) @@ -23,6 +23,7 @@ (import $___unlock "env" "___unlock" (param i32)) (import $___syscall140 "env" "___syscall140" (param i32 i32) (result i32)) (import $___syscall146 "env" "___syscall146" (param i32 i32) (result i32)) + (import $i32u-div "asm2wasm" "i32u-div" (param i32 i32) (result i32)) (export "_free" $_free) (export "_main" $_main) (export "_memset" $_memset) @@ -11326,7 +11327,7 @@ (get_local $i3) ) (set_local $i9 - (i32.div_u + (call_import $i32u-div (get_local $i8) (get_local $i2) ) diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm index 79f28f9e8..93932a33f 100644 --- a/test/emcc_hello_world.fromasm +++ b/test/emcc_hello_world.fromasm @@ -3,11 +3,11 @@ (export "memory" memory) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$id (func (param f64) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$v (func)) (type $FUNCSIG$i (func (result i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$vii (func (param i32 i32))) (import $abort "env" "abort") (import $nullFunc_ii "env" "nullFunc_ii" (param i32)) @@ -28,6 +28,10 @@ (import $_sysconf "env" "_sysconf" (param i32) (result i32)) (import $___syscall146 "env" "___syscall146" (param i32 i32) (result i32)) (import $f64-to-int "asm2wasm" "f64-to-int" (param f64) (result i32)) + (import $i32s-div "asm2wasm" "i32s-div" (param i32 i32) (result i32)) + (import $i32s-rem "asm2wasm" "i32s-rem" (param i32 i32) (result i32)) + (import $i32u-rem "asm2wasm" "i32u-rem" (param i32 i32) (result i32)) + (import $i32u-div "asm2wasm" "i32u-div" (param i32 i32) (result i32)) (export "_i64Subtract" $_i64Subtract) (export "_free" $_free) (export "_main" $_main) @@ -6057,7 +6061,7 @@ (set_local $8 (i32.add (i32.and - (i32.div_s + (call_import $i32s-div (i32.add (get_local $1) (i32.const 25) @@ -6441,7 +6445,7 @@ (i32.shl (i32.add (i32.and - (i32.div_s + (call_import $i32s-div (set_local $5 (i32.add (get_local $5) @@ -6463,7 +6467,7 @@ (set_local $9 (i32.add (i32.and - (i32.rem_s + (call_import $i32s-rem (get_local $5) (i32.const 9) ) @@ -6524,7 +6528,7 @@ (i32.eq (set_local $21 (i32.and - (i32.rem_u + (call_import $i32u-rem (set_local $5 (i32.load (get_local $7) @@ -6557,7 +6561,7 @@ (i32.eq (i32.and (i32.and - (i32.div_u + (call_import $i32u-div (get_local $5) (get_local $16) ) @@ -6575,7 +6579,7 @@ (get_local $21) (set_local $13 (i32.and - (i32.div_s + (call_import $i32s-div (get_local $16) (i32.const 2) ) @@ -6998,7 +7002,7 @@ (if (i32.eq (i32.and - (i32.rem_u + (call_import $i32u-rem (get_local $1) (i32.const 10) ) @@ -7031,7 +7035,7 @@ (if (i32.ne (i32.and - (i32.rem_u + (call_import $i32u-rem (get_local $1) (set_local $5 (i32.mul @@ -9516,7 +9520,7 @@ (i32.and (i32.or (i32.and - (i32.rem_u + (call_import $i32u-rem (get_local $2) (i32.const 10) ) @@ -9529,7 +9533,7 @@ ) (set_local $0 (i32.and - (i32.div_u + (call_import $i32u-div (get_local $2) (i32.const 10) ) @@ -18885,7 +18889,7 @@ (block (i32.store (get_local $4) - (i32.rem_u + (call_import $i32u-rem (get_local $7) (get_local $5) ) @@ -18896,15 +18900,18 @@ ) ) ) + (set_local $0 + (call_import $i32u-div + (get_local $7) + (get_local $5) + ) + ) (i32.store (i32.const 168) (i32.const 0) ) (return - (i32.div_u - (get_local $7) - (get_local $5) - ) + (get_local $0) ) ) (block @@ -18971,7 +18978,7 @@ (block (i32.store (get_local $4) - (i32.rem_u + (call_import $i32u-rem (get_local $6) (get_local $5) ) @@ -18982,15 +18989,18 @@ ) ) ) + (set_local $0 + (call_import $i32u-div + (get_local $6) + (get_local $5) + ) + ) (i32.store (i32.const 168) (i32.const 0) ) (return - (i32.div_u - (get_local $6) - (get_local $5) - ) + (get_local $0) ) ) ) @@ -19012,22 +19022,25 @@ ) (i32.store offset=4 (get_local $4) - (i32.rem_u + (call_import $i32u-rem (get_local $6) (get_local $8) ) ) ) ) + (set_local $0 + (call_import $i32u-div + (get_local $6) + (get_local $8) + ) + ) (i32.store (i32.const 168) (i32.const 0) ) (return - (i32.div_u - (get_local $6) - (get_local $8) - ) + (get_local $0) ) ) ) diff --git a/test/emcc_hello_world.fromasm.no-opts b/test/emcc_hello_world.fromasm.no-opts index ffd67e6f0..41e3e9e26 100644 --- a/test/emcc_hello_world.fromasm.no-opts +++ b/test/emcc_hello_world.fromasm.no-opts @@ -3,11 +3,11 @@ (export "memory" memory) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$id (func (param f64) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$v (func)) (type $FUNCSIG$i (func (result i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$vii (func (param i32 i32))) (import $abort "env" "abort") (import $nullFunc_ii "env" "nullFunc_ii" (param i32)) @@ -28,6 +28,10 @@ (import $_sysconf "env" "_sysconf" (param i32) (result i32)) (import $___syscall146 "env" "___syscall146" (param i32 i32) (result i32)) (import $f64-to-int "asm2wasm" "f64-to-int" (param f64) (result i32)) + (import $i32s-div "asm2wasm" "i32s-div" (param i32 i32) (result i32)) + (import $i32s-rem "asm2wasm" "i32s-rem" (param i32 i32) (result i32)) + (import $i32u-rem "asm2wasm" "i32u-rem" (param i32 i32) (result i32)) + (import $i32u-div "asm2wasm" "i32u-div" (param i32 i32) (result i32)) (export "_i64Subtract" $_i64Subtract) (export "_free" $_free) (export "_main" $_main) @@ -10317,7 +10321,7 @@ ) (set_local $$div274$i (i32.and - (i32.div_s + (call_import $i32s-div (get_local $$add273$i) (i32.const 9) ) @@ -10865,7 +10869,7 @@ ) (set_local $$div356$i (i32.and - (i32.div_s + (call_import $i32s-div (get_local $$add355$i) (i32.const 9) ) @@ -10889,7 +10893,7 @@ ) (set_local $$rem360$i (i32.and - (i32.rem_s + (call_import $i32s-rem (get_local $$add355$i) (i32.const 9) ) @@ -10967,7 +10971,7 @@ ) (set_local $$rem370$i (i32.and - (i32.rem_u + (call_import $i32u-rem (get_local $$231) (get_local $$i$1$lcssa$i) ) @@ -11015,7 +11019,7 @@ (block (set_local $$div378$i (i32.and - (i32.div_u + (call_import $i32u-div (get_local $$231) (get_local $$i$1$lcssa$i) ) @@ -11043,7 +11047,7 @@ ) (set_local $$div384$i (i32.and - (i32.div_s + (call_import $i32s-div (get_local $$i$1$lcssa$i) (i32.const 2) ) @@ -11666,7 +11670,7 @@ ) (set_local $$rem494$510$i (i32.and - (i32.rem_u + (call_import $i32u-rem (get_local $$237) (i32.const 10) ) @@ -11711,7 +11715,7 @@ ) (set_local $$rem494$i (i32.and - (i32.rem_u + (call_import $i32u-rem (get_local $$237) (get_local $$mul499$i) ) @@ -16032,7 +16036,7 @@ (loop $while-out$2 $while-in$3 (set_local $$rem4 (i32.and - (i32.rem_u + (call_import $i32u-rem (get_local $$y$010) (i32.const 10) ) @@ -16063,7 +16067,7 @@ ) (set_local $$div9 (i32.and - (i32.div_u + (call_import $i32u-div (get_local $$y$010) (i32.const 10) ) @@ -31549,7 +31553,7 @@ (block (i32.store (get_local $$rem) - (i32.rem_u + (call_import $i32u-rem (get_local $$n_sroa_0_0_extract_trunc) (get_local $$d_sroa_0_0_extract_trunc) ) @@ -31567,7 +31571,7 @@ (i32.const 0) ) (set_local $$_0$0 - (i32.div_u + (call_import $i32u-div (get_local $$n_sroa_0_0_extract_trunc) (get_local $$d_sroa_0_0_extract_trunc) ) @@ -31665,7 +31669,7 @@ (block (i32.store (get_local $$rem) - (i32.rem_u + (call_import $i32u-rem (get_local $$n_sroa_1_4_extract_trunc) (get_local $$d_sroa_0_0_extract_trunc) ) @@ -31683,7 +31687,7 @@ (i32.const 0) ) (set_local $$_0$0 - (i32.div_u + (call_import $i32u-div (get_local $$n_sroa_1_4_extract_trunc) (get_local $$d_sroa_0_0_extract_trunc) ) @@ -31720,7 +31724,7 @@ (get_local $$rem) (i32.const 4) ) - (i32.rem_u + (call_import $i32u-rem (get_local $$n_sroa_1_4_extract_trunc) (get_local $$d_sroa_1_4_extract_trunc) ) @@ -31731,7 +31735,7 @@ (i32.const 0) ) (set_local $$_0$0 - (i32.div_u + (call_import $i32u-div (get_local $$n_sroa_1_4_extract_trunc) (get_local $$d_sroa_1_4_extract_trunc) ) diff --git a/test/memorygrowth.fromasm b/test/memorygrowth.fromasm index 9f2c4b2b8..394cc94c9 100644 --- a/test/memorygrowth.fromasm +++ b/test/memorygrowth.fromasm @@ -2,11 +2,11 @@ (memory 256 256) (export "memory" memory) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$v (func)) (type $FUNCSIG$vii (func (param i32 i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (import $ja "env" "abort" (param i32)) (import $oa "env" "_pthread_cleanup_pop" (param i32)) (import $pa "env" "___lock" (param i32)) @@ -19,6 +19,7 @@ (import $wa "env" "___syscall54" (param i32 i32) (result i32)) (import $xa "env" "___unlock" (param i32)) (import $ya "env" "___syscall146" (param i32 i32) (result i32)) + (import $i32u-div "asm2wasm" "i32u-div" (param i32 i32) (result i32)) (export "_free" $fb) (export "_main" $Na) (export "_pthread_self" $ib) @@ -9607,7 +9608,7 @@ (get_local $4) ) (get_local $2) - (i32.div_u + (call_import $i32u-div (get_local $0) (get_local $1) ) diff --git a/test/memorygrowth.fromasm.no-opts b/test/memorygrowth.fromasm.no-opts index dd03e651e..29aa4aa30 100644 --- a/test/memorygrowth.fromasm.no-opts +++ b/test/memorygrowth.fromasm.no-opts @@ -2,11 +2,11 @@ (memory 256 256) (export "memory" memory) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$v (func)) (type $FUNCSIG$vii (func (param i32 i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (import $ja "env" "abort" (param i32)) (import $oa "env" "_pthread_cleanup_pop" (param i32)) (import $pa "env" "___lock" (param i32)) @@ -19,6 +19,7 @@ (import $wa "env" "___syscall54" (param i32 i32) (result i32)) (import $xa "env" "___unlock" (param i32)) (import $ya "env" "___syscall146" (param i32 i32) (result i32)) + (import $i32u-div "asm2wasm" "i32u-div" (param i32 i32) (result i32)) (export "_free" $fb) (export "_main" $Na) (export "_pthread_self" $ib) @@ -11295,7 +11296,7 @@ (get_local $c) ) (set_local $i - (i32.div_u + (call_import $i32u-div (get_local $h) (get_local $b) ) diff --git a/test/unit.fromasm b/test/unit.fromasm index e5b08cdf5..15a2f2007 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -3,6 +3,7 @@ (export "memory" memory) (type $FUNCSIG$id (func (param f64) (result i32))) (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$vd (func (param f64))) @@ -11,6 +12,7 @@ (import $h "env" "h" (param i32)) (import $f64-to-int "asm2wasm" "f64-to-int" (param f64) (result i32)) (import $f64-rem "asm2wasm" "f64-rem" (param f64 f64) (result f64)) + (import $i32u-div "asm2wasm" "i32u-div" (param i32 i32) (result i32)) (export "big_negative" $big_negative) (export "pick" $big_negative) (table $big_negative $big_negative $big_negative $big_negative $big_negative $big_negative $importedDoubles $big_negative $big_negative $cneg) @@ -208,7 +210,13 @@ ) ) (func $big_uint_div_u (result i32) - (i32.const 2147483647) + (i32.and + (call_import $i32u-div + (i32.const -1) + (i32.const 2) + ) + (i32.const -1) + ) ) (func $fr (param $0 f32) (nop) diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts index e4338b657..c10bd3dff 100644 --- a/test/unit.fromasm.no-opts +++ b/test/unit.fromasm.no-opts @@ -3,6 +3,7 @@ (export "memory" memory) (type $FUNCSIG$id (func (param f64) (result i32))) (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$vd (func (param f64))) @@ -11,6 +12,7 @@ (import $h "env" "h" (param i32)) (import $f64-to-int "asm2wasm" "f64-to-int" (param f64) (result i32)) (import $f64-rem "asm2wasm" "f64-rem" (param f64 f64) (result f64)) + (import $i32u-div "asm2wasm" "i32u-div" (param i32 i32) (result i32)) (export "big_negative" $big_negative) (export "pick" $exportMe) (table $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg) @@ -329,7 +331,7 @@ (local $x i32) (set_local $x (i32.and - (i32.div_u + (call_import $i32u-div (i32.const -1) (i32.const 2) ) |