summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-07-14 17:59:33 -0700
committerGitHub <noreply@github.com>2016-07-14 17:59:33 -0700
commite4f99f6c81a5f23318787adba6fea1137dc755bb (patch)
tree2fff27409e894cbfb0d473c4e768455795903505 /src
parent4994da80284c337e5395ad836948ee38ffb967f1 (diff)
downloadbinaryen-e4f99f6c81a5f23318787adba6fea1137dc755bb.tar.gz
binaryen-e4f99f6c81a5f23318787adba6fea1137dc755bb.tar.bz2
binaryen-e4f99f6c81a5f23318787adba6fea1137dc755bb.zip
emit safe calls for i32 div/rem when in precise mode in asm2wasm, as they can trap (#637)
Diffstat (limited to 'src')
-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
4 files changed, 45 insertions, 0 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;
},