Skip to content

Commit f8a9e56

Browse files
Importer support for float80 (#14971)
* First pass at implementing support for mapping between long double and Float80. * Only define CLongDouble on platforms where I know what it is. * remove some hacks that are no longer necessary.
1 parent e38ea2d commit f8a9e56

File tree

10 files changed

+124
-40
lines changed

10 files changed

+124
-40
lines changed

include/swift/ClangImporter/BuiltinMappedTypes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ MAP_BUILTIN_INTEGER_TYPE(LongLong, CLongLong)
4848
MAP_BUILTIN_INTEGER_TYPE(Int128, CInt128)
4949
MAP_BUILTIN_TYPE(Float, CFloat)
5050
MAP_BUILTIN_TYPE(Double, CDouble)
51+
MAP_BUILTIN_TYPE(LongDouble, CLongDouble)
5152

5253
#undef MAP_BUILTIN_TYPE
5354
#undef MAP_BUILTIN_INTEGER_TYPE

lib/ClangImporter/ImportType.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ namespace {
224224

225225
// FIXME: Types that can be mapped, but aren't yet.
226226
case clang::BuiltinType::Half:
227-
case clang::BuiltinType::LongDouble:
228227
case clang::BuiltinType::Float128:
229228
case clang::BuiltinType::NullPtr:
230229
return Type();

stdlib/public/Platform/tgmath.swift.gyb

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,8 @@ public func trunc<T: FloatingPoint>(_ x: T) -> T {
6262
%{
6363

6464
# Don't need 64-bit (Double/CDouble) overlays. The ordinary C imports work fine.
65-
# FIXME: need 80-bit (Float80/long double) versions when long double is imported
66-
overlayFloatBits = [32] # 80
67-
allFloatBits = [32, 64] # 80
65+
overlayFloatBits = [32, 80]
66+
allFloatBits = [32, 64, 80]
6867

6968
def floatName(bits):
7069
if bits == 32:
@@ -168,21 +167,33 @@ def TypedBinaryFunctions():
168167
// Unary functions
169168
// Note these do not have a corresponding LLVM intrinsic
170169
% for T, CT, f, ufunc in TypedUnaryFunctions():
170+
% if T == 'Float80':
171+
#if arch(i386) || arch(x86_64)
172+
% end
171173
@_transparent
172174
public func ${ufunc}(_ x: ${T}) -> ${T} {
173175
return ${T}(${ufunc}${f}(${CT}(x)))
174176
}
177+
% if T == 'Float80':
178+
#endif
179+
% end
175180

176181
% end
177182

178183
#if os(OSX) || os(iOS) || os(tvOS) || os(watchOS)
179184
// Unary intrinsic functions
180185
// Note these have a corresponding LLVM intrinsic
181186
% for T, ufunc in TypedUnaryIntrinsicFunctions():
187+
% if T == 'Float80':
188+
#if arch(i386) || arch(x86_64)
189+
% end
182190
@_transparent
183191
public func ${ufunc}(_ x: ${T}) -> ${T} {
184192
return _${ufunc}(x)
185193
}
194+
% if T == 'Float80':
195+
#endif
196+
% end
186197

187198
% end
188199
#else
@@ -204,21 +215,30 @@ public func ${ufunc}(_ x: ${T}) -> ${T} {
204215
// Binary functions
205216

206217
% for T, CT, f, bfunc in TypedBinaryFunctions():
218+
% if T == 'Float80':
219+
#if arch(i386) || arch(x86_64)
220+
% end
207221
@_transparent
208222
public func ${bfunc}(_ lhs: ${T}, _ rhs: ${T}) -> ${T} {
209223
return ${T}(${bfunc}${f}(${CT}(lhs), ${CT}(rhs)))
210224
}
225+
% if T == 'Float80':
226+
#endif
227+
% end
211228

212229
% end
213230

214231
// Other functions
215232
% for T, CT, f in AllFloatTypes():
233+
% if T == 'Float80':
234+
#if arch(i386) || arch(x86_64)
235+
% end
216236
@available(*, deprecated, message: "use the floatingPointClass property.")
217237
public func fpclassify(_ value: ${T}) -> Int {
218238
%if T == 'Double':
219239
#if os(Linux) || os(Haiku)
220240
return Int(__fpclassify(CDouble(value)))
221-
#elseif os(Windows)
241+
#elseif os(Windows)
222242
return Int(_dclass(CDouble(value)))
223243
#else
224244
return Int(__fpclassifyd(CDouble(value)))
@@ -247,59 +267,95 @@ public func isnan(_ value: ${T}) -> Bool { return value.isNaN }
247267
@available(*, unavailable, message: "use the sign property.")
248268
public func signbit(_ value: ${T}) -> Int { return value.sign.rawValue }
249269

270+
% if T == 'Float80':
271+
#endif
272+
% end
250273
% end
251274

252275
% # These are AllFloatTypes not OverlayFloatTypes because of the tuple return.
253276
% for T, CT, f in AllFloatTypes():
277+
% if T == 'Float80':
278+
#if arch(i386) || arch(x86_64)
279+
% end
254280
@_transparent
255281
public func modf(_ value: ${T}) -> (${T}, ${T}) {
256282
var ipart = ${CT}(0)
257283
let fpart = modf${f}(${CT}(value), &ipart)
258284
return (${T}(ipart), ${T}(fpart))
259285
}
286+
% if T == 'Float80':
287+
#endif
288+
% end
260289

261290
% end
262291

263292
% # This is AllFloatTypes not OverlayFloatTypes because of the Int parameter.
264293
% for T, CT, f in AllFloatTypes():
294+
% if T == 'Float80':
295+
#if arch(i386) || arch(x86_64)
296+
% end
265297
@_transparent
266298
public func ldexp(_ x: ${T}, _ n: Int) -> ${T} {
267299
return ${T}(ldexp${f}(${CT}(x), Int32(n)))
268300
}
301+
% if T == 'Float80':
302+
#endif
303+
% end
269304

270305
% end
271306

272307
% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
273308
% for T, CT, f in AllFloatTypes():
309+
% if T == 'Float80':
310+
#if arch(i386) || arch(x86_64)
311+
% end
274312
@_transparent
275313
public func frexp(_ value: ${T}) -> (${T}, Int) {
276314
var exp = Int32(0)
277315
let frac = frexp${f}(${CT}(value), &exp)
278316
return (${T}(frac), Int(exp))
279317
}
318+
% if T == 'Float80':
319+
#endif
320+
% end
280321

281322
% end
282323

283324
% # This is AllFloatTypes not OverlayFloatTypes because of the Int return.
284325
% for T, CT, f in AllFloatTypes():
326+
% if T == 'Float80':
327+
#if arch(i386) || arch(x86_64)
328+
% end
285329
@_transparent
286330
public func ilogb(_ x: ${T}) -> Int {
287331
return Int(ilogb${f}(${CT}(x)) as Int32)
288332
}
333+
% if T == 'Float80':
334+
#endif
335+
% end
289336

290337
% end
291338

292339
% # This is AllFloatTypes not OverlayFloatTypes because of the Int parameter.
293340
% for T, CT, f in AllFloatTypes():
341+
% if T == 'Float80':
342+
#if arch(i386) || arch(x86_64)
343+
% end
294344
@_transparent
295345
public func scalbn(_ x: ${T}, _ n: Int) -> ${T} {
296346
return ${T}(scalbn${f}(${CT}(x), Int32(n)))
297347
}
348+
% if T == 'Float80':
349+
#endif
350+
% end
298351

299352
% end
300353

301354
% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
302355
% for T, CT, f in AllFloatTypes():
356+
% if T == 'Float80':
357+
#if arch(i386) || arch(x86_64)
358+
% end
303359
#if os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
304360
@_transparent
305361
public func lgamma(_ x: ${T}) -> (${T}, Int) {
@@ -322,25 +378,40 @@ public func lgamma(_ x: ${T}) -> (${T}, Int) {
322378
return (${T}(value), Int(sign))
323379
}
324380
#endif
381+
% if T == 'Float80':
382+
#endif
383+
% end
325384

326385
% end
327386

328387
% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
329388
% for T, CT, f in AllFloatTypes():
389+
% if T == 'Float80':
390+
#if arch(i386) || arch(x86_64)
391+
% end
330392
@_transparent
331393
public func remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) {
332394
var quo = Int32(0)
333395
let rem = remquo${f}(${CT}(x), ${CT}(y), &quo)
334396
return (${T}(rem), Int(quo))
335397
}
398+
% if T == 'Float80':
399+
#endif
400+
% end
336401

337402
% end
338403

339404
% for T, CT, f in OverlayFloatTypes():
405+
% if T == 'Float80':
406+
#if arch(i386) || arch(x86_64)
407+
% end
340408
@_transparent
341409
public func nan(_ tag: String) -> ${T} {
342410
return ${T}(nan${f}(tag))
343411
}
412+
% if T == 'Float80':
413+
#endif
414+
% end
344415

345416
% end
346417

stdlib/public/SwiftShims/LibcShims.h

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,18 @@ double _stdlib_squareRoot(double _self) {
170170
return __builtin_sqrt(_self);
171171
}
172172

173+
#if !defined _WIN32 && (defined __i386__ || defined __x86_64__)
174+
static inline SWIFT_ALWAYS_INLINE
175+
long double _stdlib_remainderl(long double _self, long double _other) {
176+
return __builtin_remainderl(_self, _other);
177+
}
178+
179+
static inline SWIFT_ALWAYS_INLINE
180+
long double _stdlib_squareRootl(long double _self) {
181+
return __builtin_sqrtl(_self);
182+
}
183+
#endif
184+
173185
// Apple's math.h does not declare lgamma_r() etc by default
174186
#if defined(__APPLE__)
175187
SWIFT_RUNTIME_STDLIB_INTERNAL
@@ -210,21 +222,6 @@ SWIFT_RUNTIME_STDLIB_INTERNAL
210222
int _stdlib_thread_setspecific(__swift_thread_key_t key,
211223
const void * _Nullable value);
212224

213-
// TODO: Remove horrible workaround when importer does Float80 <-> long double.
214-
#if (defined __i386__ || defined __x86_64__) && !defined _MSC_VER
215-
static inline SWIFT_ALWAYS_INLINE
216-
void _stdlib_remainderl(void *_self, const void *_other) {
217-
long double *_f80self = (long double *)_self;
218-
*_f80self = __builtin_remainderl(*_f80self, *(const long double *)_other);
219-
}
220-
221-
static inline SWIFT_ALWAYS_INLINE
222-
void _stdlib_squareRootl(void *_self) {
223-
long double *_f80self = (long double *)_self;
224-
*_f80self = __builtin_sqrtl(*_f80self);
225-
}
226-
#endif // Have Float80
227-
228225
#ifdef __cplusplus
229226
}} // extern "C", namespace swift
230227
#endif

stdlib/public/core/BuiltinMath.swift.gyb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@
1313
%{
1414

1515
# Don't need 64-bit (Double/CDouble) overlays. The ordinary C imports work fine.
16-
# FIXME: need 80-bit (Float80/long double) versions when long double is imported
17-
overlayFloatBits = [32] # 80
18-
allFloatBits = [32, 64] # 80
16+
overlayFloatBits = [32, 80]
17+
allFloatBits = [32, 64, 80]
1918

2019
def floatName(bits):
2120
if bits == 32:
@@ -62,12 +61,17 @@ def TypedUnaryIntrinsicFunctions():
6261
// Unary intrinsic functions
6362
// Note these have a corresponding LLVM intrinsic
6463
% for T, CT, bits, ufunc in TypedUnaryIntrinsicFunctions():
64+
% if bits == 80:
65+
#if arch(i386) || arch(x86_64)
66+
% end
6567
@_inlineable // FIXME(sil-serialize-all)
6668
@_transparent
6769
public func _${ufunc}(_ x: ${T}) -> ${T} {
6870
return ${T}(_bits: Builtin.int_${ufunc}_FPIEEE${bits}(x._value))
6971
}
70-
72+
% if bits == 80:
73+
#endif
74+
% end
7175
% end
7276

7377
// ${'Local Variables'}:

stdlib/public/core/CTypes.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,27 @@ public typealias CFloat = Float
6262
/// The C 'double' type.
6363
public typealias CDouble = Double
6464

65-
// FIXME: long double
65+
/// The C 'long double' type.
66+
#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
67+
// On Darwin, long double is Float80 on x86, and Double otherwise.
68+
#if arch(x86_64) || arch(i386)
69+
public typealias CLongDouble = Float80
70+
#else
71+
public typealias CLongDouble = Double
72+
#endif
73+
#elseif os(Windows)
74+
// On Windows, long double is always Double.
75+
public typealias CLongDouble = Double
76+
#elseif os(Linux)
77+
// On Linux/x86, long double is Float80.
78+
// TODO: Fill in definitions for additional architectures as needed. IIRC
79+
// armv7 should map to Double, but arm64 and ppc64le should map to Float128,
80+
// which we don't yet have in Swift.
81+
#if arch(x86_64) || arch(i386)
82+
public typealias CLongDouble = Float80
83+
#endif
84+
// TODO: Fill in definitions for other OSes.
85+
#endif
6686

6787
// FIXME: Is it actually UTF-32 on Darwin?
6888
//

stdlib/public/core/FloatingPointTypes.swift.gyb

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,12 +1085,7 @@ extension ${Self}: BinaryFloatingPoint {
10851085
@_inlineable // FIXME(sil-serialize-all)
10861086
@_transparent
10871087
public mutating func formRemainder(dividingBy other: ${Self}) {
1088-
%if bits == 80:
1089-
var other = other
1090-
_stdlib_remainderl(&self, &other)
1091-
%else:
10921088
self = _stdlib_remainder${cFuncSuffix}(self, other)
1093-
%end
10941089
}
10951090

10961091
/// Replaces this value with the remainder of itself divided by the given
@@ -1133,11 +1128,7 @@ extension ${Self}: BinaryFloatingPoint {
11331128
@_inlineable // FIXME(sil-serialize-all)
11341129
@_transparent
11351130
public mutating func formSquareRoot( ) {
1136-
%if bits == 80:
1137-
_stdlib_squareRootl(&self)
1138-
%else:
11391131
self = _stdlib_squareRoot${cFuncSuffix}(self)
1140-
%end
11411132
}
11421133

11431134
/// Adds the product of the two given values to this value in place, computed

test/ClangImporter/cfuncs_parse.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ func test_pow() {
5151
pow(1.5, 2.5)
5252
}
5353

54+
func test_powl() {
55+
powl(1.5, 2.5)
56+
}
57+
5458
func test_puts(_ s: String) {
5559
_ = s.withCString { puts($0) + 32 };
5660
}

test/ClangImporter/ctypes_parse_macosx.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@
55
import ctypes
66

77
func testImportMacTypes() {
8-
// FIXME: this should work. We cannot map Float80 to 'long double' because
9-
// 'long double' has size of 128 bits on SysV ABI, and 80 != 128. 'long
10-
// double' is currently not handled by the importer, so it cannot be
11-
// imported in normal way either.
12-
var t11_unqual : Float80 = Float80_test // expected-error {{use of unresolved identifier 'Float80_test'}}
13-
var t11_qual : ctypes.Float80 = 0.0 // expected-error {{no type named 'Float80' in module 'ctypes'}}
8+
var _ : Float80 = Float80_test
9+
var _ : ctypes.Float80 = 0.0
1410
}
1511

test/Inputs/clang-importer-sdk/usr/include/cfuncs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ float cfunc4();
1111
void exit(int);
1212

1313
double pow(double x, double y);
14+
long double powl(long double x, long double y);
1415

1516
int puts(const char *);
1617

0 commit comments

Comments
 (0)