mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 17:19:47 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8383f25b4 | ||
|
|
64a9e6fe56 | ||
|
|
0ef36489c8 |
No files matched your search
@@ -149,9 +149,9 @@ export MODE
|
||||
export SOURCE_DATE_EPOCH
|
||||
export TMPDIR
|
||||
|
||||
COSMOCC = .cosmocc/3.3.1
|
||||
COSMOCC = .cosmocc/3.3.2
|
||||
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
|
||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.1 079622f9772c19e24db4bfa71c1ed90b7d436e9a4b6f4c579b525df5a48fe620)
|
||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.2 a695012ffbeac5e26e3c4a740debc15273f47e9a8bdc55e8b76a623154d5914b)
|
||||
|
||||
AS = $(TOOLCHAIN)as
|
||||
CC = $(TOOLCHAIN)gcc
|
||||
|
||||
+8
-8
@@ -6,14 +6,14 @@ if [ -n "$OBJDUMP" ]; then
|
||||
fi
|
||||
|
||||
find_objdump() {
|
||||
if [ -x .cosmocc/3.3/bin/$1-linux-cosmo-objdump ]; then
|
||||
OBJDUMP=.cosmocc/3.3/bin/$1-linux-cosmo-objdump
|
||||
elif [ -x .cosmocc/3.3/bin/$1-linux-musl-objdump ]; then
|
||||
OBJDUMP=.cosmocc/3.3/bin/$1-linux-musl-objdump
|
||||
elif [ -x "$COSMO/.cosmocc/3.3/bin/$1-linux-cosmo-objdump" ]; then
|
||||
OBJDUMP="$COSMO/.cosmocc/3.3/bin/$1-linux-cosmo-objdump"
|
||||
elif [ -x "$COSMO/.cosmocc/3.3/bin/$1-linux-musl-objdump" ]; then
|
||||
OBJDUMP="$COSMO/.cosmocc/3.3/bin/$1-linux-musl-objdump"
|
||||
if [ -x .cosmocc/3.3.2/bin/$1-linux-cosmo-objdump ]; then
|
||||
OBJDUMP=.cosmocc/3.3.2/bin/$1-linux-cosmo-objdump
|
||||
elif [ -x .cosmocc/3.3.2/bin/$1-linux-musl-objdump ]; then
|
||||
OBJDUMP=.cosmocc/3.3.2/bin/$1-linux-musl-objdump
|
||||
elif [ -x "$COSMO/.cosmocc/3.3.2/bin/$1-linux-cosmo-objdump" ]; then
|
||||
OBJDUMP="$COSMO/.cosmocc/3.3.2/bin/$1-linux-cosmo-objdump"
|
||||
elif [ -x "$COSMO/.cosmocc/3.3.2/bin/$1-linux-musl-objdump" ]; then
|
||||
OBJDUMP="$COSMO/.cosmocc/3.3.2/bin/$1-linux-musl-objdump"
|
||||
else
|
||||
echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
|
||||
exit 1
|
||||
|
||||
+6
-7
@@ -22,16 +22,15 @@ COSMOPOLITAN_C_START_
|
||||
* @see libc/sysv/dos2errno.sh for multimapped numbers
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__) && defined(__aarch64__) && !defined(__STRICT_ANSI__) && \
|
||||
!defined(__cplusplus)
|
||||
#if defined(__GNUC__) && defined(__aarch64__) && !defined(__cplusplus)
|
||||
/* this header is included by 700+ files; therefore we */
|
||||
/* hand-roll &__get_tls()->tib_errno to avoid #include */
|
||||
/* cosmopolitan uses x28 as the tls register b/c apple */
|
||||
#define errno \
|
||||
(*({ \
|
||||
errno_t *__ep; \
|
||||
asm("sub\t%0,x28,#192-0x3c" : "=r"(__ep)); \
|
||||
__ep; \
|
||||
#define errno \
|
||||
(*__extension__({ \
|
||||
errno_t *__ep; \
|
||||
__asm__("sub\t%0,x28,#192-0x3c" : "=r"(__ep)); \
|
||||
__ep; \
|
||||
}))
|
||||
#else
|
||||
#define errno (*__errno_location())
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
#define COSMOPOLITAN_LIBC_FMT_DIVMOD10_H_
|
||||
|
||||
forceinline uint64_t __divmod10(uint64_t __x, unsigned *__r) {
|
||||
#if defined(__STRICT_ANSI__) || !defined(__GNUC__) || \
|
||||
(defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__))
|
||||
#if !defined(__GNUC__) || (defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__))
|
||||
*__r = __x % 10;
|
||||
return __x / 10;
|
||||
#else
|
||||
|
||||
+66
-146
@@ -16,8 +16,7 @@
|
||||
|
||||
#if !defined(__GNUC__) && __cplusplus + 0 >= 201103L
|
||||
#define typeof(x) decltype(x)
|
||||
#elif (defined(__STRICT_ANSI__) || !defined(__GNUC__)) && \
|
||||
__STDC_VERSION__ + 0 < 201112
|
||||
#elif !defined(__GNUC__) && __STDC_VERSION__ + 0 < 201112
|
||||
#define typeof(x) __typeof(x)
|
||||
#endif
|
||||
|
||||
@@ -27,7 +26,7 @@
|
||||
#endif /* C++11 */
|
||||
#else /* __cplusplus */
|
||||
#if __STDC_VERSION__ + 0 < 201112
|
||||
#if __GNUC__ + _MSC_VER + 0 && !defined(__STRICT_ANSI__)
|
||||
#if __GNUC__ + _MSC_VER + 0
|
||||
#define _Alignof(x) __alignof(x)
|
||||
#else
|
||||
#define _Alignof(x) /* basically all it ever did lool */ sizeof(x)
|
||||
@@ -36,7 +35,7 @@
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#if !defined(__cplusplus) && !defined(inline) && __STDC_VERSION__ + 0 < 199901
|
||||
#if !defined(__STRICT_ANSI__) && (defined(__GNUC__) || defined(_MSC_VER))
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
#define inline __inline
|
||||
#else
|
||||
#define inline
|
||||
@@ -49,7 +48,7 @@
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ + 0 < 201112
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#ifdef __GNUC__
|
||||
#define _Alignas(x) __attribute__((__aligned__(x)))
|
||||
#elif defined(_MSC_VER)
|
||||
#define _Alignas(x) __declspec(align(x))
|
||||
@@ -58,17 +57,15 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define __builtin_unreachable() __assume(false)
|
||||
#elif defined(__STRICT_ANSI__) || \
|
||||
!((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 405 || \
|
||||
defined(__clang__) || defined(__INTEL_COMPILER) || \
|
||||
__has_builtin(__builtin_unreachable))
|
||||
#elif !((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 405 || \
|
||||
defined(__clang__) || defined(__INTEL_COMPILER) || \
|
||||
__has_builtin(__builtin_unreachable))
|
||||
#define __builtin_unreachable() \
|
||||
for (;;) { \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__STRICT_ANSI__) || \
|
||||
(!defined(__llvm__) && !__has_builtin(__builtin_assume))
|
||||
#if (!defined(__llvm__) && !__has_builtin(__builtin_assume))
|
||||
#define __builtin_assume(x) \
|
||||
do { \
|
||||
if (!(x)) __builtin_unreachable(); \
|
||||
@@ -134,9 +131,7 @@ typedef __UINTMAX_TYPE__ uintmax_t;
|
||||
typedef long double max_align_t;
|
||||
|
||||
#ifdef _COSMO_SOURCE
|
||||
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406 || \
|
||||
defined(__llvm__)) && \
|
||||
!defined(__STRICT_ANSI__)
|
||||
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406 || defined(__llvm__)
|
||||
typedef signed __int128 int128_t;
|
||||
typedef unsigned __int128 uint128_t;
|
||||
#endif
|
||||
@@ -169,11 +164,7 @@ typedef struct {
|
||||
#define interruptfn nocallersavedregisters forcealignargpointer
|
||||
|
||||
#ifndef pureconst
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define pureconst __attribute__((__const__))
|
||||
#else
|
||||
#define pureconst
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef forcealign
|
||||
@@ -181,15 +172,9 @@ typedef struct {
|
||||
#endif
|
||||
#define thatispacked __attribute__((__packed__))
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define printfesque(n) __attribute__((__format__(__gnu_printf__, n, n + 1)))
|
||||
#define scanfesque(n) __attribute__((__format__(__gnu_scanf__, n, n + 1)))
|
||||
#define strftimeesque(n) __attribute__((__format__(__strftime__, n, 0)))
|
||||
#else
|
||||
#define printfesque(n)
|
||||
#define scanfesque(n)
|
||||
#define strftimeesque(n)
|
||||
#endif
|
||||
|
||||
#ifndef privileged
|
||||
#define privileged \
|
||||
@@ -197,8 +182,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef wontreturn
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__noreturn__) || \
|
||||
#if (__has_attribute(__noreturn__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 208)
|
||||
#define wontreturn __attribute__((__noreturn__))
|
||||
#else
|
||||
@@ -207,8 +191,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef nosideeffect
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__pure__) || \
|
||||
#if (__has_attribute(__pure__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 296)
|
||||
#define nosideeffect __attribute__((__pure__))
|
||||
#else
|
||||
@@ -219,9 +202,8 @@ typedef struct {
|
||||
#ifndef dontinline
|
||||
#ifdef _MSC_VER
|
||||
#define dontinline __declspec(noinline)
|
||||
#elif !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__noinline__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 301)
|
||||
#elif (__has_attribute(__noinline__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 301)
|
||||
#define dontinline __attribute__((__noinline__))
|
||||
#else
|
||||
#define dontinline
|
||||
@@ -229,8 +211,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef dontclone
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__noclone__) || \
|
||||
#if (__has_attribute(__noclone__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 405)
|
||||
#define dontclone __attribute__((__noclone__))
|
||||
#else
|
||||
@@ -242,8 +223,7 @@ typedef struct {
|
||||
#ifdef __cplusplus
|
||||
#define forceinline inline
|
||||
#else
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 302
|
||||
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 302
|
||||
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403 || \
|
||||
!defined(__cplusplus) || \
|
||||
(defined(__clang__) && \
|
||||
@@ -267,8 +247,7 @@ typedef struct {
|
||||
#endif /* forceinline */
|
||||
|
||||
#ifndef __wur
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 304 || \
|
||||
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 304 || \
|
||||
__has_attribute(__warn_unused_result__))
|
||||
#define __wur __attribute__((__warn_unused_result__))
|
||||
#else
|
||||
@@ -277,8 +256,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef nullterminated
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__sentinel__) || __GNUC__ + 0 >= 4)
|
||||
#if __has_attribute(__sentinel__) || __GNUC__ + 0 >= 4
|
||||
#define nullterminated(x) __attribute__((__sentinel__ x))
|
||||
#else
|
||||
#define nullterminated(x)
|
||||
@@ -295,8 +273,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef externinline
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(!defined(__cplusplus) || \
|
||||
#if (!defined(__cplusplus) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403 || \
|
||||
(defined(__clang__) && \
|
||||
(defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__))))
|
||||
@@ -311,8 +288,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef relegated
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__cold__) || \
|
||||
#if (__has_attribute(__cold__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
|
||||
#define relegated __attribute__((__cold__))
|
||||
#else
|
||||
@@ -320,8 +296,7 @@ typedef struct {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__warning__) || \
|
||||
#if (__has_attribute(__warning__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
|
||||
#define warnifused(s) __attribute__((__warning__(s)))
|
||||
#else
|
||||
@@ -329,8 +304,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef firstclass
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__hot__) || \
|
||||
#if (__has_attribute(__hot__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
|
||||
#define firstclass __attribute__((__hot__))
|
||||
#else
|
||||
@@ -339,8 +313,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef paramsnonnull
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__nonnull__) || \
|
||||
#if (__has_attribute(__nonnull__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
|
||||
#define paramsnonnull(opt_1idxs) __attribute__((__nonnull__ opt_1idxs))
|
||||
#else
|
||||
@@ -355,7 +328,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ + 0 < 199901L && !defined(restrict)
|
||||
#if !defined(__STRICT_ANSI__) && !defined(__cplusplus) && \
|
||||
#if !defined(__cplusplus) && \
|
||||
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 301 || defined(_MSC_VER))
|
||||
#define restrict __restrict__
|
||||
#else
|
||||
@@ -365,8 +338,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef dontcallback
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__leaf__) || \
|
||||
#if (__has_attribute(__leaf__) || \
|
||||
(!defined(__llvm__) && \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406))
|
||||
#define dontcallback __attribute__((__leaf__))
|
||||
@@ -376,8 +348,8 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef dontthrow
|
||||
#if defined(__cplusplus) && !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(dontthrow) || \
|
||||
#if defined(__cplusplus) && \
|
||||
(__has_attribute(dontthrow) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 303)
|
||||
#define dontthrow __attribute__((__nothrow__))
|
||||
#elif defined(_MSC_VER)
|
||||
@@ -388,8 +360,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef returnstwice
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__returns_twice__) || \
|
||||
#if (__has_attribute(__returns_twice__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 402)
|
||||
#define returnstwice __attribute__((__returns_twice__))
|
||||
#else
|
||||
@@ -398,8 +369,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef nodebuginfo
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__nodebug__) || defined(__llvm__))
|
||||
#if __has_attribute(__nodebug__) || defined(__llvm__)
|
||||
#define nodebuginfo __attribute__((__nodebug__))
|
||||
#else
|
||||
#define nodebuginfo
|
||||
@@ -414,8 +384,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef returnsnonnull
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__returns_nonnull__) || \
|
||||
#if (__has_attribute(__returns_nonnull__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
|
||||
#define returnsnonnull __attribute__((__returns_nonnull__))
|
||||
#else
|
||||
@@ -423,8 +392,7 @@ typedef struct {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__assume_aligned__) || \
|
||||
#if (__has_attribute(__assume_aligned__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
|
||||
#define returnsaligned(x) __attribute__((__assume_aligned__ x))
|
||||
#else
|
||||
@@ -432,8 +400,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef returnspointerwithnoaliases
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__malloc__) || \
|
||||
#if (__has_attribute(__malloc__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
|
||||
#define returnspointerwithnoaliases __attribute__((__malloc__))
|
||||
#elif defined(_MSC_VER)
|
||||
@@ -444,8 +411,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef attributeallocsize
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__alloc_size__) || \
|
||||
#if (__has_attribute(__alloc_size__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
|
||||
#define attributeallocsize(x) __attribute__((__alloc_size__ x))
|
||||
#else
|
||||
@@ -454,8 +420,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef attributeallocalign
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__alloc_align__) || \
|
||||
#if (__has_attribute(__alloc_align__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
|
||||
#define attributeallocalign(x) __attribute__((__alloc_align__ x))
|
||||
#else
|
||||
@@ -478,8 +443,7 @@ typedef struct {
|
||||
#ifdef _COSMO_SOURCE
|
||||
|
||||
#ifndef dontinstrument
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__no_instrument_function__) || \
|
||||
#if (__has_attribute(__no_instrument_function__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 204)
|
||||
#if ((__GNUC__ + 0) >= 7 && !defined(__chibicc__)) || \
|
||||
__has_attribute(__patchable_function_entry__)
|
||||
@@ -495,8 +459,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef mayalias
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__may_alias__) || \
|
||||
#if (__has_attribute(__may_alias__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 303)
|
||||
#define mayalias __attribute__((__may_alias__))
|
||||
#else
|
||||
@@ -505,35 +468,26 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef dontoptimize
|
||||
#ifndef __STRICT_ANSI__
|
||||
#if defined(__llvm__) || __has_attribute(__optnone__)
|
||||
#define dontoptimize __attribute__((__optnone__))
|
||||
#elif (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
|
||||
__has_attribute(__optimize__)
|
||||
#define dontoptimize __attribute__((__optimize__(0)))
|
||||
#endif
|
||||
#else
|
||||
#define dontoptimize
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef optimizesize
|
||||
#ifndef __STRICT_ANSI__
|
||||
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
|
||||
__has_attribute(__optimize__)
|
||||
#define optimizesize __attribute__((__optimize__("s")))
|
||||
#elif defined(__llvm__) || __has_attribute(__optnone__)
|
||||
#define optimizesize __attribute__((__optnone__))
|
||||
#endif
|
||||
#else
|
||||
#define optimizesize
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef optimizespeed
|
||||
/* warning: corrupts frame pointer; only use on leaf functions */
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
|
||||
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
|
||||
__has_attribute(__optimize__))
|
||||
#define optimizespeed __attribute__((__optimize__(3)))
|
||||
#else
|
||||
@@ -542,8 +496,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef unrollloops
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
|
||||
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
|
||||
__has_attribute(__optimize__))
|
||||
#define unrollloops __attribute__((__optimize__("unroll-loops")))
|
||||
#else
|
||||
@@ -552,8 +505,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifndef _Microarchitecture
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__has_attribute(__target__) || \
|
||||
#if (__has_attribute(__target__) || \
|
||||
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 404)
|
||||
#define _Microarchitecture(march) __attribute__((__target__(march)))
|
||||
#else
|
||||
@@ -572,64 +524,48 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \
|
||||
__has_attribute(__no_sanitize_address__)) && \
|
||||
!defined(__STRICT_ANSI__)
|
||||
__has_attribute(__no_sanitize_address__))
|
||||
#define dontasan __attribute__((__no_sanitize_address__))
|
||||
#else
|
||||
#define dontasan
|
||||
#endif
|
||||
|
||||
#if ((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \
|
||||
__has_attribute(__no_sanitize_undefined__)) && \
|
||||
!defined(__STRICT_ANSI__)
|
||||
__has_attribute(__no_sanitize_undefined__))
|
||||
#define dontubsan __attribute__((__no_sanitize_undefined__))
|
||||
#else
|
||||
#define dontubsan
|
||||
#endif
|
||||
|
||||
#ifdef __STRICT_ANSI__
|
||||
void abort(void) wontreturn;
|
||||
#define notpossible abort()
|
||||
#else
|
||||
#ifdef __x86_64__
|
||||
#define notpossible \
|
||||
do { \
|
||||
asm("nop\n\t" \
|
||||
"ud2\n\t" \
|
||||
"nop"); \
|
||||
__asm__("nop\n\t" \
|
||||
"ud2\n\t" \
|
||||
"nop"); \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
#elif defined(__aarch64__)
|
||||
#define notpossible \
|
||||
do { \
|
||||
asm("udf\t#0\n\t" \
|
||||
"nop"); \
|
||||
__asm__("udf\t#0\n\t" \
|
||||
"nop"); \
|
||||
__builtin_unreachable(); \
|
||||
} while (0)
|
||||
#else
|
||||
#define notpossible __builtin_trap()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define donothing \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define textstartup _Section(".text.startup")
|
||||
#define textexit _Section(".text.exit")
|
||||
#define textreal _Section(".text.real")
|
||||
#define texthead _Section(".text.head")
|
||||
#define textwindows _Section(".text.windows")
|
||||
#define antiquity _Section(".text.antiquity")
|
||||
#else
|
||||
#define textstartup
|
||||
#define textexit
|
||||
#define textreal
|
||||
#define texthead
|
||||
#define textwindows
|
||||
#define antiquity
|
||||
#endif
|
||||
|
||||
#ifdef __llvm__
|
||||
#define __builtin_ia32_movntdq(x, y) (*(x) = (y))
|
||||
@@ -660,66 +596,50 @@ void abort(void) wontreturn;
|
||||
#pragma GCC diagnostic ignored "-Wold-style-definition" /* orwellian bullsh */
|
||||
#endif
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#ifdef __x86_64__
|
||||
#define DebugBreak() asm("int3")
|
||||
#define DebugBreak() __asm__("int3")
|
||||
#else
|
||||
#define DebugBreak() __builtin_trap()
|
||||
#endif
|
||||
#else
|
||||
#define DebugBreak() (void)0
|
||||
#endif
|
||||
|
||||
#endif /* _COSMO_SOURCE */
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define __veil(CONSTRAINT, EXPRESSION) \
|
||||
({ \
|
||||
autotype(EXPRESSION) VeiledValue = (EXPRESSION); \
|
||||
asm("" : "=" CONSTRAINT ""(VeiledValue) : "0"(VeiledValue)); \
|
||||
VeiledValue; \
|
||||
#define __veil(CONSTRAINT, EXPRESSION) \
|
||||
__extension__({ \
|
||||
autotype(EXPRESSION) VeiledValue = (EXPRESSION); \
|
||||
__asm__("" : "=" CONSTRAINT ""(VeiledValue) : "0"(VeiledValue)); \
|
||||
VeiledValue; \
|
||||
})
|
||||
#else
|
||||
#define __veil(CONSTRAINT, EXPRESSION) (EXPRESSION)
|
||||
#endif
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define __conceal(CONSTRAINT, EXPRESSION) \
|
||||
({ \
|
||||
autotype(EXPRESSION) VeiledValue = (EXPRESSION); \
|
||||
asm volatile("" : "=" CONSTRAINT ""(VeiledValue) : "0"(VeiledValue)); \
|
||||
VeiledValue; \
|
||||
#define __conceal(CONSTRAINT, EXPRESSION) \
|
||||
__extension__({ \
|
||||
autotype(EXPRESSION) VeiledValue = (EXPRESSION); \
|
||||
__asm__ volatile("" : "=" CONSTRAINT ""(VeiledValue) : "0"(VeiledValue)); \
|
||||
VeiledValue; \
|
||||
})
|
||||
#else
|
||||
#define __conceal(CONSTRAINT, EXPRESSION) (EXPRESSION)
|
||||
#endif
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define __expropriate(EXPRESSION) \
|
||||
({ \
|
||||
asm volatile("" ::"g"(EXPRESSION) : "memory"); \
|
||||
0; \
|
||||
#define __expropriate(EXPRESSION) \
|
||||
__extension__({ \
|
||||
__asm__ volatile("" ::"g"(EXPRESSION) : "memory"); \
|
||||
0; \
|
||||
})
|
||||
#else
|
||||
#define __expropriate(EXPRESSION) (EXPRESSION)
|
||||
#endif
|
||||
|
||||
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__) && defined(__x86_64__)
|
||||
#if !defined(__APPLE__) && defined(__x86_64__)
|
||||
#define __yoink(SYMBOL) \
|
||||
asm(".section .yoink\n\tnopl\t%0\n\t.previous" : : "m"(SYMBOL))
|
||||
__asm__(".section .yoink\n\tnopl\t%0\n\t.previous" : : "m"(SYMBOL))
|
||||
#elif defined(__aarch64__)
|
||||
#define __yoink(SYMBOL) \
|
||||
asm(".section .yoink\n\tb\t%0\n\t.previous" : : "m"(SYMBOL))
|
||||
__asm__(".section .yoink\n\tb\t%0\n\t.previous" : : "m"(SYMBOL))
|
||||
#else
|
||||
#define __yoink(SYMBOL) (void)0
|
||||
#endif
|
||||
|
||||
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__) && defined(__x86_64__)
|
||||
#if !defined(__APPLE__) && defined(__x86_64__)
|
||||
#define __static_yoink(SYMBOLSTR) \
|
||||
asm(".section .yoink\n\tnopl\t\"" SYMBOLSTR "\"\n\t.previous")
|
||||
__asm__(".section .yoink\n\tnopl\t\"" SYMBOLSTR "\"\n\t.previous")
|
||||
#elif defined(__aarch64__)
|
||||
#define __static_yoink(SYMBOLSTR) \
|
||||
asm(".section .yoink\n\tb\t\"" SYMBOLSTR "\"\n\t.previous")
|
||||
__asm__(".section .yoink\n\tb\t\"" SYMBOLSTR "\"\n\t.previous")
|
||||
#else
|
||||
#define __static_yoink(SYMBOLSTR)
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#define __COSMOPOLITAN_MAJOR__ 3
|
||||
#define __COSMOPOLITAN_MINOR__ 3
|
||||
#define __COSMOPOLITAN_PATCH__ 1
|
||||
#define __COSMOPOLITAN_PATCH__ 2
|
||||
#define __COSMOPOLITAN__ \
|
||||
(100000000 * __COSMOPOLITAN_MAJOR__ + 1000000 * __COSMOPOLITAN_MINOR__ + \
|
||||
__COSMOPOLITAN_PATCH__)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
/**
|
||||
* @fileoverview fp16 compiler runtime
|
||||
*/
|
||||
|
||||
#define asint(x) ((union pun){x}).i
|
||||
#define isnan(x) (((x) & 0x7fff) > 0x7c00)
|
||||
|
||||
union pun {
|
||||
_Float16 f;
|
||||
unsigned short i;
|
||||
};
|
||||
|
||||
int __eqhf2(_Float16 fx, _Float16 fy) {
|
||||
int x = asint(fx);
|
||||
int y = asint(fy);
|
||||
return (x == y) & !isnan(x) & !isnan(y);
|
||||
}
|
||||
|
||||
int __nehf2(_Float16 fx, _Float16 fy) {
|
||||
int x = asint(fx);
|
||||
int y = asint(fy);
|
||||
return (x != y) & !isnan(x) & !isnan(y);
|
||||
}
|
||||
@@ -10,8 +10,7 @@
|
||||
#endif
|
||||
|
||||
#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) && \
|
||||
!defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) && \
|
||||
!defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__)
|
||||
!defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) && !defined(_BSD_SOURCE)
|
||||
#define _BSD_SOURCE 1
|
||||
#define _XOPEN_SOURCE 700
|
||||
#endif
|
||||
|
||||
@@ -25,33 +25,33 @@ forceinline char *__stpcpy(char *d, const char *s) {
|
||||
}
|
||||
|
||||
forceinline void *__repstosb(void *di, char al, size_t cx) {
|
||||
#if defined(__x86__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
asm("rep stosb"
|
||||
: "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di)
|
||||
: "0"(di), "1"(cx), "a"(al));
|
||||
#if defined(__x86__) && defined(__GNUC__)
|
||||
__asm__("rep stosb"
|
||||
: "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di)
|
||||
: "0"(di), "1"(cx), "a"(al));
|
||||
return di;
|
||||
#else
|
||||
char *d = di;
|
||||
while (cx--) {
|
||||
*d++ = al;
|
||||
asm volatile("" ::: "memory");
|
||||
__asm__ volatile("" ::: "memory");
|
||||
}
|
||||
return (void *)d;
|
||||
#endif
|
||||
}
|
||||
|
||||
forceinline void *__repmovsb(void *di, const void *si, size_t cx) {
|
||||
#if defined(__x86__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
asm("rep movsb"
|
||||
: "=D"(di), "=S"(si), "=c"(cx), "=m"(*(char(*)[cx])di)
|
||||
: "0"(di), "1"(si), "2"(cx), "m"(*(char(*)[cx])si));
|
||||
#if defined(__x86__) && defined(__GNUC__)
|
||||
__asm__("rep movsb"
|
||||
: "=D"(di), "=S"(si), "=c"(cx), "=m"(*(char(*)[cx])di)
|
||||
: "0"(di), "1"(si), "2"(cx), "m"(*(char(*)[cx])si));
|
||||
return di;
|
||||
#else
|
||||
char *d = di;
|
||||
const char *s = si;
|
||||
while (cx--) {
|
||||
*d++ = *s++;
|
||||
asm volatile("" ::: "memory");
|
||||
__asm__ volatile("" ::: "memory");
|
||||
}
|
||||
return (void *)d;
|
||||
#endif
|
||||
@@ -61,7 +61,7 @@ forceinline void *__mempcpy(void *d, const void *s, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i) {
|
||||
((char *)d)[i] = ((const char *)s)[i];
|
||||
asm volatile("" ::: "memory");
|
||||
__asm__ volatile("" ::: "memory");
|
||||
}
|
||||
return (char *)d + n;
|
||||
}
|
||||
|
||||
+4
-4
@@ -159,10 +159,10 @@ typedef double double_t;
|
||||
#define fpclassify(x) \
|
||||
__builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
|
||||
|
||||
#define signbit(x) \
|
||||
(sizeof(x) == sizeof(double) ? __builtin_signbit(x) \
|
||||
: sizeof(x) == sizeof(float) ? __builtin_signbitf(x) \
|
||||
: __builtin_signbitl(x))
|
||||
#define signbit(x) \
|
||||
(sizeof(x) == sizeof(long double) ? __builtin_signbitl(x) \
|
||||
: sizeof(x) == sizeof(float) ? __builtin_signbitf(x) \
|
||||
: __builtin_signbit(x))
|
||||
|
||||
extern int signgam;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_NT_TEB_H_
|
||||
#define COSMOPOLITAN_LIBC_NT_TEB_H_
|
||||
#include "libc/nt/struct/peb.h"
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#ifdef __GNUC__
|
||||
|
||||
/*
|
||||
* These macros address directly into NT's TEB a.k.a. TIB
|
||||
@@ -21,5 +21,5 @@
|
||||
#define _NtGetRpc() ((void *)*(__seg_gs uintptr_t *)0x50)
|
||||
#define _NtGetTls() ((void *)*(__seg_gs uintptr_t *)0x58)
|
||||
|
||||
#endif /* __GNUC__ && !__STRICT_ANSI__ */
|
||||
#endif /* __GNUC__ */
|
||||
#endif /* COSMOPOLITAN_LIBC_NT_TEB_H_ */
|
||||
@@ -2,8 +2,7 @@
|
||||
#define COSMOPOLITAN_LIBC_NT_THUNK_MSABI_H_
|
||||
#ifdef __x86_64__
|
||||
|
||||
#if !defined(__STRICT_ANSI__) && \
|
||||
(__GNUC__ * 100 + __GNUC_MINOR__ >= 408 || \
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 408 || \
|
||||
(__has_attribute(__ms_abi__) || defined(__llvm__)))
|
||||
/**
|
||||
* Defines function as using Microsoft x64 calling convention.
|
||||
|
||||
+7
-7
@@ -8,13 +8,13 @@ bool32 GetVersionEx(struct NtOsVersionInfo *lpVersionInformation);
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(__x86_64__)
|
||||
#define IsAtLeastWindows10() (GetNtMajorVersion() >= 10)
|
||||
#define GetNtMajorVersion() \
|
||||
({ \
|
||||
uintptr_t __x; \
|
||||
asm("mov\t%%gs:96,%q0\r\n" \
|
||||
"mov\t280(%q0),%b0" \
|
||||
: "=q"(__x)); \
|
||||
(unsigned char)__x; \
|
||||
#define GetNtMajorVersion() \
|
||||
__extension__({ \
|
||||
uintptr_t __x; \
|
||||
__asm__("mov\t%%gs:96,%q0\r\n" \
|
||||
"mov\t280(%q0),%b0" \
|
||||
: "=q"(__x)); \
|
||||
(unsigned char)__x; \
|
||||
})
|
||||
#endif
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
#define _STACK_EXTRA ""
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(__ELF__) && !defined(__STRICT_ANSI__)
|
||||
#if defined(__GNUC__) && defined(__ELF__)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern char ape_stack_prot[] __attribute__((__weak__));
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "libc/dce.h"
|
||||
#include "libc/thread/tls.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__STRICT_ANSI__)
|
||||
#if defined(__GNUC__) && defined(__x86_64__)
|
||||
|
||||
/**
|
||||
* Returns location of thread information block.
|
||||
@@ -14,9 +14,9 @@ COSMOPOLITAN_C_START_
|
||||
forceinline struct CosmoTib *__get_tls_privileged(void) {
|
||||
char *tib, *lin = (char *)0x30;
|
||||
if (IsNetbsd() || IsOpenbsd()) {
|
||||
asm("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
||||
__asm__("mov\t%%fs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
||||
} else {
|
||||
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
||||
__asm__("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
||||
if (IsWindows()) {
|
||||
tib = *(char **)(tib + 0x1480 + __tls_index * 8);
|
||||
}
|
||||
@@ -26,13 +26,13 @@ forceinline struct CosmoTib *__get_tls_privileged(void) {
|
||||
|
||||
forceinline struct CosmoTib *__get_tls_win32(void) {
|
||||
char *tib, *lin = (char *)0x30;
|
||||
asm("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
||||
__asm__("mov\t%%gs:(%1),%0" : "=a"(tib) : "r"(lin) : "memory");
|
||||
tib = *(char **)(tib + 0x1480 + __tls_index * 8);
|
||||
return (struct CosmoTib *)tib;
|
||||
}
|
||||
|
||||
forceinline void __set_tls_win32(void *tls) {
|
||||
asm("mov\t%1,%%gs:%0" : "=m"(*((long *)0x1480 + __tls_index)) : "r"(tls));
|
||||
__asm__("mov\t%1,%%gs:%0" : "=m"(*((long *)0x1480 + __tls_index)) : "r"(tls));
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
|
||||
#define CHECK(x) \
|
||||
if (!(x)) return __LINE__
|
||||
#define FALSE(x) \
|
||||
{ \
|
||||
volatile bool x_ = x; \
|
||||
if (x_) return __LINE__; \
|
||||
}
|
||||
#define TRUE(x) \
|
||||
{ \
|
||||
volatile bool x_ = x; \
|
||||
if (!x_) return __LINE__; \
|
||||
}
|
||||
|
||||
_Float16 identity(_Float16 x) {
|
||||
return x;
|
||||
}
|
||||
_Float16 (*half)(_Float16) = identity;
|
||||
|
||||
int main() {
|
||||
volatile float f;
|
||||
volatile double d;
|
||||
volatile _Float16 pi = 3.141;
|
||||
|
||||
// half → float → half
|
||||
f = pi;
|
||||
pi = f;
|
||||
|
||||
// half → float
|
||||
float __extendhfsf2(_Float16);
|
||||
CHECK(0.f == __extendhfsf2(0));
|
||||
CHECK(3.140625f == __extendhfsf2(pi));
|
||||
CHECK(3.140625f == pi);
|
||||
|
||||
// half → double → half
|
||||
d = pi;
|
||||
pi = d;
|
||||
|
||||
// half → double
|
||||
double __extendhfdf2(_Float16);
|
||||
CHECK(0. == __extendhfdf2(0));
|
||||
CHECK(3.140625 == __extendhfdf2(pi));
|
||||
|
||||
// float → half
|
||||
_Float16 __truncsfhf2(float);
|
||||
CHECK(0 == (float)__truncsfhf2(0));
|
||||
CHECK(pi == (float)__truncsfhf2(3.141f));
|
||||
CHECK(3.140625f == (float)__truncsfhf2(3.141f));
|
||||
|
||||
// double → half
|
||||
_Float16 __truncdfhf2(double);
|
||||
CHECK(0 == (double)__truncdfhf2(0));
|
||||
CHECK(3.140625 == (double)__truncdfhf2(3.141));
|
||||
|
||||
// specials
|
||||
volatile _Float16 nan = NAN;
|
||||
volatile _Float16 positive_infinity = +INFINITY;
|
||||
volatile _Float16 negative_infinity = -INFINITY;
|
||||
CHECK(isnan(nan));
|
||||
CHECK(!isinf(pi));
|
||||
CHECK(!isnan(pi));
|
||||
CHECK(isinf(positive_infinity));
|
||||
CHECK(isinf(negative_infinity));
|
||||
CHECK(!isnan(positive_infinity));
|
||||
CHECK(!isnan(negative_infinity));
|
||||
CHECK(!signbit(pi));
|
||||
CHECK(signbit(half(-pi)));
|
||||
CHECK(!signbit(half(+0.)));
|
||||
CHECK(signbit(half(-0.)));
|
||||
|
||||
// arithmetic
|
||||
CHECK(half(-3) == -half(3));
|
||||
CHECK(half(9) == half(3) * half(3));
|
||||
CHECK(half(0) == half(pi) - half(pi));
|
||||
CHECK(half(6.28125) == half(pi) + half(pi));
|
||||
|
||||
// comparisons
|
||||
CHECK(half(3) > half(2));
|
||||
CHECK(half(3) < half(4));
|
||||
CHECK(half(3) <= half(3));
|
||||
CHECK(half(3) >= half(3));
|
||||
TRUE(half(NAN) != half(NAN));
|
||||
FALSE(half(NAN) == half(NAN));
|
||||
TRUE(half(3) != half(NAN));
|
||||
FALSE(half(3) == half(NAN));
|
||||
TRUE(half(NAN) != half(3));
|
||||
FALSE(half(NAN) == half(3));
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
//===-- lib/extendhfdf2.c - half -> dubble conversion -------------*- C -*-===//
|
||||
//
|
||||
// The Cosmopolitan Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
#define SRC_HALF
|
||||
#define DST_DOUBLE
|
||||
#include "third_party/compiler_rt/fp16_extend_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI dst_t __extendhfdf2(src_t a) {
|
||||
return __extendXfYf2__(a);
|
||||
}
|
||||
+9
-17
@@ -1,35 +1,27 @@
|
||||
//===-- lib/extendhfsf2.c - half -> single conversion -------------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
__static_yoink("huge_compiler_rt_license");
|
||||
|
||||
#define SRC_HALF
|
||||
#define DST_SINGLE
|
||||
#include "third_party/compiler_rt/fp_extend_impl.inc"
|
||||
#include "fp16_extend_impl.inc"
|
||||
|
||||
// Use a forwarding definition and noinline to implement a poor man's alias,
|
||||
// as there isn't a good cross-platform way of defining one.
|
||||
COMPILER_RT_ABI __attribute__((__noinline__)) float __extendhfsf2(uint16_t a) {
|
||||
return __extendXfYf2__(a);
|
||||
COMPILER_RT_ABI NOINLINE float __extendhfsf2(src_t a) {
|
||||
return __extendXfYf2__(a);
|
||||
}
|
||||
|
||||
COMPILER_RT_ABI float __gnu_h2f_ieee(uint16_t a) {
|
||||
return __extendhfsf2(a);
|
||||
}
|
||||
COMPILER_RT_ABI float __gnu_h2f_ieee(src_t a) { return __extendhfsf2(a); }
|
||||
|
||||
#if defined(__ARM_EABI__)
|
||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||
AEABI_RTABI float __aeabi_h2f(uint16_t a) {
|
||||
return __extendhfsf2(a);
|
||||
}
|
||||
AEABI_RTABI float __aeabi_h2f(src_t a) { return __extendhfsf2(a); }
|
||||
#else
|
||||
AEABI_RTABI float __aeabi_h2f(uint16_t a) COMPILER_RT_ALIAS(__extendhfsf2);
|
||||
COMPILER_RT_ALIAS(__extendhfsf2, __aeabi_h2f)
|
||||
#endif
|
||||
#endif
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
//===-lib/fp_extend.h - low precision -> high precision conversion -*- C
|
||||
//-*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Set source and destination setting
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef FP_EXTEND_HEADER
|
||||
#define FP_EXTEND_HEADER
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if defined SRC_SINGLE
|
||||
typedef float src_t;
|
||||
typedef uint32_t src_rep_t;
|
||||
#define SRC_REP_C UINT32_C
|
||||
static const int srcBits = sizeof(src_t) * CHAR_BIT;
|
||||
static const int srcSigFracBits = 23;
|
||||
// -1 accounts for the sign bit.
|
||||
// srcBits - srcSigFracBits - 1
|
||||
static const int srcExpBits = 8;
|
||||
#define src_rep_t_clz clzsi
|
||||
|
||||
#elif defined SRC_DOUBLE
|
||||
typedef double src_t;
|
||||
typedef uint64_t src_rep_t;
|
||||
#define SRC_REP_C UINT64_C
|
||||
static const int srcBits = sizeof(src_t) * CHAR_BIT;
|
||||
static const int srcSigFracBits = 52;
|
||||
// -1 accounts for the sign bit.
|
||||
// srcBits - srcSigFracBits - 1
|
||||
static const int srcExpBits = 11;
|
||||
|
||||
static inline int src_rep_t_clz_impl(src_rep_t a) {
|
||||
#if defined __LP64__
|
||||
return __builtin_clzl(a);
|
||||
#else
|
||||
if (a & REP_C(0xffffffff00000000))
|
||||
return clzsi(a >> 32);
|
||||
else
|
||||
return 32 + clzsi(a & REP_C(0xffffffff));
|
||||
#endif
|
||||
}
|
||||
#define src_rep_t_clz src_rep_t_clz_impl
|
||||
|
||||
#elif defined SRC_80
|
||||
typedef xf_float src_t;
|
||||
typedef __uint128_t src_rep_t;
|
||||
#define SRC_REP_C (__uint128_t)
|
||||
// sign bit, exponent and significand occupy the lower 80 bits.
|
||||
static const int srcBits = 80;
|
||||
static const int srcSigFracBits = 63;
|
||||
// -1 accounts for the sign bit.
|
||||
// -1 accounts for the explicitly stored integer bit.
|
||||
// srcBits - srcSigFracBits - 1 - 1
|
||||
static const int srcExpBits = 15;
|
||||
|
||||
#elif defined SRC_HALF
|
||||
typedef _Float16 src_t;
|
||||
typedef uint16_t src_rep_t;
|
||||
#define SRC_REP_C UINT16_C
|
||||
static const int srcBits = sizeof(src_t) * CHAR_BIT;
|
||||
static const int srcSigFracBits = 10;
|
||||
// -1 accounts for the sign bit.
|
||||
// srcBits - srcSigFracBits - 1
|
||||
static const int srcExpBits = 5;
|
||||
|
||||
static inline int src_rep_t_clz_impl(src_rep_t a) {
|
||||
return __builtin_clz(a) - 16;
|
||||
}
|
||||
|
||||
#define src_rep_t_clz src_rep_t_clz_impl
|
||||
|
||||
#else
|
||||
#error Source should be half, single, or double precision!
|
||||
#endif // end source precision
|
||||
|
||||
#if defined DST_SINGLE
|
||||
typedef float dst_t;
|
||||
typedef uint32_t dst_rep_t;
|
||||
#define DST_REP_C UINT32_C
|
||||
static const int dstBits = sizeof(dst_t) * CHAR_BIT;
|
||||
static const int dstSigFracBits = 23;
|
||||
// -1 accounts for the sign bit.
|
||||
// dstBits - dstSigFracBits - 1
|
||||
static const int dstExpBits = 8;
|
||||
|
||||
#elif defined DST_DOUBLE
|
||||
typedef double dst_t;
|
||||
typedef uint64_t dst_rep_t;
|
||||
#define DST_REP_C UINT64_C
|
||||
static const int dstBits = sizeof(dst_t) * CHAR_BIT;
|
||||
static const int dstSigFracBits = 52;
|
||||
// -1 accounts for the sign bit.
|
||||
// dstBits - dstSigFracBits - 1
|
||||
static const int dstExpBits = 11;
|
||||
|
||||
#elif defined DST_QUAD
|
||||
typedef tf_float dst_t;
|
||||
typedef __uint128_t dst_rep_t;
|
||||
#define DST_REP_C (__uint128_t)
|
||||
static const int dstBits = sizeof(dst_t) * CHAR_BIT;
|
||||
static const int dstSigFracBits = 112;
|
||||
// -1 accounts for the sign bit.
|
||||
// dstBits - dstSigFracBits - 1
|
||||
static const int dstExpBits = 15;
|
||||
|
||||
#else
|
||||
#error Destination should be single, double, or quad precision!
|
||||
#endif // end destination precision
|
||||
|
||||
// End of specialization parameters.
|
||||
|
||||
// TODO: These helper routines should be placed into fp_lib.h
|
||||
// Currently they depend on macros/constants defined above.
|
||||
|
||||
static inline src_rep_t extract_sign_from_src(src_rep_t x) {
|
||||
const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1);
|
||||
return (x & srcSignMask) >> (srcBits - 1);
|
||||
}
|
||||
|
||||
static inline src_rep_t extract_exp_from_src(src_rep_t x) {
|
||||
const int srcSigBits = srcBits - 1 - srcExpBits;
|
||||
const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits;
|
||||
return (x & srcExpMask) >> srcSigBits;
|
||||
}
|
||||
|
||||
static inline src_rep_t extract_sig_frac_from_src(src_rep_t x) {
|
||||
const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1;
|
||||
return x & srcSigFracMask;
|
||||
}
|
||||
|
||||
#ifdef src_rep_t_clz
|
||||
static inline int clz_in_sig_frac(src_rep_t sigFrac) {
|
||||
const int skip = 1 + srcExpBits;
|
||||
return src_rep_t_clz(sigFrac) - skip;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) {
|
||||
return (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac;
|
||||
}
|
||||
|
||||
// Two helper routines for conversion to and from the representation of
|
||||
// floating-point data as integer values follow.
|
||||
|
||||
static inline src_rep_t srcToRep(src_t x) {
|
||||
const union {
|
||||
src_t f;
|
||||
src_rep_t i;
|
||||
} rep = {.f = x};
|
||||
return rep.i;
|
||||
}
|
||||
|
||||
static inline dst_t dstFromRep(dst_rep_t x) {
|
||||
const union {
|
||||
dst_t f;
|
||||
dst_rep_t i;
|
||||
} rep = {.i = x};
|
||||
return rep.f;
|
||||
}
|
||||
// End helper routines. Conversion implementation follows.
|
||||
|
||||
#endif // FP_EXTEND_HEADER
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
//=-lib/fp_extend_impl.inc - low precision -> high precision conversion -*-- -//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a fairly generic conversion from a narrower to a wider
|
||||
// IEEE-754 floating-point type. The constants and types defined following the
|
||||
// includes below parameterize the conversion.
|
||||
//
|
||||
// It does not support types that don't use the usual IEEE-754 interchange
|
||||
// formats; specifically, some work would be needed to adapt it to
|
||||
// (for example) the Intel 80-bit format or PowerPC double-double format.
|
||||
//
|
||||
// Note please, however, that this implementation is only intended to support
|
||||
// *widening* operations; if you need to convert to a *narrower* floating-point
|
||||
// type (e.g. double -> float), then this routine will not do what you want it
|
||||
// to.
|
||||
//
|
||||
// It also requires that integer types at least as large as both formats
|
||||
// are available on the target platform; this may pose a problem when trying
|
||||
// to add support for quad on some 32-bit systems, for example. You also may
|
||||
// run into trouble finding an appropriate CLZ function for wide source types;
|
||||
// you will likely need to roll your own on some platforms.
|
||||
//
|
||||
// Finally, the following assumptions are made:
|
||||
//
|
||||
// 1. Floating-point types and integer types have the same endianness on the
|
||||
// target platform.
|
||||
//
|
||||
// 2. Quiet NaNs, if supported, are indicated by the leading bit of the
|
||||
// significand field being set.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "fp16_extend.inc"
|
||||
|
||||
// The source type may use a usual IEEE-754 interchange format or Intel 80-bit
|
||||
// format. In particular, for the source type srcSigFracBits may be not equal to
|
||||
// srcSigBits. The destination type is assumed to be one of IEEE-754 standard
|
||||
// types.
|
||||
static __inline dst_t __extendXfYf2__(src_t a) {
|
||||
// Various constants whose values follow from the type parameters.
|
||||
// Any reasonable optimizer will fold and propagate all of these.
|
||||
const int srcInfExp = (1 << srcExpBits) - 1;
|
||||
const int srcExpBias = srcInfExp >> 1;
|
||||
|
||||
const int dstInfExp = (1 << dstExpBits) - 1;
|
||||
const int dstExpBias = dstInfExp >> 1;
|
||||
|
||||
// Break a into a sign and representation of the absolute value.
|
||||
const src_rep_t aRep = srcToRep(a);
|
||||
const src_rep_t srcSign = extract_sign_from_src(aRep);
|
||||
const src_rep_t srcExp = extract_exp_from_src(aRep);
|
||||
const src_rep_t srcSigFrac = extract_sig_frac_from_src(aRep);
|
||||
|
||||
dst_rep_t dstSign = srcSign;
|
||||
dst_rep_t dstExp;
|
||||
dst_rep_t dstSigFrac;
|
||||
|
||||
if (srcExp >= 1 && srcExp < (src_rep_t)srcInfExp) {
|
||||
// a is a normal number.
|
||||
dstExp = (dst_rep_t)srcExp + (dst_rep_t)(dstExpBias - srcExpBias);
|
||||
dstSigFrac = (dst_rep_t)srcSigFrac << (dstSigFracBits - srcSigFracBits);
|
||||
}
|
||||
|
||||
else if (srcExp == srcInfExp) {
|
||||
// a is NaN or infinity.
|
||||
dstExp = dstInfExp;
|
||||
dstSigFrac = (dst_rep_t)srcSigFrac << (dstSigFracBits - srcSigFracBits);
|
||||
}
|
||||
|
||||
else if (srcSigFrac) {
|
||||
// a is denormal.
|
||||
if (srcExpBits == dstExpBits) {
|
||||
// The exponent fields are identical and this is a denormal number, so all
|
||||
// the non-significand bits are zero. In particular, this branch is always
|
||||
// taken when we extend a denormal F80 to F128.
|
||||
dstExp = 0;
|
||||
dstSigFrac = ((dst_rep_t)srcSigFrac) << (dstSigFracBits - srcSigFracBits);
|
||||
} else {
|
||||
#ifndef src_rep_t_clz
|
||||
// If src_rep_t_clz is not defined this branch must be unreachable.
|
||||
__builtin_unreachable();
|
||||
#else
|
||||
// Renormalize the significand and clear the leading bit.
|
||||
// For F80 -> F128 this codepath is unused.
|
||||
const int scale = clz_in_sig_frac(srcSigFrac) + 1;
|
||||
dstExp = dstExpBias - srcExpBias - scale + 1;
|
||||
dstSigFrac = (dst_rep_t)srcSigFrac
|
||||
<< (dstSigFracBits - srcSigFracBits + scale);
|
||||
const dst_rep_t dstMinNormal = DST_REP_C(1) << (dstBits - 1 - dstExpBits);
|
||||
dstSigFrac ^= dstMinNormal;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
// a is zero.
|
||||
dstExp = 0;
|
||||
dstSigFrac = 0;
|
||||
}
|
||||
|
||||
const dst_rep_t result = construct_dst_rep(dstSign, dstExp, dstSigFrac);
|
||||
return dstFromRep(result);
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
//=== lib/fp_trunc.h - high precision -> low precision conversion *- C -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Set source and destination precision setting
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef FP_TRUNC_HEADER
|
||||
#define FP_TRUNC_HEADER
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if defined SRC_SINGLE
|
||||
typedef float src_t;
|
||||
typedef uint32_t src_rep_t;
|
||||
#define SRC_REP_C UINT32_C
|
||||
static const int srcBits = sizeof(src_t) * CHAR_BIT;
|
||||
static const int srcSigFracBits = 23;
|
||||
// -1 accounts for the sign bit.
|
||||
// srcBits - srcSigFracBits - 1
|
||||
static const int srcExpBits = 8;
|
||||
|
||||
#elif defined SRC_DOUBLE
|
||||
typedef double src_t;
|
||||
typedef uint64_t src_rep_t;
|
||||
#define SRC_REP_C UINT64_C
|
||||
static const int srcBits = sizeof(src_t) * CHAR_BIT;
|
||||
static const int srcSigFracBits = 52;
|
||||
// -1 accounts for the sign bit.
|
||||
// srcBits - srcSigFracBits - 1
|
||||
static const int srcExpBits = 11;
|
||||
|
||||
#elif defined SRC_QUAD
|
||||
typedef tf_float src_t;
|
||||
typedef __uint128_t src_rep_t;
|
||||
#define SRC_REP_C (__uint128_t)
|
||||
static const int srcBits = sizeof(src_t) * CHAR_BIT;
|
||||
static const int srcSigFracBits = 112;
|
||||
// -1 accounts for the sign bit.
|
||||
// srcBits - srcSigFracBits - 1
|
||||
static const int srcExpBits = 15;
|
||||
|
||||
#else
|
||||
#error Source should be double precision or quad precision!
|
||||
#endif // end source precision
|
||||
|
||||
#if defined DST_DOUBLE
|
||||
typedef double dst_t;
|
||||
typedef uint64_t dst_rep_t;
|
||||
#define DST_REP_C UINT64_C
|
||||
static const int dstBits = sizeof(dst_t) * CHAR_BIT;
|
||||
static const int dstSigFracBits = 52;
|
||||
// -1 accounts for the sign bit.
|
||||
// dstBits - dstSigFracBits - 1
|
||||
static const int dstExpBits = 11;
|
||||
|
||||
#elif defined DST_80
|
||||
typedef xf_float dst_t;
|
||||
typedef __uint128_t dst_rep_t;
|
||||
#define DST_REP_C (__uint128_t)
|
||||
static const int dstBits = 80;
|
||||
static const int dstSigFracBits = 63;
|
||||
// -1 accounts for the sign bit.
|
||||
// -1 accounts for the explicitly stored integer bit.
|
||||
// dstBits - dstSigFracBits - 1 - 1
|
||||
static const int dstExpBits = 15;
|
||||
|
||||
#elif defined DST_SINGLE
|
||||
typedef float dst_t;
|
||||
typedef uint32_t dst_rep_t;
|
||||
#define DST_REP_C UINT32_C
|
||||
static const int dstBits = sizeof(dst_t) * CHAR_BIT;
|
||||
static const int dstSigFracBits = 23;
|
||||
// -1 accounts for the sign bit.
|
||||
// dstBits - dstSigFracBits - 1
|
||||
static const int dstExpBits = 8;
|
||||
|
||||
#elif defined DST_HALF
|
||||
typedef _Float16 dst_t;
|
||||
typedef uint16_t dst_rep_t;
|
||||
#define DST_REP_C UINT16_C
|
||||
static const int dstBits = sizeof(dst_t) * CHAR_BIT;
|
||||
static const int dstSigFracBits = 10;
|
||||
// -1 accounts for the sign bit.
|
||||
// dstBits - dstSigFracBits - 1
|
||||
static const int dstExpBits = 5;
|
||||
|
||||
#elif defined DST_BFLOAT
|
||||
typedef __bf16 dst_t;
|
||||
typedef uint16_t dst_rep_t;
|
||||
#define DST_REP_C UINT16_C
|
||||
static const int dstBits = sizeof(dst_t) * CHAR_BIT;
|
||||
static const int dstSigFracBits = 7;
|
||||
// -1 accounts for the sign bit.
|
||||
// dstBits - dstSigFracBits - 1
|
||||
static const int dstExpBits = 8;
|
||||
|
||||
#else
|
||||
#error Destination should be single precision or double precision!
|
||||
#endif // end destination precision
|
||||
|
||||
// TODO: These helper routines should be placed into fp_lib.h
|
||||
// Currently they depend on macros/constants defined above.
|
||||
|
||||
static inline src_rep_t extract_sign_from_src(src_rep_t x) {
|
||||
const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1);
|
||||
return (x & srcSignMask) >> (srcBits - 1);
|
||||
}
|
||||
|
||||
static inline src_rep_t extract_exp_from_src(src_rep_t x) {
|
||||
const int srcSigBits = srcBits - 1 - srcExpBits;
|
||||
const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits;
|
||||
return (x & srcExpMask) >> srcSigBits;
|
||||
}
|
||||
|
||||
static inline src_rep_t extract_sig_frac_from_src(src_rep_t x) {
|
||||
const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1;
|
||||
return x & srcSigFracMask;
|
||||
}
|
||||
|
||||
static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) {
|
||||
dst_rep_t result = (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac;
|
||||
// Set the explicit integer bit in F80 if present.
|
||||
if (dstBits == 80 && exp) {
|
||||
result |= (DST_REP_C(1) << dstSigFracBits);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// End of specialization parameters. Two helper routines for conversion to and
|
||||
// from the representation of floating-point data as integer values follow.
|
||||
|
||||
static inline src_rep_t srcToRep(src_t x) {
|
||||
const union {
|
||||
src_t f;
|
||||
src_rep_t i;
|
||||
} rep = {.f = x};
|
||||
return rep.i;
|
||||
}
|
||||
|
||||
static inline dst_t dstFromRep(dst_rep_t x) {
|
||||
const union {
|
||||
dst_t f;
|
||||
dst_rep_t i;
|
||||
} rep = {.i = x};
|
||||
return rep.f;
|
||||
}
|
||||
|
||||
#endif // FP_TRUNC_HEADER
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
//= lib/fp_trunc_impl.inc - high precision -> low precision conversion *-*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a fairly generic conversion from a wider to a narrower
|
||||
// IEEE-754 floating-point type in the default (round to nearest, ties to even)
|
||||
// rounding mode. The constants and types defined following the includes below
|
||||
// parameterize the conversion.
|
||||
//
|
||||
// This routine can be trivially adapted to support conversions to
|
||||
// half-precision or from quad-precision. It does not support types that don't
|
||||
// use the usual IEEE-754 interchange formats; specifically, some work would be
|
||||
// needed to adapt it to (for example) the Intel 80-bit format or PowerPC
|
||||
// double-double format.
|
||||
//
|
||||
// Note please, however, that this implementation is only intended to support
|
||||
// *narrowing* operations; if you need to convert to a *wider* floating-point
|
||||
// type (e.g. float -> double), then this routine will not do what you want it
|
||||
// to.
|
||||
//
|
||||
// It also requires that integer types at least as large as both formats
|
||||
// are available on the target platform; this may pose a problem when trying
|
||||
// to add support for quad on some 32-bit systems, for example.
|
||||
//
|
||||
// Finally, the following assumptions are made:
|
||||
//
|
||||
// 1. Floating-point types and integer types have the same endianness on the
|
||||
// target platform.
|
||||
//
|
||||
// 2. Quiet NaNs, if supported, are indicated by the leading bit of the
|
||||
// significand field being set.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "fp16_trunc.inc"
|
||||
|
||||
// The destination type may use a usual IEEE-754 interchange format or Intel
|
||||
// 80-bit format. In particular, for the destination type dstSigFracBits may be
|
||||
// not equal to dstSigBits. The source type is assumed to be one of IEEE-754
|
||||
// standard types.
|
||||
static __inline dst_t __truncXfYf2__(src_t a) {
|
||||
// Various constants whose values follow from the type parameters.
|
||||
// Any reasonable optimizer will fold and propagate all of these.
|
||||
const int srcInfExp = (1 << srcExpBits) - 1;
|
||||
const int srcExpBias = srcInfExp >> 1;
|
||||
|
||||
const src_rep_t srcMinNormal = SRC_REP_C(1) << srcSigFracBits;
|
||||
const src_rep_t roundMask =
|
||||
(SRC_REP_C(1) << (srcSigFracBits - dstSigFracBits)) - 1;
|
||||
const src_rep_t halfway = SRC_REP_C(1)
|
||||
<< (srcSigFracBits - dstSigFracBits - 1);
|
||||
const src_rep_t srcQNaN = SRC_REP_C(1) << (srcSigFracBits - 1);
|
||||
const src_rep_t srcNaNCode = srcQNaN - 1;
|
||||
|
||||
const int dstInfExp = (1 << dstExpBits) - 1;
|
||||
const int dstExpBias = dstInfExp >> 1;
|
||||
const int overflowExponent = srcExpBias + dstInfExp - dstExpBias;
|
||||
|
||||
const dst_rep_t dstQNaN = DST_REP_C(1) << (dstSigFracBits - 1);
|
||||
const dst_rep_t dstNaNCode = dstQNaN - 1;
|
||||
|
||||
const src_rep_t aRep = srcToRep(a);
|
||||
const src_rep_t srcSign = extract_sign_from_src(aRep);
|
||||
const src_rep_t srcExp = extract_exp_from_src(aRep);
|
||||
const src_rep_t srcSigFrac = extract_sig_frac_from_src(aRep);
|
||||
|
||||
dst_rep_t dstSign = srcSign;
|
||||
dst_rep_t dstExp;
|
||||
dst_rep_t dstSigFrac;
|
||||
|
||||
// Same size exponents and a's significand tail is 0.
|
||||
// The significand can be truncated and the exponent can be copied over.
|
||||
const int sigFracTailBits = srcSigFracBits - dstSigFracBits;
|
||||
if (srcExpBits == dstExpBits &&
|
||||
((aRep >> sigFracTailBits) << sigFracTailBits) == aRep) {
|
||||
dstExp = srcExp;
|
||||
dstSigFrac = (dst_rep_t)(srcSigFrac >> sigFracTailBits);
|
||||
return dstFromRep(construct_dst_rep(dstSign, dstExp, dstSigFrac));
|
||||
}
|
||||
|
||||
const int dstExpCandidate = ((int)srcExp - srcExpBias) + dstExpBias;
|
||||
if (dstExpCandidate >= 1 && dstExpCandidate < dstInfExp) {
|
||||
// The exponent of a is within the range of normal numbers in the
|
||||
// destination format. We can convert by simply right-shifting with
|
||||
// rounding and adjusting the exponent.
|
||||
dstExp = dstExpCandidate;
|
||||
dstSigFrac = (dst_rep_t)(srcSigFrac >> sigFracTailBits);
|
||||
|
||||
const src_rep_t roundBits = srcSigFrac & roundMask;
|
||||
// Round to nearest.
|
||||
if (roundBits > halfway)
|
||||
dstSigFrac++;
|
||||
// Tie to even.
|
||||
else if (roundBits == halfway)
|
||||
dstSigFrac += dstSigFrac & 1;
|
||||
|
||||
// Rounding has changed the exponent.
|
||||
if (dstSigFrac >= (DST_REP_C(1) << dstSigFracBits)) {
|
||||
dstExp += 1;
|
||||
dstSigFrac ^= (DST_REP_C(1) << dstSigFracBits);
|
||||
}
|
||||
} else if (srcExp == srcInfExp && srcSigFrac) {
|
||||
// a is NaN.
|
||||
// Conjure the result by beginning with infinity, setting the qNaN
|
||||
// bit and inserting the (truncated) trailing NaN field.
|
||||
dstExp = dstInfExp;
|
||||
dstSigFrac = dstQNaN;
|
||||
dstSigFrac |= ((srcSigFrac & srcNaNCode) >> sigFracTailBits) & dstNaNCode;
|
||||
} else if ((int)srcExp >= overflowExponent) {
|
||||
dstExp = dstInfExp;
|
||||
dstSigFrac = 0;
|
||||
} else {
|
||||
// a underflows on conversion to the destination type or is an exact
|
||||
// zero. The result may be a denormal or zero. Extract the exponent
|
||||
// to get the shift amount for the denormalization.
|
||||
src_rep_t significand = srcSigFrac;
|
||||
int shift = srcExpBias - dstExpBias - srcExp;
|
||||
|
||||
if (srcExp) {
|
||||
// Set the implicit integer bit if the source is a normal number.
|
||||
significand |= srcMinNormal;
|
||||
shift += 1;
|
||||
}
|
||||
|
||||
// Right shift by the denormalization amount with sticky.
|
||||
if (shift > srcSigFracBits) {
|
||||
dstExp = 0;
|
||||
dstSigFrac = 0;
|
||||
} else {
|
||||
dstExp = 0;
|
||||
const bool sticky = shift && ((significand << (srcBits - shift)) != 0);
|
||||
src_rep_t denormalizedSignificand = significand >> shift | sticky;
|
||||
dstSigFrac = denormalizedSignificand >> sigFracTailBits;
|
||||
const src_rep_t roundBits = denormalizedSignificand & roundMask;
|
||||
// Round to nearest
|
||||
if (roundBits > halfway)
|
||||
dstSigFrac++;
|
||||
// Ties to even
|
||||
else if (roundBits == halfway)
|
||||
dstSigFrac += dstSigFrac & 1;
|
||||
|
||||
// Rounding has changed the exponent.
|
||||
if (dstSigFrac >= (DST_REP_C(1) << dstSigFracBits)) {
|
||||
dstExp += 1;
|
||||
dstSigFrac ^= (DST_REP_C(1) << dstSigFracBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dstFromRep(construct_dst_rep(dstSign, dstExp, dstSigFrac));
|
||||
}
|
||||
+12
-2
@@ -41,11 +41,21 @@ static __inline int src_rep_t_clz(src_rep_t a) {
|
||||
}
|
||||
|
||||
#elif defined SRC_HALF
|
||||
typedef uint16_t src_t;
|
||||
#error use fp16_extend.inc
|
||||
typedef _Float16 src_t;
|
||||
typedef uint16_t src_rep_t;
|
||||
#define SRC_REP_C UINT16_C
|
||||
static const int srcBits = sizeof(src_t) * CHAR_BIT;
|
||||
static const int srcSigBits = 10;
|
||||
#define src_rep_t_clz __builtin_clz
|
||||
// -1 accounts for the sign bit.
|
||||
// srcBits - srcSigFracBits - 1
|
||||
static const int srcExpBits = 5;
|
||||
|
||||
static inline int src_rep_t_clz_impl(src_rep_t a) {
|
||||
return __builtin_clz(a) - 16;
|
||||
}
|
||||
|
||||
#define src_rep_t_clz src_rep_t_clz_impl
|
||||
|
||||
#else
|
||||
#error Source should be half, single, or double precision!
|
||||
|
||||
+1
@@ -51,6 +51,7 @@ typedef uint32_t dst_rep_t;
|
||||
static const int dstSigBits = 23;
|
||||
|
||||
#elif defined DST_HALF
|
||||
#error use fp16_trunc.inc
|
||||
typedef uint16_t dst_t;
|
||||
typedef uint16_t dst_rep_t;
|
||||
#define DST_REP_C UINT16_C
|
||||
|
||||
Vendored
+2
@@ -46,10 +46,12 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define ALWAYS_INLINE __forceinline
|
||||
#define NOINLINE __declspec(noinline)
|
||||
#define NORETURN __declspec(noreturn)
|
||||
#define UNUSED
|
||||
#else
|
||||
#define ALWAYS_INLINE __attribute__((__always_inline__))
|
||||
#define NOINLINE __attribute__((__noinline__))
|
||||
#define NORETURN __attribute__((__noreturn__))
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
#endif
|
||||
|
||||
Vendored
+7
-14
@@ -1,28 +1,21 @@
|
||||
//===-- lib/truncdfhf2.c - double -> half conversion --------------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
__static_yoink("huge_compiler_rt_license");
|
||||
|
||||
#define SRC_DOUBLE
|
||||
#define DST_HALF
|
||||
#include "third_party/compiler_rt/fp_trunc_impl.inc"
|
||||
#include "fp16_trunc_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI uint16_t __truncdfhf2(double a) {
|
||||
return __truncXfYf2__(a);
|
||||
}
|
||||
COMPILER_RT_ABI dst_t __truncdfhf2(double a) { return __truncXfYf2__(a); }
|
||||
|
||||
#if defined(__ARM_EABI__)
|
||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||
AEABI_RTABI uint16_t __aeabi_d2h(double a) {
|
||||
return __truncdfhf2(a);
|
||||
}
|
||||
AEABI_RTABI dst_t __aeabi_d2h(double a) { return __truncdfhf2(a); }
|
||||
#else
|
||||
AEABI_RTABI uint16_t __aeabi_d2h(double a) COMPILER_RT_ALIAS(__truncdfhf2);
|
||||
COMPILER_RT_ALIAS(__truncdfhf2, __aeabi_d2h)
|
||||
#endif
|
||||
#endif
|
||||
Vendored
+9
-16
@@ -1,34 +1,27 @@
|
||||
//===-- lib/truncsfhf2.c - single -> half conversion --------------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
__static_yoink("huge_compiler_rt_license");
|
||||
|
||||
#define SRC_SINGLE
|
||||
#define DST_HALF
|
||||
#include "third_party/compiler_rt/fp_trunc_impl.inc"
|
||||
#include "fp16_trunc_impl.inc"
|
||||
|
||||
// Use a forwarding definition and noinline to implement a poor man's alias,
|
||||
// as there isn't a good cross-platform way of defining one.
|
||||
COMPILER_RT_ABI __attribute__((__noinline__)) uint16_t __truncsfhf2(float a) {
|
||||
return __truncXfYf2__(a);
|
||||
COMPILER_RT_ABI NOINLINE dst_t __truncsfhf2(float a) {
|
||||
return __truncXfYf2__(a);
|
||||
}
|
||||
|
||||
COMPILER_RT_ABI uint16_t __gnu_f2h_ieee(float a) {
|
||||
return __truncsfhf2(a);
|
||||
}
|
||||
COMPILER_RT_ABI dst_t __gnu_f2h_ieee(float a) { return __truncsfhf2(a); }
|
||||
|
||||
#if defined(__ARM_EABI__)
|
||||
#if defined(COMPILER_RT_ARMHF_TARGET)
|
||||
AEABI_RTABI uint16_t __aeabi_f2h(float a) {
|
||||
return __truncsfhf2(a);
|
||||
}
|
||||
AEABI_RTABI dst_t __aeabi_f2h(float a) { return __truncsfhf2(a); }
|
||||
#else
|
||||
AEABI_RTABI uint16_t __aeabi_f2h(float a) COMPILER_RT_ALIAS(__truncsfhf2);
|
||||
COMPILER_RT_ALIAS(__truncsfhf2, __aeabi_f2h)
|
||||
#endif
|
||||
#endif
|
||||
Reference in new issue
Block a user