From a108e12c505ab6d6a5577b6fb39166e049271221 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Thu, 2 May 2024 21:43:13 +0200 Subject: compat/assert: reduce executable size --- bench/critter.cpp | 6 +--- compat/assert.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++ compat/assert.hpp | 100 ++++++++++++++++------------------------------------- editor/inspect.cpp | 3 +- editor/save.cpp | 9 ++--- main/draw.cpp | 2 +- src/script.inl | 14 +++----- src/timer-ns.cpp | 1 + test/critter.cpp | 5 +-- 9 files changed, 126 insertions(+), 94 deletions(-) create mode 100644 compat/assert.cpp diff --git a/bench/critter.cpp b/bench/critter.cpp index 3f8505c1..dc60a71a 100644 --- a/bench/critter.cpp +++ b/bench/critter.cpp @@ -138,11 +138,7 @@ bool run(world& w, const function_view& make_dt, if (b) [[likely]] return false; else - { - fm_assert(false); - fm_EMIT_DEBUG("", "assertion failed: false in %s:%d", file, line); - fm_EMIT_ABORT(); - } + fm_emit_assert_fail("false", file, line); }; for (i = 0; true; i++) 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 +#include +#include + +#ifdef __GNUG__ +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + +namespace floormat { + +namespace { + +template +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_(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_(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_(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_("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 // todo speed up loading by moving printing into a .cpp file -#include // 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 +#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__) diff --git a/editor/inspect.cpp b/editor/inspect.cpp index 470c5bd2..e7d8878a 100644 --- a/editor/inspect.cpp +++ b/editor/inspect.cpp @@ -3,6 +3,8 @@ #include "compat/defs.hpp" #include "entity/accessor.hpp" #include "imgui-raii.hpp" +#include +#include #include #include #include @@ -10,7 +12,6 @@ #include #include #include -#include namespace floormat::entities { diff --git a/editor/save.cpp b/editor/save.cpp index ef14c11c..2c073e01 100644 --- a/editor/save.cpp +++ b/editor/save.cpp @@ -2,6 +2,7 @@ #include "floormat/main.hpp" #include "src/world.hpp" #include "loader/loader.hpp" +#include #include #include @@ -36,10 +37,10 @@ void app::do_quicksave() world.collect(true); if (Path::exists(tmp)) Path::remove(tmp); - fputs("quicksave... ", stderr); fflush(stderr); + std::fputs("quicksave... ", stderr); std::fflush(stderr); world.serialize(tmp); Path::move(tmp, file); - fputs("done\n", stderr); fflush(stderr); + std::fputs("done\n", stderr); std::fflush(stderr); } void app::do_quickload() @@ -52,9 +53,9 @@ void app::do_quickload() fm_warn("no quicksave"); return; } - fputs("quickload... ", stderr); fflush(stderr); + std::fputs("quickload... ", stderr); std::fflush(stderr); reset_world(world::deserialize(file, loader_policy::warn)); - fputs("done\n", stderr); fflush(stderr); + std::fputs("done\n", stderr); std::fflush(stderr); } void app::do_new_file() diff --git a/main/draw.cpp b/main/draw.cpp index e5fb9e69..802a4e9d 100644 --- a/main/draw.cpp +++ b/main/draw.cpp @@ -36,7 +36,7 @@ void main_impl::do_update(const Ns& dtʹ) value = secs; #endif if (secs > 35e-3f /* && !dt_expected.do_sleep */) [[likely]] - fm_debug("%zu frame took %.2f milliseconds", bad_frame_counter++, (double)(secs*1e3)); + fm_debug("%zu frame took %.2f milliseconds", bad_frame_counter++, (double)secs*1e3); } else swapBuffers(); diff --git a/src/script.inl b/src/script.inl index e5057039..a6c93588 100644 --- a/src/script.inl +++ b/src/script.inl @@ -63,15 +63,11 @@ Script::Script(): ptr{nullptr}, _state{script_lifecycle::no_init} template void Script::_assert_state(script_lifecycle s, const char* file, int line) { - if (_state != s) - { - fm_EMIT_DEBUG2("fatal: ", - "invalid state transition from '%s' to '%s'", - base_script::state_name(_state).data(), - base_script::state_name(s).data()); - fm_EMIT_DEBUG("", " in %s:%d", file, line); - fm_EMIT_ABORT(); - } + if (_state != s) [[unlikely]] + fm_emit_abort(file, line, + "invalid state transition from '%s' to '%s'", + base_script::state_name(_state).data(), + base_script::state_name(s).data()); } template script_lifecycle Script::state() const { return _state; } diff --git a/src/timer-ns.cpp b/src/timer-ns.cpp index e781e66c..196888d0 100644 --- a/src/timer-ns.cpp +++ b/src/timer-ns.cpp @@ -2,6 +2,7 @@ #include "compat/assert.hpp" #include "compat/debug.hpp" #include +#include #include #include diff --git a/test/critter.cpp b/test/critter.cpp index d9f50205..950e2d01 100644 --- a/test/critter.cpp +++ b/test/critter.cpp @@ -147,10 +147,7 @@ bool run(world& w, const function_view& make_dt, if (b) [[likely]] return false; else - { - fm_EMIT_DEBUG("", "assertion failed: false in %s:%d", file, line); - fm_EMIT_ABORT(); - } + fm_emit_assert_fail("false", file, line); }; for (i = 0; true; i++) -- cgit v1.2.3