summaryrefslogtreecommitdiffhomepage
path: root/compat
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-05-02 21:43:13 +0200
committerStanislaw Halik <sthalik@misaki.pl>2024-05-02 22:54:16 +0200
commita108e12c505ab6d6a5577b6fb39166e049271221 (patch)
treef335aa190a97f47dd91c7da6ff5af0a9d372a398 /compat
parent518efccab147cae5b670c14ea1fc7b477f696a09 (diff)
compat/assert: reduce executable size
Diffstat (limited to 'compat')
-rw-r--r--compat/assert.cpp80
-rw-r--r--compat/assert.hpp100
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__)