Skip to content

fix: Properly handle "-0" literal for floating point context #2478

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

Merged
merged 18 commits into from
Aug 31, 2022
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
18 changes: 11 additions & 7 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7794,19 +7794,23 @@ export class Compiler extends DiagnosticEmitter {
case LiteralKind.INTEGER: {
let expr = <IntegerLiteralExpression>expression;
let type = this.resolver.determineIntegerLiteralType(expr, implicitlyNegate, contextualType);

let intValue = implicitlyNegate
? i64_neg(expr.value)
: expr.value;

this.currentType = type;
let intValue = expr.value;
let sign = 1.0; // should multiply for float literals
if (implicitlyNegate) {
if (type.isFloatValue) {
sign = -1.0;
} else {
intValue = i64_neg(intValue);
}
}
switch (type.kind) {
case TypeKind.ISIZE: if (!this.options.isWasm64) return module.i32(i64_low(intValue));
case TypeKind.I64: return module.i64(i64_low(intValue), i64_high(intValue));
case TypeKind.USIZE: if (!this.options.isWasm64) return module.i32(i64_low(intValue));
case TypeKind.U64: return module.i64(i64_low(intValue), i64_high(intValue));
case TypeKind.F32: return module.f32(i64_to_f32(intValue));
case TypeKind.F64: return module.f64(i64_to_f64(intValue));
case TypeKind.F32: return module.f32(<f32>sign * i64_to_f32(intValue));
case TypeKind.F64: return module.f64(sign * i64_to_f64(intValue));
default: return module.i32(i64_low(intValue));
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1603,6 +1603,16 @@ export class Resolver extends DiagnosticEmitter {
DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types,
range, range.source.text.substring(range.start - 1, range.end)
);
} else if (i64_eq(intValue, i64_zero)) {
// Special handling for -0
if (ctxType.isFloatValue) {
return ctxType.kind == TypeKind.F32
? Type.f32
: Type.f64;
} else if (!ctxType.isIntegerValue) {
// If it's unknown just always assume this is f64
return Type.f64;
}
}
intValue = i64_neg(intValue);
}
Expand Down
10 changes: 10 additions & 0 deletions tests/compiler/literals.debug.wat
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@
drop
i64.const -9223372036854775808
drop
i32.const 0
drop
i64.const 0
drop
f64.const -0
drop
f32.const -0
drop
f64.const -0
drop
)
(func $~start
call $start:literals
Expand Down
6 changes: 6 additions & 0 deletions tests/compiler/literals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,9 @@ false;
-0x8000000000000000;
0o1000000000000000000000;
-0o1000000000000000000000;

<i32>-0; // i32.const 0
<u64>-0; // i64.const 0
<f64>-0; // f64.const -0.
f32(-0); // f32.const -0.
-0; // f64.const -0.
4 changes: 2 additions & 2 deletions tests/compiler/std/hash.debug.wat
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@
call $~lib/util/hash/HASH<f32>
call $std/hash/check
drop
f32.const 0
f32.const -0
call $~lib/util/hash/HASH<f32>
call $std/hash/check
drop
Expand All @@ -850,7 +850,7 @@
call $~lib/util/hash/HASH<f64>
call $std/hash/check
drop
f64.const 0
f64.const -0
call $~lib/util/hash/HASH<f64>
call $std/hash/check
drop
Expand Down
4 changes: 2 additions & 2 deletions tests/compiler/std/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ check(HASH<string>("abcdefghi"));
check(HASH<f32>(0.0));
check(HASH<f32>(1.0));
check(HASH<f32>(1.1));
check(HASH<f32>(-0));
check(HASH<f32>(-0.0));
check(HASH<f32>(Infinity));
check(HASH<f32>(NaN));

check(HASH<f64>(0.0));
check(HASH<f64>(1.0));
check(HASH<f64>(1.1));
check(HASH<f64>(-0));
check(HASH<f64>(-0.0));
check(HASH<f64>(Infinity));
check(HASH<f64>(NaN));
2 changes: 1 addition & 1 deletion tests/compiler/std/math.debug.wat
Original file line number Diff line number Diff line change
Expand Up @@ -29598,7 +29598,7 @@
call $~lib/builtins/abort
unreachable
end
f64.const 0
f64.const -0
i64.const 4607182418800017408
f64.reinterpret_i64
f64.const 0
Expand Down
2 changes: 1 addition & 1 deletion tests/compiler/std/math.release.wat
Original file line number Diff line number Diff line change
Expand Up @@ -27420,7 +27420,7 @@
call $~lib/builtins/abort
unreachable
end
f64.const 0
f64.const -0
f64.const 1
f64.const 0
call $std/math/test_exp2
Expand Down
34 changes: 17 additions & 17 deletions tests/compiler/std/math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1558,31 +1558,31 @@ assert(test_exp2(reinterpret<f64>(0x3FE8C5DB097F7442), reinterpret<f64>(0x3FFB5C
assert(test_exp2(reinterpret<f64>(0xBFE5B86EA8118A0E), reinterpret<f64>(0x3FE3FD8BA33216B9), reinterpret<f64>(0xBFD3F71A00000000), INEXACT));

// special
assert(test_exp2( 0, reinterpret<f64>(0x3FF0000000000000), 0, 0));
assert(test_exp2( -0, reinterpret<f64>(0x3FF0000000000000), 0, 0));
assert(test_exp2( 1, reinterpret<f64>(0x4000000000000000), 0, 0));
assert(test_exp2( -1, reinterpret<f64>(0x3FE0000000000000), 0, 0));
assert(test_exp2( 0.0, reinterpret<f64>(0x3FF0000000000000), 0, 0));
assert(test_exp2( -0.0, reinterpret<f64>(0x3FF0000000000000), 0, 0));
assert(test_exp2( 1.0, reinterpret<f64>(0x4000000000000000), 0, 0));
assert(test_exp2( -1.0, reinterpret<f64>(0x3FE0000000000000), 0, 0));
assert(test_exp2( Infinity, Infinity, 0, 0));
assert(test_exp2( -Infinity, 0, 0, 0));
assert(test_exp2( NaN, NaN, 0, 0));
assert(test_exp2(reinterpret<f64>(0x3FFFF80000000000), reinterpret<f64>(0x400FF4EACA4391B6), reinterpret<f64>(0x3FC2E60C60000000), INEXACT));
assert(test_exp2(reinterpret<f64>(0xC08FEF3333333333), reinterpret<f64>(0x1125FBEE2506B0), reinterpret<f64>(0xBFCC612EC0000000), INEXACT));
assert(test_exp2(reinterpret<f64>(0xC08FF00000000000), reinterpret<f64>(0x10000000000000), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC08FF0CCCCCCCCCD), reinterpret<f64>(0xEEDB4008BD547), reinterpret<f64>(0x3FC966DFC0000000), INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC08FF80000000000), reinterpret<f64>(0x8000000000000), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC08FEF3333333333), reinterpret<f64>(0x001125FBEE2506B0), reinterpret<f64>(0xBFCC612EC0000000), INEXACT));
assert(test_exp2(reinterpret<f64>(0xC08FF00000000000), reinterpret<f64>(0x0010000000000000), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC08FF0CCCCCCCCCD), reinterpret<f64>(0x000EEDB4008BD547), reinterpret<f64>(0x3FC966DFC0000000), INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC08FF80000000000), reinterpret<f64>(0x0008000000000000), 0, 0));
assert(test_exp2(reinterpret<f64>(0x408FFF3333333333), reinterpret<f64>(0x7FEDDB680117AA8E), reinterpret<f64>(0x3FD966DFC0000000), INEXACT));
assert(test_exp2(reinterpret<f64>(0x4090000000000000), Infinity, 0, INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0x4090006666666666), Infinity, 0, INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0x40091EB851EB851F), reinterpret<f64>(0x4021A167423FC31C), reinterpret<f64>(0x3FD9287B80000000), INEXACT));
assert(test_exp2(reinterpret<f64>(0xC08FF40000000000), reinterpret<f64>(0xB504F333F9DE6), reinterpret<f64>(0xBFD2116600000000), INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC08FF80000000000), reinterpret<f64>(0x8000000000000), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC08FFC0000000000), reinterpret<f64>(0x5A827999FCEF3), reinterpret<f64>(0xBFC2116600000000), INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC090000000000000), reinterpret<f64>(0x4000000000000), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC090040000000000), reinterpret<f64>(0x2000000000000), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC090C80000000000), reinterpret<f64>(0x1), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC090CA0000000000), reinterpret<f64>(0x1), reinterpret<f64>(0x3FD2BEC340000000), INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC090CC0000000000), 0, reinterpret<f64>(0xBFE0000000000000), INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC0A0000000000000), 0, 0, INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC08FF40000000000), reinterpret<f64>(0x000B504F333F9DE6), reinterpret<f64>(0xBFD2116600000000), INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC08FF80000000000), reinterpret<f64>(0x0008000000000000), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC08FFC0000000000), reinterpret<f64>(0x0005A827999FCEF3), reinterpret<f64>(0xBFC2116600000000), INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC090000000000000), reinterpret<f64>(0x0004000000000000), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC090040000000000), reinterpret<f64>(0x0002000000000000), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC090C80000000000), reinterpret<f64>(1), 0, 0));
assert(test_exp2(reinterpret<f64>(0xC090CA0000000000), reinterpret<f64>(1), reinterpret<f64>(0x3FD2BEC340000000), INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC090CC0000000000), 0, reinterpret<f64>(0xBFE0000000000000), INEXACT | UNDERFLOW));
assert(test_exp2(reinterpret<f64>(0xC0A0000000000000), 0, 0, INEXACT | UNDERFLOW));

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mathf.exp2
Expand Down
44 changes: 13 additions & 31 deletions tests/compiler/std/object.debug.wat
Original file line number Diff line number Diff line change
Expand Up @@ -705,24 +705,6 @@
call $~lib/builtins/abort
unreachable
end
f64.const 0
f64.const 0.1
f64.const -1e-308
f64.mul
call $~lib/object/Object.is<f64>
i32.const 0
i32.ne
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 32
i32.const 34
i32.const 1
call $~lib/builtins/abort
unreachable
end
f64.const -0
f64.const 0.1
f64.const -1e-308
Expand All @@ -736,7 +718,7 @@
if
i32.const 0
i32.const 32
i32.const 35
i32.const 34
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -752,7 +734,7 @@
if
i32.const 0
i32.const 32
i32.const 36
i32.const 35
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -766,7 +748,7 @@
if
i32.const 0
i32.const 32
i32.const 38
i32.const 37
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -780,7 +762,7 @@
if
i32.const 0
i32.const 32
i32.const 39
i32.const 38
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -794,7 +776,7 @@
if
i32.const 0
i32.const 32
i32.const 41
i32.const 40
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -808,7 +790,7 @@
if
i32.const 0
i32.const 32
i32.const 42
i32.const 41
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -822,7 +804,7 @@
if
i32.const 0
i32.const 32
i32.const 43
i32.const 42
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -846,7 +828,7 @@
if
i32.const 0
i32.const 32
i32.const 45
i32.const 44
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -870,7 +852,7 @@
if
i32.const 0
i32.const 32
i32.const 46
i32.const 45
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -894,7 +876,7 @@
if
i32.const 0
i32.const 32
i32.const 47
i32.const 46
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -908,7 +890,7 @@
if
i32.const 0
i32.const 32
i32.const 49
i32.const 48
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -927,7 +909,7 @@
if
i32.const 0
i32.const 32
i32.const 50
i32.const 49
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -946,7 +928,7 @@
if
i32.const 0
i32.const 32
i32.const 51
i32.const 50
i32.const 1
call $~lib/builtins/abort
unreachable
Expand Down
12 changes: 6 additions & 6 deletions tests/compiler/std/object.release.wat
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@
if
i32.const 0
i32.const 1056
i32.const 45
i32.const 44
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -187,7 +187,7 @@
if
i32.const 0
i32.const 1056
i32.const 46
i32.const 45
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -205,7 +205,7 @@
if
i32.const 0
i32.const 1056
i32.const 47
i32.const 46
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -218,7 +218,7 @@
if
i32.const 0
i32.const 1056
i32.const 49
i32.const 48
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -232,7 +232,7 @@
if
i32.const 0
i32.const 1056
i32.const 50
i32.const 49
i32.const 1
call $~lib/builtins/abort
unreachable
Expand All @@ -246,7 +246,7 @@
if
i32.const 0
i32.const 1056
i32.const 51
i32.const 50
i32.const 1
call $~lib/builtins/abort
unreachable
Expand Down
1 change: 0 additions & 1 deletion tests/compiler/std/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ assert(Object.is<f32>(+Infinity, NaN) == false);
assert(Object.is<f32>(NaN, Infinity) == false);
assert(Object.is<f32>(NaN, NaN) == true);

assert(Object.is(-0, 1e-1 * (-1e-308)) == false);
assert(Object.is(-0.0, 1e-1 * (-1e-308)) == false);
assert(Object.is(0, 0.0) == true);

Expand Down