diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-07-14 17:59:33 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-14 17:59:33 -0700 |
commit | e4f99f6c81a5f23318787adba6fea1137dc755bb (patch) | |
tree | 2fff27409e894cbfb0d473c4e768455795903505 /src | |
parent | 4994da80284c337e5395ad836948ee38ffb967f1 (diff) | |
download | binaryen-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.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 |
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; }, |