Files
swift-mirror/stdlib/public/SwiftShims/LibcShims.h
Saleem Abdulrasool 4cf189f0ae shims: add a workaround for sqrtf on Windows x86
When building for Windows x86, we have a few conspiring issues to
contend with.  `__builtin_sqrtf` is treated by clang as a `__builtin_`
prefixed libm call.  On windows, there is no libm, with the role being
taken up by ucrt.  However, on 32-bit x86 targets, ucrt does not provide
an implementation of `sqrtf` instead defining it inline as a wrapper
which widens the argument to a double precision and invokes `sqrt`, the
result of which is narrowed to the result.  This function is locally
defined and expected to be inlined and no out-of-line definition is
provided by ucrt that can be referenced.

Adjusting the shims to use the intrinsics would be the next option
(thanks @stephentyrone!) which would work.  However, when building the
standard library, we need to combine the system headers which results in
the use of the MSVCRT headers for `xmmintrin.h` rather than clang.  As a
result, we cannot directly use the intrinsics.

Opt to instead open-code the intrinsic path by using the compiler
builtin for sqrt.  This both yields the optimal implementation and
avoids providing an additional entry point in the runtime.  It also has
code size benefits.

A special thanks to @stephentyrone for all the discussion and help with
this!
2020-12-11 13:44:25 -08:00

180 lines
5.4 KiB
C++

//===--- LibcShims.h - Access to POSIX for Swift's core stdlib --*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 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
//
//===----------------------------------------------------------------------===//
//
// Using the Darwin (or Glibc) module in the core stdlib would create a
// circular dependency, so instead we import these declarations as part of
// SwiftShims.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_STDLIB_SHIMS_LIBCSHIMS_H
#define SWIFT_STDLIB_SHIMS_LIBCSHIMS_H
#include "SwiftStdbool.h"
#include "SwiftStdint.h"
#include "SwiftStddef.h"
#include "Visibility.h"
#if __has_feature(nullability)
#pragma clang assume_nonnull begin
#endif
#ifdef __cplusplus
extern "C" {
#endif
// Input/output <stdio.h>
SWIFT_RUNTIME_STDLIB_INTERNAL
int _swift_stdlib_putchar_unlocked(int c);
SWIFT_RUNTIME_STDLIB_INTERNAL
__swift_size_t _swift_stdlib_fwrite_stdout(const void *ptr, __swift_size_t size,
__swift_size_t nitems);
// General utilities <stdlib.h>
// Memory management functions
static inline void _swift_stdlib_free(void *_Nullable ptr) {
extern void free(void *);
free(ptr);
}
// <unistd.h>
SWIFT_RUNTIME_STDLIB_SPI
__swift_ssize_t _swift_stdlib_read(int fd, void *buf, __swift_size_t nbyte);
SWIFT_RUNTIME_STDLIB_SPI
__swift_ssize_t _swift_stdlib_write(int fd, const void *buf, __swift_size_t nbyte);
SWIFT_RUNTIME_STDLIB_SPI
int _swift_stdlib_close(int fd);
// String handling <string.h>
SWIFT_READONLY
static inline __swift_size_t _swift_stdlib_strlen(const char *s) {
extern __swift_size_t strlen(const char *);
return strlen(s);
}
SWIFT_READONLY
static inline __swift_size_t _swift_stdlib_strlen_unsigned(const unsigned char *s) {
return _swift_stdlib_strlen((const char *)s);
}
SWIFT_READONLY
static inline int _swift_stdlib_memcmp(const void *s1, const void *s2,
__swift_size_t n) {
extern int memcmp(const void *, const void *, __swift_size_t);
return memcmp(s1, s2, n);
}
// Casting helper. This code needs to work when included from C or C++.
// Casting away const with a C-style cast warns in C++. Use a const_cast
// there.
#ifdef __cplusplus
#define CONST_CAST(type, value) const_cast<type>(value)
#else
#define CONST_CAST(type, value) (type)value
#endif
// Non-standard extensions
#if defined(__APPLE__)
#define HAS_MALLOC_SIZE 1
static inline __swift_size_t _swift_stdlib_malloc_size(const void *ptr) {
extern __swift_size_t malloc_size(const void *);
return malloc_size(ptr);
}
#elif defined(__linux__) || defined(__CYGWIN__) || defined(__ANDROID__) \
|| defined(__HAIKU__) || defined(__FreeBSD__) || defined(__wasi__)
#define HAS_MALLOC_SIZE 1
static inline __swift_size_t _swift_stdlib_malloc_size(const void *ptr) {
#if defined(__ANDROID__)
#if !defined(__ANDROID_API__) || __ANDROID_API__ >= 17
extern __swift_size_t malloc_usable_size(const void *ptr);
#endif
#else
extern __swift_size_t malloc_usable_size(void *ptr);
#endif
return malloc_usable_size(CONST_CAST(void *, ptr));
}
#elif defined(_WIN32)
#define HAS_MALLOC_SIZE 1
static inline __swift_size_t _swift_stdlib_malloc_size(const void *ptr) {
extern __swift_size_t _msize(void *ptr);
return _msize(CONST_CAST(void *, ptr));
}
#else
#define HAS_MALLOC_SIZE 0
static inline __swift_size_t _swift_stdlib_malloc_size(const void *ptr) {
return 0;
}
#endif
static inline __swift_bool _swift_stdlib_has_malloc_size() {
return HAS_MALLOC_SIZE != 0;
}
// Math library functions
static inline SWIFT_ALWAYS_INLINE
float _stdlib_remainderf(float _self, float _other) {
return __builtin_remainderf(_self, _other);
}
static inline SWIFT_ALWAYS_INLINE
float _stdlib_squareRootf(float _self) {
#if defined(_WIN32) && (defined(_M_IX86) || defined(__i386__))
typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16)));
return __builtin_ia32_sqrtss(__extension__ (__m128){ _self, 0, 0, 0 })[0];
#else
return __builtin_sqrtf(_self);
#endif
}
static inline SWIFT_ALWAYS_INLINE
double _stdlib_remainder(double _self, double _other) {
return __builtin_remainder(_self, _other);
}
static inline SWIFT_ALWAYS_INLINE
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, but they're
// unconditionally exported by libsystem_m.dylib in all OS versions that
// support Swift development; we simply need to provide declarations here.
#if defined(__APPLE__)
float lgammaf_r(float x, int *psigngam);
double lgamma_r(double x, int *psigngam);
long double lgammal_r(long double x, int *psigngam);
#endif // defined(__APPLE__)
#ifdef __cplusplus
} // extern "C"
#endif
#if __has_feature(nullability)
#pragma clang assume_nonnull end
#endif
#endif // SWIFT_STDLIB_SHIMS_LIBCSHIMS_H