summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asm2wasm.h25
-rw-r--r--src/asmjs/shared-constants.cpp4
-rw-r--r--src/asmjs/shared-constants.h4
-rw-r--r--src/js/wasm.js-post.js12
-rw-r--r--test/emcc_O2_hello_world.fromasm5
-rw-r--r--test/emcc_O2_hello_world.fromasm.no-opts5
-rw-r--r--test/emcc_hello_world.fromasm65
-rw-r--r--test/emcc_hello_world.fromasm.no-opts38
-rw-r--r--test/memorygrowth.fromasm5
-rw-r--r--test/memorygrowth.fromasm.no-opts5
-rw-r--r--test/unit.fromasm10
-rw-r--r--test/unit.fromasm.no-opts4
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)
)