From af54e5437def0e07d604750034737b3d7fb1bb48 Mon Sep 17 00:00:00 2001 From: Stephen Canon Date: Wed, 18 Nov 2020 21:41:59 -0500 Subject: [PATCH] Make Float16 available for macOS on Apple Silicon 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. --- stdlib/public/core/CTypes.swift | 6 +++--- stdlib/public/core/Codable.swift | 6 +++--- .../core/FloatingPointParsing.swift.gyb | 19 ++++++------------- .../public/core/FloatingPointTypes.swift.gyb | 14 +++++++++----- stdlib/public/core/IntegerTypes.swift.gyb | 12 +++++------- stdlib/public/core/Runtime.swift | 6 +++--- stdlib/public/core/SIMDVectorTypes.swift.gyb | 12 +++++++----- test/ClangImporter/simd.swift | 4 ++++ test/stdlib/PrintFloat.swift.gyb | 14 ++++++-------- 9 files changed, 46 insertions(+), 47 deletions(-) diff --git a/stdlib/public/core/CTypes.swift b/stdlib/public/core/CTypes.swift index a07d756b3f17c..a68bf7ddba69c 100644 --- a/stdlib/public/core/CTypes.swift +++ b/stdlib/public/core/CTypes.swift @@ -56,11 +56,11 @@ public typealias CLong = Int /// The C 'long long' type. public typealias CLongLong = Int64 +#if !(os(macOS) && arch(x86_64)) /// The C '_Float16' type. -@available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) -@available(macOS, unavailable) -@available(macCatalyst, unavailable) +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) public typealias CFloat16 = Float16 +#endif /// The C 'float' type. public typealias CFloat = Float diff --git a/stdlib/public/core/Codable.swift b/stdlib/public/core/Codable.swift index 3c9d02bcd839f..5057970760b23 100644 --- a/stdlib/public/core/Codable.swift +++ b/stdlib/public/core/Codable.swift @@ -4730,9 +4730,8 @@ extension RawRepresentable where RawValue == Float, Self: Decodable { } } -@available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) -@available(macOS, unavailable) -@available(macCatalyst, unavailable) +#if !(os(macOS) && arch(x86_64)) +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) extension Float16: Codable { /// Creates a new instance by decoding from the given decoder. /// @@ -4763,6 +4762,7 @@ extension Float16: Codable { try Float(self).encode(to: encoder) } } +#endif extension Int: Codable { /// Creates a new instance by decoding from the given decoder. diff --git a/stdlib/public/core/FloatingPointParsing.swift.gyb b/stdlib/public/core/FloatingPointParsing.swift.gyb index 0ae7a0a3e6dbb..a3c4b1b883bfd 100644 --- a/stdlib/public/core/FloatingPointParsing.swift.gyb +++ b/stdlib/public/core/FloatingPointParsing.swift.gyb @@ -42,13 +42,12 @@ internal func _isspace_clocale(_ u: UTF16.CodeUnit) -> Bool { % if bits == 80: #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) +% elif bits == 16: +#if !(os(macOS) && arch(x86_64)) % end -//===--- Parsing ----------------------------------------------------------===// %if bits == 16: -@available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) -@available(macOS, unavailable) -@available(macCatalyst, unavailable) +@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. @@ -136,7 +135,7 @@ extension ${Self}: LosslessStringConvertible { %if bits == 16: self.init(Substring(text)) %else: - if #available(macOS 10.16, iOS 14.0, watchOS 7.0, tvOS 14.0, *) { + if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) { self.init(Substring(text)) } else { self = 0.0 @@ -166,13 +165,7 @@ extension ${Self}: LosslessStringConvertible { // In particular, we still have to export // _swift_stdlib_strtoXYZ_clocale() // as ABI to support old compiled code that still requires it. -%if bits == 16: - @available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) - @available(macOS, unavailable) - @available(macCatalyst, unavailable) -%else: - @available(macOS 10.16, iOS 14.0, watchOS 7.0, tvOS 14.0, *) -%end + @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 @@ -196,7 +189,7 @@ extension ${Self}: LosslessStringConvertible { } } -% if bits == 80: +% if bits in [16,80]: #endif % end diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb index 59a3a0379d2a8..ac7ec998e675d 100644 --- a/stdlib/public/core/FloatingPointTypes.swift.gyb +++ b/stdlib/public/core/FloatingPointTypes.swift.gyb @@ -40,7 +40,7 @@ RawSignificand = 'UInt' + str(SignificandSize) def Availability(bits): if bits == 16: - return '@available(iOS 14.0, watchOS 7.0, tvOS 14.0, *)\n@available(macOS, unavailable)\n@available(macCatalyst, unavailable)' + return '@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)' return '' if Self == 'Float16': @@ -65,6 +65,8 @@ else: % if bits == 80: #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) +% elif bits == 16: +#if !(os(macOS) && arch(x86_64)) % end ${SelfDocComment} @@ -1106,8 +1108,10 @@ extension ${Self} { % srcBits = src_type.bits % That = src_type.stdlib_name -% if (srcBits == 80) and (bits != 80): +% if srcBits == 80: #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) +% elif srcBits == 16: +#if !(os(macOS) && arch(x86_64)) % end % if srcBits == bits: @@ -1192,7 +1196,7 @@ extension ${Self} { } } -% if (srcBits == 80) and (bits != 80): +% if srcBits in [16,80]: #endif % end % end @@ -1343,12 +1347,12 @@ internal struct _${Self}AnyHashableBox: _AnyHashableBox { // Deprecated operators //===----------------------------------------------------------------------===// -% if bits == 80: +% if bits in [16,80]: #else ${SelfDocComment} @frozen -@available(*, unavailable, message: "Float80 is not available on target platform.") +@available(*, unavailable, message: "${Self} is not available on target platform.") public struct ${Self} { /// Creates a value initialized to zero. @_transparent diff --git a/stdlib/public/core/IntegerTypes.swift.gyb b/stdlib/public/core/IntegerTypes.swift.gyb index c275c30d86d2e..4b4c6c7cbe716 100644 --- a/stdlib/public/core/IntegerTypes.swift.gyb +++ b/stdlib/public/core/IntegerTypes.swift.gyb @@ -1129,6 +1129,8 @@ public struct ${Self} % if FloatType == 'Float80': #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) +% elif FloatType == 'Float16': +#if !(os(macOS) && arch(x86_64)) % end /// Creates an integer from the given floating-point value, rounding toward @@ -1152,9 +1154,7 @@ public struct ${Self} /// `source` must be representable in this type after rounding toward /// zero. % if FloatType == 'Float16': - @available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) - @available(macOS, unavailable) - @available(macCatalyst, unavailable) + @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) % end @_transparent public init(_ source: ${FloatType}) { @@ -1184,9 +1184,7 @@ public struct ${Self} /// /// - Parameter source: A floating-point value to convert to an integer. % if FloatType == 'Float16': - @available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) - @available(macOS, unavailable) - @available(macCatalyst, unavailable) + @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) % end @_transparent public init?(exactly source: ${FloatType}) { @@ -1206,7 +1204,7 @@ public struct ${Self} self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value) } -% if FloatType == 'Float80': +% if FloatType in ['Float16', 'Float80']: #endif % end diff --git a/stdlib/public/core/Runtime.swift b/stdlib/public/core/Runtime.swift index 086588cffc43d..c1e72cdd0eae2 100644 --- a/stdlib/public/core/Runtime.swift +++ b/stdlib/public/core/Runtime.swift @@ -293,6 +293,7 @@ internal struct _Buffer72 { } } +#if !(os(macOS) && arch(x86_64)) // Note that this takes a Float32 argument instead of Float16, because clang // doesn't have _Float16 on all platforms yet. @_silgen_name("swift_float16ToString") @@ -303,9 +304,7 @@ internal func _float16ToStringImpl( _ debug: Bool ) -> Int -@available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) -@available(macOS, unavailable) -@available(macCatalyst, unavailable) +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) internal func _float16ToString( _ value: Float16, debug: Bool @@ -317,6 +316,7 @@ internal func _float16ToString( } return (buffer, length) } +#endif // Returns a UInt64, but that value is the length of the string, so it's // guaranteed to fit into an Int. This is part of the ABI, so we can't diff --git a/stdlib/public/core/SIMDVectorTypes.swift.gyb b/stdlib/public/core/SIMDVectorTypes.swift.gyb index 0faf4371bc7f7..0002f8cdcf293 100644 --- a/stdlib/public/core/SIMDVectorTypes.swift.gyb +++ b/stdlib/public/core/SIMDVectorTypes.swift.gyb @@ -253,11 +253,10 @@ extension ${Self}: SIMDScalar { %end %for (Self, bits) in [('Float16',16), ('Float',32), ('Double',64)]: -%if bits == 16: -@available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) -@available(macOS, unavailable) -@available(macCatalyst, unavailable) -%end +% if bits == 16: +#if !(os(macOS) && arch(x86_64)) +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) +% end extension ${Self} : SIMDScalar { public typealias SIMDMaskScalar = Int${bits} @@ -299,5 +298,8 @@ extension ${Self} : SIMDScalar { % end } +% if bits == 16: +#endif +% end %end diff --git a/test/ClangImporter/simd.swift b/test/ClangImporter/simd.swift index e308b0792b46a..69eb614057023 100644 --- a/test/ClangImporter/simd.swift +++ b/test/ClangImporter/simd.swift @@ -22,12 +22,14 @@ let ll3_value: ll3 = makes_ll3() let ll8_value: ll8 = makes_ll8() let ull4_value: ull4 = makes_ull4() let ull16_value: ull16 = makes_ull16() +#if !(os(macOS) && arch(x86_64)) let half2_value: half2 = makes_half2() let half3_value: half3 = makes_half3() let half4_value: half4 = makes_half4() let half8_value: half8 = makes_half8() let half16_value: half16 = makes_half16() let half32_value: half32 = makes_half32() +#endif let float2_value: float2 = makes_float2() let float3_value: float3 = makes_float3() let float4_value: float4 = makes_float4() @@ -58,12 +60,14 @@ takes_ll3(ll3_value) takes_ll8(ll8_value) takes_ull4(ull4_value) takes_ull16(ull16_value) +#if !(os(macOS) && arch(x86_64)) takes_half2(half2_value) takes_half3(half3_value) takes_half4(half4_value) takes_half8(half8_value) takes_half16(half16_value) takes_half32(half32_value) +#endif takes_float2(float2_value) takes_float3(float3_value) takes_float4(float4_value) diff --git a/test/stdlib/PrintFloat.swift.gyb b/test/stdlib/PrintFloat.swift.gyb index ec24b7ba11113..b151df19893df 100644 --- a/test/stdlib/PrintFloat.swift.gyb +++ b/test/stdlib/PrintFloat.swift.gyb @@ -345,11 +345,9 @@ let PrintTests = TestSuite("FloatingPointPrinting") % for FloatType in ['Float16', 'Float', 'Double', 'Float80']: % if FloatType == 'Float16': -@available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) -@available(macOS, unavailable) -@available(macCatalyst, unavailable) -% end -% if FloatType == 'Float80': +#if !(os(macOS) && arch(x86_64)) +@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) +% elif FloatType == 'Float80': #if !os(Windows) && (arch(i386) || arch(x86_64)) % end @@ -425,7 +423,7 @@ fileprivate func expectAccurateDescription(_ object: ${FloatType}, // that the result is not closer. Note this requires higher-precision // arithmetic. } -% if FloatType == 'Float80': +% if FloatType in ['Float16','Float80']: #endif % end % end @@ -587,8 +585,8 @@ PrintTests.test("Printable_CDouble") { expectDescription("-1.0", CDouble(-1.0)) } -#if !os(macOS) && !(os(iOS) && targetEnvironment(macCatalyst)) -if #available(iOS 14.0, watchOS 7.0, tvOS 14.0, *) { +#if !(os(macOS) && arch(x86_64)) +if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) { PrintTests.test("Printable_Float16") { func asFloat16(_ f: Float16) -> Float16 { return f }