mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Due to an unstable (and undesirable) calling convention in the LLVM layer for x86, I had previously marked Float16 unconditionally unavailable on macOS. My hope was that Intel would stabilize the calling convention and we could make it available on both macOS platforms at the same time. Unfortunately, that hasn't happened, and we want to make the type available for macOS/arm users. So, I am making the availability mirror Float80--the type will be unavailable for macOS on x86_64, and available on all other platforms (the other x86 platforms don't have a binary-stability guarantee to worry about). This isn't ideal. In particular, if/when the calling conventions for Float16 stabilize in LLVM, we would want to make the type available, but it would then have _different_ availability for different architectures of macOS, which the current availability system is not well-equipped to handle (it's possible, but not very ergonomic). Nonetheless, this seems like the best option. The good news is that because the full API is already built in Swift (and simply marked unavailable), we can simply add macOS 11.0 availability for these API and it will work.
201 lines
6.5 KiB
Swift
201 lines
6.5 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import SwiftShims
|
|
|
|
%{
|
|
|
|
allFloatBits = [16, 32, 64, 80]
|
|
|
|
def floatName(bits):
|
|
if bits == 16:
|
|
return 'Float16'
|
|
if bits == 32:
|
|
return 'Float'
|
|
if bits == 64:
|
|
return 'Double'
|
|
if bits == 80:
|
|
return 'Float80'
|
|
|
|
cFuncSuffix2 = {16: 'f16', 32: 'f', 64: 'd', 80: 'ld'}
|
|
|
|
}%
|
|
|
|
/// Returns `true` iff isspace(u) would return nonzero when the current
|
|
/// locale is the C locale.
|
|
@inlinable // FIXME(sil-serialize-all)
|
|
internal func _isspace_clocale(_ u: UTF16.CodeUnit) -> Bool {
|
|
return "\t\n\u{b}\u{c}\r ".utf16.contains(u)
|
|
}
|
|
|
|
% for bits in allFloatBits:
|
|
% Self = floatName(bits)
|
|
|
|
% if bits == 80:
|
|
#if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
|
|
% elif bits == 16:
|
|
#if !(os(macOS) && arch(x86_64))
|
|
% end
|
|
|
|
%if bits == 16:
|
|
@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
|
|
%end
|
|
extension ${Self}: LosslessStringConvertible {
|
|
/// Creates a new instance from the given string.
|
|
///
|
|
/// The string passed as `text` can represent a real number in decimal or
|
|
/// hexadecimal format or special floating-point values for infinity and NaN
|
|
/// ("not a number").
|
|
///
|
|
/// The given string may begin with a plus or minus sign character (`+` or
|
|
/// `-`). The allowed formats for each of these representations is then as
|
|
/// follows:
|
|
///
|
|
/// - A *decimal value* contains the significand, a sequence of decimal
|
|
/// digits that may include a decimal point.
|
|
///
|
|
/// let c = ${Self}("-1.0")
|
|
/// // c == -1.0
|
|
///
|
|
/// let d = ${Self}("28.375")
|
|
/// // d == 28.375
|
|
///
|
|
/// A decimal value may also include an exponent following the significand,
|
|
/// indicating the power of 10 by which the significand should be
|
|
/// multiplied. If included, the exponent is separated by a single
|
|
/// character, `e` or `E`, and consists of an optional plus or minus sign
|
|
/// character and a sequence of decimal digits.
|
|
///
|
|
/// let e = ${Self}("2837.5e-2")
|
|
/// // e == 28.375
|
|
///
|
|
/// - A *hexadecimal value* contains the significand, either `0X` or `0x`,
|
|
/// followed by a sequence of hexadecimal digits. The significand may
|
|
/// include a decimal point.
|
|
///
|
|
/// let f = ${Self}("0x1c.6")
|
|
/// // f == 28.375
|
|
///
|
|
/// A hexadecimal value may also include an exponent following the
|
|
/// significand, indicating the power of 2 by which the significand should
|
|
/// be multiplied. If included, the exponent is separated by a single
|
|
/// character, `p` or `P`, and consists of an optional plus or minus sign
|
|
/// character and a sequence of decimal digits.
|
|
///
|
|
/// let g = ${Self}("0x1.c6p4")
|
|
/// // g == 28.375
|
|
///
|
|
/// - A value of *infinity* contains one of the strings `"inf"` or
|
|
/// `"infinity"`, case insensitive.
|
|
///
|
|
/// let i = ${Self}("inf")
|
|
/// // i == ${Self}.infinity
|
|
///
|
|
/// let j = ${Self}("-Infinity")
|
|
/// // j == -${Self}.infinity
|
|
///
|
|
/// - A value of *NaN* contains the string `"nan"`, case insensitive.
|
|
///
|
|
/// let n = ${Self}("-nan")
|
|
/// // n?.isNaN == true
|
|
/// // n?.sign == .minus
|
|
///
|
|
/// A NaN value may also include a payload in parentheses following the
|
|
/// `"nan"` keyword. The payload consists of a sequence of decimal digits,
|
|
/// or the characters `0X` or `0x` followed by a sequence of hexadecimal
|
|
/// digits. If the payload contains any other characters, it is ignored.
|
|
/// If the value of the payload is larger than can be stored as the
|
|
/// payload of a `${Self}.nan`, the least significant bits are used.
|
|
///
|
|
/// let p = ${Self}("nan(0x10)")
|
|
/// // p?.isNaN == true
|
|
/// // String(p!) == "nan(0x10)"
|
|
///
|
|
/// Passing any other format or any additional characters as `text` results
|
|
/// in `nil`. For example, the following conversions result in `nil`:
|
|
///
|
|
/// ${Self}(" 5.0") // Includes whitespace
|
|
/// ${Self}("±2.0") // Invalid character
|
|
/// ${Self}("0x1.25e4") // Incorrect exponent format
|
|
///
|
|
/// - Parameter text: The input string to convert to a `${Self}` instance. If
|
|
/// `text` has invalid characters or is in an invalid format, the result
|
|
/// is `nil`.
|
|
@inlinable
|
|
public init?<S: StringProtocol>(_ text: S) {
|
|
%if bits == 16:
|
|
self.init(Substring(text))
|
|
%else:
|
|
if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) {
|
|
self.init(Substring(text))
|
|
} else {
|
|
self = 0.0
|
|
let success = withUnsafeMutablePointer(to: &self) { p -> Bool in
|
|
text.withCString { chars -> Bool in
|
|
switch chars[0] {
|
|
case 9, 10, 11, 12, 13, 32:
|
|
return false // Reject leading whitespace
|
|
case 0:
|
|
return false // Reject empty string
|
|
default:
|
|
break
|
|
}
|
|
let endPtr = _swift_stdlib_strto${cFuncSuffix2[bits]}_clocale(chars, p)
|
|
// Succeed only if endPtr points to end of C string
|
|
return endPtr != nil && endPtr![0] == 0
|
|
}
|
|
}
|
|
if !success {
|
|
return nil
|
|
}
|
|
}
|
|
%end
|
|
}
|
|
|
|
// Caveat: This implementation used to be inlineable.
|
|
// In particular, we still have to export
|
|
// _swift_stdlib_strtoXYZ_clocale()
|
|
// as ABI to support old compiled code that still requires it.
|
|
@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
|
|
public init?(_ text: Substring) {
|
|
self = 0.0
|
|
let success = withUnsafeMutablePointer(to: &self) { p -> Bool in
|
|
text.withCString { chars -> Bool in
|
|
switch chars[0] {
|
|
case 9, 10, 11, 12, 13, 32:
|
|
return false // Reject leading whitespace
|
|
case 0:
|
|
return false // Reject empty string
|
|
default:
|
|
break
|
|
}
|
|
let endPtr = _swift_stdlib_strto${cFuncSuffix2[bits]}_clocale(chars, p)
|
|
// Succeed only if endPtr points to end of C string
|
|
return endPtr != nil && endPtr![0] == 0
|
|
}
|
|
}
|
|
if !success {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
% if bits in [16,80]:
|
|
#endif
|
|
% end
|
|
|
|
% end
|
|
|
|
// ${'Local Variables'}:
|
|
// eval: (read-only-mode 1)
|
|
// End:
|