Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix f32 frem in asm2wasm #1105 #1106

Merged
merged 1 commit into from
Jul 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 20 additions & 33 deletions src/asm2wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,19 @@ class Asm2WasmBuilder {
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);
Expand Down Expand Up @@ -803,14 +816,7 @@ class Asm2WasmBuilder {
}
// 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) {
Expand Down Expand Up @@ -894,14 +900,7 @@ class Asm2WasmBuilder {
}
// 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;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
5 changes: 4 additions & 1 deletion test/unit.asm.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 };
}

14 changes: 14 additions & 0 deletions test/unit.fromasm
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions test/unit.fromasm.clamp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions test/unit.fromasm.clamp.no-opts
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions test/unit.fromasm.imprecise
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
)
Expand Down Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions test/unit.fromasm.imprecise.no-opts
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions test/unit.fromasm.no-opts
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down