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 {
|
||||
var i = start + 2 // Skip leading '0x'
|
||||
let firstDigitOffset = i
|
||||
|
||||
let limit = UInt64(1) << 60
|
||||
var significand: UInt64 = 0
|
||||
|
||||
//
|
||||
@@ -458,10 +458,10 @@ fileprivate func hexFloat(
|
||||
//
|
||||
|
||||
// Accumulate the most significant 64 bits...
|
||||
while i < input.count && hexdigit(input[i]) < 16 && significand < (1 << 60) {
|
||||
significand &<<= 4
|
||||
significand += UInt64(hexdigit(input[i]))
|
||||
i += 1
|
||||
while i < input.count && hexdigit(input[i]) < 16 && significand < limit {
|
||||
significand &<<= 4
|
||||
significand += UInt64(hexdigit(input[i]))
|
||||
i += 1
|
||||
}
|
||||
|
||||
// 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)
|
||||
while i < input.count && hexdigit(input[i]) < 16 && significand < (1 << 60) {
|
||||
while i < input.count && hexdigit(input[i]) < 16 && significand < limit {
|
||||
significand &<<= 4
|
||||
significand += UInt64(hexdigit(input[i]))
|
||||
i += 1
|
||||
@@ -631,12 +631,12 @@ fileprivate func hexFloat(
|
||||
&& (targetSignificand & 1) == 1)) {
|
||||
// Round up, test for overflow
|
||||
targetSignificand += 1
|
||||
if targetSignificand >= (1 << targetFormat.significandBits) {
|
||||
if targetSignificand >= (UInt64(1) << targetFormat.significandBits) {
|
||||
// Normal overflowed, need to renormalize
|
||||
targetSignificand >>= 1
|
||||
binaryExponent += 1
|
||||
} else if (binaryExponent < targetFormat.minBinaryExponent
|
||||
&& targetSignificand >= (1 << (targetFormat.significandBits - 1))) {
|
||||
&& targetSignificand >= (UInt64(1) << (targetFormat.significandBits - 1))) {
|
||||
// Subnormal overflowed to normal
|
||||
binaryExponent += 1
|
||||
}
|
||||
@@ -1769,7 +1769,7 @@ fileprivate func slowDecimalToBinary(
|
||||
count: targetFormat.significandBits,
|
||||
remainderNonZero: false)
|
||||
|
||||
if significand >= (1 &<< targetFormat.significandBits) {
|
||||
if significand >= (UInt64(1) &<< targetFormat.significandBits) {
|
||||
significand >>= 1
|
||||
binaryExponent &+= 1
|
||||
}
|
||||
@@ -1865,7 +1865,7 @@ fileprivate func slowDecimalToBinary(
|
||||
range: quotientRange,
|
||||
count: targetFormat.significandBits,
|
||||
remainderNonZero: remainderNonZero)
|
||||
if significand >= (1 &<< targetFormat.significandBits) {
|
||||
if significand >= (UInt64(1) &<< targetFormat.significandBits) {
|
||||
significand >>= 1
|
||||
binaryExponent &+= 1
|
||||
}
|
||||
@@ -1889,7 +1889,7 @@ fileprivate func slowDecimalToBinary(
|
||||
// exponent. Then we've transitioned from a subnormal to
|
||||
// a normal, so the extra overflow bit will naturally get
|
||||
// dropped, we just have to bump the exponent.
|
||||
if significand >= (1 &<< (targetFormat.significandBits &- 1)) {
|
||||
if significand >= (UInt64(1) &<< (targetFormat.significandBits &- 1)) {
|
||||
binaryExponent &+= 1
|
||||
}
|
||||
targetSignificand = significand
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
// Float16 is only available in watchOS 7.0 or newer
|
||||
// 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
|
||||
// for parsing, which results in incorrect results.
|
||||
// UNSUPPORTED: use_os_stdlib
|
||||
@@ -105,7 +102,9 @@ tests.test("NaNs") {
|
||||
expectRoundTrip(Float16.nan)
|
||||
expectRoundTrip(-Float16.nan)
|
||||
expectRoundTrip(Float16(nan:73, signaling:false))
|
||||
#if !arch(wasm32)
|
||||
expectRoundTrip(Float16(nan:73, signaling:true))
|
||||
#endif
|
||||
expectParse("nan", Float16.nan)
|
||||
expectParse("NAN", Float16.nan)
|
||||
expectParse("NaN", Float16.nan)
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
|
||||
// REQUIRES: executable_test
|
||||
|
||||
// TODO: Figure out why this test breaks on wasm32
|
||||
// UNSUPPORTED: CPU=wasm32
|
||||
|
||||
// Needed to declare the ABI entry point
|
||||
// REQUIRES: swift_feature_Extern
|
||||
|
||||
|
||||
Reference in New Issue
Block a user