diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-05-02 21:43:13 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-05-02 22:54:16 +0200 |
commit | a108e12c505ab6d6a5577b6fb39166e049271221 (patch) | |
tree | f335aa190a97f47dd91c7da6ff5af0a9d372a398 /compat | |
parent | 518efccab147cae5b670c14ea1fc7b477f696a09 (diff) |
compat/assert: reduce executable size
Diffstat (limited to 'compat')
-rw-r--r-- | compat/assert.cpp | 80 | ||||
-rw-r--r-- | compat/assert.hpp | 100 |
2 files changed, 110 insertions, 70 deletions
diff --git a/compat/assert.cpp b/compat/assert.cpp new file mode 100644 index 00000000..279a08c0 --- /dev/null +++ b/compat/assert.cpp @@ -0,0 +1,80 @@ +#include "assert.hpp" +#include <cstdlib> +#include <cstdio> +#include <cstdarg> + +#ifdef __GNUG__ +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + +namespace floormat { + +namespace { + +template<bool DoPrefix, bool DoSourceLocation> +CORRADE_NEVER_INLINE +void fm_emit_debug_(const char* prefix, const char* file, int line, const char* fmt, va_list arg_ptr) +{ + std::fflush(stdout); + std::fflush(stderr); + if constexpr(DoPrefix) + std::fputs(prefix, stderr); + std::vfprintf(stderr, fmt, arg_ptr); + if constexpr(DoSourceLocation) + std::fprintf(stderr, " in %s:%d", file, line); + std::fputc('\n', stderr); + std::fflush(stderr); +} + +} // namespace + +void fm_emit_debug(const char* prefix, fm_FORMAT_ARG_MSVC const char* fmt, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, fmt); + fm_emit_debug_<true, false>(prefix, nullptr, 0, fmt, arg_ptr); + va_end(arg_ptr); +} + +void fm_emit_debug0(fm_FORMAT_ARG_MSVC const char* fmt, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, fmt); + fm_emit_debug_<false, false>(nullptr, nullptr, 0, fmt, arg_ptr); + va_end(arg_ptr); +} + +void CORRADE_NEVER_INLINE fm_emit_debug_loc(const char* prefix, const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, fmt); + fm_emit_debug_<true, true>(prefix, file, line, fmt, arg_ptr); + va_end(arg_ptr); +} + +void fm_emit_assert_fail(const char* expr, const char* file, int line) +{ + std::fflush(stdout); + std::fflush(stderr); + std::fprintf(stderr, "assertion failed: %s in %s:%d", expr, file, line); + std::fflush(stderr); + std::abort(); +} + +void fm_emit_abort(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, fmt); + fm_emit_debug_<true, true>("fatal: ", file, line, fmt, arg_ptr); + va_end(arg_ptr); + std::abort(); +} + +void fm_emit_abort() +{ + std::fflush(stdout); + std::fflush(stderr); + std::abort(); +} + +} // namespace floormat diff --git a/compat/assert.hpp b/compat/assert.hpp index 363d418b..b048f547 100644 --- a/compat/assert.hpp +++ b/compat/assert.hpp @@ -1,78 +1,43 @@ #pragma once -#include "defs.hpp" -#include <cstdlib> // todo speed up loading by moving printing into a .cpp file -#include <cstdio> // idem. - -namespace floormat::assert_detail { +//#include "defs.hpp" +#if defined __GNUG__ || defined __CLION_IDE__ +#define fm_FORMAT_ARG(n) __attribute__((format (gnu_printf, (n), (n+1)))) +#define fm_FORMAT_ARG_MSVC +#elif defined _MSC_VER +#include <sal.h> +#define fm_FORMAT_ARG(n) +#define fm_FORMAT_ARG_MSVC _Printf_format_string_ +#else +#define fm_FORMAT_ARG(n) +#define fm_FORMAT_ARG_MSVC +#endif +namespace floormat { -#define fm_EMIT_ABORT() do { std::fflush(stdout); std::fflush(stderr); ::std::abort(); } while (false) +void fm_emit_debug(const char* prefix, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(2); +void fm_emit_debug0(fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(1); +void fm_emit_debug_loc(const char* prefix, const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(4); +void fm_emit_debug_loc0(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(3); -} // namespace floormat::assert_detail +[[noreturn]] CORRADE_NEVER_INLINE void fm_emit_assert_fail(const char* expr, const char* file, int line); +[[noreturn]] CORRADE_NEVER_INLINE void fm_emit_abort(const char* file, int line, fm_FORMAT_ARG_MSVC const char* fmt, ...) fm_FORMAT_ARG(3); +[[noreturn]] CORRADE_NEVER_INLINE void fm_emit_abort(); +} // namespace floormat #ifdef __GNUG__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-macros" -#ifdef __clang__ -# define FM_KILL_PRINTF_WARN_1_2() \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wformat-nonliteral\"") -# define FM_KILL_PRINTF_WARN_2_2() _Pragma("clang diagnostic pop") -#else -#define FM_KILL_PRINTF_WARN_1_2() -#define FM_KILL_PRINTF_WARN_2_2() -#endif - -#define FM_KILL_PRINTF_WARN_1() \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wdouble-promotion\"") \ - FM_KILL_PRINTF_WARN_1_2() - -#define FM_KILL_PRINTF_WARN_2() _Pragma("GCC diagnostic pop") FM_KILL_PRINTF_WARN_2_2() -#else -#define FM_KILL_PRINTF_WARN_1() -#define FM_KILL_PRINTF_WARN_2() #endif -#define fm_EMIT_DEBUG2(pfx, ...) \ - do { \ - if (!std::is_constant_evaluated()) \ - { \ - if constexpr (sizeof(pfx) > 1) \ - std::fputs((pfx), stderr); \ - std::fflush(stderr); \ - FM_KILL_PRINTF_WARN_1() \ - std::fprintf(stderr, __VA_ARGS__); \ - FM_KILL_PRINTF_WARN_2() \ - } \ - } while (false) - -#define fm_EMIT_DEBUG(pfx, ...) \ - do { \ - if (!std::is_constant_evaluated()) \ - { \ - fm_EMIT_DEBUG2(pfx, __VA_ARGS__); \ - std::fputc('\n', stderr); \ - std::fflush(stderr); \ - } \ - } while (false) - -#define fm_abort(...) \ - do { \ - fm_EMIT_DEBUG2("fatal: ", __VA_ARGS__); \ - fm_EMIT_DEBUG("", " in %s:%d", __FILE__, __LINE__); \ - fm_EMIT_ABORT(); \ - } while (false) - -#define fm_assert(...) \ - do { \ - if (!(__VA_ARGS__)) /*NOLINT(*-simplify-boolean-expr)*/ [[unlikely]] { \ - fm_EMIT_DEBUG("", "assertion failed: %s in %s:%d", \ - #__VA_ARGS__, __FILE__, __LINE__); \ - fm_EMIT_ABORT(); \ - } \ - } while(false) +#define fm_assert(...) ((__VA_ARGS__) ? void() : ::floormat::fm_emit_assert_fail(#__VA_ARGS__, __FILE__, __LINE__)) +#define fm_abort(...) (::floormat::fm_emit_abort(__FILE__, __LINE__, __VA_ARGS__)) +#define fm_warn(...) (::floormat::fm_emit_debug("warning: ", __VA_ARGS__)) +#define fm_error(...) (::floormat::fm_emit_debug("error: ", __VA_ARGS__)) +#define fm_log(...) (::floormat::fm_emit_debug0(__VA_ARGS__)) +#define fm_debug(...) (::floormat::fm_emit_debug0(__VA_ARGS__)) +#define fm_debug_loc(pfx, ...) (::floormat::fm_emit_debug_loc(pfx, __FILE__, __LINE__,__VA_ARGS__)) +#define fm_debug_loc0(...) (::floormat::fm_emit_debug_loc0(__FILE__, __LINE__,__VA_ARGS__)) #ifndef FM_NO_DEBUG #define fm_debug_assert(...) fm_assert(__VA_ARGS__) @@ -80,11 +45,6 @@ namespace floormat::assert_detail { #define fm_debug_assert(...) void() #endif -#define fm_warn(...) fm_EMIT_DEBUG("warning: ", __VA_ARGS__) -#define fm_error(...) fm_EMIT_DEBUG("error: ", __VA_ARGS__) -#define fm_log(...) fm_EMIT_DEBUG("", __VA_ARGS__) -#define fm_debug(...) fm_EMIT_DEBUG("", __VA_ARGS__) - #define fm_warn_once(...) do { \ static bool _fm_once_flag = false; \ if (!_fm_once_flag) [[unlikely]] { \ @@ -106,7 +66,7 @@ namespace floormat::assert_detail { ERR_nospace << #__VA_ARGS__; \ ERR_nospace << " expected: " << a; \ ERR_nospace << " actual: " << b; \ - fm_EMIT_ABORT(); \ + fm_emit_abort(); \ } \ })(__VA_ARGS__) |