summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-04-18 17:27:32 -0700
committerGitHub <noreply@github.com>2017-04-18 17:27:32 -0700
commitc945f3be7732e77402d696389482b290be7626cd (patch)
tree4c7b5ccbe6f57ff4ec5aa9e89bc298f38dc5408f
parent0dc8efbf7f5ac474fadff934eb78cd5f8551d0bb (diff)
parenta9b1d78072bd1875d926cfb0ae51a6eb4dc49b4e (diff)
downloadbinaryen-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-xcheck.py1
-rw-r--r--src/asm2wasm.h20
-rw-r--r--test/emcc_hello_world.fromasm.imprecise2
-rw-r--r--test/emcc_hello_world.fromasm.imprecise.no-opts2
-rw-r--r--test/unit.asm.js11
-rw-r--r--test/unit.fromasm15
-rw-r--r--test/unit.fromasm.clamp15
-rw-r--r--test/unit.fromasm.clamp.no-opts24
-rw-r--r--test/unit.fromasm.imprecise20
-rw-r--r--test/unit.fromasm.imprecise.no-opts24
-rw-r--r--test/unit.fromasm.no-opts24
11 files changed, 153 insertions, 5 deletions
diff --git a/check.py b/check.py
index 57eedc423..2171a330d 100755
--- a/check.py
+++ b/check.py
@@ -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)