diff options
author | Alon Zakai <alonzakai@gmail.com> | 2017-04-18 17:27:32 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-18 17:27:32 -0700 |
commit | c945f3be7732e77402d696389482b290be7626cd (patch) | |
tree | 4c7b5ccbe6f57ff4ec5aa9e89bc298f38dc5408f | |
parent | 0dc8efbf7f5ac474fadff934eb78cd5f8551d0bb (diff) | |
parent | a9b1d78072bd1875d926cfb0ae51a6eb4dc49b4e (diff) | |
download | binaryen-c945f3be7732e77402d696389482b290be7626cd.tar.gz binaryen-c945f3be7732e77402d696389482b290be7626cd.tar.bz2 binaryen-c945f3be7732e77402d696389482b290be7626cd.zip |
Merge pull request #976 from WebAssembly/fix-f2u
Fix asm2wasm unsigned float-to-int
-rwxr-xr-x | check.py | 1 | ||||
-rw-r--r-- | src/asm2wasm.h | 20 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm.imprecise | 2 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm.imprecise.no-opts | 2 | ||||
-rw-r--r-- | test/unit.asm.js | 11 | ||||
-rw-r--r-- | test/unit.fromasm | 15 | ||||
-rw-r--r-- | test/unit.fromasm.clamp | 15 | ||||
-rw-r--r-- | test/unit.fromasm.clamp.no-opts | 24 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise | 20 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise.no-opts | 24 | ||||
-rw-r--r-- | test/unit.fromasm.no-opts | 24 |
11 files changed, 153 insertions, 5 deletions
@@ -576,6 +576,7 @@ if EMCC: for method in ['interpret-asm2wasm', 'interpret-s-expr', 'interpret-binary']: command = [EMCC, '-o', 'a.wasm.js', '-s', 'BINARYEN=1', os.path.join(options.binaryen_test, c)] + opts + extra command += ['-s', 'BINARYEN_METHOD="' + method + '"'] + command += ['-s', 'BINARYEN_TRAP_MODE="js"'] print '....' + ' '.join(command) subprocess.check_call(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if post: diff --git a/src/asm2wasm.h b/src/asm2wasm.h index ada026176..ed8c75e56 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -485,6 +485,14 @@ private: return detectSign(ast, Math_fround) == ASM_UNSIGNED; } + bool isParentUnsignedCoercion(Ref parent) { + // parent may not exist, or may be a non-relevant node + if (!!parent && parent->isArray() && parent[0] == BINARY && isUnsignedCoercion(parent)) { + return true; + } + return false; + } + BinaryOp parseAsmBinaryOp(IString op, Ref left, Ref right, Expression* leftWasm, Expression* rightWasm) { WasmType leftType = leftWasm->type; bool isInteger = leftType == WasmType::i32; @@ -735,11 +743,16 @@ private: } // Some conversions might trap, so emit them safely if necessary - Expression* makeTrappingFloatToInt(Expression* value) { + Expression* makeTrappingFloatToInt(bool signed_, Expression* value) { if (trapMode == TrapMode::Allow) { auto ret = allocator.alloc<Unary>(); ret->value = value; - ret->op = ret->value->type == f64 ? TruncSFloat64ToInt32 : TruncSFloat32ToInt32; + bool isF64 = ret->value->type == f64; + if (signed_) { + ret->op = isF64 ? TruncSFloat64ToInt32 : TruncSFloat32ToInt32; + } else { + ret->op = isF64 ? TruncUFloat64ToInt32 : TruncUFloat32ToInt32; + } ret->type = WasmType::i32; return ret; } @@ -1752,7 +1765,8 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { } else if (ast[1] == B_NOT) { // ~, might be ~~ as a coercion or just a not if (ast[2]->isArray(UNARY_PREFIX) && ast[2][1] == B_NOT) { - return makeTrappingFloatToInt(process(ast[2][2])); + // if we have an unsigned coercion on us, it is an unsigned op + return makeTrappingFloatToInt(!isParentUnsignedCoercion(astStackHelper.getParent()), process(ast[2][2])); } // no bitwise unary not, so do xor with -1 auto ret = allocator.alloc<Binary>(); diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise index 20af7061a..3aa9ed739 100644 --- a/test/emcc_hello_world.fromasm.imprecise +++ b/test/emcc_hello_world.fromasm.imprecise @@ -4530,7 +4530,7 @@ (i32.store (get_local $7) (tee_local $5 - (i32.trunc_s/f64 + (i32.trunc_u/f64 (get_local $15) ) ) diff --git a/test/emcc_hello_world.fromasm.imprecise.no-opts b/test/emcc_hello_world.fromasm.imprecise.no-opts index 7faa18088..d33f824e2 100644 --- a/test/emcc_hello_world.fromasm.imprecise.no-opts +++ b/test/emcc_hello_world.fromasm.imprecise.no-opts @@ -9847,7 +9847,7 @@ (loop $while-in60 (block $while-out59 (set_local $$conv216$i - (i32.trunc_s/f64 + (i32.trunc_u/f64 (get_local $$y$addr$4$i) ) ) diff --git a/test/unit.asm.js b/test/unit.asm.js index 11de89c60..9d5f40aea 100644 --- a/test/unit.asm.js +++ b/test/unit.asm.js @@ -680,8 +680,19 @@ function asm(global, env, buffer) { return +(+Math_sqrt(x) + +Math_fround(Math_sqrt(Math_fround(x)))); } + function f2u(x) { + x = +x; + return (~~x>>>0) | 0; + } + function f2s(x) { + x = +x; + return (~~x) | 0; + } + function keepAlive() { sqrts(3.14159); + f2u(100.0); + f2s(100.0); } function v() { diff --git a/test/unit.fromasm b/test/unit.fromasm index fd0fb27a0..45dc81937 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -1155,12 +1155,27 @@ ) ) ) + (func $f2u (param $0 f64) (result i32) + (call $f64-to-int + (get_local $0) + ) + ) (func $keepAlive (drop (call $sqrts (f64.const 3.14159) ) ) + (drop + (call $f2u + (f64.const 100) + ) + ) + (drop + (call $f2u + (f64.const 100) + ) + ) ) (func $vi (param $0 i32) (nop) diff --git a/test/unit.fromasm.clamp b/test/unit.fromasm.clamp index ffe26a3a2..469c4932b 100644 --- a/test/unit.fromasm.clamp +++ b/test/unit.fromasm.clamp @@ -1179,12 +1179,27 @@ ) ) ) + (func $f2u (param $0 f64) (result i32) + (call $f64-to-int + (get_local $0) + ) + ) (func $keepAlive (drop (call $sqrts (f64.const 3.14159) ) ) + (drop + (call $f2u + (f64.const 100) + ) + ) + (drop + (call $f2u + (f64.const 100) + ) + ) ) (func $vi (param $0 i32) (nop) diff --git a/test/unit.fromasm.clamp.no-opts b/test/unit.fromasm.clamp.no-opts index 9d9258bf2..d8fab1d25 100644 --- a/test/unit.fromasm.clamp.no-opts +++ b/test/unit.fromasm.clamp.no-opts @@ -1911,12 +1911,36 @@ ) ) ) + (func $f2u (param $x f64) (result i32) + (return + (call $f64-to-int + (get_local $x) + ) + ) + ) + (func $f2s (param $x f64) (result i32) + (return + (call $f64-to-int + (get_local $x) + ) + ) + ) (func $keepAlive (drop (call $sqrts (f64.const 3.14159) ) ) + (drop + (call $f2u + (f64.const 100) + ) + ) + (drop + (call $f2s + (f64.const 100) + ) + ) ) (func $v (nop) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index e94c07f7f..3254980d9 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -1123,12 +1123,32 @@ ) ) ) + (func $f2u (param $0 f64) (result i32) + (i32.trunc_u/f64 + (get_local $0) + ) + ) + (func $f2s (param $0 f64) (result i32) + (i32.trunc_s/f64 + (get_local $0) + ) + ) (func $keepAlive (drop (call $sqrts (f64.const 3.14159) ) ) + (drop + (call $f2u + (f64.const 100) + ) + ) + (drop + (call $f2s + (f64.const 100) + ) + ) ) (func $vi (param $0 i32) (nop) diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts index f1625311d..736f51222 100644 --- a/test/unit.fromasm.imprecise.no-opts +++ b/test/unit.fromasm.imprecise.no-opts @@ -1871,12 +1871,36 @@ ) ) ) + (func $f2u (param $x f64) (result i32) + (return + (i32.trunc_u/f64 + (get_local $x) + ) + ) + ) + (func $f2s (param $x f64) (result i32) + (return + (i32.trunc_s/f64 + (get_local $x) + ) + ) + ) (func $keepAlive (drop (call $sqrts (f64.const 3.14159) ) ) + (drop + (call $f2u + (f64.const 100) + ) + ) + (drop + (call $f2s + (f64.const 100) + ) + ) ) (func $v (nop) diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts index 2bffda308..3b80ebe1b 100644 --- a/test/unit.fromasm.no-opts +++ b/test/unit.fromasm.no-opts @@ -1887,12 +1887,36 @@ ) ) ) + (func $f2u (param $x f64) (result i32) + (return + (call $f64-to-int + (get_local $x) + ) + ) + ) + (func $f2s (param $x f64) (result i32) + (return + (call $f64-to-int + (get_local $x) + ) + ) + ) (func $keepAlive (drop (call $sqrts (f64.const 3.14159) ) ) + (drop + (call $f2u + (f64.const 100) + ) + ) + (drop + (call $f2s + (f64.const 100) + ) + ) ) (func $v (nop) |