summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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.fromasm.imprecise7
-rw-r--r--test/unit.fromasm.imprecise.no-opts2
5 files changed, 26 insertions, 7 deletions
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.fromasm.imprecise b/test/unit.fromasm.imprecise
index 18eba6cee..3254980d9 100644
--- a/test/unit.fromasm.imprecise
+++ b/test/unit.fromasm.imprecise
@@ -1124,6 +1124,11 @@
)
)
(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)
)
@@ -1140,7 +1145,7 @@
)
)
(drop
- (call $f2u
+ (call $f2s
(f64.const 100)
)
)
diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts
index 109afbf26..736f51222 100644
--- a/test/unit.fromasm.imprecise.no-opts
+++ b/test/unit.fromasm.imprecise.no-opts
@@ -1873,7 +1873,7 @@
)
(func $f2u (param $x f64) (result i32)
(return
- (i32.trunc_s/f64
+ (i32.trunc_u/f64
(get_local $x)
)
)