summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asm2wasm.h53
-rw-r--r--test/unit.asm.js5
-rw-r--r--test/unit.fromasm14
-rw-r--r--test/unit.fromasm.clamp14
-rw-r--r--test/unit.fromasm.clamp.no-opts20
-rw-r--r--test/unit.fromasm.imprecise14
-rw-r--r--test/unit.fromasm.imprecise.no-opts20
-rw-r--r--test/unit.fromasm.no-opts20
8 files changed, 126 insertions, 34 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index e2b1802b5..9abfe7432 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -675,6 +675,19 @@ private:
return ret;
}
+ // converts an f32 to an f64 if necessary
+ Expression* ensureDouble(Expression* expr) {
+ if (expr->type == f32) {
+ auto conv = allocator.alloc<Unary>();
+ conv->op = PromoteFloat32;
+ conv->value = expr;
+ conv->type = WasmType::f64;
+ return conv;
+ }
+ assert(expr->type == f64);
+ return expr;
+ }
+
// Some binary opts might trap, so emit them safely if necessary
Expression* makeTrappingI32Binary(BinaryOp op, Expression* left, Expression* right) {
if (trapMode == TrapMode::Allow) return builder.makeBinary(op, left, right);
@@ -803,14 +816,7 @@ private:
}
// WebAssembly traps on float-to-int overflows, but asm.js wouldn't, so we must do something
// First, normalize input to f64
- auto input = value;
- if (input->type == f32) {
- auto conv = allocator.alloc<Unary>();
- conv->op = PromoteFloat32;
- conv->value = input;
- conv->type = WasmType::f64;
- input = conv;
- }
+ auto input = ensureDouble(value);
// We can handle this in one of two ways: clamping, which is fast, or JS, which
// is precisely like JS but in order to do that we do a slow ffi
if (trapMode == TrapMode::JS) {
@@ -894,14 +900,7 @@ private:
}
// WebAssembly traps on float-to-int overflows, but asm.js wouldn't, so we must do something
// First, normalize input to f64
- auto input = value;
- if (input->type == f32) {
- auto conv = allocator.alloc<Unary>();
- conv->op = PromoteFloat32;
- conv->value = input;
- conv->type = WasmType::f64;
- input = conv;
- }
+ auto input = ensureDouble(value);
// There is no "JS" way to handle this, as no i64s in JS, so always clamp if we don't allow traps
Call *ret = allocator.alloc<Call>();
ret->target = F64_TO_INT64;
@@ -1795,11 +1794,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
conv->type = WasmType::f32;
ret->value = conv;
} else if (ret->valueType == f64 && ret->value->type == f32) {
- auto conv = allocator.alloc<Unary>();
- conv->op = PromoteFloat32;
- conv->value = ret->value;
- conv->type = WasmType::f64;
- ret->value = conv;
+ ret->value = ensureDouble(ret->value);
} else {
abort_on("bad sub[] types", ast);
}
@@ -1822,8 +1817,8 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
// WebAssembly does not have floating-point remainder, we have to emit a call to a special import of ours
CallImport *call = allocator.alloc<CallImport>();
call->target = F64_REM;
- call->operands.push_back(ret->left);
- call->operands.push_back(ret->right);
+ call->operands.push_back(ensureDouble(ret->left));
+ call->operands.push_back(ensureDouble(ret->right));
call->type = f64;
static bool addedImport = false;
if (!addedImport) {
@@ -1873,11 +1868,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
return conv;
}
if (ret->type == f32) {
- auto conv = allocator.alloc<Unary>();
- conv->op = PromoteFloat32;
- conv->value = ret;
- conv->type = WasmType::f64;
- return conv;
+ return ensureDouble(ret);
}
fixCallType(ret, f64);
return ret;
@@ -2485,11 +2476,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
conv->value = process(writtenValue);
conv->type = WasmType::f32;
if (readType == ASM_DOUBLE) {
- auto promote = allocator.alloc<Unary>();
- promote->op = PromoteFloat32;
- promote->value = conv;
- promote->type = WasmType::f64;
- return promote;
+ return ensureDouble(conv);
}
return conv;
} else if (writeType == ASM_FLOAT && readType == ASM_INT) {
diff --git a/test/unit.asm.js b/test/unit.asm.js
index 22e180078..065512011 100644
--- a/test/unit.asm.js
+++ b/test/unit.asm.js
@@ -137,6 +137,9 @@ function asm(global, env, buffer) {
function frem() {
return +(5.5 % 1.2);
}
+ function frem_float() {
+ return Math_fround(Math_fround(5.5) % Math_fround(1.2));
+ }
function big_uint_div_u() {
var x = 0;
x = (4294967295 / 2)&-1;
@@ -740,6 +743,6 @@ function asm(global, env, buffer) {
var FUNCTION_TABLE_vi = [ vi, vi, vi, vi, vi, vi, vi, vi ];
var FUNCTION_TABLE_ii = [ ii ];
- return { big_negative: big_negative, pick: forgetMe, pick: exportMe, doubleCompares: doubleCompares, intOps: intOps, conversions: conversions, switcher: switcher, frem: frem, big_uint_div_u: big_uint_div_u, fr: fr, negZero: negZero, neg: neg, smallCompare: smallCompare, cneg_nosemicolon: cneg_nosemicolon, forLoop: forLoop, ceiling_32_64: ceiling_32_64, aborts: aborts, continues: continues, bitcasts: bitcasts, recursiveBlockMerging: recursiveBlockMerging, lb: lb, zeroInit: zeroInit, phi: phi, smallIf: smallIf, dropCall: dropCall, useSetGlobal: useSetGlobal, usesSetGlobal2: usesSetGlobal2, breakThroughMany: breakThroughMany, ifChainEmpty: ifChainEmpty, heap8NoShift: heap8NoShift, conditionalTypeFun: conditionalTypeFun, loadSigned: loadSigned, globalOpts: globalOpts, dropCallImport: dropCallImport, loophi: loophi, loophi2: loophi2, relooperJumpThreading: relooperJumpThreading, relooperJumpThreading__ZN4game14preloadweaponsEv: relooperJumpThreading__ZN4game14preloadweaponsEv, __Z12multi_varargiz: __Z12multi_varargiz, jumpThreadDrop: jumpThreadDrop, dropIgnoredImportInIf: dropIgnoredImportInIf, dropIgnoredImportsInIf: dropIgnoredImportsInIf, relooperJumpThreading_irreducible: relooperJumpThreading_irreducible, store_fround: store_fround, exportedNumber: 42, relocatableAndModules: relocatableAndModules, exported_f32_user: exported_f32_user, keepAlive: keepAlive };
+ return { big_negative: big_negative, pick: forgetMe, pick: exportMe, doubleCompares: doubleCompares, intOps: intOps, conversions: conversions, switcher: switcher, frem: frem, frem_float: frem_float, big_uint_div_u: big_uint_div_u, fr: fr, negZero: negZero, neg: neg, smallCompare: smallCompare, cneg_nosemicolon: cneg_nosemicolon, forLoop: forLoop, ceiling_32_64: ceiling_32_64, aborts: aborts, continues: continues, bitcasts: bitcasts, recursiveBlockMerging: recursiveBlockMerging, lb: lb, zeroInit: zeroInit, phi: phi, smallIf: smallIf, dropCall: dropCall, useSetGlobal: useSetGlobal, usesSetGlobal2: usesSetGlobal2, breakThroughMany: breakThroughMany, ifChainEmpty: ifChainEmpty, heap8NoShift: heap8NoShift, conditionalTypeFun: conditionalTypeFun, loadSigned: loadSigned, globalOpts: globalOpts, dropCallImport: dropCallImport, loophi: loophi, loophi2: loophi2, relooperJumpThreading: relooperJumpThreading, relooperJumpThreading__ZN4game14preloadweaponsEv: relooperJumpThreading__ZN4game14preloadweaponsEv, __Z12multi_varargiz: __Z12multi_varargiz, jumpThreadDrop: jumpThreadDrop, dropIgnoredImportInIf: dropIgnoredImportInIf, dropIgnoredImportsInIf: dropIgnoredImportsInIf, relooperJumpThreading_irreducible: relooperJumpThreading_irreducible, store_fround: store_fround, exportedNumber: 42, relocatableAndModules: relocatableAndModules, exported_f32_user: exported_f32_user, keepAlive: keepAlive };
}
diff --git a/test/unit.fromasm b/test/unit.fromasm
index 68f5920ee..020ded163 100644
--- a/test/unit.fromasm
+++ b/test/unit.fromasm
@@ -33,6 +33,7 @@
(export "conversions" (func $conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
+ (export "frem_float" (func $legalstub$frem_float))
(export "big_uint_div_u" (func $big_uint_div_u))
(export "fr" (func $legalstub$fr))
(export "negZero" (func $negZero))
@@ -245,6 +246,14 @@
(f64.const 1.2)
)
)
+ (func $frem_float (result f32)
+ (f32.demote/f64
+ (call $f64-rem
+ (f64.const 5.5)
+ (f64.const 1.2000000476837158)
+ )
+ )
+ )
(func $i32u-div (param $0 i32) (param $1 i32) (result i32)
(if (result i32)
(get_local $1)
@@ -1217,6 +1226,11 @@
(func $ii (param $0 i32) (result i32)
(get_local $0)
)
+ (func $legalstub$frem_float (result f64)
+ (f64.promote/f32
+ (call $frem_float)
+ )
+ )
(func $legalstub$fr (param $0 f64)
(call $fr
(f32.demote/f64
diff --git a/test/unit.fromasm.clamp b/test/unit.fromasm.clamp
index 1442ea947..06c577753 100644
--- a/test/unit.fromasm.clamp
+++ b/test/unit.fromasm.clamp
@@ -31,6 +31,7 @@
(export "conversions" (func $conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
+ (export "frem_float" (func $legalstub$frem_float))
(export "big_uint_div_u" (func $big_uint_div_u))
(export "fr" (func $legalstub$fr))
(export "negZero" (func $negZero))
@@ -269,6 +270,14 @@
(f64.const 1.2)
)
)
+ (func $frem_float (result f32)
+ (f32.demote/f64
+ (call $f64-rem
+ (f64.const 5.5)
+ (f64.const 1.2000000476837158)
+ )
+ )
+ )
(func $i32u-div (param $0 i32) (param $1 i32) (result i32)
(if (result i32)
(get_local $1)
@@ -1241,6 +1250,11 @@
(func $ii (param $0 i32) (result i32)
(get_local $0)
)
+ (func $legalstub$frem_float (result f64)
+ (f64.promote/f32
+ (call $frem_float)
+ )
+ )
(func $legalstub$fr (param $0 f64)
(call $fr
(f32.demote/f64
diff --git a/test/unit.fromasm.clamp.no-opts b/test/unit.fromasm.clamp.no-opts
index 37456128f..393147603 100644
--- a/test/unit.fromasm.clamp.no-opts
+++ b/test/unit.fromasm.clamp.no-opts
@@ -38,6 +38,7 @@
(export "conversions" (func $conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
+ (export "frem_float" (func $legalstub$frem_float))
(export "big_uint_div_u" (func $big_uint_div_u))
(export "fr" (func $legalstub$fr))
(export "negZero" (func $negZero))
@@ -407,6 +408,20 @@
)
)
)
+ (func $frem_float (result f32)
+ (return
+ (f32.demote/f64
+ (call $f64-rem
+ (f64.promote/f32
+ (f32.const 5.5)
+ )
+ (f64.promote/f32
+ (f32.const 1.2000000476837158)
+ )
+ )
+ )
+ )
+ )
(func $i32u-div (param $0 i32) (param $1 i32) (result i32)
(if (result i32)
(i32.eqz
@@ -2030,6 +2045,11 @@
(get_local $x)
)
)
+ (func $legalstub$frem_float (result f64)
+ (f64.promote/f32
+ (call $frem_float)
+ )
+ )
(func $legalstub$fr (param $0 f64)
(call $fr
(f32.demote/f64
diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise
index ea664d5f0..8ee0b073f 100644
--- a/test/unit.fromasm.imprecise
+++ b/test/unit.fromasm.imprecise
@@ -30,6 +30,7 @@
(export "conversions" (func $big_negative))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
+ (export "frem_float" (func $legalstub$frem_float))
(export "big_uint_div_u" (func $big_uint_div_u))
(export "fr" (func $legalstub$fr))
(export "negZero" (func $negZero))
@@ -226,6 +227,14 @@
(f64.const 1.2)
)
)
+ (func $frem_float (result f32)
+ (f32.demote/f64
+ (call $f64-rem
+ (f64.const 5.5)
+ (f64.const 1.2000000476837158)
+ )
+ )
+ )
(func $big_uint_div_u (result i32)
(i32.const 2147483647)
)
@@ -1190,6 +1199,11 @@
(func $ii (param $0 i32) (result i32)
(get_local $0)
)
+ (func $legalstub$frem_float (result f64)
+ (f64.promote/f32
+ (call $frem_float)
+ )
+ )
(func $legalstub$fr (param $0 f64)
(call $fr
(f32.demote/f64
diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts
index 227cf5e79..70eece97d 100644
--- a/test/unit.fromasm.imprecise.no-opts
+++ b/test/unit.fromasm.imprecise.no-opts
@@ -38,6 +38,7 @@
(export "conversions" (func $conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
+ (export "frem_float" (func $legalstub$frem_float))
(export "big_uint_div_u" (func $big_uint_div_u))
(export "fr" (func $legalstub$fr))
(export "negZero" (func $negZero))
@@ -379,6 +380,20 @@
)
)
)
+ (func $frem_float (result f32)
+ (return
+ (f32.demote/f64
+ (call $f64-rem
+ (f64.promote/f32
+ (f32.const 5.5)
+ )
+ (f64.promote/f32
+ (f32.const 1.2000000476837158)
+ )
+ )
+ )
+ )
+ )
(func $big_uint_div_u (result i32)
(local $x i32)
(set_local $x
@@ -1990,6 +2005,11 @@
(get_local $x)
)
)
+ (func $legalstub$frem_float (result f64)
+ (f64.promote/f32
+ (call $frem_float)
+ )
+ )
(func $legalstub$fr (param $0 f64)
(call $fr
(f32.demote/f64
diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts
index 878011cef..511e310a3 100644
--- a/test/unit.fromasm.no-opts
+++ b/test/unit.fromasm.no-opts
@@ -40,6 +40,7 @@
(export "conversions" (func $conversions))
(export "switcher" (func $switcher))
(export "frem" (func $frem))
+ (export "frem_float" (func $legalstub$frem_float))
(export "big_uint_div_u" (func $big_uint_div_u))
(export "fr" (func $legalstub$fr))
(export "negZero" (func $negZero))
@@ -383,6 +384,20 @@
)
)
)
+ (func $frem_float (result f32)
+ (return
+ (f32.demote/f64
+ (call $f64-rem
+ (f64.promote/f32
+ (f32.const 5.5)
+ )
+ (f64.promote/f32
+ (f32.const 1.2000000476837158)
+ )
+ )
+ )
+ )
+ )
(func $i32u-div (param $0 i32) (param $1 i32) (result i32)
(if (result i32)
(i32.eqz
@@ -2006,6 +2021,11 @@
(get_local $x)
)
)
+ (func $legalstub$frem_float (result f64)
+ (f64.promote/f32
+ (call $frem_float)
+ )
+ )
(func $legalstub$fr (param $0 f64)
(call $fr
(f32.demote/f64