From 15cd0f04612c90292792c4d123ebe84bf4bf93a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 24 Jun 2022 14:44:02 +0200 Subject: [PATCH 1/3] gmacros: Provide platform-independent G_ALWAYS_INLINE and G_NO_INLINE We had gcc-only implementations for them while both can be used in all the supported platforms we have. So let's just provide generic definitions, while we keep the old ones for both consistency and retro-compatibility. --- docs/reference/glib/glib-sections.txt | 5 ++ glib/gmacros.h | 99 +++++++++++++++++++++++++++ glib/tests/cxx.cpp | 25 +++++++ 3 files changed, 129 insertions(+) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 8dcc251a4..38b35386e 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -516,6 +516,10 @@ G_CONST_RETURN G_NORETURN G_NORETURN_FUNCPTR + +G_ALWAYS_INLINE +G_NO_INLINE + G_N_ELEMENTS @@ -782,6 +786,7 @@ g_macro__has_attribute g_macro__has_builtin g_macro__has_feature g_macro__has_extension +g_macro__has_attribute___always_inline__ g_macro__has_attribute___alloc_size__ g_macro__has_attribute___const__ g_macro__has_attribute___deprecated__ diff --git a/glib/gmacros.h b/glib/gmacros.h index 8001a448e..218ee4f25 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -212,6 +212,9 @@ * Declaring a function as `noinline` prevents the function from being * considered for inlining. * + * This macro is provided for retro-compatibility and will be eventually + * deprecated, but %G_NO_INLINE should be used instead. + * * The attribute may be placed before the declaration or definition, * right before the `static` keyword. * @@ -228,6 +231,8 @@ * [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noinline-function-attribute) * for more details. * + * See also: %G_NO_INLINE, %G_ALWAYS_INLINE. + * * Since: 2.58 */ /* Note: We can’t annotate this with GLIB_AVAILABLE_MACRO_IN_2_58 because it’s @@ -1069,6 +1074,100 @@ GLIB_AVAILABLE_MACRO_IN_2_68 #endif +/** + * G_ALWAYS_INLINE: + * + * Expands to the GNU C `always_inline` or MSVC `__forceinline` function + * attribute depending on the compiler. It is used for declaring functions + * as always inlined, ignoring the compiler optimization levels. + * + * The attribute may be placed before the declaration or definition, + * right before the `static` keyword. + * + * |[ + * G_ALWAYS_INLINE + * static int + * do_inline_this (void) + * { + * ... + * } + * ]| + * + * See the + * [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-always_005finline-function-attribute) + * and the + * [MSVC documentation](https://docs.microsoft.com/en-us/visualstudio/misc/inline-inline-forceinline) + * + * Since: 2.74 + */ +/* Note: We can’t annotate this with GLIB_AVAILABLE_MACRO_IN_2_74 because it’s + * used within the GLib headers in function declarations which are always + * evaluated when a header is included. This results in warnings in third party + * code which includes glib.h, even if the third party code doesn’t use the new + * macro itself. */ +#if g_macro__has_attribute(__always_inline__) +# if defined (__cplusplus) && __cplusplus >= 201103L + /* Use ISO C++11 syntax when the compiler supports it. */ +# define G_ALWAYS_INLINE [[gnu::always_inline]] +# else +# define G_ALWAYS_INLINE __attribute__ ((__always_inline__)) +# endif +#elif defined (_MSC_VER) + /* Use MSVC specific syntax. */ +# define G_ALWAYS_INLINE __forceinline +#else +# define G_ALWAYS_INLINE /* empty */ +#endif + +/** + * G_NO_INLINE: + * + * Expands to the GNU C or MSVC `noinline` function attribute + * depending on the compiler. It is used for declaring functions + * preventing from being considered for inlining. + * + * Note that %G_NO_INLINE supersedes the previous %G_GNUC_NO_INLINE + * macro, which will eventually be deprecated. + * %G_NO_INLINE supports more platforms. + * + * The attribute may be placed before the declaration or definition, + * right before the `static` keyword. + * + * |[ + * G_NO_INLINE + * static int + * do_not_inline_this (void) + * { + * ... + * } + * ]| + * + * Since: 2.74 + */ +/* Note: We can’t annotate this with GLIB_AVAILABLE_MACRO_IN_2_74 because it’s + * used within the GLib headers in function declarations which are always + * evaluated when a header is included. This results in warnings in third party + * code which includes glib.h, even if the third party code doesn’t use the new + * macro itself. */ +#if g_macro__has_attribute(__noinline__) +# if defined (__cplusplus) && __cplusplus >= 201103L + /* Use ISO C++11 syntax when the compiler supports it. */ +# define G_NO_INLINE [[gnu::noinline]] +# else +# define G_NO_INLINE __attribute__ ((__noinline__)) +# endif +#elif defined (_MSC_VER) && (1200 <= _MSC_VER) + /* Use MSVC specific syntax. */ +# if defined (__cplusplus) && __cplusplus >= 201103L + /* Use ISO C++11 syntax when the compiler supports it. */ +# define G_NO_INLINE [[msvc::noinline]] +# else +# define G_NO_INLINE __declspec (noinline) +# endif +#else +# define G_NO_INLINE /* empty */ +#endif + /* * The G_LIKELY and G_UNLIKELY macros let the programmer give hints to * the compiler about the expected result of an expression. Some compilers diff --git a/glib/tests/cxx.cpp b/glib/tests/cxx.cpp index 363700d14..bab5aa9c5 100644 --- a/glib/tests/cxx.cpp +++ b/glib/tests/cxx.cpp @@ -158,6 +158,30 @@ test_atomic_int_exchange (void) #endif } +G_NO_INLINE +static gboolean +do_not_inline_this (void) +{ + return FALSE; +} + +G_ALWAYS_INLINE +static inline gboolean +do_inline_this (void) +{ + return TRUE; +} + +static void +test_inline_no_inline_macros (void) +{ + g_test_message ("Test that G_NO_INLINE and G_ALWAYS_INLINE functions " + "can be compiled with C++ compiler"); + + g_assert_false (do_not_inline_this ()); + g_assert_true (do_inline_this ()); +} + int main (int argc, char *argv[]) { @@ -174,6 +198,7 @@ main (int argc, char *argv[]) g_test_add_func ("/C++/atomic-int-compare-and-exchange-full", test_atomic_int_compare_and_exchange_full); g_test_add_func ("/C++/atomic-pointer-exchange", test_atomic_pointer_exchange); g_test_add_func ("/C++/atomic-int-exchange", test_atomic_int_exchange); + g_test_add_func ("/C++/inlined-not-inlined-functions", test_inline_no_inline_macros); return g_test_run (); } From a6f8fe071e44b0145619c21f3bfbc90c56ab805e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 24 Jun 2022 14:46:41 +0200 Subject: [PATCH 2/3] cleanup: Replace G_GNUC_NO_INLINE with G_NO_INLINE As per this we can also now mark G_GNUC_NO_INLINE as GLIB_AVAILABLE_MACRO_IN_2_58, given that we don't have anymore headers using it. --- glib/gmacros.h | 11 ++++------- gobject/gtype.h | 8 ++++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/glib/gmacros.h b/glib/gmacros.h index 218ee4f25..d4e5124cf 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -235,11 +235,6 @@ * * Since: 2.58 */ -/* Note: We can’t annotate this with GLIB_AVAILABLE_MACRO_IN_2_58 because it’s - * used within the GLib headers in function declarations which are always - * evaluated when a header is included. This results in warnings in third party - * code which includes glib.h, even if the third party code doesn’t use the new - * macro itself. */ #if g_macro__has_attribute(__pure__) #define G_GNUC_PURE __attribute__((__pure__)) @@ -254,9 +249,11 @@ #endif #if g_macro__has_attribute(__noinline__) -#define G_GNUC_NO_INLINE __attribute__ ((__noinline__)) +#define G_GNUC_NO_INLINE __attribute__ ((__noinline__)) \ + GLIB_AVAILABLE_MACRO_IN_2_58 #else -#define G_GNUC_NO_INLINE +#define G_GNUC_NO_INLINE \ + GLIB_AVAILABLE_MACRO_IN_2_58 #endif /** diff --git a/gobject/gtype.h b/gobject/gtype.h index 73d665626..85c5ea2fc 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -2158,7 +2158,7 @@ type_name##_get_type (void) \ return static_g_define_type_id; \ } /* closes type_name##_get_type() */ \ \ -G_GNUC_NO_INLINE \ +G_NO_INLINE \ static GType \ type_name##_get_type_once (void) \ { \ @@ -2327,7 +2327,7 @@ type_name##_get_type (void) \ return static_g_define_type_id; \ } \ \ -G_GNUC_NO_INLINE \ +G_NO_INLINE \ static GType \ type_name##_get_type_once (void) \ { \ @@ -2364,7 +2364,7 @@ type_name##_get_type (void) \ return static_g_define_type_id; \ } \ \ -G_GNUC_NO_INLINE \ +G_NO_INLINE \ static GType \ type_name##_get_type_once (void) \ { \ @@ -2417,7 +2417,7 @@ type_name##_get_type (void) \ return static_g_define_type_id; \ } \ \ -G_GNUC_NO_INLINE \ +G_NO_INLINE \ static GType \ type_name##_get_type_once (void) \ { \ From e59ac0bc2daad41b2043c6f63989ffc5add1b76b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 24 Jun 2022 12:34:28 +0200 Subject: [PATCH 3/3] gthread-posix: Use G_NO_INLINE instead of actual attribute Even if this is gcc/clang-only code, it's just better to use the generic macros we now have. --- glib/gthread-posix.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c index 751533f56..fbf7531fe 100644 --- a/glib/gthread-posix.c +++ b/glib/gthread-posix.c @@ -1490,7 +1490,8 @@ g_mutex_clear (GMutex *mutex) } } -static void __attribute__((noinline)) +G_GNUC_NO_INLINE +static void g_mutex_lock_slowpath (GMutex *mutex) { /* Set to contended. If it was empty before then we @@ -1505,7 +1506,8 @@ g_mutex_lock_slowpath (GMutex *mutex) } } -static void __attribute__((noinline)) +G_GNUC_NO_INLINE +static void g_mutex_unlock_slowpath (GMutex *mutex, guint prev) {