Skip to content

Commit 248c554

Browse files
Add Float16 to stdlib (#30130)
Add Float16 (IEEE 754 binary16) to the standard library, plus assorted runtime support operations. Swift Evolution thread: https://forums.swift.org/t/se-0277-float16/33546
1 parent b2fe997 commit 248c554

File tree

20 files changed

+436
-51
lines changed

20 files changed

+436
-51
lines changed

include/swift/ClangImporter/BuiltinMappedTypes.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ MAP_BUILTIN_INTEGER_TYPE(Int, CInt)
4646
MAP_BUILTIN_INTEGER_TYPE(Long, CLong)
4747
MAP_BUILTIN_INTEGER_TYPE(LongLong, CLongLong)
4848
MAP_BUILTIN_INTEGER_TYPE(Int128, CInt128)
49-
MAP_BUILTIN_TYPE(Float, CFloat)
50-
MAP_BUILTIN_TYPE(Double, CDouble)
49+
MAP_BUILTIN_TYPE(Float16, CFloat16)
50+
MAP_BUILTIN_TYPE(Half, CFloat16)
51+
MAP_BUILTIN_TYPE(Float, CFloat)
52+
MAP_BUILTIN_TYPE(Double, CDouble)
5153
MAP_BUILTIN_TYPE(LongDouble, CLongDouble)
5254

5355
#undef MAP_BUILTIN_TYPE

lib/ClangImporter/ImportType.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,6 @@ namespace {
248248
case clang::BuiltinType::SatUShortFract:
249249
case clang::BuiltinType::SatUFract:
250250
case clang::BuiltinType::SatULongFract:
251-
case clang::BuiltinType::Half:
252-
case clang::BuiltinType::Float16:
253251
case clang::BuiltinType::Float128:
254252
case clang::BuiltinType::NullPtr:
255253
case clang::BuiltinType::Char8:

lib/SILOptimizer/Utils/ConstantFolding.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -995,14 +995,18 @@ struct IEEESemantics {
995995

996996
IEEESemantics getFPSemantics(BuiltinFloatType *fpType) {
997997
switch (fpType->getFPKind()) {
998+
case BuiltinFloatType::IEEE16:
999+
return IEEESemantics(16, 5, 10, false);
9981000
case BuiltinFloatType::IEEE32:
9991001
return IEEESemantics(32, 8, 23, false);
10001002
case BuiltinFloatType::IEEE64:
10011003
return IEEESemantics(64, 11, 52, false);
10021004
case BuiltinFloatType::IEEE80:
10031005
return IEEESemantics(80, 15, 63, true);
1004-
default:
1005-
llvm_unreachable("Unexpected semantics");
1006+
case BuiltinFloatType::IEEE128:
1007+
return IEEESemantics(128, 15, 112, false);
1008+
case BuiltinFloatType::PPC128:
1009+
llvm_unreachable("ppc128 is not supported");
10061010
}
10071011
}
10081012

stdlib/public/SwiftShims/RuntimeShims.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ const char *_swift_stdlib_strtod_clocale(const char *nptr, double *outResult);
4444
/// overflow.
4545
SWIFT_RUNTIME_STDLIB_API
4646
const char *_swift_stdlib_strtof_clocale(const char *nptr, float *outResult);
47+
/// Call strtof_l with the C locale, swapping argument and return
48+
/// types so we can operate consistently on Float80. Return NULL on
49+
/// overflow.
50+
SWIFT_RUNTIME_STDLIB_API
51+
const char *_swift_stdlib_strtof16_clocale(const char *nptr, __fp16 *outResult);
4752

4853
SWIFT_RUNTIME_STDLIB_API
4954
void _swift_stdlib_immortalize(void *obj);

stdlib/public/core/CTypes.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ public typealias CLong = Int
5656
/// The C 'long long' type.
5757
public typealias CLongLong = Int64
5858

59+
/// The C '_Float16' type.
60+
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
61+
public typealias CFloat16 = Float16
62+
5963
/// The C 'float' type.
6064
public typealias CFloat = Float
6165

stdlib/public/core/Codable.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4592,6 +4592,38 @@ extension RawRepresentable where RawValue == Float, Self: Decodable {
45924592
}
45934593
}
45944594

4595+
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
4596+
extension Float16: Codable {
4597+
/// Creates a new instance by decoding from the given decoder.
4598+
///
4599+
/// This initializer throws an error if reading from the decoder fails, or
4600+
/// if the data read is corrupted or otherwise invalid.
4601+
///
4602+
/// - Parameter decoder: The decoder to read data from.
4603+
public init(from decoder: Decoder) throws {
4604+
let floatValue = try Float(from: decoder)
4605+
self = Float16(floatValue)
4606+
if isInfinite && floatValue.isFinite {
4607+
throw DecodingError.dataCorrupted(
4608+
DecodingError.Context(
4609+
codingPath: decoder.codingPath,
4610+
debugDescription: "Parsed JSON number \(floatValue) does not fit in Float16."
4611+
)
4612+
)
4613+
}
4614+
}
4615+
4616+
/// Encodes this value into the given encoder.
4617+
///
4618+
/// This function throws an error if any values are invalid for the given
4619+
/// encoder's format.
4620+
///
4621+
/// - Parameter encoder: The encoder to write data to.
4622+
public func encode(to encoder: Encoder) throws {
4623+
try Float(self).encode(to: encoder)
4624+
}
4625+
}
4626+
45954627
extension Int: Codable {
45964628
/// Creates a new instance by decoding from the given decoder.
45974629
///

stdlib/public/core/FloatingPointParsing.swift.gyb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,19 @@ import SwiftShims
1414

1515
%{
1616

17-
allFloatBits = [32, 64, 80]
17+
allFloatBits = [16, 32, 64, 80]
1818

1919
def floatName(bits):
20+
if bits == 16:
21+
return 'Float16'
2022
if bits == 32:
2123
return 'Float'
2224
if bits == 64:
2325
return 'Double'
2426
if bits == 80:
2527
return 'Float80'
2628

27-
cFuncSuffix2 = {32: 'f', 64: 'd', 80: 'ld'}
29+
cFuncSuffix2 = {16: 'f16', 32: 'f', 64: 'd', 80: 'ld'}
2830

2931
}%
3032

@@ -43,6 +45,9 @@ internal func _isspace_clocale(_ u: UTF16.CodeUnit) -> Bool {
4345
% end
4446

4547
//===--- Parsing ----------------------------------------------------------===//
48+
%if bits == 16:
49+
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
50+
%end
4651
extension ${Self}: LosslessStringConvertible {
4752
/// Creates a new instance from the given string.
4853
///
@@ -126,6 +131,9 @@ extension ${Self}: LosslessStringConvertible {
126131
/// is `nil`.
127132
@inlinable
128133
public init?<S: StringProtocol>(_ text: S) {
134+
%if bits == 16:
135+
self.init(Substring(text))
136+
%else:
129137
if #available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) {
130138
self.init(Substring(text))
131139
} else {
@@ -149,6 +157,7 @@ extension ${Self}: LosslessStringConvertible {
149157
return nil
150158
}
151159
}
160+
%end
152161
}
153162

154163
// Caveat: This implementation used to be inlineable.

0 commit comments

Comments
 (0)