1072 lines
31 KiB
C++
1072 lines
31 KiB
C++
#if __GNUC__ + 0 < 2
|
|
#define __attribute__(x)
|
|
#endif
|
|
|
|
#ifndef __cplusplus
|
|
#define COSMOPOLITAN_C_START_
|
|
#define COSMOPOLITAN_C_END_
|
|
#define COSMOPOLITAN_CXX_START_
|
|
#define COSMOPOLITAN_CXX_END_
|
|
#define COSMOPOLITAN_CXX_USING_
|
|
#endif
|
|
|
|
#ifdef __STRICT_ANSI__
|
|
#define asm __asm__
|
|
#endif
|
|
|
|
#ifndef __ia16__
|
|
#define __far
|
|
#endif
|
|
|
|
/**
|
|
* Gets type of expression.
|
|
* @see autotype() which is a better alternative for certain use cases
|
|
*/
|
|
#if !defined(__GNUC__) && __cplusplus + 0 >= 201103L
|
|
#define typeof(x) decltype(x)
|
|
#elif (defined(__STRICT_ANSI__) || !defined(__GNUC__)) && \
|
|
__STDC_VERSION__ + 0 < 201112
|
|
#define typeof(x) __typeof(x)
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
#if __cplusplus >= 201103L
|
|
#define _Alignof(x) alignof(x)
|
|
#endif /* C++11 */
|
|
#else /* __cplusplus */
|
|
#define alignof(x) _Alignof(x)
|
|
#if __STDC_VERSION__ + 0 < 201112
|
|
#if __GNUC__ + _MSC_VER + 0 && !defined(__STRICT_ANSI__)
|
|
#define _Alignof(x) __alignof(x)
|
|
#else
|
|
#define _Alignof(x) /* basically all it ever did lool */ sizeof(x)
|
|
#endif /* GNU/MSVC/!ANSI */
|
|
#endif /* C11 */
|
|
#endif /* __cplusplus */
|
|
|
|
#if !defined(__cplusplus) && !defined(inline) && __STDC_VERSION__ + 0 < 199901
|
|
#if !defined(__STRICT_ANSI__) && (defined(__GNUC__) || defined(_MSC_VER))
|
|
#define inline __inline
|
|
#else
|
|
#define inline
|
|
#define __inline
|
|
#endif
|
|
#endif
|
|
|
|
#if __STDC_VERSION__ + 0 < 201112
|
|
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
|
#define _Alignas(x) __attribute__((__aligned__(x)))
|
|
#elif defined(_MSC_VER)
|
|
#define _Alignas(x) __declspec(align(x))
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(__STRICT_ANSI__) || \
|
|
(!defined(__GNUC__) && !__has_builtin(unreachable))
|
|
#define __builtin_unreachable() \
|
|
for (;;) { \
|
|
}
|
|
#endif
|
|
|
|
#if defined(__STRICT_ANSI__) || (!defined(__llvm__) && !__has_builtin(assume))
|
|
#define __builtin_assume(x) \
|
|
do { \
|
|
if (!(x)) __builtin_unreachable(); \
|
|
} while (0)
|
|
#endif
|
|
|
|
#if __STDC_VERSION__ + 0 < 201112
|
|
#define ____Static_assert(x, y) A##B
|
|
#define ___Static_assert(x, y) ____Static_assert(x, y)
|
|
#ifndef __cplusplus /* todo jart what */
|
|
#define __Static_assert(x) __builtin_choose_expr(__builtin_constant_p(x), x, 1)
|
|
#else
|
|
#define __Static_assert(x) (x)
|
|
#endif
|
|
#define _Static_assert(x, s) /* clang-format off */ do { \
|
|
__builtin_assume(x); \
|
|
enum { ___Static_assert(_Assert, __COUNTER__) = \
|
|
1 / !!__Static_assert(x) \
|
|
} /*_Unused*/; /* clang-format on */ \
|
|
} while (0)
|
|
#endif
|
|
|
|
#if __STDC_VERSION__ + 0 < 201112 && defined(__x86__)
|
|
#define _Atomic(TYPE) TYPE
|
|
#endif
|
|
|
|
#ifdef __llvm__
|
|
#define __gnu_printf__ __printf__
|
|
#define __gnu_scanf__ __scanf__
|
|
#endif
|
|
|
|
#if __cplusplus + 0 >= 201103L
|
|
#define NULL nullptr
|
|
#elif !defined(__cplusplus)
|
|
#define NULL ((void *)0)
|
|
#else
|
|
#define NULL 0
|
|
#endif
|
|
|
|
#ifndef __cplusplus
|
|
#if __STDC_VERSION__ + 0 >= 201112
|
|
typedef _Bool bool;
|
|
#define true ((bool)+1)
|
|
#define false ((bool)+0)
|
|
#else
|
|
#define bool int
|
|
#define true 1
|
|
#define false 0
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef __cplusplus
|
|
typedef __WCHAR_TYPE__ wchar_t;
|
|
typedef __CHAR16_TYPE__ char16_t;
|
|
typedef __CHAR32_TYPE__ char32_t;
|
|
#endif
|
|
|
|
typedef int errno_t;
|
|
typedef __SIZE_TYPE__ size_t;
|
|
typedef __PTRDIFF_TYPE__ ssize_t;
|
|
typedef __INTPTR_TYPE__ intptr_t;
|
|
typedef __UINTPTR_TYPE__ uintptr_t;
|
|
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
|
typedef __WINT_TYPE__ wint_t; /* uint32_t on linux but int32_t on xnu */
|
|
typedef __INT32_TYPE__ bool32;
|
|
typedef __INT8_TYPE__ int8_t;
|
|
typedef __UINT8_TYPE__ uint8_t;
|
|
typedef __INT16_TYPE__ int16_t;
|
|
typedef __UINT16_TYPE__ uint16_t;
|
|
typedef __INT32_TYPE__ int32_t;
|
|
typedef __UINT32_TYPE__ uint32_t;
|
|
typedef __INT64_TYPE__ int64_t;
|
|
typedef __UINT64_TYPE__ uint64_t;
|
|
|
|
/**
|
|
* AX:DX register pair.
|
|
*
|
|
* Every ABI we support permits functions to return two machine words.
|
|
* Normally it's best to define a one-off struct. Sometimes we don't
|
|
* want the boilerplate.
|
|
*
|
|
* @see System V Application Binary Interface NexGen32e Architecture
|
|
* Processor Supplement, Version 1.0, December 5th, 2018
|
|
* @see agner.org/optimize/calling_conventions.pdf (chapter 6)
|
|
* @see LISP primitives CONS[CAR,CDR] w/ IBM 704 naming
|
|
* @see int128_t
|
|
*/
|
|
typedef struct {
|
|
intptr_t ax, dx;
|
|
} axdx_t;
|
|
|
|
/*
|
|
* GCC, Clang, and System V ABI all incorrectly define intmax_t.
|
|
*
|
|
* “[intmax_t] designates a signed integer type capable of
|
|
* representing any value of any signed integer type.”
|
|
* ──Quoth ISO/IEC 9899:201x 7.20.1.5
|
|
*
|
|
* This surprising contradiction is most likely due to Linux distro
|
|
* practices of using dynamic shared objects which needs to change.
|
|
*
|
|
* http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2303.pdf
|
|
*/
|
|
#ifdef __SIZEOF_INTMAX__
|
|
#undef __SIZEOF_INTMAX__
|
|
#endif
|
|
#if !defined(__STRICT_ANSI__) && __SIZEOF_POINTER__ == 8 && \
|
|
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406 || defined(__llvm__))
|
|
#define __SIZEOF_INTMAX__ 16
|
|
#else
|
|
#define __SIZEOF_INTMAX__ __SIZEOF_POINTER__
|
|
#endif
|
|
#if __SIZEOF_INTMAX__ == 16
|
|
typedef signed __int128 int128_t;
|
|
typedef unsigned __int128 uint128_t;
|
|
typedef int128_t intmax_t;
|
|
typedef uint128_t uintmax_t;
|
|
#elif __SIZEOF_INTMAX__ == 8
|
|
typedef int64_t intmax_t;
|
|
typedef uint64_t uintmax_t;
|
|
#endif
|
|
|
|
#ifndef __chibicc__
|
|
#define va_list __builtin_va_list
|
|
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
|
#define va_copy(dest, src) __builtin_va_copy(dest, src)
|
|
#define va_end(ap) __builtin_va_end(ap)
|
|
#define va_start(ap, last) __builtin_va_start(ap, last)
|
|
#else
|
|
#include "libc/integral/lp64arg.inc"
|
|
#endif
|
|
|
|
#define libcesque nothrow nocallback
|
|
#define memcpyesque libcesque
|
|
#define strlenesque libcesque nosideeffect paramsnonnull()
|
|
#define vallocesque \
|
|
libcesque nodiscard returnsaligned((PAGESIZE)) returnspointerwithnoaliases
|
|
#define reallocesque libcesque returnsaligned((__BIGGEST_ALIGNMENT__))
|
|
#define mallocesque reallocesque returnspointerwithnoaliases
|
|
#define interruptfn nocallersavedregisters forcealignargpointer
|
|
|
|
/**
|
|
* Declares combinator, i.e. never reads/writes global memory.
|
|
* Thus enabling LICM, CSE, DCE, etc. optimizations.
|
|
* @see nosideeffect
|
|
*/
|
|
#ifndef pureconst
|
|
#ifndef __STRICT_ANSI__
|
|
#define pureconst __attribute__((__const__))
|
|
#else
|
|
#define pureconst
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Aligns automatic or static variable.
|
|
*/
|
|
#ifndef forcealign
|
|
#ifndef __STRICT_ANSI__
|
|
#define forcealign(bytes) __attribute__((__aligned__(bytes)))
|
|
#else
|
|
#define forcealign(bytes)
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Disables alignment.
|
|
* @param opt_bytes defaults to __BIGGEST_ALIGNMENT__
|
|
* @see nosideeffect
|
|
*/
|
|
#ifndef __STRICT_ANSI__
|
|
#define thatispacked __attribute__((__packed__))
|
|
#else
|
|
#define thatispacked
|
|
#endif
|
|
|
|
/**
|
|
* Declares prototype as using well-known format string DSL.
|
|
* Thereby allowing compiler to identify certain bugs.
|
|
*/
|
|
#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 hidden
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__visibility__) || defined(__GNUC__)) && !defined(_WIN32)
|
|
#define hidden __attribute__((__visibility__("hidden")))
|
|
#else
|
|
#define hidden
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef privileged
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__visibility__) || defined(__GNUC__))
|
|
#define privileged _Section(".privileged") noinstrument
|
|
#else
|
|
#define privileged _Section(".privileged") noinstrument
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef noinstrument
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__no_instrument_function__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 204)
|
|
#define noinstrument __attribute__((__no_instrument_function__))
|
|
#else
|
|
#define noinstrument
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef wontreturn
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__noreturn__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 208)
|
|
#define wontreturn __attribute__((__noreturn__))
|
|
#else
|
|
#define wontreturn
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Declares prototype as never mutating global memory.
|
|
* Thus enabling CSE, DCE, LICM [clang-only?], etc. optimizations.
|
|
* @see pureconst
|
|
*/
|
|
#ifndef nosideeffect
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__pure__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 296)
|
|
#define nosideeffect __attribute__((__pure__))
|
|
#else
|
|
#define nosideeffect
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef noinline
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__noinline__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 301)
|
|
#define noinline __attribute__((__noinline__))
|
|
#else
|
|
#define noinline
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef noclone
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__noclone__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 405)
|
|
#define noclone __attribute__((__noclone__))
|
|
#else
|
|
#define noclone
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Makes function behave as much like macro as possible, meaning:
|
|
*
|
|
* 1. always inlined, i.e. even with -fno-inline
|
|
* 2. unlinkable, i.e. elf data is not generated
|
|
* 3. steppable, i.e. dwarf data is generated
|
|
* 4. unprofilable
|
|
* 5. unhookable
|
|
*
|
|
* @note consider static or writing a macro
|
|
* @see externinline
|
|
*/
|
|
#ifndef forceinline
|
|
#ifdef __cplusplus
|
|
#define forceinline inline
|
|
#else
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 302
|
|
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403 || \
|
|
!defined(__cplusplus) || \
|
|
(defined(__clang__) && \
|
|
(defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__)))
|
|
#if defined(__GNUC_STDC_INLINE__) || defined(__cplusplus)
|
|
#define forceinline \
|
|
static __inline __attribute__((__always_inline__, __gnu_inline__, \
|
|
__no_instrument_function__, __unused__))
|
|
#else
|
|
#define forceinline \
|
|
static __inline __attribute__( \
|
|
(__always_inline__, __no_instrument_function__, __unused__))
|
|
#endif /* __GNUC_STDC_INLINE__ */
|
|
#endif /* GCC >= 4.3 */
|
|
#elif defined(_MSC_VER)
|
|
#define forceinline __forceinline
|
|
#else
|
|
#define forceinline static inline
|
|
#endif /* !ANSI && GCC >= 3.2 */
|
|
#endif /* __cplusplus */
|
|
#endif /* forceinline */
|
|
|
|
/**
|
|
* Permits untyped or punned memory manipulation w/o asm.
|
|
*
|
|
* “The fundamental problem is that it is not possible to write real
|
|
* programs using the X3J11 definition of C. The committee has created
|
|
* an unreal language that no one can or will actually use. While the
|
|
* problems of `const' may owe to careless drafting of the
|
|
* specification, `noalias' is an altogether mistaken notion, and must
|
|
* not survive.” ──Dennis Ritchie in 1988-03-20.
|
|
*
|
|
* @see asm(), memcpy(), memset(), read32be(), etc.
|
|
* @see unsigned char
|
|
*/
|
|
#ifndef mayalias
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__may_alias__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 303)
|
|
#define mayalias __attribute__((__may_alias__))
|
|
#else
|
|
#define mayalias
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Declares prototype as returning freeable resource.
|
|
* Compilation will fail if caller ignores return value.
|
|
* @see gc(), free(), close(), etc.
|
|
*/
|
|
#ifndef nodiscard
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 304 || \
|
|
__has_attribute(__warn_unused_result__))
|
|
#define nodiscard __attribute__((__warn_unused_result__))
|
|
#else
|
|
#define nodiscard
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Declares variadic function as needing NULL sentinel argument.
|
|
* @see execl() for example
|
|
*/
|
|
#ifndef nullterminated
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__sentinel__) || __GNUC__ >= 4)
|
|
#define nullterminated(x) __attribute__((__sentinel__ x))
|
|
#else
|
|
#define nullterminated(x)
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef flattenout
|
|
#if __has_attribute(__flatten__) || \
|
|
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 401 && !defined(__llvm__))
|
|
#define flattenout __attribute__((__flatten__))
|
|
#else
|
|
#define flattenout
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef externinline
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(!defined(__cplusplus) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403 || \
|
|
(defined(__clang__) && \
|
|
(defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__))))
|
|
#if defined(__GNUC_STDC_INLINE__) || defined(__cplusplus)
|
|
#define externinline extern __inline __attribute__((__gnu_inline__))
|
|
#else
|
|
#define externinline extern __inline __attribute__((__always_inline__))
|
|
#endif
|
|
#else
|
|
#define externinline inline
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Relocates function to .text.unlikely section of binary.
|
|
* @note can be used to minimize page-faults and improve locality
|
|
*/
|
|
#ifndef relegated
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__cold__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
|
|
#define relegated __attribute__((__cold__))
|
|
#else
|
|
#define relegated
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__warning__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
|
|
#define warnifused(s) __attribute__((__warning__(s)))
|
|
#else
|
|
#define warnifused(s)
|
|
#endif
|
|
|
|
/**
|
|
* Relocates function to .text.hot section of binary.
|
|
* @note can be used to minimize page-faults w/ improved locality
|
|
* @note most appropriately automated by profile-guided opts
|
|
*/
|
|
#ifndef firstclass
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__hot__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
|
|
#define firstclass __attribute__((__hot__))
|
|
#else
|
|
#define firstclass
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Declares all or specific parameters as never receiving NULL.
|
|
*
|
|
* This can be checked at both compile-time (only for constexprs) and
|
|
* runtime too (only in MODE=dbg mode) by synthetic Ubsan code.
|
|
*/
|
|
#ifndef paramsnonnull
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__nonnull__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
|
|
#define paramsnonnull(opt_1idxs) __attribute__((__nonnull__ opt_1idxs))
|
|
#else
|
|
#define paramsnonnull(opt_1idxs)
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Declares array argument w/ minimum size contract, e.g.
|
|
*
|
|
* int foo(int bar[hasatleast 2]) { ... }
|
|
*/
|
|
#if __STDC_VERSION__ + 0 >= 199901L
|
|
#define hasatleast static
|
|
#else
|
|
#define hasatleast
|
|
#endif
|
|
|
|
/**
|
|
* Qualifies char pointer so it's treated like every other type.
|
|
*
|
|
* int foo(int bar[hasatleast 2]) { ... }
|
|
*/
|
|
#if __STDC_VERSION__ + 0 < 199901L && !defined(restrict)
|
|
#if !defined(__STRICT_ANSI__) && !defined(__cplusplus) && \
|
|
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 301 || defined(_MSC_VER))
|
|
#define restrict __restrict__
|
|
#else
|
|
#define restrict
|
|
#define __restrict
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Declares prototype that can't mutate caller's static variables.
|
|
* @note consider more .c files or declare in function
|
|
*/
|
|
#ifndef nocallback
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__leaf__) || \
|
|
(!defined(__llvm__) && \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 406))
|
|
#define nocallback __attribute__((__leaf__))
|
|
#else
|
|
#define nocallback
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef nothrow
|
|
#if defined(__cplusplus) && !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(nothrow) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 303)
|
|
#define nothrow __attribute__((__nothrow__))
|
|
#elif defined(_MSC_VER)
|
|
#define nothrow __declspec(nothrow)
|
|
#else
|
|
#define nothrow
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Asks compiler to not optimize function definition.
|
|
*
|
|
* @todo this is dangerous delete?
|
|
*/
|
|
#ifndef nooptimize
|
|
#ifndef __STRICT_ANSI__
|
|
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
|
|
__has_attribute(__optimize__)
|
|
#define nooptimize __attribute__((__optimize__(1)))
|
|
#elif defined(__llvm__) || __has_attribute(__optnone__)
|
|
#define nooptimize __attribute__((__optnone__))
|
|
#endif
|
|
#else
|
|
#define nooptimize
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Asks compiler to generate as little code as possible for function.
|
|
*
|
|
* This does the same thing as relegated, but without relocation.
|
|
*
|
|
* @todo this is dangerous delete?
|
|
*/
|
|
#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
|
|
|
|
/**
|
|
* Asks compiler to always heavily optimize function.
|
|
*
|
|
* This keyword provides an alternative to build flag tuning, in cases
|
|
* where the compiler is reluctant to vectorize mathematical code that's
|
|
* written in standards-compliant C rather than GCC extensions.
|
|
*
|
|
* @todo this is dangerous delete?
|
|
*/
|
|
#ifndef optimizespeed
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
((__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407 || \
|
|
__has_attribute(__optimize__))
|
|
#define optimizespeed __attribute__((__optimize__(3)))
|
|
#else
|
|
#define optimizespeed
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Declares prototype that behaves similar to setjmp() or vfork().
|
|
*/
|
|
#ifndef returnstwice
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__returns_twice__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 402)
|
|
#define returnstwice __attribute__((__returns_twice__))
|
|
#else
|
|
#define returnstwice
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Asks compiler to not emit DWARF assembly for function.
|
|
* @see artificial
|
|
*/
|
|
#ifndef nodebuginfo
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__nodebug__) || defined(__llvm__))
|
|
#define nodebuginfo __attribute__((__nodebug__))
|
|
#else
|
|
#define nodebuginfo
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Associates debug information with call site.
|
|
* @see nodebuginfo
|
|
*/
|
|
#ifndef artificial
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__artificial__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 403)
|
|
#define artificial __attribute__((__artificial__))
|
|
#else
|
|
#define artificial
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Defines function as specially compiled for newer cpu model.
|
|
* @see -ftree-vectorize and consider assembly
|
|
* @see libc/dce.h
|
|
*/
|
|
#ifndef microarchitecture
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__target__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 404)
|
|
#define microarchitecture(march) __attribute__((__target__(march)))
|
|
#else
|
|
#define microarchitecture(march)
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Compiles function multiple times for different cpu models.
|
|
* @see libc/dce.h
|
|
*/
|
|
#ifndef targetclones
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__target_clones__) || __GNUC__ >= 6)
|
|
#define targetclones(archs) __attribute__((__target_clones__(archs)))
|
|
#else
|
|
#define targetclones(archs)
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Defines function with prologue that fixes misaligned stack.
|
|
* @see nocallersavedregisters and consider assembly
|
|
*/
|
|
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 408 || \
|
|
__has_attribute(__force_align_arg_pointer__)
|
|
#define forcealignargpointer __attribute__((__force_align_arg_pointer__))
|
|
#else
|
|
#define forcealignargpointer "need modern compiler"
|
|
#endif
|
|
|
|
/**
|
|
* Declares prototype as never returning NULL.
|
|
*
|
|
* This is checked at compile-time for constexprs. It'll be checked at
|
|
* runtime too by synthetic code, only in MODE=dbg mode.
|
|
*/
|
|
#ifndef returnsnonnull
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__returns_nonnull__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
|
|
#define returnsnonnull __attribute__((__returns_nonnull__))
|
|
#else
|
|
#define returnsnonnull
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Attests return value is aligned.
|
|
*
|
|
* @param (alignment)
|
|
* @param (alignment, misalignment)
|
|
* @see attributeallocalign(), returnspointerwithnoaliases, mallocesque
|
|
*/
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__assume_aligned__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
|
|
#define returnsaligned(x) __attribute__((__assume_aligned__ x))
|
|
#else
|
|
#define returnsaligned(x)
|
|
#endif
|
|
|
|
/**
|
|
* Declares prototype as behaving similar to malloc().
|
|
* @see attributeallocsize(), attributeallocalign()
|
|
*/
|
|
#ifndef returnspointerwithnoaliases
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__malloc__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
|
|
#define returnspointerwithnoaliases __attribute__((__malloc__))
|
|
#elif defined(_MSC_VER)
|
|
#define returnspointerwithnoaliases __declspec(allocator)
|
|
#else
|
|
#define returnspointerwithnoaliases
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef attributeallocsize
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__alloc_size__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
|
|
#define attributeallocsize(x) __attribute__((__alloc_size__ x))
|
|
#else
|
|
#define attributeallocsize(x)
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef attributeallocalign
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(__has_attribute(__alloc_align__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409)
|
|
#define attributeallocalign(x) __attribute__((__alloc_align__ x))
|
|
#else
|
|
#define attributeallocalign(x)
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Defines variable as having same type as right-hand side.
|
|
*
|
|
* This enables safe, backwards-compatible, non-explosive macros, e.g.:
|
|
*
|
|
* #define bar(FOO) \
|
|
* ({ \
|
|
* autotype(FOO) Foo = (FOO); \
|
|
* Foo + Foo * 2; \
|
|
* })
|
|
*
|
|
* @param x must be identical to rhs
|
|
* @note typeof goes back to gcc 2.x
|
|
*/
|
|
#if __cplusplus + 0 >= 201103L
|
|
#define autotype(x) auto
|
|
#elif ((__has_builtin(auto_type) || defined(__llvm__) || \
|
|
(__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 409) && \
|
|
!defined(__chibicc__))
|
|
#define autotype(x) __auto_type
|
|
#else
|
|
#define autotype(x) typeof(x)
|
|
#endif
|
|
|
|
/**
|
|
* Defines interrupt handler that can call non-interrupt functions.
|
|
* @see forcealignargpointer, -mgeneral-regs-only and consider assembly
|
|
*/
|
|
#if __GNUC__ >= 7 || __has_attribute(__no_caller_saved_registers__)
|
|
#define nocallersavedregisters __attribute__((__no_caller_saved_registers__))
|
|
#else
|
|
#define nocallersavedregisters "need modern compiler"
|
|
#endif
|
|
|
|
/**
|
|
* Attests that execution of statement is impossible.
|
|
*/
|
|
#ifndef unreachable
|
|
#define unreachable __builtin_unreachable()
|
|
#endif
|
|
|
|
/**
|
|
* Statement that does nothing.
|
|
* @note can help avoid drama w/ linters, warnings, formatters, etc.
|
|
*/
|
|
#define donothing \
|
|
do { \
|
|
} while (0)
|
|
|
|
#ifndef likely
|
|
#define likely(expr) __builtin_expect(!!(expr), 1)
|
|
#endif
|
|
|
|
#ifndef unlikely
|
|
#define unlikely(expr) __builtin_expect(!!(expr), 0)
|
|
#endif
|
|
|
|
/**
|
|
* Evaluates ternary expression without type promotion.
|
|
*/
|
|
#ifndef chooseexpr
|
|
#define chooseexpr(pred, a, b) __builtin_choose_expr(pred, a, b)
|
|
#endif
|
|
|
|
/**
|
|
* Returns true if expression can be evaluated at compile-time.
|
|
*/
|
|
#ifndef isconstant
|
|
#define isconstant(expr) __builtin_constant_p(expr)
|
|
#endif
|
|
|
|
#ifndef static_assert
|
|
#define static_assert(expr) _Static_assert(expr, #expr)
|
|
#endif
|
|
|
|
#ifndef typescompatible
|
|
#define typescompatible(a, b) __builtin_types_compatible_p(a, b)
|
|
#endif
|
|
|
|
#ifndef __STRICT_ANSI__
|
|
#define testonly noinline _Section(".test")
|
|
#define textstartup _Section(".text.startup") noinstrument
|
|
#define textexit _Section(".text.exit") noinstrument
|
|
#define textreal _Section(".text.real")
|
|
#define textwindows _Section(".text.windows")
|
|
#define antiquity _Section(".text.antiquity")
|
|
#else
|
|
#define testonly
|
|
#define textstartup
|
|
#define textexit
|
|
#define textreal
|
|
#define textwindows
|
|
#define antiquity
|
|
#endif
|
|
|
|
#ifndef compatfn
|
|
#define compatfn
|
|
#endif
|
|
|
|
#ifndef frownedupon
|
|
#define frownedupon(alternative)
|
|
#endif
|
|
|
|
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
|
#define _Vector_size(k) __attribute__((__vector_size__(k)))
|
|
#else
|
|
#define _Vector_size(k) [k]
|
|
#endif
|
|
|
|
#if defined(__STRICT_ANSI__) || \
|
|
(!defined(__GNUC__) && !defined(__builtin_offsetof))
|
|
#define offsetof(type, member) ((unsigned long)&((type *)0)->member)
|
|
#else
|
|
#define offsetof(type, member) __builtin_offsetof(type, member)
|
|
#endif
|
|
|
|
#ifndef alignas
|
|
#define alignas(x) _Alignas(x)
|
|
#endif
|
|
|
|
#ifndef _Section
|
|
#ifndef __STRICT_ANSI__
|
|
#define _Section(s) __attribute__((__section__(s)))
|
|
#else
|
|
#define _Section(s)
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef __llvm__
|
|
#define initarray _Section(".init_array,\"a\",@init_array #")
|
|
#else
|
|
#define initarray _Section(".init_array")
|
|
#endif
|
|
|
|
/**
|
|
* Systemic suppressions.
|
|
*/
|
|
#ifndef __STRICT_ANSI__
|
|
#if defined(__GNUC__) || defined(__llvm__)
|
|
#pragma GCC diagnostic ignored "-Wsign-compare" /* lint needs to change */
|
|
#pragma GCC diagnostic ignored "-Wtype-limits" /* makes macros unsafe */
|
|
#pragma GCC diagnostic ignored "-Woverflow" /* also breaks macros */
|
|
#pragma GCC diagnostic ignored "-Wformat" /* forces only gnu pf */
|
|
#pragma GCC diagnostic ignored "-Wunused-parameter" /* extreme prejudice */
|
|
#pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce! */
|
|
#pragma GCC diagnostic ignored "-Wunused-variable" /* belongs in tidy */
|
|
#pragma GCC diagnostic ignored "-Wformat-extra-args" /* is also broken */
|
|
#pragma GCC diagnostic ignored "-Wparentheses" /* annoying tidy */
|
|
#pragma GCC diagnostic ignored "-Wdangling-else" /* come on tidy */
|
|
#ifndef __cplusplus
|
|
#pragma GCC diagnostic ignored "-Wimplicit-int"
|
|
#endif /* C++ */
|
|
#endif /* GCC || LLVM */
|
|
#if defined(__GNUC__) && !defined(__llvm__)
|
|
/* why we need authorization to name a variable `yn' */
|
|
#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
|
|
#pragma GCC diagnostic ignored "-Wfree-nonheap-object" /* broken #54202 */
|
|
#ifndef __cplusplus
|
|
#if __GNUC__ >= 6
|
|
#pragma GCC diagnostic ignored /* wut */ "-Wdiscarded-qualifiers"
|
|
#pragma GCC diagnostic ignored /* tidy */ "-Wunused-but-set-variable"
|
|
#pragma GCC diagnostic ignored /* tidy */ "-Wunused-but-set-parameter"
|
|
#endif /* GCC6+ */
|
|
#if __GNUC__ >= 8
|
|
#pragma GCC diagnostic ignored "-Wstringop-truncation"
|
|
#endif /* GCC8+ */
|
|
#if __GNUC__ + 0 >= 9
|
|
#pragma GCC diagnostic ignored /* "always true" breaks dce */ "-Waddress"
|
|
#endif /* GCC9+ */
|
|
#endif /* !C++ */
|
|
#endif /* GCC && !LLVM */
|
|
#ifdef __llvm__
|
|
#pragma clang diagnostic ignored \
|
|
"-Wincompatible-pointer-types-discards-qualifiers"
|
|
#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
|
|
#pragma clang diagnostic ignored "-Wparentheses-equality" /*-save-temps*/
|
|
#pragma clang diagnostic ignored "-Wunused-value" /*({-save-temps})*/
|
|
#pragma clang diagnostic ignored "-Wstring-plus-int" /* special ed */
|
|
#pragma clang diagnostic ignored "-Wunused-value" /* extreme prejudice */
|
|
#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
|
|
#pragma clang diagnostic ignored \
|
|
"-Wincompatible-pointer-types-discards-qualifiers"
|
|
#endif /* !GCC && LLVM */
|
|
#endif /* ANSI */
|
|
|
|
/**
|
|
* Elevate warnings of material consequence.
|
|
*
|
|
* These aren't stylistic in nature; but are perfectly fine to disable,
|
|
* assuming we're ok with the compiler simply generating a runtime crash
|
|
* instead. Otherwise what usually happens with these is that a weakness
|
|
* is introduced, important optimizations can't be performed; or worst
|
|
* of all: the code will need patching if ported to a toy or any machine
|
|
* designed by an engineer who hadn't understood John von Neumann at the
|
|
* time, e.g. 1's complement, big endian, under 32bit word size, etc.
|
|
*/
|
|
#ifndef __W__
|
|
#ifndef __STRICT_ANSI__
|
|
#if defined(__GNUC__) || defined(__llvm__)
|
|
#pragma GCC diagnostic error "-Wpointer-arith"
|
|
#pragma GCC diagnostic error "-Wnonnull"
|
|
#pragma GCC diagnostic error "-Wunused-result"
|
|
#pragma GCC diagnostic error "-Wuninitialized"
|
|
#pragma GCC diagnostic error "-Wstrict-aliasing"
|
|
#pragma GCC diagnostic error "-Wshift-negative-value"
|
|
#ifndef __cplusplus
|
|
#pragma GCC diagnostic error "-Wimplicit-function-declaration"
|
|
#if __GNUC__ >= 6
|
|
#pragma GCC diagnostic error "-Wincompatible-pointer-types"
|
|
#if __GNUC__ >= 8
|
|
#pragma GCC diagnostic error "-Wmultistatement-macros"
|
|
#pragma GCC diagnostic error "-Wpacked-not-aligned"
|
|
#pragma GCC diagnostic error "-Wcast-align=strict"
|
|
#pragma GCC diagnostic error "-Wif-not-aligned"
|
|
#endif /* GCC 8+ */
|
|
#endif /* GCC 6+ */
|
|
#endif /* __cplusplus */
|
|
#endif /* GCC || LLVM */
|
|
#if defined(__GNUC__) && !defined(__llvm__)
|
|
#pragma GCC diagnostic error "-Wwrite-strings"
|
|
#pragma GCC diagnostic error "-Wtrampolines"
|
|
#pragma GCC diagnostic error "-Wmaybe-uninitialized"
|
|
#pragma GCC diagnostic error "-Wredundant-decls"
|
|
#if __GNUC__ >= 6
|
|
#pragma GCC diagnostic error "-Wnonnull-compare"
|
|
#if !defined(MODE_DBG) && !defined(STACK_FRAME_UNLIMITED)
|
|
#pragma GCC diagnostic error "-Wframe-larger-than=4096"
|
|
#if __GNUC__ >= 9
|
|
#pragma GCC diagnostic error "-Walloca-larger-than=1024"
|
|
#pragma GCC diagnostic error "-Wvla-larger-than=1024"
|
|
#endif /* GCC 9+ */
|
|
#endif /* STACK_FRAME_UNLIMITED */
|
|
#elif __GNUC__ >= 9
|
|
#pragma GCC diagnostic error /* e.g. fabs not abs */ "-Wabsolute-value"
|
|
#endif /* GCC 6+ */
|
|
#endif /* GCC && !LLVM */
|
|
#ifdef __llvm__
|
|
#pragma clang diagnostic error "-Wassume"
|
|
#endif /* !GCC && LLVM */
|
|
#endif /* ANSI */
|
|
#endif /* -w */
|
|
|
|
/**
|
|
* Sets manual breakpoint.
|
|
* @see showcrashreports() for auto gdb attach
|
|
*/
|
|
#define DebugBreak() asm("int3")
|
|
|
|
#define VEIL(CONSTRAINT, EXPRESSION) \
|
|
({ \
|
|
autotype(EXPRESSION) VeiledValue = (EXPRESSION); \
|
|
asm("" : "=" CONSTRAINT ""(VeiledValue) : "0"(VeiledValue)); \
|
|
VeiledValue; \
|
|
})
|
|
|
|
#define CONCEAL(CONSTRAINT, EXPRESSION) \
|
|
({ \
|
|
autotype(EXPRESSION) VeiledValue = (EXPRESSION); \
|
|
asm volatile("" : "=" CONSTRAINT ""(VeiledValue) : "0"(VeiledValue)); \
|
|
VeiledValue; \
|
|
})
|
|
|
|
#define EXPROPRIATE(EXPRESSION) \
|
|
({ \
|
|
asm volatile("" ::"g"(EXPRESSION) : "memory"); \
|
|
0; \
|
|
})
|
|
|
|
/**
|
|
* Pulls another module, by symbol, into linkage.
|
|
* @note nop is discarded by ape/ape.lds
|
|
*/
|
|
#define YOINK(SYMBOL) \
|
|
do { \
|
|
_Static_assert(!typescompatible(typeof(SYMBOL), char[]), \
|
|
"Please YOINK(symbol), not YOINK(\"symbol\")"); \
|
|
asm(".pushsection .yoink\n\t" \
|
|
"nop\t%a0\n\t" \
|
|
".popsection" \
|
|
: /* no outputs */ \
|
|
: "X"(SYMBOL)); \
|
|
} while (0)
|
|
|
|
/**
|
|
* Pulls another module into linkage from top-level scope.
|
|
* @note nop is discarded by ape/ape.lds
|
|
*/
|
|
#define STATIC_YOINK(SYMBOLSTR) \
|
|
asm(".pushsection .yoink\n\tnop\t\"" SYMBOLSTR "\"\n\t.popsection")
|
|
|
|
/**
|
|
* Pulls source file into ZIP portion of binary.
|
|
* @see build/rules.mk which defines the wildcard build rule %.zip.o
|
|
*/
|
|
#if !defined(IM_FEELING_NAUGHTY) && !defined(__STRICT_ANSI__)
|
|
#define STATIC_YOINK_SOURCE(PATH) STATIC_YOINK(PATH)
|
|
#else
|
|
#define STATIC_YOINK_SOURCE(PATH)
|
|
#endif
|
|
|
|
/**
|
|
* Pulls source of object being compiled into zip.
|
|
* @note automates most compliance with gpl terms
|
|
* @see libc/zipos/zipcentraldir.S
|
|
* @see ape/ape.lds
|
|
*/
|
|
#ifdef __BASE_FILE__
|
|
STATIC_YOINK_SOURCE(__BASE_FILE__);
|
|
#endif
|
|
|
|
#define MACHINE_CODE_ANALYSIS_BEGIN_
|
|
#define MACHINE_CODE_ANALYSIS_END_
|