mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Fix parsing issues on 32-bit hosts
These were mostly bugs with code of the following form: ``` if uint64Value < (... literal expression ...) ``` Swift's comparison operators allow their left- and right-hand sides to be of different widths. This in turn means that the literal expression above typically gets typechecked by default as a plain `Int` or `UInt` expression. In a number of cases, this led to truncation on platforms where `Int` is not 64 bits. In particular, this seems to fix tests on wasm32.
This commit is contained in:
@@ -450,7 +450,7 @@ fileprivate func hexFloat(
|
|||||||
) -> ParseResult {
|
) -> ParseResult {
|
||||||
var i = start + 2 // Skip leading '0x'
|
var i = start + 2 // Skip leading '0x'
|
||||||
let firstDigitOffset = i
|
let firstDigitOffset = i
|
||||||
|
let limit = UInt64(1) << 60
|
||||||
var significand: UInt64 = 0
|
var significand: UInt64 = 0
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -458,10 +458,10 @@ fileprivate func hexFloat(
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Accumulate the most significant 64 bits...
|
// Accumulate the most significant 64 bits...
|
||||||
while i < input.count && hexdigit(input[i]) < 16 && significand < (1 << 60) {
|
while i < input.count && hexdigit(input[i]) < 16 && significand < limit {
|
||||||
significand &<<= 4
|
significand &<<= 4
|
||||||
significand += UInt64(hexdigit(input[i]))
|
significand += UInt64(hexdigit(input[i]))
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize binary exponent to the number of bits we collected above
|
// Initialize binary exponent to the number of bits we collected above
|
||||||
@@ -521,7 +521,7 @@ fileprivate func hexFloat(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Pack more bits into the accumulator (up to 60)
|
// Pack more bits into the accumulator (up to 60)
|
||||||
while i < input.count && hexdigit(input[i]) < 16 && significand < (1 << 60) {
|
while i < input.count && hexdigit(input[i]) < 16 && significand < limit {
|
||||||
significand &<<= 4
|
significand &<<= 4
|
||||||
significand += UInt64(hexdigit(input[i]))
|
significand += UInt64(hexdigit(input[i]))
|
||||||
i += 1
|
i += 1
|
||||||
@@ -631,12 +631,12 @@ fileprivate func hexFloat(
|
|||||||
&& (targetSignificand & 1) == 1)) {
|
&& (targetSignificand & 1) == 1)) {
|
||||||
// Round up, test for overflow
|
// Round up, test for overflow
|
||||||
targetSignificand += 1
|
targetSignificand += 1
|
||||||
if targetSignificand >= (1 << targetFormat.significandBits) {
|
if targetSignificand >= (UInt64(1) << targetFormat.significandBits) {
|
||||||
// Normal overflowed, need to renormalize
|
// Normal overflowed, need to renormalize
|
||||||
targetSignificand >>= 1
|
targetSignificand >>= 1
|
||||||
binaryExponent += 1
|
binaryExponent += 1
|
||||||
} else if (binaryExponent < targetFormat.minBinaryExponent
|
} else if (binaryExponent < targetFormat.minBinaryExponent
|
||||||
&& targetSignificand >= (1 << (targetFormat.significandBits - 1))) {
|
&& targetSignificand >= (UInt64(1) << (targetFormat.significandBits - 1))) {
|
||||||
// Subnormal overflowed to normal
|
// Subnormal overflowed to normal
|
||||||
binaryExponent += 1
|
binaryExponent += 1
|
||||||
}
|
}
|
||||||
@@ -1769,7 +1769,7 @@ fileprivate func slowDecimalToBinary(
|
|||||||
count: targetFormat.significandBits,
|
count: targetFormat.significandBits,
|
||||||
remainderNonZero: false)
|
remainderNonZero: false)
|
||||||
|
|
||||||
if significand >= (1 &<< targetFormat.significandBits) {
|
if significand >= (UInt64(1) &<< targetFormat.significandBits) {
|
||||||
significand >>= 1
|
significand >>= 1
|
||||||
binaryExponent &+= 1
|
binaryExponent &+= 1
|
||||||
}
|
}
|
||||||
@@ -1865,7 +1865,7 @@ fileprivate func slowDecimalToBinary(
|
|||||||
range: quotientRange,
|
range: quotientRange,
|
||||||
count: targetFormat.significandBits,
|
count: targetFormat.significandBits,
|
||||||
remainderNonZero: remainderNonZero)
|
remainderNonZero: remainderNonZero)
|
||||||
if significand >= (1 &<< targetFormat.significandBits) {
|
if significand >= (UInt64(1) &<< targetFormat.significandBits) {
|
||||||
significand >>= 1
|
significand >>= 1
|
||||||
binaryExponent &+= 1
|
binaryExponent &+= 1
|
||||||
}
|
}
|
||||||
@@ -1889,7 +1889,7 @@ fileprivate func slowDecimalToBinary(
|
|||||||
// exponent. Then we've transitioned from a subnormal to
|
// exponent. Then we've transitioned from a subnormal to
|
||||||
// a normal, so the extra overflow bit will naturally get
|
// a normal, so the extra overflow bit will naturally get
|
||||||
// dropped, we just have to bump the exponent.
|
// dropped, we just have to bump the exponent.
|
||||||
if significand >= (1 &<< (targetFormat.significandBits &- 1)) {
|
if significand >= (UInt64(1) &<< (targetFormat.significandBits &- 1)) {
|
||||||
binaryExponent &+= 1
|
binaryExponent &+= 1
|
||||||
}
|
}
|
||||||
targetSignificand = significand
|
targetSignificand = significand
|
||||||
|
|||||||
@@ -7,9 +7,6 @@
|
|||||||
// Float16 is only available in watchOS 7.0 or newer
|
// Float16 is only available in watchOS 7.0 or newer
|
||||||
// UNSUPPORTED: OS=watchos
|
// UNSUPPORTED: OS=watchos
|
||||||
|
|
||||||
// TODO: Figure out why this test breaks on wasm32
|
|
||||||
// UNSUPPORTED: CPU=wasm32
|
|
||||||
|
|
||||||
// Cannot test with old OS stdlib, because that used libc strtof
|
// Cannot test with old OS stdlib, because that used libc strtof
|
||||||
// for parsing, which results in incorrect results.
|
// for parsing, which results in incorrect results.
|
||||||
// UNSUPPORTED: use_os_stdlib
|
// UNSUPPORTED: use_os_stdlib
|
||||||
@@ -105,7 +102,9 @@ tests.test("NaNs") {
|
|||||||
expectRoundTrip(Float16.nan)
|
expectRoundTrip(Float16.nan)
|
||||||
expectRoundTrip(-Float16.nan)
|
expectRoundTrip(-Float16.nan)
|
||||||
expectRoundTrip(Float16(nan:73, signaling:false))
|
expectRoundTrip(Float16(nan:73, signaling:false))
|
||||||
|
#if !arch(wasm32)
|
||||||
expectRoundTrip(Float16(nan:73, signaling:true))
|
expectRoundTrip(Float16(nan:73, signaling:true))
|
||||||
|
#endif
|
||||||
expectParse("nan", Float16.nan)
|
expectParse("nan", Float16.nan)
|
||||||
expectParse("NAN", Float16.nan)
|
expectParse("NAN", Float16.nan)
|
||||||
expectParse("NaN", Float16.nan)
|
expectParse("NaN", Float16.nan)
|
||||||
|
|||||||
@@ -5,9 +5,6 @@
|
|||||||
|
|
||||||
// REQUIRES: executable_test
|
// REQUIRES: executable_test
|
||||||
|
|
||||||
// TODO: Figure out why this test breaks on wasm32
|
|
||||||
// UNSUPPORTED: CPU=wasm32
|
|
||||||
|
|
||||||
// Needed to declare the ABI entry point
|
// Needed to declare the ABI entry point
|
||||||
// REQUIRES: swift_feature_Extern
|
// REQUIRES: swift_feature_Extern
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user