Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f52f612

Browse files
authoredAug 31, 2022
fix: Properly handle "-0" literal for floating point context (#2478)
1 parent 12838ac commit f52f612

12 files changed

+79
-68
lines changed
 

‎src/compiler.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -7794,19 +7794,23 @@ export class Compiler extends DiagnosticEmitter {
77947794
case LiteralKind.INTEGER: {
77957795
let expr = <IntegerLiteralExpression>expression;
77967796
let type = this.resolver.determineIntegerLiteralType(expr, implicitlyNegate, contextualType);
7797-
7798-
let intValue = implicitlyNegate
7799-
? i64_neg(expr.value)
7800-
: expr.value;
7801-
78027797
this.currentType = type;
7798+
let intValue = expr.value;
7799+
let sign = 1.0; // should multiply for float literals
7800+
if (implicitlyNegate) {
7801+
if (type.isFloatValue) {
7802+
sign = -1.0;
7803+
} else {
7804+
intValue = i64_neg(intValue);
7805+
}
7806+
}
78037807
switch (type.kind) {
78047808
case TypeKind.ISIZE: if (!this.options.isWasm64) return module.i32(i64_low(intValue));
78057809
case TypeKind.I64: return module.i64(i64_low(intValue), i64_high(intValue));
78067810
case TypeKind.USIZE: if (!this.options.isWasm64) return module.i32(i64_low(intValue));
78077811
case TypeKind.U64: return module.i64(i64_low(intValue), i64_high(intValue));
7808-
case TypeKind.F32: return module.f32(i64_to_f32(intValue));
7809-
case TypeKind.F64: return module.f64(i64_to_f64(intValue));
7812+
case TypeKind.F32: return module.f32(<f32>sign * i64_to_f32(intValue));
7813+
case TypeKind.F64: return module.f64(sign * i64_to_f64(intValue));
78107814
default: return module.i32(i64_low(intValue));
78117815
}
78127816
}

‎src/resolver.ts

+10
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,16 @@ export class Resolver extends DiagnosticEmitter {
16031603
DiagnosticCode.Literal_0_does_not_fit_into_i64_or_u64_types,
16041604
range, range.source.text.substring(range.start - 1, range.end)
16051605
);
1606+
} else if (i64_eq(intValue, i64_zero)) {
1607+
// Special handling for -0
1608+
if (ctxType.isFloatValue) {
1609+
return ctxType.kind == TypeKind.F32
1610+
? Type.f32
1611+
: Type.f64;
1612+
} else if (!ctxType.isIntegerValue) {
1613+
// If it's unknown just always assume this is f64
1614+
return Type.f64;
1615+
}
16061616
}
16071617
intValue = i64_neg(intValue);
16081618
}

‎tests/compiler/literals.debug.wat

+10
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@
105105
drop
106106
i64.const -9223372036854775808
107107
drop
108+
i32.const 0
109+
drop
110+
i64.const 0
111+
drop
112+
f64.const -0
113+
drop
114+
f32.const -0
115+
drop
116+
f64.const -0
117+
drop
108118
)
109119
(func $~start
110120
call $start:literals

‎tests/compiler/literals.ts

+6
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,9 @@ false;
4747
-0x8000000000000000;
4848
0o1000000000000000000000;
4949
-0o1000000000000000000000;
50+
51+
<i32>-0; // i32.const 0
52+
<u64>-0; // i64.const 0
53+
<f64>-0; // f64.const -0.
54+
f32(-0); // f32.const -0.
55+
-0; // f64.const -0.

‎tests/compiler/std/hash.debug.wat

+2-2
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@
826826
call $~lib/util/hash/HASH<f32>
827827
call $std/hash/check
828828
drop
829-
f32.const 0
829+
f32.const -0
830830
call $~lib/util/hash/HASH<f32>
831831
call $std/hash/check
832832
drop
@@ -850,7 +850,7 @@
850850
call $~lib/util/hash/HASH<f64>
851851
call $std/hash/check
852852
drop
853-
f64.const 0
853+
f64.const -0
854854
call $~lib/util/hash/HASH<f64>
855855
call $std/hash/check
856856
drop

‎tests/compiler/std/hash.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ check(HASH<string>("abcdefghi"));
1919
check(HASH<f32>(0.0));
2020
check(HASH<f32>(1.0));
2121
check(HASH<f32>(1.1));
22-
check(HASH<f32>(-0));
22+
check(HASH<f32>(-0.0));
2323
check(HASH<f32>(Infinity));
2424
check(HASH<f32>(NaN));
2525

2626
check(HASH<f64>(0.0));
2727
check(HASH<f64>(1.0));
2828
check(HASH<f64>(1.1));
29-
check(HASH<f64>(-0));
29+
check(HASH<f64>(-0.0));
3030
check(HASH<f64>(Infinity));
3131
check(HASH<f64>(NaN));

‎tests/compiler/std/math.debug.wat

+1-1
Original file line numberDiff line numberDiff line change
@@ -29598,7 +29598,7 @@
2959829598
call $~lib/builtins/abort
2959929599
unreachable
2960029600
end
29601-
f64.const 0
29601+
f64.const -0
2960229602
i64.const 4607182418800017408
2960329603
f64.reinterpret_i64
2960429604
f64.const 0

‎tests/compiler/std/math.release.wat

+1-1
Original file line numberDiff line numberDiff line change
@@ -27420,7 +27420,7 @@
2742027420
call $~lib/builtins/abort
2742127421
unreachable
2742227422
end
27423-
f64.const 0
27423+
f64.const -0
2742427424
f64.const 1
2742527425
f64.const 0
2742627426
call $std/math/test_exp2

‎tests/compiler/std/math.ts

+17-17
Original file line numberDiff line numberDiff line change
@@ -1558,31 +1558,31 @@ assert(test_exp2(reinterpret<f64>(0x3FE8C5DB097F7442), reinterpret<f64>(0x3FFB5C
15581558
assert(test_exp2(reinterpret<f64>(0xBFE5B86EA8118A0E), reinterpret<f64>(0x3FE3FD8BA33216B9), reinterpret<f64>(0xBFD3F71A00000000), INEXACT));
15591559

15601560
// special
1561-
assert(test_exp2( 0, reinterpret<f64>(0x3FF0000000000000), 0, 0));
1562-
assert(test_exp2( -0, reinterpret<f64>(0x3FF0000000000000), 0, 0));
1563-
assert(test_exp2( 1, reinterpret<f64>(0x4000000000000000), 0, 0));
1564-
assert(test_exp2( -1, reinterpret<f64>(0x3FE0000000000000), 0, 0));
1561+
assert(test_exp2( 0.0, reinterpret<f64>(0x3FF0000000000000), 0, 0));
1562+
assert(test_exp2( -0.0, reinterpret<f64>(0x3FF0000000000000), 0, 0));
1563+
assert(test_exp2( 1.0, reinterpret<f64>(0x4000000000000000), 0, 0));
1564+
assert(test_exp2( -1.0, reinterpret<f64>(0x3FE0000000000000), 0, 0));
15651565
assert(test_exp2( Infinity, Infinity, 0, 0));
15661566
assert(test_exp2( -Infinity, 0, 0, 0));
15671567
assert(test_exp2( NaN, NaN, 0, 0));
15681568
assert(test_exp2(reinterpret<f64>(0x3FFFF80000000000), reinterpret<f64>(0x400FF4EACA4391B6), reinterpret<f64>(0x3FC2E60C60000000), INEXACT));
1569-
assert(test_exp2(reinterpret<f64>(0xC08FEF3333333333), reinterpret<f64>(0x1125FBEE2506B0), reinterpret<f64>(0xBFCC612EC0000000), INEXACT));
1570-
assert(test_exp2(reinterpret<f64>(0xC08FF00000000000), reinterpret<f64>(0x10000000000000), 0, 0));
1571-
assert(test_exp2(reinterpret<f64>(0xC08FF0CCCCCCCCCD), reinterpret<f64>(0xEEDB4008BD547), reinterpret<f64>(0x3FC966DFC0000000), INEXACT | UNDERFLOW));
1572-
assert(test_exp2(reinterpret<f64>(0xC08FF80000000000), reinterpret<f64>(0x8000000000000), 0, 0));
1569+
assert(test_exp2(reinterpret<f64>(0xC08FEF3333333333), reinterpret<f64>(0x001125FBEE2506B0), reinterpret<f64>(0xBFCC612EC0000000), INEXACT));
1570+
assert(test_exp2(reinterpret<f64>(0xC08FF00000000000), reinterpret<f64>(0x0010000000000000), 0, 0));
1571+
assert(test_exp2(reinterpret<f64>(0xC08FF0CCCCCCCCCD), reinterpret<f64>(0x000EEDB4008BD547), reinterpret<f64>(0x3FC966DFC0000000), INEXACT | UNDERFLOW));
1572+
assert(test_exp2(reinterpret<f64>(0xC08FF80000000000), reinterpret<f64>(0x0008000000000000), 0, 0));
15731573
assert(test_exp2(reinterpret<f64>(0x408FFF3333333333), reinterpret<f64>(0x7FEDDB680117AA8E), reinterpret<f64>(0x3FD966DFC0000000), INEXACT));
15741574
assert(test_exp2(reinterpret<f64>(0x4090000000000000), Infinity, 0, INEXACT | UNDERFLOW));
15751575
assert(test_exp2(reinterpret<f64>(0x4090006666666666), Infinity, 0, INEXACT | UNDERFLOW));
15761576
assert(test_exp2(reinterpret<f64>(0x40091EB851EB851F), reinterpret<f64>(0x4021A167423FC31C), reinterpret<f64>(0x3FD9287B80000000), INEXACT));
1577-
assert(test_exp2(reinterpret<f64>(0xC08FF40000000000), reinterpret<f64>(0xB504F333F9DE6), reinterpret<f64>(0xBFD2116600000000), INEXACT | UNDERFLOW));
1578-
assert(test_exp2(reinterpret<f64>(0xC08FF80000000000), reinterpret<f64>(0x8000000000000), 0, 0));
1579-
assert(test_exp2(reinterpret<f64>(0xC08FFC0000000000), reinterpret<f64>(0x5A827999FCEF3), reinterpret<f64>(0xBFC2116600000000), INEXACT | UNDERFLOW));
1580-
assert(test_exp2(reinterpret<f64>(0xC090000000000000), reinterpret<f64>(0x4000000000000), 0, 0));
1581-
assert(test_exp2(reinterpret<f64>(0xC090040000000000), reinterpret<f64>(0x2000000000000), 0, 0));
1582-
assert(test_exp2(reinterpret<f64>(0xC090C80000000000), reinterpret<f64>(0x1), 0, 0));
1583-
assert(test_exp2(reinterpret<f64>(0xC090CA0000000000), reinterpret<f64>(0x1), reinterpret<f64>(0x3FD2BEC340000000), INEXACT | UNDERFLOW));
1584-
assert(test_exp2(reinterpret<f64>(0xC090CC0000000000), 0, reinterpret<f64>(0xBFE0000000000000), INEXACT | UNDERFLOW));
1585-
assert(test_exp2(reinterpret<f64>(0xC0A0000000000000), 0, 0, INEXACT | UNDERFLOW));
1577+
assert(test_exp2(reinterpret<f64>(0xC08FF40000000000), reinterpret<f64>(0x000B504F333F9DE6), reinterpret<f64>(0xBFD2116600000000), INEXACT | UNDERFLOW));
1578+
assert(test_exp2(reinterpret<f64>(0xC08FF80000000000), reinterpret<f64>(0x0008000000000000), 0, 0));
1579+
assert(test_exp2(reinterpret<f64>(0xC08FFC0000000000), reinterpret<f64>(0x0005A827999FCEF3), reinterpret<f64>(0xBFC2116600000000), INEXACT | UNDERFLOW));
1580+
assert(test_exp2(reinterpret<f64>(0xC090000000000000), reinterpret<f64>(0x0004000000000000), 0, 0));
1581+
assert(test_exp2(reinterpret<f64>(0xC090040000000000), reinterpret<f64>(0x0002000000000000), 0, 0));
1582+
assert(test_exp2(reinterpret<f64>(0xC090C80000000000), reinterpret<f64>(1), 0, 0));
1583+
assert(test_exp2(reinterpret<f64>(0xC090CA0000000000), reinterpret<f64>(1), reinterpret<f64>(0x3FD2BEC340000000), INEXACT | UNDERFLOW));
1584+
assert(test_exp2(reinterpret<f64>(0xC090CC0000000000), 0, reinterpret<f64>(0xBFE0000000000000), INEXACT | UNDERFLOW));
1585+
assert(test_exp2(reinterpret<f64>(0xC0A0000000000000), 0, 0, INEXACT | UNDERFLOW));
15861586

15871587
////////////////////////////////////////////////////////////////////////////////////////////////////
15881588
// Mathf.exp2

‎tests/compiler/std/object.debug.wat

+13-31
Original file line numberDiff line numberDiff line change
@@ -705,24 +705,6 @@
705705
call $~lib/builtins/abort
706706
unreachable
707707
end
708-
f64.const 0
709-
f64.const 0.1
710-
f64.const -1e-308
711-
f64.mul
712-
call $~lib/object/Object.is<f64>
713-
i32.const 0
714-
i32.ne
715-
i32.const 0
716-
i32.eq
717-
i32.eqz
718-
if
719-
i32.const 0
720-
i32.const 32
721-
i32.const 34
722-
i32.const 1
723-
call $~lib/builtins/abort
724-
unreachable
725-
end
726708
f64.const -0
727709
f64.const 0.1
728710
f64.const -1e-308
@@ -736,7 +718,7 @@
736718
if
737719
i32.const 0
738720
i32.const 32
739-
i32.const 35
721+
i32.const 34
740722
i32.const 1
741723
call $~lib/builtins/abort
742724
unreachable
@@ -752,7 +734,7 @@
752734
if
753735
i32.const 0
754736
i32.const 32
755-
i32.const 36
737+
i32.const 35
756738
i32.const 1
757739
call $~lib/builtins/abort
758740
unreachable
@@ -766,7 +748,7 @@
766748
if
767749
i32.const 0
768750
i32.const 32
769-
i32.const 38
751+
i32.const 37
770752
i32.const 1
771753
call $~lib/builtins/abort
772754
unreachable
@@ -780,7 +762,7 @@
780762
if
781763
i32.const 0
782764
i32.const 32
783-
i32.const 39
765+
i32.const 38
784766
i32.const 1
785767
call $~lib/builtins/abort
786768
unreachable
@@ -794,7 +776,7 @@
794776
if
795777
i32.const 0
796778
i32.const 32
797-
i32.const 41
779+
i32.const 40
798780
i32.const 1
799781
call $~lib/builtins/abort
800782
unreachable
@@ -808,7 +790,7 @@
808790
if
809791
i32.const 0
810792
i32.const 32
811-
i32.const 42
793+
i32.const 41
812794
i32.const 1
813795
call $~lib/builtins/abort
814796
unreachable
@@ -822,7 +804,7 @@
822804
if
823805
i32.const 0
824806
i32.const 32
825-
i32.const 43
807+
i32.const 42
826808
i32.const 1
827809
call $~lib/builtins/abort
828810
unreachable
@@ -846,7 +828,7 @@
846828
if
847829
i32.const 0
848830
i32.const 32
849-
i32.const 45
831+
i32.const 44
850832
i32.const 1
851833
call $~lib/builtins/abort
852834
unreachable
@@ -870,7 +852,7 @@
870852
if
871853
i32.const 0
872854
i32.const 32
873-
i32.const 46
855+
i32.const 45
874856
i32.const 1
875857
call $~lib/builtins/abort
876858
unreachable
@@ -894,7 +876,7 @@
894876
if
895877
i32.const 0
896878
i32.const 32
897-
i32.const 47
879+
i32.const 46
898880
i32.const 1
899881
call $~lib/builtins/abort
900882
unreachable
@@ -908,7 +890,7 @@
908890
if
909891
i32.const 0
910892
i32.const 32
911-
i32.const 49
893+
i32.const 48
912894
i32.const 1
913895
call $~lib/builtins/abort
914896
unreachable
@@ -927,7 +909,7 @@
927909
if
928910
i32.const 0
929911
i32.const 32
930-
i32.const 50
912+
i32.const 49
931913
i32.const 1
932914
call $~lib/builtins/abort
933915
unreachable
@@ -946,7 +928,7 @@
946928
if
947929
i32.const 0
948930
i32.const 32
949-
i32.const 51
931+
i32.const 50
950932
i32.const 1
951933
call $~lib/builtins/abort
952934
unreachable

‎tests/compiler/std/object.release.wat

+6-6
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
if
170170
i32.const 0
171171
i32.const 1056
172-
i32.const 45
172+
i32.const 44
173173
i32.const 1
174174
call $~lib/builtins/abort
175175
unreachable
@@ -187,7 +187,7 @@
187187
if
188188
i32.const 0
189189
i32.const 1056
190-
i32.const 46
190+
i32.const 45
191191
i32.const 1
192192
call $~lib/builtins/abort
193193
unreachable
@@ -205,7 +205,7 @@
205205
if
206206
i32.const 0
207207
i32.const 1056
208-
i32.const 47
208+
i32.const 46
209209
i32.const 1
210210
call $~lib/builtins/abort
211211
unreachable
@@ -218,7 +218,7 @@
218218
if
219219
i32.const 0
220220
i32.const 1056
221-
i32.const 49
221+
i32.const 48
222222
i32.const 1
223223
call $~lib/builtins/abort
224224
unreachable
@@ -232,7 +232,7 @@
232232
if
233233
i32.const 0
234234
i32.const 1056
235-
i32.const 50
235+
i32.const 49
236236
i32.const 1
237237
call $~lib/builtins/abort
238238
unreachable
@@ -246,7 +246,7 @@
246246
if
247247
i32.const 0
248248
i32.const 1056
249-
i32.const 51
249+
i32.const 50
250250
i32.const 1
251251
call $~lib/builtins/abort
252252
unreachable

‎tests/compiler/std/object.ts

-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ assert(Object.is<f32>(+Infinity, NaN) == false);
3131
assert(Object.is<f32>(NaN, Infinity) == false);
3232
assert(Object.is<f32>(NaN, NaN) == true);
3333

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

0 commit comments

Comments
 (0)
Failed to load comments.