2017-10-04 07:07:04 +02:00
|
|
|
/*
|
2019-08-03 19:43:48 +02:00
|
|
|
* This software is licensed under the terms of the MIT License.
|
2017-10-04 07:07:04 +02:00
|
|
|
* See COPYING for further information.
|
|
|
|
* ---
|
2024-05-16 23:30:41 +02:00
|
|
|
* Copyright (c) 2011-2024, Lukas Weber <laochailan@web.de>.
|
|
|
|
* Copyright (c) 2012-2024, Andrei Alexeyev <akari@taisei-project.org>.
|
2017-10-04 07:07:04 +02:00
|
|
|
*/
|
|
|
|
|
2021-08-12 23:09:01 +02:00
|
|
|
#pragma once
|
2017-11-25 20:45:11 +01:00
|
|
|
#include "taisei.h"
|
2017-10-04 07:07:04 +02:00
|
|
|
|
2019-03-18 05:41:12 +01:00
|
|
|
// Common standard library headers
|
2024-05-17 04:41:28 +02:00
|
|
|
#include <complex.h> // IWYU pragma: export
|
|
|
|
#include <ctype.h> // IWYU pragma: export
|
|
|
|
#include <float.h> // IWYU pragma: export
|
|
|
|
#include <inttypes.h> // IWYU pragma: export
|
|
|
|
#include <limits.h> // IWYU pragma: export
|
|
|
|
#include <math.h> // IWYU pragma: export
|
|
|
|
#include <stdalign.h> // IWYU pragma: export
|
|
|
|
#include <stdbool.h> // IWYU pragma: export
|
|
|
|
#include <stddef.h> // IWYU pragma: export
|
|
|
|
#include <stdint.h> // IWYU pragma: export
|
|
|
|
#include <stdlib.h> // IWYU pragma: export
|
|
|
|
#include <stdnoreturn.h> // IWYU pragma: export
|
|
|
|
#include <string.h> // IWYU pragma: export
|
2018-04-12 16:08:48 +02:00
|
|
|
|
2023-03-26 03:08:33 +02:00
|
|
|
// clang defines this too
|
|
|
|
#ifndef __GNUC__
|
|
|
|
#warning Unsupported compiler. Only GCC and Clang are officially supported. Expect errors.
|
|
|
|
#endif
|
|
|
|
|
2022-09-01 05:50:55 +02:00
|
|
|
#ifdef TAISEI_BUILDCONF_REL_SRC_DIR
|
|
|
|
#define _TAISEI_SRC_FILE ((const char *)__FILE__ + sizeof(TAISEI_BUILDCONF_REL_SRC_DIR) - 1)
|
|
|
|
#else
|
|
|
|
#define _TAISEI_SRC_FILE __FILE__
|
|
|
|
#endif
|
|
|
|
|
2024-05-17 04:41:28 +02:00
|
|
|
#include "util/assert.h" // IWYU pragma: export
|
2019-02-02 12:25:06 +01:00
|
|
|
|
2018-07-04 10:55:33 +02:00
|
|
|
#ifdef __FAST_MATH__
|
|
|
|
#error -ffast-math is prohibited
|
|
|
|
#endif
|
|
|
|
|
2018-05-13 15:44:06 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
// Include the god-awful windows.h header here so that we can fight the obnoxious namespace pollution it introduces.
|
|
|
|
// We obviously don't need it in every source file, but it's easier to do it globally and early than to try to infer
|
|
|
|
// just where down the maze of includes some of our dependencies happens to smuggle it in.
|
|
|
|
//
|
|
|
|
// *sigh*
|
|
|
|
//
|
|
|
|
// Goddamn it.
|
|
|
|
|
|
|
|
// Make sure we get the "unicode" (actually UTF-16) versions of win32 APIs; it defaults to legacy crippled ones.
|
|
|
|
#ifndef UNICODE
|
2024-09-05 05:54:03 +02:00
|
|
|
#define UNICODE 1
|
2018-05-13 15:44:06 +02:00
|
|
|
#endif
|
|
|
|
#ifndef _UNICODE
|
2024-09-05 05:54:03 +02:00
|
|
|
#define _UNICODE 1
|
2018-05-13 15:44:06 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Ask windows.h to include a little bit less of the stupid crap we'll never use.
|
|
|
|
// Some of it actually clashes with our names.
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#define NOGDI
|
2018-07-28 12:53:12 +02:00
|
|
|
#define NOMINMAX
|
2018-05-13 15:44:06 +02:00
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
// far/near pointers are obviously very relevant for modern CPUs and totally deserve their very own, unprefixed keywords!
|
|
|
|
#undef near
|
|
|
|
#undef far
|
2021-07-10 20:28:01 +02:00
|
|
|
|
|
|
|
// fixup other random name clashes
|
|
|
|
#define mouse_event _taisei_mouse_event
|
2018-05-13 15:44:06 +02:00
|
|
|
#endif
|
|
|
|
|
2018-05-15 02:27:25 +02:00
|
|
|
// This macro should be provided by stddef.h, but in practice it sometimes is not.
|
2018-04-12 16:08:48 +02:00
|
|
|
#ifndef offsetof
|
2023-03-26 03:08:33 +02:00
|
|
|
#define offsetof(type, field) __builtin_offsetof(type, field)
|
2018-04-12 16:08:48 +02:00
|
|
|
#endif
|
|
|
|
|
2019-02-02 12:25:06 +01:00
|
|
|
#define PRAGMA(p) _Pragma(#p)
|
2023-03-26 03:14:07 +02:00
|
|
|
#define UNREACHABLE ({ \
|
|
|
|
assert(0, "This code should never be reachable"); \
|
|
|
|
__builtin_unreachable(); \
|
|
|
|
})
|
2023-03-26 03:08:33 +02:00
|
|
|
#define DIAGNOSTIC(x) PRAGMA(GCC diagnostic x)
|
2019-02-02 12:25:06 +01:00
|
|
|
|
2023-03-26 03:08:33 +02:00
|
|
|
#if defined(__clang__)
|
2019-11-22 04:37:11 +01:00
|
|
|
#define DIAGNOSTIC_GCC(x)
|
2023-03-26 03:08:33 +02:00
|
|
|
#define DIAGNOSTIC_CLANG(x) PRAGMA(clang diagnostic x)
|
2017-10-04 07:07:04 +02:00
|
|
|
#else
|
2023-03-26 03:08:33 +02:00
|
|
|
#define DIAGNOSTIC_GCC(x) PRAGMA(GCC diagnostic x)
|
|
|
|
#define DIAGNOSTIC_CLANG(x)
|
2018-04-12 16:08:48 +02:00
|
|
|
#endif
|
|
|
|
|
2023-03-26 03:08:33 +02:00
|
|
|
#define LIKELY(x) __builtin_expect((bool)(x), 1)
|
|
|
|
#define UNLIKELY(x) __builtin_expect((bool)(x), 0)
|
|
|
|
|
2018-04-12 16:08:48 +02:00
|
|
|
#ifndef __has_attribute
|
2023-03-26 03:08:33 +02:00
|
|
|
// FIXME: maybe should be 0?
|
|
|
|
#define __has_attribute(attr) 1
|
2017-10-04 07:07:04 +02:00
|
|
|
#endif
|
|
|
|
|
2020-01-23 19:49:04 +01:00
|
|
|
#ifndef __has_feature
|
|
|
|
#define __has_feature(feature) 0
|
|
|
|
#endif
|
|
|
|
|
2019-02-02 12:25:06 +01:00
|
|
|
#undef ASSUME
|
|
|
|
|
|
|
|
#ifdef __has_builtin
|
|
|
|
#if __has_builtin(__builtin_assume)
|
|
|
|
#define ASSUME(x) __builtin_assume(x)
|
|
|
|
#endif
|
2020-08-15 13:51:12 +02:00
|
|
|
|
|
|
|
#if __has_builtin(__builtin_popcount)
|
|
|
|
#undef TAISEI_BUILDCONF_HAVE_BUILTIN_POPCOUNT
|
|
|
|
#define TAISEI_BUILDCONF_HAVE_BUILTIN_POPCOUNT 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if __has_builtin(__builtin_popcountll)
|
|
|
|
#undef TAISEI_BUILDCONF_HAVE_BUILTIN_POPCOUNTLL
|
|
|
|
#define TAISEI_BUILDCONF_HAVE_BUILTIN_POPCOUNTLL 1
|
|
|
|
#endif
|
2019-02-02 12:25:06 +01:00
|
|
|
#endif
|
|
|
|
|
2023-03-26 03:08:33 +02:00
|
|
|
#if !defined(ASSUME)
|
2019-02-02 12:25:06 +01:00
|
|
|
#define ASSUME(x) do { if(!(x)) { UNREACHABLE; } } while(0)
|
|
|
|
#endif
|
|
|
|
|
2018-05-15 02:27:25 +02:00
|
|
|
// On windows, use the MinGW implementations of printf and friends instead of the crippled mscrt ones.
|
2017-12-24 16:54:06 +01:00
|
|
|
#ifdef __USE_MINGW_ANSI_STDIO
|
2018-01-12 19:26:07 +01:00
|
|
|
#define FORMAT_ATTR __MINGW_PRINTF_FORMAT
|
2017-10-04 07:07:04 +02:00
|
|
|
#else
|
2018-01-12 19:26:07 +01:00
|
|
|
#define FORMAT_ATTR printf
|
2017-10-04 07:07:04 +02:00
|
|
|
#endif
|
2018-04-12 16:08:48 +02:00
|
|
|
|
|
|
|
#undef uint
|
|
|
|
typedef unsigned int uint;
|
|
|
|
|
|
|
|
#undef ushort
|
|
|
|
typedef unsigned short ushort;
|
|
|
|
|
|
|
|
#undef ulong
|
|
|
|
typedef unsigned long ulong;
|
|
|
|
|
|
|
|
#undef uchar
|
|
|
|
typedef unsigned char uchar;
|
|
|
|
|
|
|
|
#undef schar
|
|
|
|
typedef signed char schar;
|
|
|
|
|
2019-11-22 04:37:11 +01:00
|
|
|
#undef real
|
2020-05-09 08:25:38 +02:00
|
|
|
typedef double real;
|
2019-11-22 04:37:11 +01:00
|
|
|
|
2020-05-09 08:31:20 +02:00
|
|
|
#undef cmplxf
|
|
|
|
typedef _Complex float cmplxf;
|
2019-11-22 04:37:11 +01:00
|
|
|
|
|
|
|
#undef cmplx
|
2020-05-09 08:31:20 +02:00
|
|
|
typedef _Complex double cmplx;
|
2019-11-22 04:37:11 +01:00
|
|
|
|
2018-05-15 02:27:25 +02:00
|
|
|
// These definitions are common but non-standard, so we provide our own
|
|
|
|
#undef M_PI
|
|
|
|
#undef M_PI_2
|
|
|
|
#undef M_PI_4
|
|
|
|
#undef M_E
|
|
|
|
#define M_PI 3.14159265358979323846
|
|
|
|
#define M_PI_2 1.57079632679489661923
|
|
|
|
#define M_PI_4 0.78539816339744830962
|
|
|
|
#define M_E 2.7182818284590452354
|
|
|
|
|
2019-12-18 14:33:36 +01:00
|
|
|
#ifndef TAISEI_BUILDCONF_HAVE_MAX_ALIGN_T
|
|
|
|
#if TAISEI_BUILDCONF_MALLOC_ALIGNMENT <= 0
|
|
|
|
#warning malloc alignment is unknown, assuming 8
|
|
|
|
#undef TAISEI_BUILDCONF_MALLOC_ALIGNMENT
|
|
|
|
#define TAISEI_BUILDCONF_MALLOC_ALIGNMENT 8
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#undef max_align_t
|
|
|
|
#define max_align_t _fake_max_align_t
|
|
|
|
typedef struct { alignas(TAISEI_BUILDCONF_MALLOC_ALIGNMENT) char a; } max_align_t;
|
2019-02-22 00:56:48 +01:00
|
|
|
#endif
|
|
|
|
|
2019-12-11 10:25:57 +01:00
|
|
|
// polyfill CMPLX macros
|
2024-05-17 04:41:28 +02:00
|
|
|
#include "compat_cmplx.h" // IWYU pragma: export
|
2018-06-29 23:36:51 +02:00
|
|
|
|
2018-04-12 16:08:48 +02:00
|
|
|
/*
|
|
|
|
* Abstract away the nasty GNU attribute syntax.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Function is a hot spot.
|
|
|
|
#define attr_hot \
|
|
|
|
__attribute__ ((hot))
|
|
|
|
|
|
|
|
// Function has no side-effects.
|
|
|
|
#define attr_pure \
|
|
|
|
__attribute__ ((pure))
|
|
|
|
|
|
|
|
// Function has no side-effects, return value depends on arguments only.
|
|
|
|
// Must not take pointer parameters, must not return void.
|
|
|
|
#define attr_const \
|
|
|
|
__attribute__ ((const))
|
|
|
|
|
|
|
|
// Function never returns NULL.
|
|
|
|
#define attr_returns_nonnull \
|
|
|
|
__attribute__ ((returns_nonnull))
|
|
|
|
|
|
|
|
// Function must be called with NULL as the last argument (for varargs functions).
|
|
|
|
#define attr_sentinel \
|
|
|
|
__attribute__ ((sentinel))
|
|
|
|
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
// Symbol is meant to be possibly unused.
|
2018-04-12 16:08:48 +02:00
|
|
|
#define attr_unused \
|
|
|
|
__attribute__ ((unused))
|
|
|
|
|
Emscripten compatibility (#161)
* Major refactoring of the main loop(s) and control flow (WIP)
run_at_fps() is gone 🦀
Instead of nested blocking event loops, there is now an eventloop API
that manages an explicit stack of scenes. This makes Taisei a lot more
portable to async environments where spinning a loop forever without
yielding control simply is not an option, and that is the entire point
of this change.
A prime example of such an environment is the Web (via emscripten).
Taisei was able to run there through a terrible hack: inserting
emscripten_sleep calls into the loop, which would yield to the browser.
This has several major drawbacks: first of all, every function that
could possibly call emscripten_sleep must be compiled into a special
kind of bytecode, which then has to be interpreted at runtime, *much*
slower than JITed WebAssembly. And that includes *everything* down the
call stack, too! For more information, see
https://emscripten.org/docs/porting/emterpreter.html
Even though that method worked well enough for experimenting, despite
suboptimal performance, there is another obvious drawback:
emscripten_sleep is implemented via setTimeout(), which can be very
imprecise and is generally not reliable for fluid animation. Browsers
actually have an API specifically for that use case:
window.requestAnimationFrame(), but Taisei's original blocking control
flow style is simply not compatible with it. Emscripten exposes this API
with its emscripten_set_main_loop(), which the eventloop backend now
uses on that platform.
Unfortunately, C is still C, with no fancy closures or coroutines.
With blocking calls into menu/scene loops gone, the control flow is
reimplemented via so-called (pun intended) "call chains". That is
basically an euphemism for callback hell. With manual memory management
and zero type-safety. Not that the menu system wasn't shitty enough
already. I'll just keep telling myself that this is all temporary and
will be replaced with scripts in v1.4.
* improve build system for emscripten + various fixes
* squish menu bugs
* improve emscripten event loop; disable EMULATE_FUNCTION_POINTER_CASTS
Note that stock freetype does not work without
EMULATE_FUNCTION_POINTER_CASTS; use a patched version from the
"emscripten" branch here:
https://github.com/taisei-project/freetype2/tree/emscripten
* Enable -Wcast-function-type
Calling functions through incompatible pointers is nasal demons and
doesn't work in WASM.
* webgl: workaround a crash on some browsers
* emscripten improvements:
* Persist state (config, progress, replays, ...) in local IndexDB
* Simpler HTML shell (temporary)
* Enable more optimizations
* fix build if validate_glsl=false
* emscripten: improve asset packaging, with local cache
Note that even though there are rules to build audio bundles, audio
does *not* work yet. It looks like SDL2_mixer can not work without
threads, which is a problem. Yet another reason to write an OpenAL
backend - emscripten supports that natively.
* emscripten: customize the html shell
* emscripten: force "show log" checkbox unchecked initially
* emscripten: remove quit shortcut from main menu (since there's no quit)
* emscripten: log area fixes
* emscripten/webgl: workaround for fullscreen viewport issue
* emscripten: implement frameskip
* emscripter: improve framerate limiter
* align List to at least 8 bytes (shut up warnings)
* fix non-emscripten builds
* improve fullscreen handling, mainly for emscripten
* Workaround to make audio work in chromium
emscripten-core/emscripten#6511
* emscripten: better vsync handling; enable vsync & disable fxaa by default
2019-03-09 20:32:32 +01:00
|
|
|
// Symbol should be emitted even if it appears to be unused.
|
|
|
|
#define attr_used \
|
|
|
|
__attribute__ ((used))
|
|
|
|
|
2018-04-12 16:08:48 +02:00
|
|
|
// Function or type is deprecated and should not be used.
|
|
|
|
#define attr_deprecated(msg) \
|
|
|
|
__attribute__ ((deprecated(msg)))
|
|
|
|
|
|
|
|
// Function parameters at specified positions must not be NULL.
|
|
|
|
#define attr_nonnull(...) \
|
|
|
|
__attribute__ ((nonnull(__VA_ARGS__)))
|
|
|
|
|
2020-01-23 01:23:35 +01:00
|
|
|
// All pointer parameters must not be NULL.
|
|
|
|
#define attr_nonnull_all \
|
|
|
|
__attribute__ ((nonnull))
|
|
|
|
|
2018-04-12 16:08:48 +02:00
|
|
|
// The return value of this function must not be ignored.
|
|
|
|
#define attr_nodiscard \
|
|
|
|
__attribute__ ((warn_unused_result))
|
|
|
|
|
|
|
|
// Function takes a printf-style format string and variadic arguments.
|
|
|
|
#define attr_printf(fmt_index, firstarg_index) \
|
|
|
|
__attribute__ ((format(FORMAT_ATTR, fmt_index, firstarg_index)))
|
|
|
|
|
|
|
|
// Function must be inlined regardless of optimization settings.
|
|
|
|
#define attr_must_inline \
|
|
|
|
__attribute__ ((always_inline))
|
|
|
|
|
2019-04-12 10:36:40 +02:00
|
|
|
// Function returns a pointer aligned to x bytes
|
|
|
|
#define attr_returns_aligned(x) \
|
|
|
|
__attribute__ ((assume_aligned(x)))
|
|
|
|
|
|
|
|
// Function returns a pointer aligned the same as max_align_t
|
|
|
|
#define attr_returns_max_aligned \
|
|
|
|
attr_returns_aligned(alignof(max_align_t))
|
|
|
|
|
2019-08-04 00:29:41 +02:00
|
|
|
// Shorthand: always returns non-null pointer aligned to max_align_t; no discard.
|
|
|
|
#define attr_returns_allocated \
|
|
|
|
attr_returns_nonnull attr_returns_max_aligned attr_nodiscard
|
|
|
|
|
2018-04-12 16:08:48 +02:00
|
|
|
// Structure must not be initialized with an implicit (non-designated) initializer.
|
2023-01-08 23:54:01 +01:00
|
|
|
#if __has_attribute(designated_init) && defined(TAISEI_BUILDCONF_HAVE_ATTR_DESIGNATED_INIT)
|
2018-04-12 16:08:48 +02:00
|
|
|
#define attr_designated_init \
|
|
|
|
__attribute__ ((designated_init))
|
|
|
|
#else
|
|
|
|
#define attr_designated_init
|
|
|
|
#endif
|
2019-01-23 21:10:43 +01:00
|
|
|
|
2020-04-06 03:30:52 +02:00
|
|
|
// Function returns a pointer that can't alias any other pointer when the function returns.
|
|
|
|
// Storage pointed at doesn't contain pointers to any valid objects.
|
|
|
|
#define attr_malloc \
|
|
|
|
__attribute__ ((malloc))
|
|
|
|
|
2024-08-02 15:33:47 +02:00
|
|
|
#ifdef __clang__
|
|
|
|
#undef TAISEI_BUILDCONF_HAVE_ATTR_MALLOC_WITH_ARGS
|
|
|
|
#endif
|
|
|
|
|
2023-01-08 23:54:01 +01:00
|
|
|
// Function returns a pointer that must be 'freed' with the specified deallocator function
|
|
|
|
#ifdef TAISEI_BUILDCONF_HAVE_ATTR_MALLOC_WITH_ARGS
|
|
|
|
#define attr_dealloc(deallocator, arg_index) \
|
|
|
|
__attribute__ ((malloc(deallocator, arg_index)))
|
|
|
|
#else
|
|
|
|
#define attr_dealloc(deallocator, arg_index)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// With one argument n: function returns a pointer to object whose size is specified by the
|
|
|
|
// nth argument.
|
|
|
|
// With two arguments n, m: function returns a pointer to object whose size is specified by the
|
|
|
|
// product of nth and mth arguments.
|
|
|
|
#define attr_alloc_size(...) \
|
|
|
|
__attribute__ ((alloc_size(__VA_ARGS__)))
|
|
|
|
|
|
|
|
// Function returns a pointer aligned to a byte boundary specified by nth argument
|
|
|
|
#define attr_alloc_align(arg_index) \
|
|
|
|
__attribute__ ((alloc_align(arg_index)))
|
|
|
|
|
2020-04-06 03:30:52 +02:00
|
|
|
|
2020-03-17 09:09:49 +01:00
|
|
|
#define INLINE static inline attr_must_inline __attribute__((gnu_inline))
|
2019-08-03 18:47:21 +02:00
|
|
|
|
2021-08-12 16:12:40 +02:00
|
|
|
#define ASSUME_ALIGNED(expr, alignment) ({ \
|
|
|
|
static_assert(__builtin_constant_p(alignment), ""); \
|
2023-01-08 23:46:37 +01:00
|
|
|
auto _assume_aligned_ptr = (expr); \
|
2021-08-12 16:12:40 +02:00
|
|
|
assert(((uintptr_t)_assume_aligned_ptr & ((alignment) - 1)) == 0); \
|
|
|
|
__builtin_assume_aligned(_assume_aligned_ptr, (alignment)); \
|
|
|
|
})
|
2019-02-02 12:25:06 +01:00
|
|
|
|
2020-04-17 09:18:53 +02:00
|
|
|
#define UNION_CAST(_from_type, _to_type, _expr) \
|
|
|
|
((union { _from_type f; _to_type t; }) { .f = (_expr) }).t
|
|
|
|
|
2019-02-02 12:25:06 +01:00
|
|
|
#define CASTPTR_ASSUME_ALIGNED(expr, type) ((type*)ASSUME_ALIGNED((expr), alignof(type)))
|
|
|
|
|
2021-08-12 16:12:40 +02:00
|
|
|
#define NOT_NULL(expr) ({ \
|
2023-01-08 23:46:37 +01:00
|
|
|
auto _assume_not_null_ptr = (expr); \
|
2021-08-12 16:12:40 +02:00
|
|
|
assume(_assume_not_null_ptr != NULL); \
|
|
|
|
_assume_not_null_ptr; \
|
|
|
|
})
|
2020-03-08 01:34:36 +01:00
|
|
|
|
2019-08-02 20:38:33 +02:00
|
|
|
#ifdef __SWITCH__
|
|
|
|
#include "../arch_switch.h"
|
|
|
|
#define atexit nxAtExit
|
|
|
|
#define exit nxExit
|
|
|
|
#define abort nxAbort
|
|
|
|
#endif
|
|
|
|
|
2019-11-13 01:24:01 +01:00
|
|
|
#ifdef RNG_API_CHECK
|
|
|
|
#define _Generic(ignore, ...) _Generic(0, __VA_ARGS__)
|
|
|
|
#endif
|
|
|
|
|
2020-01-23 19:49:04 +01:00
|
|
|
#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
|
|
|
|
#define ADDRESS_SANITIZER
|
|
|
|
#endif
|
2023-01-08 23:46:37 +01:00
|
|
|
|
|
|
|
// `auto` for type inference is standardized in C23 based on GCC's __auto_type semantics.
|
|
|
|
// We want to have it now, and we don't care about the useless original purpose of C's `auto`.
|
|
|
|
// from __future__ import auto
|
|
|
|
#define auto __auto_type
|