Skip to content

Importer support for float80 #14971

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/swift/ClangImporter/BuiltinMappedTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ MAP_BUILTIN_INTEGER_TYPE(LongLong, CLongLong)
MAP_BUILTIN_INTEGER_TYPE(Int128, CInt128)
MAP_BUILTIN_TYPE(Float, CFloat)
MAP_BUILTIN_TYPE(Double, CDouble)
MAP_BUILTIN_TYPE(LongDouble, CLongDouble)

#undef MAP_BUILTIN_TYPE
#undef MAP_BUILTIN_INTEGER_TYPE
Expand Down
1 change: 0 additions & 1 deletion lib/ClangImporter/ImportType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ namespace {

// FIXME: Types that can be mapped, but aren't yet.
case clang::BuiltinType::Half:
case clang::BuiltinType::LongDouble:
case clang::BuiltinType::Float128:
case clang::BuiltinType::NullPtr:
return Type();
Expand Down
79 changes: 75 additions & 4 deletions stdlib/public/Platform/tgmath.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,8 @@ public func trunc<T: FloatingPoint>(_ x: T) -> T {
%{

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

def floatName(bits):
if bits == 32:
Expand Down Expand Up @@ -168,21 +167,33 @@ def TypedBinaryFunctions():
// Unary functions
// Note these do not have a corresponding LLVM intrinsic
% for T, CT, f, ufunc in TypedUnaryFunctions():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func ${ufunc}(_ x: ${T}) -> ${T} {
return ${T}(${ufunc}${f}(${CT}(x)))
}
% if T == 'Float80':
#endif
% end

% end

#if os(OSX) || os(iOS) || os(tvOS) || os(watchOS)
// Unary intrinsic functions
// Note these have a corresponding LLVM intrinsic
% for T, ufunc in TypedUnaryIntrinsicFunctions():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func ${ufunc}(_ x: ${T}) -> ${T} {
return _${ufunc}(x)
}
% if T == 'Float80':
#endif
% end

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

% for T, CT, f, bfunc in TypedBinaryFunctions():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func ${bfunc}(_ lhs: ${T}, _ rhs: ${T}) -> ${T} {
return ${T}(${bfunc}${f}(${CT}(lhs), ${CT}(rhs)))
}
% if T == 'Float80':
#endif
% end

% end

// Other functions
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@available(*, deprecated, message: "use the floatingPointClass property.")
public func fpclassify(_ value: ${T}) -> Int {
%if T == 'Double':
#if os(Linux) || os(Haiku)
return Int(__fpclassify(CDouble(value)))
#elseif os(Windows)
#elseif os(Windows)
return Int(_dclass(CDouble(value)))
#else
return Int(__fpclassifyd(CDouble(value)))
Expand Down Expand Up @@ -247,59 +267,95 @@ public func isnan(_ value: ${T}) -> Bool { return value.isNaN }
@available(*, unavailable, message: "use the sign property.")
public func signbit(_ value: ${T}) -> Int { return value.sign.rawValue }

% if T == 'Float80':
#endif
% end
% end

% # These are AllFloatTypes not OverlayFloatTypes because of the tuple return.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func modf(_ value: ${T}) -> (${T}, ${T}) {
var ipart = ${CT}(0)
let fpart = modf${f}(${CT}(value), &ipart)
return (${T}(ipart), ${T}(fpart))
}
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the Int parameter.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func ldexp(_ x: ${T}, _ n: Int) -> ${T} {
return ${T}(ldexp${f}(${CT}(x), Int32(n)))
}
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func frexp(_ value: ${T}) -> (${T}, Int) {
var exp = Int32(0)
let frac = frexp${f}(${CT}(value), &exp)
return (${T}(frac), Int(exp))
}
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the Int return.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func ilogb(_ x: ${T}) -> Int {
return Int(ilogb${f}(${CT}(x)) as Int32)
}
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the Int parameter.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func scalbn(_ x: ${T}, _ n: Int) -> ${T} {
return ${T}(scalbn${f}(${CT}(x), Int32(n)))
}
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
#if os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
@_transparent
public func lgamma(_ x: ${T}) -> (${T}, Int) {
Expand All @@ -322,25 +378,40 @@ public func lgamma(_ x: ${T}) -> (${T}, Int) {
return (${T}(value), Int(sign))
}
#endif
% if T == 'Float80':
#endif
% end

% end

% # This is AllFloatTypes not OverlayFloatTypes because of the tuple return.
% for T, CT, f in AllFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func remquo(_ x: ${T}, _ y: ${T}) -> (${T}, Int) {
var quo = Int32(0)
let rem = remquo${f}(${CT}(x), ${CT}(y), &quo)
return (${T}(rem), Int(quo))
}
% if T == 'Float80':
#endif
% end

% end

% for T, CT, f in OverlayFloatTypes():
% if T == 'Float80':
#if arch(i386) || arch(x86_64)
% end
@_transparent
public func nan(_ tag: String) -> ${T} {
return ${T}(nan${f}(tag))
}
% if T == 'Float80':
#endif
% end

% end

Expand Down
27 changes: 12 additions & 15 deletions stdlib/public/SwiftShims/LibcShims.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,18 @@ double _stdlib_squareRoot(double _self) {
return __builtin_sqrt(_self);
}

#if !defined _WIN32 && (defined __i386__ || defined __x86_64__)
static inline SWIFT_ALWAYS_INLINE
long double _stdlib_remainderl(long double _self, long double _other) {
return __builtin_remainderl(_self, _other);
}

static inline SWIFT_ALWAYS_INLINE
long double _stdlib_squareRootl(long double _self) {
return __builtin_sqrtl(_self);
}
#endif

// Apple's math.h does not declare lgamma_r() etc by default
#if defined(__APPLE__)
SWIFT_RUNTIME_STDLIB_INTERNAL
Expand Down Expand Up @@ -210,21 +222,6 @@ SWIFT_RUNTIME_STDLIB_INTERNAL
int _stdlib_thread_setspecific(__swift_thread_key_t key,
const void * _Nullable value);

// TODO: Remove horrible workaround when importer does Float80 <-> long double.
#if (defined __i386__ || defined __x86_64__) && !defined _MSC_VER
static inline SWIFT_ALWAYS_INLINE
void _stdlib_remainderl(void *_self, const void *_other) {
long double *_f80self = (long double *)_self;
*_f80self = __builtin_remainderl(*_f80self, *(const long double *)_other);
}

static inline SWIFT_ALWAYS_INLINE
void _stdlib_squareRootl(void *_self) {
long double *_f80self = (long double *)_self;
*_f80self = __builtin_sqrtl(*_f80self);
}
#endif // Have Float80

#ifdef __cplusplus
}} // extern "C", namespace swift
#endif
Expand Down
12 changes: 8 additions & 4 deletions stdlib/public/core/BuiltinMath.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
%{

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

def floatName(bits):
if bits == 32:
Expand Down Expand Up @@ -62,12 +61,17 @@ def TypedUnaryIntrinsicFunctions():
// Unary intrinsic functions
// Note these have a corresponding LLVM intrinsic
% for T, CT, bits, ufunc in TypedUnaryIntrinsicFunctions():
% if bits == 80:
#if arch(i386) || arch(x86_64)
% end
@_inlineable // FIXME(sil-serialize-all)
@_transparent
public func _${ufunc}(_ x: ${T}) -> ${T} {
return ${T}(_bits: Builtin.int_${ufunc}_FPIEEE${bits}(x._value))
}

% if bits == 80:
#endif
% end
% end

// ${'Local Variables'}:
Expand Down
22 changes: 21 additions & 1 deletion stdlib/public/core/CTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,27 @@ public typealias CFloat = Float
/// The C 'double' type.
public typealias CDouble = Double

// FIXME: long double
/// The C 'long double' type.
#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
// On Darwin, long double is Float80 on x86, and Double otherwise.
#if arch(x86_64) || arch(i386)
public typealias CLongDouble = Float80
#else
public typealias CLongDouble = Double
#endif
#elseif os(Windows)
// On Windows, long double is always Double.
public typealias CLongDouble = Double
#elseif os(Linux)
// On Linux/x86, long double is Float80.
// TODO: Fill in definitions for additional architectures as needed. IIRC
// armv7 should map to Double, but arm64 and ppc64le should map to Float128,
// which we don't yet have in Swift.
#if arch(x86_64) || arch(i386)
public typealias CLongDouble = Float80
#endif
// TODO: Fill in definitions for other OSes.
#endif

// FIXME: Is it actually UTF-32 on Darwin?
//
Expand Down
9 changes: 0 additions & 9 deletions stdlib/public/core/FloatingPointTypes.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -1085,12 +1085,7 @@ extension ${Self}: BinaryFloatingPoint {
@_inlineable // FIXME(sil-serialize-all)
@_transparent
public mutating func formRemainder(dividingBy other: ${Self}) {
%if bits == 80:
var other = other
_stdlib_remainderl(&self, &other)
%else:
self = _stdlib_remainder${cFuncSuffix}(self, other)
%end
}

/// Replaces this value with the remainder of itself divided by the given
Expand Down Expand Up @@ -1133,11 +1128,7 @@ extension ${Self}: BinaryFloatingPoint {
@_inlineable // FIXME(sil-serialize-all)
@_transparent
public mutating func formSquareRoot( ) {
%if bits == 80:
_stdlib_squareRootl(&self)
%else:
self = _stdlib_squareRoot${cFuncSuffix}(self)
%end
}

/// Adds the product of the two given values to this value in place, computed
Expand Down
4 changes: 4 additions & 0 deletions test/ClangImporter/cfuncs_parse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ func test_pow() {
pow(1.5, 2.5)
}

func test_powl() {
powl(1.5, 2.5)
}

func test_puts(_ s: String) {
_ = s.withCString { puts($0) + 32 };
}
Expand Down
8 changes: 2 additions & 6 deletions test/ClangImporter/ctypes_parse_macosx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@
import ctypes

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

1 change: 1 addition & 0 deletions test/Inputs/clang-importer-sdk/usr/include/cfuncs.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ float cfunc4();
void exit(int);

double pow(double x, double y);
long double powl(long double x, long double y);

int puts(const char *);

Expand Down