linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
@ 2018-08-26 17:57 Miguel Ojeda
  2018-08-26 18:30 ` Miguel Ojeda
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Miguel Ojeda @ 2018-08-26 17:57 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Eli Friedman, Christopher Li, Kees Cook, Ingo Molnar,
	Geert Uytterhoeven, Arnd Bergmann, Greg Kroah-Hartman,
	Masahiro Yamada, Joe Perches, Dominique Martinet,
	Nick Desaulniers, linux-kernel

Instead of using version checks per-compiler to define (or not) each attribute,
use __has_attribute to test for them, following the cleanup started with
commit 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive").

All the attributes that are fairly common/standard (i.e. those that do not
require extra logic to define them) have been moved to a new file
include/linux/compiler_attributes.h. The attributes have been sorted
and divided between "required" and "optional".

Further, attributes that are already supported in gcc >= 4.6 and recent clang
were simply made to be required (instead of testing for them):
  * always_inline
  * const (pure was already "required", by the way)
  * gnu_inline

Finally, some other bits were cleaned up in the process:
  * __optimize: removed (unused in the whole kernel tree)
  * __must_be_array: removed from -gcc and -clang (identical), moved to _types
    (it depends on the unconditionally used  __builtin_types_compatible_p
  * Removes unneeded underscores on the attributes' names

There are some things that can be further cleaned up afterwards:
  * __attribute_const__: rename to __const
  * __noretpoline: avoid checking for defined(__notrepoline)
  * __compiletime_warning/error: they are in two different places,
    -gcc and compiler.h.
  * sparse' attributes could potentially go into the end of attributes.h
    too (as another separate section).

Compile-tested an x86 allmodconfig for a while with gcc 8.2.0 and 4.6.4.

Cc: Eli Friedman <efriedma@codeaurora.org>
Cc: Christopher Li <sparse@chrisli.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
Cc: Joe Perches <joe@perches.com>
Cc: Dominique Martinet <asmadeus@codewreck.org>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
---
*Seems* to work, but note that I did not finish the entire allmodconfig :)

A few things could be splitted into their own patch, but I kept it
as one for simplicity for a first review.

These files are becoming no-headaches-readable again, yay.

 include/linux/compiler-clang.h      |   5 --
 include/linux/compiler-gcc.h        |  60 ----------------
 include/linux/compiler-intel.h      |   6 --
 include/linux/compiler.h            |   4 --
 include/linux/compiler_attributes.h | 105 ++++++++++++++++++++++++++++
 include/linux/compiler_types.h      |  91 ++++--------------------
 6 files changed, 118 insertions(+), 153 deletions(-)
 create mode 100644 include/linux/compiler_attributes.h

diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
index b1ce500fe8b3..3e7dafb3ea80 100644
--- a/include/linux/compiler-clang.h
+++ b/include/linux/compiler-clang.h
@@ -21,8 +21,6 @@
 #define __SANITIZE_ADDRESS__
 #endif
 
-#define __no_sanitize_address __attribute__((no_sanitize("address")))
-
 /*
  * Not all versions of clang implement the the type-generic versions
  * of the builtin overflow checkers. Fortunately, clang implements
@@ -41,6 +39,3 @@
  * compilers, like ICC.
  */
 #define barrier() __asm__ __volatile__("" : : : "memory")
-#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
-#define __assume_aligned(a, ...)	\
-	__attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 763bbad1e258..dde3daae6287 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -68,13 +68,6 @@
  */
 #define uninitialized_var(x) x = x
 
-#ifdef __CHECKER__
-#define __must_be_array(a)	0
-#else
-/* &a[0] degrades to a pointer: a different type from an array */
-#define __must_be_array(a)	BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
-#endif
-
 #ifdef RETPOLINE
 #define __noretpoline __attribute__((indirect_branch("keep")))
 #endif
@@ -95,8 +88,6 @@
 
 #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
 
-#define __optimize(level)	__attribute__((__optimize__(level)))
-
 #define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
 
 #ifndef __CHECKER__
@@ -133,9 +124,6 @@
 		__builtin_unreachable();	\
 	} while (0)
 
-/* Mark a function definition as prohibited from being cloned. */
-#define __noclone	__attribute__((__noclone__, __optimize__("no-tracer")))
-
 #if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
 #define __randomize_layout __attribute__((randomize_layout))
 #define __no_randomize_layout __attribute__((no_randomize_layout))
@@ -144,32 +132,6 @@
 #define randomized_struct_fields_end	} __randomize_layout;
 #endif
 
-/*
- * When used with Link Time Optimization, gcc can optimize away C functions or
- * variables which are referenced only from assembly code.  __visible tells the
- * optimizer that something else uses this function or variable, thus preventing
- * this.
- */
-#define __visible	__attribute__((externally_visible))
-
-/* gcc version specific checks */
-
-#if GCC_VERSION >= 40900 && !defined(__CHECKER__)
-/*
- * __assume_aligned(n, k): Tell the optimizer that the returned
- * pointer can be assumed to be k modulo n. The second argument is
- * optional (default 0), so we use a variadic macro to make the
- * shorthand.
- *
- * Beware: Do not apply this to functions which may return
- * ERR_PTRs. Also, it is probably unwise to apply it to functions
- * returning extra information in the low bits (but in that case the
- * compiler should see some alignment anyway, when the return value is
- * massaged by 'flags = ptr & 3; ptr &= ~3;').
- */
-#define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
-#endif
-
 /*
  * GCC 'asm goto' miscompiles certain code sequences:
  *
@@ -201,32 +163,10 @@
 #define KASAN_ABI_VERSION 3
 #endif
 
-#if GCC_VERSION >= 40902
-/*
- * Tell the compiler that address safety instrumentation (KASAN)
- * should not be applied to that function.
- * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
- */
-#define __no_sanitize_address __attribute__((no_sanitize_address))
-#endif
-
 #if GCC_VERSION >= 50100
-/*
- * Mark structures as requiring designated initializers.
- * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
- */
-#define __designated_init __attribute__((designated_init))
 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
 #endif
 
-#if !defined(__noclone)
-#define __noclone	/* not needed */
-#endif
-
-#if !defined(__no_sanitize_address)
-#define __no_sanitize_address
-#endif
-
 /*
  * Turn individual warnings and errors on and off locally, depending
  * on version.
diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h
index 4c7f9befa9f6..fb9e77fc65ec 100644
--- a/include/linux/compiler-intel.h
+++ b/include/linux/compiler-intel.h
@@ -37,9 +37,3 @@
 /* icc has this, but it's called _bswap16 */
 #define __HAVE_BUILTIN_BSWAP16__
 #define __builtin_bswap16 _bswap16
-
-/* The following are for compatibility with GCC, from compiler-gcc.h,
- * and may be redefined here because they should not be shared with other
- * compilers, like clang.
- */
-#define __visible	__attribute__((externally_visible))
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 681d866efb1e..7c0157d50964 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -301,10 +301,6 @@ static inline void *offset_to_ptr(const int *off)
 
 #endif /* __ASSEMBLY__ */
 
-#ifndef __optimize
-# define __optimize(level)
-#endif
-
 /* Compile time object size, -1 for unknown */
 #ifndef __compiletime_object_size
 # define __compiletime_object_size(obj) -1
diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
new file mode 100644
index 000000000000..af8c8413d136
--- /dev/null
+++ b/include/linux/compiler_attributes.h
@@ -0,0 +1,105 @@
+#ifndef __LINUX_COMPILER_ATTRIBUTES_H
+#define __LINUX_COMPILER_ATTRIBUTES_H
+
+/* This file is meant to be sorted. */
+
+/*
+ * Required attributes: your compiler must support these.
+ */
+#define __alias(symbol)		__attribute__((alias(#symbol)))
+#define __aligned(x)		__attribute__((aligned(x)))
+#define __aligned_largest	__attribute__((aligned))
+#define __always_inline         inline __attribute__((always_inline))
+#define __always_unused		__attribute__((unused))
+#define __attribute_const__     __attribute__((const))
+#define __cold			__attribute__((cold))
+#define __gnu_inline            __attribute__((gnu_inline))
+#define __malloc		__attribute__((malloc))
+#define __maybe_unused		__attribute__((unused))
+#define __mode(x)		__attribute__((mode(x)))
+#define   noinline              __attribute__((noinline))
+#define __noreturn		__attribute__((noreturn))
+#define __packed		__attribute__((packed))
+#define __printf(a, b)		__attribute__((format(printf, a, b)))
+#define __pure			__attribute__((pure))
+#define __scanf(a, b)		__attribute__((format(scanf, a, b)))
+#define __section(S)		__attribute__((section(#S)))
+#define __used			__attribute__((used))
+#define __weak			__attribute__((weak))
+
+/*
+ * Optional attributes: your compiler may or may not support them.
+ *
+ * To check for them, we use __has_attribute, which is supported on gcc >= 5,
+ * clang >= 2.9 and icc >= 17. In the meantime, to support 4.6 <= gcc < 5,
+ * we implement it by hand.
+ */
+#ifndef __has_attribute
+#define __has_attribute(x) __GCC46_has_attribute_##x
+#define __GCC46_has_attribute_assume_aligned 0
+#define __GCC46_has_attribute_designated_init 0
+#define __GCC46_has_attribute_externally_visible 1
+#define __GCC46_has_attribute_noclone 1
+#define __GCC46_has_attribute_optimize 1
+#define __GCC46_has_attribute_no_sanitize_address 0
+#endif
+
+/*
+ * __assume_aligned(n, k): Tell the optimizer that the returned
+ * pointer can be assumed to be k modulo n. The second argument is
+ * optional (default 0), so we use a variadic macro to make the
+ * shorthand.
+ *
+ * Beware: Do not apply this to functions which may return
+ * ERR_PTRs. Also, it is probably unwise to apply it to functions
+ * returning extra information in the low bits (but in that case the
+ * compiler should see some alignment anyway, when the return value is
+ * massaged by 'flags = ptr & 3; ptr &= ~3;').
+ */
+#if __has_attribute(assume_aligned)
+#define __assume_aligned(a, ...) __attribute__((assume_aligned(a, ## __VA_ARGS__)))
+#else
+#define __assume_aligned(a, ...)
+#endif
+
+/*
+ * Mark structures as requiring designated initializers.
+ * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
+ */
+#if __has_attribute(designated_init)
+#define __designated_init __attribute__((designated_init))
+#else
+#define __designated_init
+#endif
+
+/*
+ * When used with Link Time Optimization, gcc can optimize away C functions or
+ * variables which are referenced only from assembly code.  __visible tells the
+ * optimizer that something else uses this function or variable, thus preventing
+ * this.
+ */
+#if __has_attribute(externally_visible)
+#define __visible __attribute__((externally_visible))
+#else
+#define __visible
+#endif
+
+/* Mark a function definition as prohibited from being cloned. */
+#if __has_attribute(noclone) && __has_attribute(optimize)
+#define __noclone __attribute__((noclone, optimize("no-tracer")))
+#else
+#define __noclone
+#endif
+
+/*
+ * Tell the compiler that address safety instrumentation (KASAN)
+ * should not be applied to that function.
+ * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ */
+#if __has_attribute(no_sanitize_address)
+#define __no_sanitize_address __attribute__((no_sanitize_address))
+#else
+#define __no_sanitize_address
+#endif
+
+#endif /* __LINUX_COMPILER_ATTRIBUTES_H */
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index 3525c179698c..8cd622bedec4 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -54,6 +54,9 @@ extern void __chk_io_ptr(const volatile void __iomem *);
 
 #ifdef __KERNEL__
 
+/* Attributes */
+#include <linux/compiler_attributes.h>
+
 /* Compiler specific macros. */
 #ifdef __clang__
 #include <linux/compiler-clang.h>
@@ -78,12 +81,6 @@ extern void __chk_io_ptr(const volatile void __iomem *);
 #include <asm/compiler.h>
 #endif
 
-/*
- * Generic compiler-independent macros required for kernel
- * build go below this comment. Actual compiler/compiler version
- * specific implementations come from the above header files
- */
-
 struct ftrace_branch_data {
 	const char *func;
 	const char *file;
@@ -119,10 +116,6 @@ struct ftrace_likely_data {
  * compilers. We don't consider that to be an error, so set them to nothing.
  * For example, some of them are for compiler specific plugins.
  */
-#ifndef __designated_init
-# define __designated_init
-#endif
-
 #ifndef __latent_entropy
 # define __latent_entropy
 #endif
@@ -140,17 +133,6 @@ struct ftrace_likely_data {
 # define randomized_struct_fields_end
 #endif
 
-#ifndef __visible
-#define __visible
-#endif
-
-/*
- * Assume alignment of return value.
- */
-#ifndef __assume_aligned
-#define __assume_aligned(a, ...)
-#endif
-
 /* Are two types/vars the same type (ignoring qualifiers)? */
 #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
 
@@ -159,14 +141,6 @@ struct ftrace_likely_data {
 	(sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
 	 sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
 
-#ifndef __attribute_const__
-#define __attribute_const__	__attribute__((__const__))
-#endif
-
-#ifndef __noclone
-#define __noclone
-#endif
-
 /* Helpers for emitting diagnostics in pragmas. */
 #ifndef __diag
 #define __diag(string)
@@ -186,34 +160,6 @@ struct ftrace_likely_data {
 #define __diag_error(compiler, version, option, comment) \
 	__diag_ ## compiler(version, error, option)
 
-/*
- * From the GCC manual:
- *
- * Many functions have no effects except the return value and their
- * return value depends only on the parameters and/or global
- * variables.  Such a function can be subject to common subexpression
- * elimination and loop optimization just as an arithmetic operator
- * would be.
- * [...]
- */
-#define __pure			__attribute__((pure))
-#define __aligned(x)		__attribute__((aligned(x)))
-#define __aligned_largest	__attribute__((aligned))
-#define __printf(a, b)		__attribute__((format(printf, a, b)))
-#define __scanf(a, b)		__attribute__((format(scanf, a, b)))
-#define __maybe_unused		__attribute__((unused))
-#define __always_unused		__attribute__((unused))
-#define __mode(x)		__attribute__((mode(x)))
-#define __malloc		__attribute__((__malloc__))
-#define __used			__attribute__((__used__))
-#define __noreturn		__attribute__((noreturn))
-#define __packed		__attribute__((packed))
-#define __weak			__attribute__((weak))
-#define __alias(symbol)		__attribute__((alias(#symbol)))
-#define __cold			__attribute__((cold))
-#define __section(S)		__attribute__((__section__(#S)))
-
-
 #ifdef CONFIG_ENABLE_MUST_CHECK
 #define __must_check		__attribute__((warn_unused_result))
 #else
@@ -228,18 +174,6 @@ struct ftrace_likely_data {
 
 #define __compiler_offsetof(a, b)	__builtin_offsetof(a, b)
 
-/*
- * Feature detection for gnu_inline (gnu89 extern inline semantics). Either
- * __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics,
- * and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not
- * defined so the gnu89 semantics are the default.
- */
-#ifdef __GNUC_STDC_INLINE__
-# define __gnu_inline	__attribute__((gnu_inline))
-#else
-# define __gnu_inline
-#endif
-
 /*
  * Force always-inline if the user requests it so via the .config.
  * GCC does not warn about unused static inline functions for
@@ -254,19 +188,13 @@ struct ftrace_likely_data {
  */
 #if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
 	!defined(CONFIG_OPTIMIZE_INLINING)
-#define inline \
-	inline __attribute__((always_inline, unused)) notrace __gnu_inline
+#define inline inline __attribute__((always_inline, unused)) notrace __gnu_inline
 #else
-#define inline inline	__attribute__((unused)) notrace __gnu_inline
+#define inline inline __attribute__((unused)) notrace __gnu_inline
 #endif
 
 #define __inline__ inline
-#define __inline inline
-#define noinline	__attribute__((noinline))
-
-#ifndef __always_inline
-#define __always_inline inline __attribute__((always_inline))
-#endif
+#define __inline   inline
 
 /*
  * Rather then using noinline to prevent stack consumption, use
@@ -274,4 +202,11 @@ struct ftrace_likely_data {
  */
 #define noinline_for_stack noinline
 
+#ifdef __CHECKER__
+#define __must_be_array(a) 0
+#else
+/* &a[0] degrades to a pointer: a different type from an array */
+#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
+#endif
+
 #endif /* __LINUX_COMPILER_TYPES_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-26 17:57 [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes Miguel Ojeda
@ 2018-08-26 18:30 ` Miguel Ojeda
  2018-08-26 18:50 ` Joe Perches
  2018-08-27 17:43 ` Nick Desaulniers
  2 siblings, 0 replies; 12+ messages in thread
From: Miguel Ojeda @ 2018-08-26 18:30 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Eli Friedman, Christopher Li, Kees Cook, Ingo Molnar,
	Geert Uytterhoeven, Arnd Bergmann, Greg Kroah-Hartman,
	Masahiro Yamada, Joe Perches, Dominique Martinet,
	Nick Desaulniers, linux-kernel

Hi,

A couple of extra notes on my patch.

On Sun, Aug 26, 2018 at 7:57 PM, Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
> +/*
> + * Optional attributes: your compiler may or may not support them.
> + *
> + * To check for them, we use __has_attribute, which is supported on gcc >= 5,
> + * clang >= 2.9 and icc >= 17. In the meantime, to support 4.6 <= gcc < 5,
> + * we implement it by hand.
> + */
> +#ifndef __has_attribute
> +#define __has_attribute(x) __GCC46_has_attribute_##x
> +#define __GCC46_has_attribute_assume_aligned 0
> +#define __GCC46_has_attribute_designated_init 0
> +#define __GCC46_has_attribute_externally_visible 1
> +#define __GCC46_has_attribute_noclone 1
> +#define __GCC46_has_attribute_optimize 1
> +#define __GCC46_has_attribute_no_sanitize_address 0

Note that:
  - assume_aligned came with gcc 4.9
  - no_sanitize_address came with gcc 4.8

So if we feel it is important to have them there (before gcc 5), we
would need here a quick version check here.

> +#endif
> +
> +/*
> + * __assume_aligned(n, k): Tell the optimizer that the returned
> + * pointer can be assumed to be k modulo n. The second argument is
> + * optional (default 0), so we use a variadic macro to make the
> + * shorthand.
> + *
> + * Beware: Do not apply this to functions which may return
> + * ERR_PTRs. Also, it is probably unwise to apply it to functions
> + * returning extra information in the low bits (but in that case the
> + * compiler should see some alignment anyway, when the return value is
> + * massaged by 'flags = ptr & 3; ptr &= ~3;').
> + */
> +#if __has_attribute(assume_aligned)
> +#define __assume_aligned(a, ...) __attribute__((assume_aligned(a, ## __VA_ARGS__)))
> +#else
> +#define __assume_aligned(a, ...)
> +#endif

Beforehand, these were !defined(__CHECKER__). I am not sure if sparse
complains too much about it. Maybe sparse could learn __has_attribute.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-26 17:57 [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes Miguel Ojeda
  2018-08-26 18:30 ` Miguel Ojeda
@ 2018-08-26 18:50 ` Joe Perches
  2018-08-27 12:33   ` Miguel Ojeda
  2018-08-27 17:43 ` Nick Desaulniers
  2 siblings, 1 reply; 12+ messages in thread
From: Joe Perches @ 2018-08-26 18:50 UTC (permalink / raw)
  To: Miguel Ojeda, Linus Torvalds
  Cc: Eli Friedman, Christopher Li, Kees Cook, Ingo Molnar,
	Geert Uytterhoeven, Arnd Bergmann, Greg Kroah-Hartman,
	Masahiro Yamada, Dominique Martinet, Nick Desaulniers,
	linux-kernel

On Sun, 2018-08-26 at 19:57 +0200, Miguel Ojeda wrote:
> Instead of using version checks per-compiler to define (or not) each attribute,
> use __has_attribute to test for them, following the cleanup started with
> commit 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive").

Very nice.  Thank you Miguel.

trivia:

I believe the alphabetic sorting of the required attributes
makes reading by use a bit difficult and I would prefer that
various required attributes are sorted by logical use instead.

ie:  keep noinline and __always_inline together,
     keep __used and __always_unused together,
     etc...



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-26 18:50 ` Joe Perches
@ 2018-08-27 12:33   ` Miguel Ojeda
  0 siblings, 0 replies; 12+ messages in thread
From: Miguel Ojeda @ 2018-08-27 12:33 UTC (permalink / raw)
  To: Joe Perches
  Cc: Linus Torvalds, Eli Friedman, Christopher Li, Kees Cook,
	Ingo Molnar, Geert Uytterhoeven, Arnd Bergmann,
	Greg Kroah-Hartman, Masahiro Yamada, Dominique Martinet,
	Nick Desaulniers, linux-kernel

Hi Joe,

On Sun, Aug 26, 2018 at 8:50 PM, Joe Perches <joe@perches.com> wrote:
> On Sun, 2018-08-26 at 19:57 +0200, Miguel Ojeda wrote:
>> Instead of using version checks per-compiler to define (or not) each attribute,
>> use __has_attribute to test for them, following the cleanup started with
>> commit 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive").
>
> Very nice.  Thank you Miguel.

Thanks!

>
> trivia:
>
> I believe the alphabetic sorting of the required attributes
> makes reading by use a bit difficult and I would prefer that
> various required attributes are sorted by logical use instead.
>
> ie:  keep noinline and __always_inline together,
>      keep __used and __always_unused together,
>      etc...
>
>

Both ways are fine with me --- I sorted them as an attempt to avoid
the file evolving into a mess again in the upcoming years :-)

Half-joking: it may also be a good way to avoid people "guessing" what
the attributes do by name and, instead, consulting the docs (either
the compiler's, or a Doc/ file maybe).

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-26 17:57 [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes Miguel Ojeda
  2018-08-26 18:30 ` Miguel Ojeda
  2018-08-26 18:50 ` Joe Perches
@ 2018-08-27 17:43 ` Nick Desaulniers
  2018-08-27 17:48   ` Nick Desaulniers
  2018-08-28 15:03   ` Miguel Ojeda
  2 siblings, 2 replies; 12+ messages in thread
From: Nick Desaulniers @ 2018-08-27 17:43 UTC (permalink / raw)
  To: miguel.ojeda.sandonis
  Cc: Linus Torvalds, efriedma, sparse, Kees Cook, Ingo Molnar,
	Geert Uytterhoeven, Arnd Bergmann, Greg KH, Masahiro Yamada, joe,
	asmadeus, LKML

On Sun, Aug 26, 2018 at 10:58 AM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> Instead of using version checks per-compiler to define (or not) each attribute,
> use __has_attribute to test for them, following the cleanup started with
> commit 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive").
>
> All the attributes that are fairly common/standard (i.e. those that do not
> require extra logic to define them) have been moved to a new file
> include/linux/compiler_attributes.h. The attributes have been sorted
> and divided between "required" and "optional".

Nice! Thanks Miguel.  Regarding sorting, I'm happy with that.  In
fact, some of the comments can be removed IMO, as the attributes have
common definitions in the docs (maybe an added link to the gcc and
clang attribute docs at the top of the file rather than per attribute
comments).

>
> Further, attributes that are already supported in gcc >= 4.6 and recent clang
> were simply made to be required (instead of testing for them):
>   * always_inline
>   * const (pure was already "required", by the way)
>   * gnu_inline

There's an important test for gnu_inline that isn't checking that it's
supported, but rather what the implicit behavior is depending on which
C standard is being used.  It's important not to remove that.

>
> Finally, some other bits were cleaned up in the process:
>   * __optimize: removed (unused in the whole kernel tree)

A+ for removing dead code.  I also don't see it used anywhere.

>   * __must_be_array: removed from -gcc and -clang (identical), moved to _types

Yep, uses a builtin (we should add guards for that, later, in a
similar style change that guards the use of builtins). Looks good.

>     (it depends on the unconditionally used  __builtin_types_compatible_p
>   * Removes unneeded underscores on the attributes' names

That doesn't sound right, but lets see what you mean by that.

>
> There are some things that can be further cleaned up afterwards:
>   * __attribute_const__: rename to __const

This doesn't look correct to me; the kernel is full of call sites for
__attribute_const__. You can't rename the definition without renaming
all of the call sites (and that would be too big a change for this
patch, IMO).  Skip the rename, and it also looks like you just removed
it outright (Oops).

>   * __noretpoline: avoid checking for defined(__notrepoline)
>   * __compiletime_warning/error: they are in two different places,
>     -gcc and compiler.h.
>   * sparse' attributes could potentially go into the end of attributes.h
>     too (as another separate section).
>
> Compile-tested an x86 allmodconfig for a while with gcc 8.2.0 and 4.6.4.

It's important to test changes to compiler-clang.h with clang. ;)

>
> Cc: Eli Friedman <efriedma@codeaurora.org>
> Cc: Christopher Li <sparse@chrisli.org>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
> Cc: Joe Perches <joe@perches.com>
> Cc: Dominique Martinet <asmadeus@codewreck.org>
> Cc: Nick Desaulniers <ndesaulniers@google.com>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
> ---
> *Seems* to work, but note that I did not finish the entire allmodconfig :)
>
> A few things could be splitted into their own patch, but I kept it
> as one for simplicity for a first review.
>
> These files are becoming no-headaches-readable again, yay.

A+

>
>  include/linux/compiler-clang.h      |   5 --
>  include/linux/compiler-gcc.h        |  60 ----------------
>  include/linux/compiler-intel.h      |   6 --
>  include/linux/compiler.h            |   4 --
>  include/linux/compiler_attributes.h | 105 ++++++++++++++++++++++++++++
>  include/linux/compiler_types.h      |  91 ++++--------------------
>  6 files changed, 118 insertions(+), 153 deletions(-)
>  create mode 100644 include/linux/compiler_attributes.h
>
> diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
> index b1ce500fe8b3..3e7dafb3ea80 100644
> --- a/include/linux/compiler-clang.h
> +++ b/include/linux/compiler-clang.h
> @@ -21,8 +21,6 @@
>  #define __SANITIZE_ADDRESS__
>  #endif
>
> -#define __no_sanitize_address __attribute__((no_sanitize("address")))
> -
>  /*
>   * Not all versions of clang implement the the type-generic versions
>   * of the builtin overflow checkers. Fortunately, clang implements
> @@ -41,6 +39,3 @@
>   * compilers, like ICC.
>   */
>  #define barrier() __asm__ __volatile__("" : : : "memory")
> -#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
> -#define __assume_aligned(a, ...)       \
> -       __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
> diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
> index 763bbad1e258..dde3daae6287 100644
> --- a/include/linux/compiler-gcc.h
> +++ b/include/linux/compiler-gcc.h
> @@ -68,13 +68,6 @@
>   */
>  #define uninitialized_var(x) x = x
>
> -#ifdef __CHECKER__
> -#define __must_be_array(a)     0
> -#else
> -/* &a[0] degrades to a pointer: a different type from an array */
> -#define __must_be_array(a)     BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
> -#endif
> -
>  #ifdef RETPOLINE
>  #define __noretpoline __attribute__((indirect_branch("keep")))
>  #endif
> @@ -95,8 +88,6 @@
>
>  #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
>
> -#define __optimize(level)      __attribute__((__optimize__(level)))
> -
>  #define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
>
>  #ifndef __CHECKER__
> @@ -133,9 +124,6 @@
>                 __builtin_unreachable();        \
>         } while (0)
>
> -/* Mark a function definition as prohibited from being cloned. */
> -#define __noclone      __attribute__((__noclone__, __optimize__("no-tracer")))
> -
>  #if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
>  #define __randomize_layout __attribute__((randomize_layout))
>  #define __no_randomize_layout __attribute__((no_randomize_layout))
> @@ -144,32 +132,6 @@
>  #define randomized_struct_fields_end   } __randomize_layout;
>  #endif
>
> -/*
> - * When used with Link Time Optimization, gcc can optimize away C functions or
> - * variables which are referenced only from assembly code.  __visible tells the
> - * optimizer that something else uses this function or variable, thus preventing
> - * this.
> - */
> -#define __visible      __attribute__((externally_visible))
> -
> -/* gcc version specific checks */
> -
> -#if GCC_VERSION >= 40900 && !defined(__CHECKER__)
> -/*
> - * __assume_aligned(n, k): Tell the optimizer that the returned
> - * pointer can be assumed to be k modulo n. The second argument is
> - * optional (default 0), so we use a variadic macro to make the
> - * shorthand.
> - *
> - * Beware: Do not apply this to functions which may return
> - * ERR_PTRs. Also, it is probably unwise to apply it to functions
> - * returning extra information in the low bits (but in that case the
> - * compiler should see some alignment anyway, when the return value is
> - * massaged by 'flags = ptr & 3; ptr &= ~3;').
> - */
> -#define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
> -#endif
> -
>  /*
>   * GCC 'asm goto' miscompiles certain code sequences:
>   *
> @@ -201,32 +163,10 @@
>  #define KASAN_ABI_VERSION 3
>  #endif
>
> -#if GCC_VERSION >= 40902
> -/*
> - * Tell the compiler that address safety instrumentation (KASAN)
> - * should not be applied to that function.
> - * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
> - */
> -#define __no_sanitize_address __attribute__((no_sanitize_address))
> -#endif
> -
>  #if GCC_VERSION >= 50100
> -/*
> - * Mark structures as requiring designated initializers.
> - * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
> - */
> -#define __designated_init __attribute__((designated_init))
>  #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
>  #endif
>
> -#if !defined(__noclone)
> -#define __noclone      /* not needed */
> -#endif
> -
> -#if !defined(__no_sanitize_address)
> -#define __no_sanitize_address
> -#endif
> -
>  /*
>   * Turn individual warnings and errors on and off locally, depending
>   * on version.
> diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h
> index 4c7f9befa9f6..fb9e77fc65ec 100644
> --- a/include/linux/compiler-intel.h
> +++ b/include/linux/compiler-intel.h
> @@ -37,9 +37,3 @@
>  /* icc has this, but it's called _bswap16 */
>  #define __HAVE_BUILTIN_BSWAP16__
>  #define __builtin_bswap16 _bswap16
> -
> -/* The following are for compatibility with GCC, from compiler-gcc.h,
> - * and may be redefined here because they should not be shared with other
> - * compilers, like clang.
> - */
> -#define __visible      __attribute__((externally_visible))
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index 681d866efb1e..7c0157d50964 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -301,10 +301,6 @@ static inline void *offset_to_ptr(const int *off)
>
>  #endif /* __ASSEMBLY__ */
>
> -#ifndef __optimize
> -# define __optimize(level)
> -#endif
> -
>  /* Compile time object size, -1 for unknown */
>  #ifndef __compiletime_object_size
>  # define __compiletime_object_size(obj) -1
> diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
> new file mode 100644
> index 000000000000..af8c8413d136
> --- /dev/null
> +++ b/include/linux/compiler_attributes.h
> @@ -0,0 +1,105 @@
> +#ifndef __LINUX_COMPILER_ATTRIBUTES_H
> +#define __LINUX_COMPILER_ATTRIBUTES_H
> +
> +/* This file is meant to be sorted. */
> +
> +/*
> + * Required attributes: your compiler must support these.
> + */
> +#define __alias(symbol)                __attribute__((alias(#symbol)))
> +#define __aligned(x)           __attribute__((aligned(x)))
> +#define __aligned_largest      __attribute__((aligned))
> +#define __always_inline         inline __attribute__((always_inline))
> +#define __always_unused                __attribute__((unused))
> +#define __attribute_const__     __attribute__((const))
> +#define __cold                 __attribute__((cold))
> +#define __gnu_inline            __attribute__((gnu_inline))
> +#define __malloc               __attribute__((malloc))
> +#define __maybe_unused         __attribute__((unused))
> +#define __mode(x)              __attribute__((mode(x)))
> +#define   noinline              __attribute__((noinline))
> +#define __noreturn             __attribute__((noreturn))
> +#define __packed               __attribute__((packed))
> +#define __printf(a, b)         __attribute__((format(printf, a, b)))
> +#define __pure                 __attribute__((pure))
> +#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
> +#define __section(S)           __attribute__((section(#S)))
> +#define __used                 __attribute__((used))
> +#define __weak                 __attribute__((weak))
> +
> +/*
> + * Optional attributes: your compiler may or may not support them.
> + *
> + * To check for them, we use __has_attribute, which is supported on gcc >= 5,
> + * clang >= 2.9 and icc >= 17. In the meantime, to support 4.6 <= gcc < 5,
> + * we implement it by hand.
> + */
> +#ifndef __has_attribute
> +#define __has_attribute(x) __GCC46_has_attribute_##x
> +#define __GCC46_has_attribute_assume_aligned 0
> +#define __GCC46_has_attribute_designated_init 0
> +#define __GCC46_has_attribute_externally_visible 1
> +#define __GCC46_has_attribute_noclone 1
> +#define __GCC46_has_attribute_optimize 1
> +#define __GCC46_has_attribute_no_sanitize_address 0
> +#endif
> +
> +/*
> + * __assume_aligned(n, k): Tell the optimizer that the returned
> + * pointer can be assumed to be k modulo n. The second argument is
> + * optional (default 0), so we use a variadic macro to make the
> + * shorthand.
> + *
> + * Beware: Do not apply this to functions which may return
> + * ERR_PTRs. Also, it is probably unwise to apply it to functions
> + * returning extra information in the low bits (but in that case the
> + * compiler should see some alignment anyway, when the return value is
> + * massaged by 'flags = ptr & 3; ptr &= ~3;').
> + */
> +#if __has_attribute(assume_aligned)
> +#define __assume_aligned(a, ...) __attribute__((assume_aligned(a, ## __VA_ARGS__)))
> +#else
> +#define __assume_aligned(a, ...)
> +#endif
> +
> +/*
> + * Mark structures as requiring designated initializers.
> + * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
> + */
> +#if __has_attribute(designated_init)
> +#define __designated_init __attribute__((designated_init))
> +#else
> +#define __designated_init
> +#endif
> +
> +/*
> + * When used with Link Time Optimization, gcc can optimize away C functions or
> + * variables which are referenced only from assembly code.  __visible tells the
> + * optimizer that something else uses this function or variable, thus preventing
> + * this.
> + */
> +#if __has_attribute(externally_visible)
> +#define __visible __attribute__((externally_visible))
> +#else
> +#define __visible
> +#endif
> +
> +/* Mark a function definition as prohibited from being cloned. */
> +#if __has_attribute(noclone) && __has_attribute(optimize)
> +#define __noclone __attribute__((noclone, optimize("no-tracer")))
> +#else
> +#define __noclone
> +#endif
> +
> +/*
> + * Tell the compiler that address safety instrumentation (KASAN)
> + * should not be applied to that function.
> + * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
> + */
> +#if __has_attribute(no_sanitize_address)
> +#define __no_sanitize_address __attribute__((no_sanitize_address))
> +#else
> +#define __no_sanitize_address
> +#endif
> +
> +#endif /* __LINUX_COMPILER_ATTRIBUTES_H */
> diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
> index 3525c179698c..8cd622bedec4 100644
> --- a/include/linux/compiler_types.h
> +++ b/include/linux/compiler_types.h
> @@ -54,6 +54,9 @@ extern void __chk_io_ptr(const volatile void __iomem *);
>
>  #ifdef __KERNEL__
>
> +/* Attributes */
> +#include <linux/compiler_attributes.h>
> +
>  /* Compiler specific macros. */
>  #ifdef __clang__
>  #include <linux/compiler-clang.h>
> @@ -78,12 +81,6 @@ extern void __chk_io_ptr(const volatile void __iomem *);
>  #include <asm/compiler.h>
>  #endif
>
> -/*
> - * Generic compiler-independent macros required for kernel
> - * build go below this comment. Actual compiler/compiler version
> - * specific implementations come from the above header files
> - */
> -
>  struct ftrace_branch_data {
>         const char *func;
>         const char *file;
> @@ -119,10 +116,6 @@ struct ftrace_likely_data {
>   * compilers. We don't consider that to be an error, so set them to nothing.
>   * For example, some of them are for compiler specific plugins.
>   */
> -#ifndef __designated_init
> -# define __designated_init
> -#endif
> -
>  #ifndef __latent_entropy
>  # define __latent_entropy
>  #endif
> @@ -140,17 +133,6 @@ struct ftrace_likely_data {
>  # define randomized_struct_fields_end
>  #endif
>
> -#ifndef __visible
> -#define __visible
> -#endif
> -
> -/*
> - * Assume alignment of return value.
> - */
> -#ifndef __assume_aligned
> -#define __assume_aligned(a, ...)
> -#endif
> -
>  /* Are two types/vars the same type (ignoring qualifiers)? */
>  #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
>
> @@ -159,14 +141,6 @@ struct ftrace_likely_data {
>         (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
>          sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
>
> -#ifndef __attribute_const__
> -#define __attribute_const__    __attribute__((__const__))
> -#endif
> -
> -#ifndef __noclone
> -#define __noclone
> -#endif
> -
>  /* Helpers for emitting diagnostics in pragmas. */
>  #ifndef __diag
>  #define __diag(string)
> @@ -186,34 +160,6 @@ struct ftrace_likely_data {
>  #define __diag_error(compiler, version, option, comment) \
>         __diag_ ## compiler(version, error, option)
>
> -/*
> - * From the GCC manual:
> - *
> - * Many functions have no effects except the return value and their
> - * return value depends only on the parameters and/or global
> - * variables.  Such a function can be subject to common subexpression
> - * elimination and loop optimization just as an arithmetic operator
> - * would be.
> - * [...]
> - */
> -#define __pure                 __attribute__((pure))
> -#define __aligned(x)           __attribute__((aligned(x)))
> -#define __aligned_largest      __attribute__((aligned))
> -#define __printf(a, b)         __attribute__((format(printf, a, b)))
> -#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
> -#define __maybe_unused         __attribute__((unused))
> -#define __always_unused                __attribute__((unused))
> -#define __mode(x)              __attribute__((mode(x)))
> -#define __malloc               __attribute__((__malloc__))
> -#define __used                 __attribute__((__used__))
> -#define __noreturn             __attribute__((noreturn))
> -#define __packed               __attribute__((packed))
> -#define __weak                 __attribute__((weak))
> -#define __alias(symbol)                __attribute__((alias(#symbol)))
> -#define __cold                 __attribute__((cold))
> -#define __section(S)           __attribute__((__section__(#S)))
> -
> -
>  #ifdef CONFIG_ENABLE_MUST_CHECK
>  #define __must_check           __attribute__((warn_unused_result))
>  #else
> @@ -228,18 +174,6 @@ struct ftrace_likely_data {
>
>  #define __compiler_offsetof(a, b)      __builtin_offsetof(a, b)
>
> -/*
> - * Feature detection for gnu_inline (gnu89 extern inline semantics). Either
> - * __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics,
> - * and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not
> - * defined so the gnu89 semantics are the default.
> - */
> -#ifdef __GNUC_STDC_INLINE__
> -# define __gnu_inline  __attribute__((gnu_inline))
> -#else
> -# define __gnu_inline
> -#endif
> -
>  /*
>   * Force always-inline if the user requests it so via the .config.
>   * GCC does not warn about unused static inline functions for
> @@ -254,19 +188,13 @@ struct ftrace_likely_data {
>   */
>  #if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
>         !defined(CONFIG_OPTIMIZE_INLINING)
> -#define inline \
> -       inline __attribute__((always_inline, unused)) notrace __gnu_inline
> +#define inline inline __attribute__((always_inline, unused)) notrace __gnu_inline
>  #else
> -#define inline inline  __attribute__((unused)) notrace __gnu_inline
> +#define inline inline __attribute__((unused)) notrace __gnu_inline
>  #endif
>
>  #define __inline__ inline
> -#define __inline inline
> -#define noinline       __attribute__((noinline))
> -
> -#ifndef __always_inline
> -#define __always_inline inline __attribute__((always_inline))
> -#endif
> +#define __inline   inline

All of the changes to inline should not be removed, see above.  It's
important to make this work correctly regardless of C standard used.

>
>  /*
>   * Rather then using noinline to prevent stack consumption, use
> @@ -274,4 +202,11 @@ struct ftrace_likely_data {
>   */
>  #define noinline_for_stack noinline
>
> +#ifdef __CHECKER__
> +#define __must_be_array(a) 0
> +#else
> +/* &a[0] degrades to a pointer: a different type from an array */
> +#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
> +#endif
> +
>  #endif /* __LINUX_COMPILER_TYPES_H */
> --
> 2.17.1
>

With the above changes requested, I'm super happy with the spirit of
this patch, and look forward to a v2.  Thanks again Miguel!
-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-27 17:43 ` Nick Desaulniers
@ 2018-08-27 17:48   ` Nick Desaulniers
  2018-08-28 15:10     ` Miguel Ojeda
  2018-08-28 15:03   ` Miguel Ojeda
  1 sibling, 1 reply; 12+ messages in thread
From: Nick Desaulniers @ 2018-08-27 17:48 UTC (permalink / raw)
  To: miguel.ojeda.sandonis
  Cc: Linus Torvalds, efriedma, sparse, Kees Cook, Ingo Molnar,
	Geert Uytterhoeven, Arnd Bergmann, Greg KH, Masahiro Yamada, joe,
	asmadeus, LKML

On Mon, Aug 27, 2018 at 10:43 AM Nick Desaulniers
<ndesaulniers@google.com> wrote:
>
> On Sun, Aug 26, 2018 at 10:58 AM Miguel Ojeda
> <miguel.ojeda.sandonis@gmail.com> wrote:
> >
> > Instead of using version checks per-compiler to define (or not) each attribute,
> > use __has_attribute to test for them, following the cleanup started with
> > commit 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive").
> >
> > All the attributes that are fairly common/standard (i.e. those that do not
> > require extra logic to define them) have been moved to a new file
> > include/linux/compiler_attributes.h. The attributes have been sorted
> > and divided between "required" and "optional".
>
> Nice! Thanks Miguel.  Regarding sorting, I'm happy with that.  In
> fact, some of the comments can be removed IMO, as the attributes have
> common definitions in the docs (maybe an added link to the gcc and
> clang attribute docs at the top of the file rather than per attribute
> comments).
>
> >
> > Further, attributes that are already supported in gcc >= 4.6 and recent clang
> > were simply made to be required (instead of testing for them):
> >   * always_inline
> >   * const (pure was already "required", by the way)
> >   * gnu_inline
>
> There's an important test for gnu_inline that isn't checking that it's
> supported, but rather what the implicit behavior is depending on which
> C standard is being used.  It's important not to remove that.
>
> >
> > Finally, some other bits were cleaned up in the process:
> >   * __optimize: removed (unused in the whole kernel tree)
>
> A+ for removing dead code.  I also don't see it used anywhere.
>
> >   * __must_be_array: removed from -gcc and -clang (identical), moved to _types
>
> Yep, uses a builtin (we should add guards for that, later, in a
> similar style change that guards the use of builtins). Looks good.
>
> >     (it depends on the unconditionally used  __builtin_types_compatible_p
> >   * Removes unneeded underscores on the attributes' names
>
> That doesn't sound right, but lets see what you mean by that.
>
> >
> > There are some things that can be further cleaned up afterwards:
> >   * __attribute_const__: rename to __const
>
> This doesn't look correct to me; the kernel is full of call sites for
> __attribute_const__. You can't rename the definition without renaming
> all of the call sites (and that would be too big a change for this
> patch, IMO).  Skip the rename, and it also looks like you just removed
> it outright (Oops).
>
> >   * __noretpoline: avoid checking for defined(__notrepoline)
> >   * __compiletime_warning/error: they are in two different places,
> >     -gcc and compiler.h.
> >   * sparse' attributes could potentially go into the end of attributes.h
> >     too (as another separate section).
> >
> > Compile-tested an x86 allmodconfig for a while with gcc 8.2.0 and 4.6.4.
>
> It's important to test changes to compiler-clang.h with clang. ;)
>
> >
> > Cc: Eli Friedman <efriedma@codeaurora.org>
> > Cc: Christopher Li <sparse@chrisli.org>
> > Cc: Kees Cook <keescook@chromium.org>
> > Cc: Ingo Molnar <mingo@kernel.org>
> > Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
> > Cc: Joe Perches <joe@perches.com>
> > Cc: Dominique Martinet <asmadeus@codewreck.org>
> > Cc: Nick Desaulniers <ndesaulniers@google.com>
> > Cc: Linus Torvalds <torvalds@linux-foundation.org>
> > Signed-off-by: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
> > ---
> > *Seems* to work, but note that I did not finish the entire allmodconfig :)
> >
> > A few things could be splitted into their own patch, but I kept it
> > as one for simplicity for a first review.
> >
> > These files are becoming no-headaches-readable again, yay.
>
> A+
>
> >
> >  include/linux/compiler-clang.h      |   5 --
> >  include/linux/compiler-gcc.h        |  60 ----------------
> >  include/linux/compiler-intel.h      |   6 --
> >  include/linux/compiler.h            |   4 --
> >  include/linux/compiler_attributes.h | 105 ++++++++++++++++++++++++++++
> >  include/linux/compiler_types.h      |  91 ++++--------------------
> >  6 files changed, 118 insertions(+), 153 deletions(-)
> >  create mode 100644 include/linux/compiler_attributes.h
> >
> > diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
> > index b1ce500fe8b3..3e7dafb3ea80 100644
> > --- a/include/linux/compiler-clang.h
> > +++ b/include/linux/compiler-clang.h
> > @@ -21,8 +21,6 @@
> >  #define __SANITIZE_ADDRESS__
> >  #endif
> >
> > -#define __no_sanitize_address __attribute__((no_sanitize("address")))
> > -
> >  /*
> >   * Not all versions of clang implement the the type-generic versions
> >   * of the builtin overflow checkers. Fortunately, clang implements
> > @@ -41,6 +39,3 @@
> >   * compilers, like ICC.
> >   */
> >  #define barrier() __asm__ __volatile__("" : : : "memory")
> > -#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
> > -#define __assume_aligned(a, ...)       \
> > -       __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
> > diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
> > index 763bbad1e258..dde3daae6287 100644
> > --- a/include/linux/compiler-gcc.h
> > +++ b/include/linux/compiler-gcc.h
> > @@ -68,13 +68,6 @@
> >   */
> >  #define uninitialized_var(x) x = x
> >
> > -#ifdef __CHECKER__
> > -#define __must_be_array(a)     0
> > -#else
> > -/* &a[0] degrades to a pointer: a different type from an array */
> > -#define __must_be_array(a)     BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
> > -#endif
> > -
> >  #ifdef RETPOLINE
> >  #define __noretpoline __attribute__((indirect_branch("keep")))
> >  #endif
> > @@ -95,8 +88,6 @@
> >
> >  #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
> >
> > -#define __optimize(level)      __attribute__((__optimize__(level)))
> > -
> >  #define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
> >
> >  #ifndef __CHECKER__
> > @@ -133,9 +124,6 @@
> >                 __builtin_unreachable();        \
> >         } while (0)
> >
> > -/* Mark a function definition as prohibited from being cloned. */
> > -#define __noclone      __attribute__((__noclone__, __optimize__("no-tracer")))
> > -
> >  #if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
> >  #define __randomize_layout __attribute__((randomize_layout))
> >  #define __no_randomize_layout __attribute__((no_randomize_layout))
> > @@ -144,32 +132,6 @@
> >  #define randomized_struct_fields_end   } __randomize_layout;
> >  #endif
> >
> > -/*
> > - * When used with Link Time Optimization, gcc can optimize away C functions or
> > - * variables which are referenced only from assembly code.  __visible tells the
> > - * optimizer that something else uses this function or variable, thus preventing
> > - * this.
> > - */
> > -#define __visible      __attribute__((externally_visible))
> > -
> > -/* gcc version specific checks */
> > -
> > -#if GCC_VERSION >= 40900 && !defined(__CHECKER__)
> > -/*
> > - * __assume_aligned(n, k): Tell the optimizer that the returned
> > - * pointer can be assumed to be k modulo n. The second argument is
> > - * optional (default 0), so we use a variadic macro to make the
> > - * shorthand.
> > - *
> > - * Beware: Do not apply this to functions which may return
> > - * ERR_PTRs. Also, it is probably unwise to apply it to functions
> > - * returning extra information in the low bits (but in that case the
> > - * compiler should see some alignment anyway, when the return value is
> > - * massaged by 'flags = ptr & 3; ptr &= ~3;').
> > - */
> > -#define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
> > -#endif
> > -
> >  /*
> >   * GCC 'asm goto' miscompiles certain code sequences:
> >   *
> > @@ -201,32 +163,10 @@
> >  #define KASAN_ABI_VERSION 3
> >  #endif
> >
> > -#if GCC_VERSION >= 40902
> > -/*
> > - * Tell the compiler that address safety instrumentation (KASAN)
> > - * should not be applied to that function.
> > - * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
> > - */
> > -#define __no_sanitize_address __attribute__((no_sanitize_address))
> > -#endif
> > -
> >  #if GCC_VERSION >= 50100
> > -/*
> > - * Mark structures as requiring designated initializers.
> > - * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
> > - */
> > -#define __designated_init __attribute__((designated_init))
> >  #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
> >  #endif
> >
> > -#if !defined(__noclone)
> > -#define __noclone      /* not needed */
> > -#endif
> > -
> > -#if !defined(__no_sanitize_address)
> > -#define __no_sanitize_address
> > -#endif
> > -
> >  /*
> >   * Turn individual warnings and errors on and off locally, depending
> >   * on version.
> > diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h
> > index 4c7f9befa9f6..fb9e77fc65ec 100644
> > --- a/include/linux/compiler-intel.h
> > +++ b/include/linux/compiler-intel.h
> > @@ -37,9 +37,3 @@
> >  /* icc has this, but it's called _bswap16 */
> >  #define __HAVE_BUILTIN_BSWAP16__
> >  #define __builtin_bswap16 _bswap16
> > -
> > -/* The following are for compatibility with GCC, from compiler-gcc.h,
> > - * and may be redefined here because they should not be shared with other
> > - * compilers, like clang.
> > - */
> > -#define __visible      __attribute__((externally_visible))
> > diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> > index 681d866efb1e..7c0157d50964 100644
> > --- a/include/linux/compiler.h
> > +++ b/include/linux/compiler.h
> > @@ -301,10 +301,6 @@ static inline void *offset_to_ptr(const int *off)
> >
> >  #endif /* __ASSEMBLY__ */
> >
> > -#ifndef __optimize
> > -# define __optimize(level)
> > -#endif
> > -
> >  /* Compile time object size, -1 for unknown */
> >  #ifndef __compiletime_object_size
> >  # define __compiletime_object_size(obj) -1
> > diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
> > new file mode 100644
> > index 000000000000..af8c8413d136
> > --- /dev/null
> > +++ b/include/linux/compiler_attributes.h
> > @@ -0,0 +1,105 @@
> > +#ifndef __LINUX_COMPILER_ATTRIBUTES_H
> > +#define __LINUX_COMPILER_ATTRIBUTES_H
> > +
> > +/* This file is meant to be sorted. */
> > +
> > +/*
> > + * Required attributes: your compiler must support these.
> > + */
> > +#define __alias(symbol)                __attribute__((alias(#symbol)))
> > +#define __aligned(x)           __attribute__((aligned(x)))
> > +#define __aligned_largest      __attribute__((aligned))
> > +#define __always_inline         inline __attribute__((always_inline))
> > +#define __always_unused                __attribute__((unused))
> > +#define __attribute_const__     __attribute__((const))
> > +#define __cold                 __attribute__((cold))
> > +#define __gnu_inline            __attribute__((gnu_inline))
> > +#define __malloc               __attribute__((malloc))
> > +#define __maybe_unused         __attribute__((unused))
> > +#define __mode(x)              __attribute__((mode(x)))
> > +#define   noinline              __attribute__((noinline))
> > +#define __noreturn             __attribute__((noreturn))
> > +#define __packed               __attribute__((packed))
> > +#define __printf(a, b)         __attribute__((format(printf, a, b)))
> > +#define __pure                 __attribute__((pure))
> > +#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
> > +#define __section(S)           __attribute__((section(#S)))
> > +#define __used                 __attribute__((used))
> > +#define __weak                 __attribute__((weak))
> > +
> > +/*
> > + * Optional attributes: your compiler may or may not support them.
> > + *
> > + * To check for them, we use __has_attribute, which is supported on gcc >= 5,
> > + * clang >= 2.9 and icc >= 17. In the meantime, to support 4.6 <= gcc < 5,
> > + * we implement it by hand.
> > + */
> > +#ifndef __has_attribute
> > +#define __has_attribute(x) __GCC46_has_attribute_##x
> > +#define __GCC46_has_attribute_assume_aligned 0
> > +#define __GCC46_has_attribute_designated_init 0
> > +#define __GCC46_has_attribute_externally_visible 1
> > +#define __GCC46_has_attribute_noclone 1
> > +#define __GCC46_has_attribute_optimize 1
> > +#define __GCC46_has_attribute_no_sanitize_address 0
> > +#endif

And a follow up; I'm trying to understand what will happen in the case
of say gcc 4.9 here.  Were any of these supported between gcc 4.6 and
5.0?  If so, then this code will not use them.  It's simpler than
explicit version checks, but it won't use features that are supported.

> > +
> > +/*
> > + * __assume_aligned(n, k): Tell the optimizer that the returned
> > + * pointer can be assumed to be k modulo n. The second argument is
> > + * optional (default 0), so we use a variadic macro to make the
> > + * shorthand.
> > + *
> > + * Beware: Do not apply this to functions which may return
> > + * ERR_PTRs. Also, it is probably unwise to apply it to functions
> > + * returning extra information in the low bits (but in that case the
> > + * compiler should see some alignment anyway, when the return value is
> > + * massaged by 'flags = ptr & 3; ptr &= ~3;').
> > + */
> > +#if __has_attribute(assume_aligned)
> > +#define __assume_aligned(a, ...) __attribute__((assume_aligned(a, ## __VA_ARGS__)))
> > +#else
> > +#define __assume_aligned(a, ...)
> > +#endif
> > +
> > +/*
> > + * Mark structures as requiring designated initializers.
> > + * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
> > + */
> > +#if __has_attribute(designated_init)
> > +#define __designated_init __attribute__((designated_init))
> > +#else
> > +#define __designated_init
> > +#endif
> > +
> > +/*
> > + * When used with Link Time Optimization, gcc can optimize away C functions or
> > + * variables which are referenced only from assembly code.  __visible tells the
> > + * optimizer that something else uses this function or variable, thus preventing
> > + * this.
> > + */
> > +#if __has_attribute(externally_visible)
> > +#define __visible __attribute__((externally_visible))
> > +#else
> > +#define __visible
> > +#endif
> > +
> > +/* Mark a function definition as prohibited from being cloned. */
> > +#if __has_attribute(noclone) && __has_attribute(optimize)
> > +#define __noclone __attribute__((noclone, optimize("no-tracer")))
> > +#else
> > +#define __noclone
> > +#endif
> > +
> > +/*
> > + * Tell the compiler that address safety instrumentation (KASAN)
> > + * should not be applied to that function.
> > + * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
> > + */
> > +#if __has_attribute(no_sanitize_address)
> > +#define __no_sanitize_address __attribute__((no_sanitize_address))
> > +#else
> > +#define __no_sanitize_address
> > +#endif
> > +
> > +#endif /* __LINUX_COMPILER_ATTRIBUTES_H */
> > diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
> > index 3525c179698c..8cd622bedec4 100644
> > --- a/include/linux/compiler_types.h
> > +++ b/include/linux/compiler_types.h
> > @@ -54,6 +54,9 @@ extern void __chk_io_ptr(const volatile void __iomem *);
> >
> >  #ifdef __KERNEL__
> >
> > +/* Attributes */
> > +#include <linux/compiler_attributes.h>
> > +
> >  /* Compiler specific macros. */
> >  #ifdef __clang__
> >  #include <linux/compiler-clang.h>
> > @@ -78,12 +81,6 @@ extern void __chk_io_ptr(const volatile void __iomem *);
> >  #include <asm/compiler.h>
> >  #endif
> >
> > -/*
> > - * Generic compiler-independent macros required for kernel
> > - * build go below this comment. Actual compiler/compiler version
> > - * specific implementations come from the above header files
> > - */
> > -
> >  struct ftrace_branch_data {
> >         const char *func;
> >         const char *file;
> > @@ -119,10 +116,6 @@ struct ftrace_likely_data {
> >   * compilers. We don't consider that to be an error, so set them to nothing.
> >   * For example, some of them are for compiler specific plugins.
> >   */
> > -#ifndef __designated_init
> > -# define __designated_init
> > -#endif
> > -
> >  #ifndef __latent_entropy
> >  # define __latent_entropy
> >  #endif
> > @@ -140,17 +133,6 @@ struct ftrace_likely_data {
> >  # define randomized_struct_fields_end
> >  #endif
> >
> > -#ifndef __visible
> > -#define __visible
> > -#endif
> > -
> > -/*
> > - * Assume alignment of return value.
> > - */
> > -#ifndef __assume_aligned
> > -#define __assume_aligned(a, ...)
> > -#endif
> > -
> >  /* Are two types/vars the same type (ignoring qualifiers)? */
> >  #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
> >
> > @@ -159,14 +141,6 @@ struct ftrace_likely_data {
> >         (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
> >          sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
> >
> > -#ifndef __attribute_const__
> > -#define __attribute_const__    __attribute__((__const__))
> > -#endif
> > -
> > -#ifndef __noclone
> > -#define __noclone
> > -#endif
> > -
> >  /* Helpers for emitting diagnostics in pragmas. */
> >  #ifndef __diag
> >  #define __diag(string)
> > @@ -186,34 +160,6 @@ struct ftrace_likely_data {
> >  #define __diag_error(compiler, version, option, comment) \
> >         __diag_ ## compiler(version, error, option)
> >
> > -/*
> > - * From the GCC manual:
> > - *
> > - * Many functions have no effects except the return value and their
> > - * return value depends only on the parameters and/or global
> > - * variables.  Such a function can be subject to common subexpression
> > - * elimination and loop optimization just as an arithmetic operator
> > - * would be.
> > - * [...]
> > - */
> > -#define __pure                 __attribute__((pure))
> > -#define __aligned(x)           __attribute__((aligned(x)))
> > -#define __aligned_largest      __attribute__((aligned))
> > -#define __printf(a, b)         __attribute__((format(printf, a, b)))
> > -#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
> > -#define __maybe_unused         __attribute__((unused))
> > -#define __always_unused                __attribute__((unused))
> > -#define __mode(x)              __attribute__((mode(x)))
> > -#define __malloc               __attribute__((__malloc__))
> > -#define __used                 __attribute__((__used__))
> > -#define __noreturn             __attribute__((noreturn))
> > -#define __packed               __attribute__((packed))
> > -#define __weak                 __attribute__((weak))
> > -#define __alias(symbol)                __attribute__((alias(#symbol)))
> > -#define __cold                 __attribute__((cold))
> > -#define __section(S)           __attribute__((__section__(#S)))
> > -
> > -
> >  #ifdef CONFIG_ENABLE_MUST_CHECK
> >  #define __must_check           __attribute__((warn_unused_result))
> >  #else
> > @@ -228,18 +174,6 @@ struct ftrace_likely_data {
> >
> >  #define __compiler_offsetof(a, b)      __builtin_offsetof(a, b)
> >
> > -/*
> > - * Feature detection for gnu_inline (gnu89 extern inline semantics). Either
> > - * __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics,
> > - * and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not
> > - * defined so the gnu89 semantics are the default.
> > - */
> > -#ifdef __GNUC_STDC_INLINE__
> > -# define __gnu_inline  __attribute__((gnu_inline))
> > -#else
> > -# define __gnu_inline
> > -#endif
> > -
> >  /*
> >   * Force always-inline if the user requests it so via the .config.
> >   * GCC does not warn about unused static inline functions for
> > @@ -254,19 +188,13 @@ struct ftrace_likely_data {
> >   */
> >  #if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
> >         !defined(CONFIG_OPTIMIZE_INLINING)
> > -#define inline \
> > -       inline __attribute__((always_inline, unused)) notrace __gnu_inline
> > +#define inline inline __attribute__((always_inline, unused)) notrace __gnu_inline
> >  #else
> > -#define inline inline  __attribute__((unused)) notrace __gnu_inline
> > +#define inline inline __attribute__((unused)) notrace __gnu_inline
> >  #endif
> >
> >  #define __inline__ inline
> > -#define __inline inline
> > -#define noinline       __attribute__((noinline))
> > -
> > -#ifndef __always_inline
> > -#define __always_inline inline __attribute__((always_inline))
> > -#endif
> > +#define __inline   inline
>
> All of the changes to inline should not be removed, see above.  It's
> important to make this work correctly regardless of C standard used.
>
> >
> >  /*
> >   * Rather then using noinline to prevent stack consumption, use
> > @@ -274,4 +202,11 @@ struct ftrace_likely_data {
> >   */
> >  #define noinline_for_stack noinline
> >
> > +#ifdef __CHECKER__
> > +#define __must_be_array(a) 0
> > +#else
> > +/* &a[0] degrades to a pointer: a different type from an array */
> > +#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
> > +#endif
> > +
> >  #endif /* __LINUX_COMPILER_TYPES_H */
> > --
> > 2.17.1
> >
>
> With the above changes requested, I'm super happy with the spirit of
> this patch, and look forward to a v2.  Thanks again Miguel!
> --
> Thanks,
> ~Nick Desaulniers



-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-27 17:43 ` Nick Desaulniers
  2018-08-27 17:48   ` Nick Desaulniers
@ 2018-08-28 15:03   ` Miguel Ojeda
  2018-08-28 16:53     ` Nick Desaulniers
  1 sibling, 1 reply; 12+ messages in thread
From: Miguel Ojeda @ 2018-08-28 15:03 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Linus Torvalds, Eli Friedman, Christopher Li, Kees Cook,
	Ingo Molnar, Geert Uytterhoeven, Arnd Bergmann, Greg KH,
	Masahiro Yamada, Joe Perches, Dominique Martinet, LKML

Hi Nick,

On Mon, Aug 27, 2018 at 7:43 PM, Nick Desaulniers
<ndesaulniers@google.com> wrote:
> On Sun, Aug 26, 2018 at 10:58 AM Miguel Ojeda
> <miguel.ojeda.sandonis@gmail.com> wrote:
>>
>> Instead of using version checks per-compiler to define (or not) each attribute,
>> use __has_attribute to test for them, following the cleanup started with
>> commit 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive").
>>
>> All the attributes that are fairly common/standard (i.e. those that do not
>> require extra logic to define them) have been moved to a new file
>> include/linux/compiler_attributes.h. The attributes have been sorted
>> and divided between "required" and "optional".
>
> Nice! Thanks Miguel.  Regarding sorting, I'm happy with that.  In
> fact, some of the comments can be removed IMO, as the attributes have
> common definitions in the docs (maybe an added link to the gcc and
> clang attribute docs at the top of the file rather than per attribute
> comments).

Thanks for the review!

I thought about that, although there isn't a single page with them in
GCC (we could group them by type though: function ones, variable
ones... and then link to those). On the other hand, maybe writing a
Doc/ file is better and allows us to write as much as one would like
about each of them (and a link to each page compiler's page about it,
etc.). I think in the end the Doc/ file might be the best, in order
not to crowd the header.

>
>>
>> Further, attributes that are already supported in gcc >= 4.6 and recent clang
>> were simply made to be required (instead of testing for them):
>>   * always_inline
>>   * const (pure was already "required", by the way)
>>   * gnu_inline
>
> There's an important test for gnu_inline that isn't checking that it's
> supported, but rather what the implicit behavior is depending on which
> C standard is being used.  It's important not to remove that.

Hm... I actually thought it was not available at some point before 4.6
and removed the #ifdef. The comment even says it is featuring
detecting it so that the old GCC inlining is used; but it shouldn't
matter if you always use it, no?

I just went looking for more info in d03db2bc2 ("compiler-gcc.h: Add
__attribute__((gnu_inline)) to all inline declarations") and if I
understood the commit message, the problem is compiling with implicit
new standard in newer compilers which trigger the C90 behavior, while
we need the old one --- but if we use gnu_inline, we are getting it
regardless.

I am sure I am missing something, but I think a clarification is
needed (and in the code comment as well) -- a bit off-topic, anyway.

[Also, I wouldn't define an attribute or not depending on some other
condition. I would, instead, define something some other symbol with
that logic (i.e. instead of using "__gnu_inline", because that is
lying -- it is not using the attribute even if the compiler supports
it).]

>
>>
>> Finally, some other bits were cleaned up in the process:
>>   * __optimize: removed (unused in the whole kernel tree)
>
> A+ for removing dead code.  I also don't see it used anywhere.
>
>>   * __must_be_array: removed from -gcc and -clang (identical), moved to _types
>
> Yep, uses a builtin (we should add guards for that, later, in a
> similar style change that guards the use of builtins). Looks good.
>
>>     (it depends on the unconditionally used  __builtin_types_compatible_p
>>   * Removes unneeded underscores on the attributes' names
>
> That doesn't sound right, but lets see what you mean by that.

Some attributes used the __name__ syntax (i.e. inside the double
parenthesis), others didn't. I simplified by removing all the extra
underscores.

>
>>
>> There are some things that can be further cleaned up afterwards:
>>   * __attribute_const__: rename to __const
>
> This doesn't look correct to me; the kernel is full of call sites for
> __attribute_const__. You can't rename the definition without renaming

Of course it is full of use sites! That is why I said it is a possible
cleanup for *afterwards* this patch :-)

> all of the call sites (and that would be too big a change for this
> patch, IMO).  Skip the rename, and it also looks like you just removed
> it outright (Oops).

Not sure what you mean by this (?). The attribute is still there unchanged.

>
>>   * __noretpoline: avoid checking for defined(__notrepoline)
>>   * __compiletime_warning/error: they are in two different places,
>>     -gcc and compiler.h.
>>   * sparse' attributes could potentially go into the end of attributes.h
>>     too (as another separate section).
>>
>> Compile-tested an x86 allmodconfig for a while with gcc 8.2.0 and 4.6.4.
>
> It's important to test changes to compiler-clang.h with clang. ;)

I would agree if the clang build wasn't broken to begin with. ;)

>
>>
>> Cc: Eli Friedman <efriedma@codeaurora.org>
>> Cc: Christopher Li <sparse@chrisli.org>
>> Cc: Kees Cook <keescook@chromium.org>
>> Cc: Ingo Molnar <mingo@kernel.org>
>> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
>> Cc: Joe Perches <joe@perches.com>
>> Cc: Dominique Martinet <asmadeus@codewreck.org>
>> Cc: Nick Desaulniers <ndesaulniers@google.com>
>> Cc: Linus Torvalds <torvalds@linux-foundation.org>
>> Signed-off-by: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
>> ---
>> *Seems* to work, but note that I did not finish the entire allmodconfig :)
>>
>> A few things could be splitted into their own patch, but I kept it
>> as one for simplicity for a first review.
>>
>> These files are becoming no-headaches-readable again, yay.
>
> A+
>
>>
>>  include/linux/compiler-clang.h      |   5 --
>>  include/linux/compiler-gcc.h        |  60 ----------------
>>  include/linux/compiler-intel.h      |   6 --
>>  include/linux/compiler.h            |   4 --
>>  include/linux/compiler_attributes.h | 105 ++++++++++++++++++++++++++++
>>  include/linux/compiler_types.h      |  91 ++++--------------------
>>  6 files changed, 118 insertions(+), 153 deletions(-)
>>  create mode 100644 include/linux/compiler_attributes.h
>>
>> diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
>> index b1ce500fe8b3..3e7dafb3ea80 100644
>> --- a/include/linux/compiler-clang.h
>> +++ b/include/linux/compiler-clang.h
>> @@ -21,8 +21,6 @@
>>  #define __SANITIZE_ADDRESS__
>>  #endif
>>
>> -#define __no_sanitize_address __attribute__((no_sanitize("address")))
>> -
>>  /*
>>   * Not all versions of clang implement the the type-generic versions
>>   * of the builtin overflow checkers. Fortunately, clang implements
>> @@ -41,6 +39,3 @@
>>   * compilers, like ICC.
>>   */
>>  #define barrier() __asm__ __volatile__("" : : : "memory")
>> -#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
>> -#define __assume_aligned(a, ...)       \
>> -       __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
>> diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
>> index 763bbad1e258..dde3daae6287 100644
>> --- a/include/linux/compiler-gcc.h
>> +++ b/include/linux/compiler-gcc.h
>> @@ -68,13 +68,6 @@
>>   */
>>  #define uninitialized_var(x) x = x
>>
>> -#ifdef __CHECKER__
>> -#define __must_be_array(a)     0
>> -#else
>> -/* &a[0] degrades to a pointer: a different type from an array */
>> -#define __must_be_array(a)     BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
>> -#endif
>> -
>>  #ifdef RETPOLINE
>>  #define __noretpoline __attribute__((indirect_branch("keep")))
>>  #endif
>> @@ -95,8 +88,6 @@
>>
>>  #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
>>
>> -#define __optimize(level)      __attribute__((__optimize__(level)))
>> -
>>  #define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
>>
>>  #ifndef __CHECKER__
>> @@ -133,9 +124,6 @@
>>                 __builtin_unreachable();        \
>>         } while (0)
>>
>> -/* Mark a function definition as prohibited from being cloned. */
>> -#define __noclone      __attribute__((__noclone__, __optimize__("no-tracer")))
>> -
>>  #if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
>>  #define __randomize_layout __attribute__((randomize_layout))
>>  #define __no_randomize_layout __attribute__((no_randomize_layout))
>> @@ -144,32 +132,6 @@
>>  #define randomized_struct_fields_end   } __randomize_layout;
>>  #endif
>>
>> -/*
>> - * When used with Link Time Optimization, gcc can optimize away C functions or
>> - * variables which are referenced only from assembly code.  __visible tells the
>> - * optimizer that something else uses this function or variable, thus preventing
>> - * this.
>> - */
>> -#define __visible      __attribute__((externally_visible))
>> -
>> -/* gcc version specific checks */
>> -
>> -#if GCC_VERSION >= 40900 && !defined(__CHECKER__)
>> -/*
>> - * __assume_aligned(n, k): Tell the optimizer that the returned
>> - * pointer can be assumed to be k modulo n. The second argument is
>> - * optional (default 0), so we use a variadic macro to make the
>> - * shorthand.
>> - *
>> - * Beware: Do not apply this to functions which may return
>> - * ERR_PTRs. Also, it is probably unwise to apply it to functions
>> - * returning extra information in the low bits (but in that case the
>> - * compiler should see some alignment anyway, when the return value is
>> - * massaged by 'flags = ptr & 3; ptr &= ~3;').
>> - */
>> -#define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
>> -#endif
>> -
>>  /*
>>   * GCC 'asm goto' miscompiles certain code sequences:
>>   *
>> @@ -201,32 +163,10 @@
>>  #define KASAN_ABI_VERSION 3
>>  #endif
>>
>> -#if GCC_VERSION >= 40902
>> -/*
>> - * Tell the compiler that address safety instrumentation (KASAN)
>> - * should not be applied to that function.
>> - * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
>> - */
>> -#define __no_sanitize_address __attribute__((no_sanitize_address))
>> -#endif
>> -
>>  #if GCC_VERSION >= 50100
>> -/*
>> - * Mark structures as requiring designated initializers.
>> - * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
>> - */
>> -#define __designated_init __attribute__((designated_init))
>>  #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
>>  #endif
>>
>> -#if !defined(__noclone)
>> -#define __noclone      /* not needed */
>> -#endif
>> -
>> -#if !defined(__no_sanitize_address)
>> -#define __no_sanitize_address
>> -#endif
>> -
>>  /*
>>   * Turn individual warnings and errors on and off locally, depending
>>   * on version.
>> diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h
>> index 4c7f9befa9f6..fb9e77fc65ec 100644
>> --- a/include/linux/compiler-intel.h
>> +++ b/include/linux/compiler-intel.h
>> @@ -37,9 +37,3 @@
>>  /* icc has this, but it's called _bswap16 */
>>  #define __HAVE_BUILTIN_BSWAP16__
>>  #define __builtin_bswap16 _bswap16
>> -
>> -/* The following are for compatibility with GCC, from compiler-gcc.h,
>> - * and may be redefined here because they should not be shared with other
>> - * compilers, like clang.
>> - */
>> -#define __visible      __attribute__((externally_visible))
>> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
>> index 681d866efb1e..7c0157d50964 100644
>> --- a/include/linux/compiler.h
>> +++ b/include/linux/compiler.h
>> @@ -301,10 +301,6 @@ static inline void *offset_to_ptr(const int *off)
>>
>>  #endif /* __ASSEMBLY__ */
>>
>> -#ifndef __optimize
>> -# define __optimize(level)
>> -#endif
>> -
>>  /* Compile time object size, -1 for unknown */
>>  #ifndef __compiletime_object_size
>>  # define __compiletime_object_size(obj) -1
>> diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
>> new file mode 100644
>> index 000000000000..af8c8413d136
>> --- /dev/null
>> +++ b/include/linux/compiler_attributes.h
>> @@ -0,0 +1,105 @@
>> +#ifndef __LINUX_COMPILER_ATTRIBUTES_H
>> +#define __LINUX_COMPILER_ATTRIBUTES_H
>> +
>> +/* This file is meant to be sorted. */
>> +
>> +/*
>> + * Required attributes: your compiler must support these.
>> + */
>> +#define __alias(symbol)                __attribute__((alias(#symbol)))
>> +#define __aligned(x)           __attribute__((aligned(x)))
>> +#define __aligned_largest      __attribute__((aligned))
>> +#define __always_inline         inline __attribute__((always_inline))
>> +#define __always_unused                __attribute__((unused))
>> +#define __attribute_const__     __attribute__((const))
>> +#define __cold                 __attribute__((cold))
>> +#define __gnu_inline            __attribute__((gnu_inline))
>> +#define __malloc               __attribute__((malloc))
>> +#define __maybe_unused         __attribute__((unused))
>> +#define __mode(x)              __attribute__((mode(x)))
>> +#define   noinline              __attribute__((noinline))
>> +#define __noreturn             __attribute__((noreturn))
>> +#define __packed               __attribute__((packed))
>> +#define __printf(a, b)         __attribute__((format(printf, a, b)))
>> +#define __pure                 __attribute__((pure))
>> +#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
>> +#define __section(S)           __attribute__((section(#S)))
>> +#define __used                 __attribute__((used))
>> +#define __weak                 __attribute__((weak))
>> +
>> +/*
>> + * Optional attributes: your compiler may or may not support them.
>> + *
>> + * To check for them, we use __has_attribute, which is supported on gcc >= 5,
>> + * clang >= 2.9 and icc >= 17. In the meantime, to support 4.6 <= gcc < 5,
>> + * we implement it by hand.
>> + */
>> +#ifndef __has_attribute
>> +#define __has_attribute(x) __GCC46_has_attribute_##x
>> +#define __GCC46_has_attribute_assume_aligned 0
>> +#define __GCC46_has_attribute_designated_init 0
>> +#define __GCC46_has_attribute_externally_visible 1
>> +#define __GCC46_has_attribute_noclone 1
>> +#define __GCC46_has_attribute_optimize 1
>> +#define __GCC46_has_attribute_no_sanitize_address 0
>> +#endif
>> +
>> +/*
>> + * __assume_aligned(n, k): Tell the optimizer that the returned
>> + * pointer can be assumed to be k modulo n. The second argument is
>> + * optional (default 0), so we use a variadic macro to make the
>> + * shorthand.
>> + *
>> + * Beware: Do not apply this to functions which may return
>> + * ERR_PTRs. Also, it is probably unwise to apply it to functions
>> + * returning extra information in the low bits (but in that case the
>> + * compiler should see some alignment anyway, when the return value is
>> + * massaged by 'flags = ptr & 3; ptr &= ~3;').
>> + */
>> +#if __has_attribute(assume_aligned)
>> +#define __assume_aligned(a, ...) __attribute__((assume_aligned(a, ## __VA_ARGS__)))
>> +#else
>> +#define __assume_aligned(a, ...)
>> +#endif
>> +
>> +/*
>> + * Mark structures as requiring designated initializers.
>> + * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
>> + */
>> +#if __has_attribute(designated_init)
>> +#define __designated_init __attribute__((designated_init))
>> +#else
>> +#define __designated_init
>> +#endif
>> +
>> +/*
>> + * When used with Link Time Optimization, gcc can optimize away C functions or
>> + * variables which are referenced only from assembly code.  __visible tells the
>> + * optimizer that something else uses this function or variable, thus preventing
>> + * this.
>> + */
>> +#if __has_attribute(externally_visible)
>> +#define __visible __attribute__((externally_visible))
>> +#else
>> +#define __visible
>> +#endif
>> +
>> +/* Mark a function definition as prohibited from being cloned. */
>> +#if __has_attribute(noclone) && __has_attribute(optimize)
>> +#define __noclone __attribute__((noclone, optimize("no-tracer")))
>> +#else
>> +#define __noclone
>> +#endif
>> +
>> +/*
>> + * Tell the compiler that address safety instrumentation (KASAN)
>> + * should not be applied to that function.
>> + * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
>> + */
>> +#if __has_attribute(no_sanitize_address)
>> +#define __no_sanitize_address __attribute__((no_sanitize_address))
>> +#else
>> +#define __no_sanitize_address
>> +#endif
>> +
>> +#endif /* __LINUX_COMPILER_ATTRIBUTES_H */
>> diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
>> index 3525c179698c..8cd622bedec4 100644
>> --- a/include/linux/compiler_types.h
>> +++ b/include/linux/compiler_types.h
>> @@ -54,6 +54,9 @@ extern void __chk_io_ptr(const volatile void __iomem *);
>>
>>  #ifdef __KERNEL__
>>
>> +/* Attributes */
>> +#include <linux/compiler_attributes.h>
>> +
>>  /* Compiler specific macros. */
>>  #ifdef __clang__
>>  #include <linux/compiler-clang.h>
>> @@ -78,12 +81,6 @@ extern void __chk_io_ptr(const volatile void __iomem *);
>>  #include <asm/compiler.h>
>>  #endif
>>
>> -/*
>> - * Generic compiler-independent macros required for kernel
>> - * build go below this comment. Actual compiler/compiler version
>> - * specific implementations come from the above header files
>> - */
>> -
>>  struct ftrace_branch_data {
>>         const char *func;
>>         const char *file;
>> @@ -119,10 +116,6 @@ struct ftrace_likely_data {
>>   * compilers. We don't consider that to be an error, so set them to nothing.
>>   * For example, some of them are for compiler specific plugins.
>>   */
>> -#ifndef __designated_init
>> -# define __designated_init
>> -#endif
>> -
>>  #ifndef __latent_entropy
>>  # define __latent_entropy
>>  #endif
>> @@ -140,17 +133,6 @@ struct ftrace_likely_data {
>>  # define randomized_struct_fields_end
>>  #endif
>>
>> -#ifndef __visible
>> -#define __visible
>> -#endif
>> -
>> -/*
>> - * Assume alignment of return value.
>> - */
>> -#ifndef __assume_aligned
>> -#define __assume_aligned(a, ...)
>> -#endif
>> -
>>  /* Are two types/vars the same type (ignoring qualifiers)? */
>>  #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
>>
>> @@ -159,14 +141,6 @@ struct ftrace_likely_data {
>>         (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
>>          sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
>>
>> -#ifndef __attribute_const__
>> -#define __attribute_const__    __attribute__((__const__))
>> -#endif
>> -
>> -#ifndef __noclone
>> -#define __noclone
>> -#endif
>> -
>>  /* Helpers for emitting diagnostics in pragmas. */
>>  #ifndef __diag
>>  #define __diag(string)
>> @@ -186,34 +160,6 @@ struct ftrace_likely_data {
>>  #define __diag_error(compiler, version, option, comment) \
>>         __diag_ ## compiler(version, error, option)
>>
>> -/*
>> - * From the GCC manual:
>> - *
>> - * Many functions have no effects except the return value and their
>> - * return value depends only on the parameters and/or global
>> - * variables.  Such a function can be subject to common subexpression
>> - * elimination and loop optimization just as an arithmetic operator
>> - * would be.
>> - * [...]
>> - */
>> -#define __pure                 __attribute__((pure))
>> -#define __aligned(x)           __attribute__((aligned(x)))
>> -#define __aligned_largest      __attribute__((aligned))
>> -#define __printf(a, b)         __attribute__((format(printf, a, b)))
>> -#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
>> -#define __maybe_unused         __attribute__((unused))
>> -#define __always_unused                __attribute__((unused))
>> -#define __mode(x)              __attribute__((mode(x)))
>> -#define __malloc               __attribute__((__malloc__))
>> -#define __used                 __attribute__((__used__))
>> -#define __noreturn             __attribute__((noreturn))
>> -#define __packed               __attribute__((packed))
>> -#define __weak                 __attribute__((weak))
>> -#define __alias(symbol)                __attribute__((alias(#symbol)))
>> -#define __cold                 __attribute__((cold))
>> -#define __section(S)           __attribute__((__section__(#S)))
>> -
>> -
>>  #ifdef CONFIG_ENABLE_MUST_CHECK
>>  #define __must_check           __attribute__((warn_unused_result))
>>  #else
>> @@ -228,18 +174,6 @@ struct ftrace_likely_data {
>>
>>  #define __compiler_offsetof(a, b)      __builtin_offsetof(a, b)
>>
>> -/*
>> - * Feature detection for gnu_inline (gnu89 extern inline semantics). Either
>> - * __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics,
>> - * and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not
>> - * defined so the gnu89 semantics are the default.
>> - */
>> -#ifdef __GNUC_STDC_INLINE__
>> -# define __gnu_inline  __attribute__((gnu_inline))
>> -#else
>> -# define __gnu_inline
>> -#endif
>> -
>>  /*
>>   * Force always-inline if the user requests it so via the .config.
>>   * GCC does not warn about unused static inline functions for
>> @@ -254,19 +188,13 @@ struct ftrace_likely_data {
>>   */
>>  #if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
>>         !defined(CONFIG_OPTIMIZE_INLINING)
>> -#define inline \
>> -       inline __attribute__((always_inline, unused)) notrace __gnu_inline
>> +#define inline inline __attribute__((always_inline, unused)) notrace __gnu_inline
>>  #else
>> -#define inline inline  __attribute__((unused)) notrace __gnu_inline
>> +#define inline inline __attribute__((unused)) notrace __gnu_inline
>>  #endif
>>
>>  #define __inline__ inline
>> -#define __inline inline
>> -#define noinline       __attribute__((noinline))
>> -
>> -#ifndef __always_inline
>> -#define __always_inline inline __attribute__((always_inline))
>> -#endif
>> +#define __inline   inline
>
> All of the changes to inline should not be removed, see above.  It's
> important to make this work correctly regardless of C standard used.
>

See above.

>>
>>  /*
>>   * Rather then using noinline to prevent stack consumption, use
>> @@ -274,4 +202,11 @@ struct ftrace_likely_data {
>>   */
>>  #define noinline_for_stack noinline
>>
>> +#ifdef __CHECKER__
>> +#define __must_be_array(a) 0
>> +#else
>> +/* &a[0] degrades to a pointer: a different type from an array */
>> +#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
>> +#endif
>> +
>>  #endif /* __LINUX_COMPILER_TYPES_H */
>> --
>> 2.17.1
>>
>
> With the above changes requested, I'm super happy with the spirit of
> this patch, and look forward to a v2.  Thanks again Miguel!

Thanks again for the very thorough review!

Cheers,
Miguel

> --
> Thanks,
> ~Nick Desaulniers

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-27 17:48   ` Nick Desaulniers
@ 2018-08-28 15:10     ` Miguel Ojeda
  2018-08-28 17:05       ` Nick Desaulniers
  0 siblings, 1 reply; 12+ messages in thread
From: Miguel Ojeda @ 2018-08-28 15:10 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Linus Torvalds, Eli Friedman, Christopher Li, Kees Cook,
	Ingo Molnar, Geert Uytterhoeven, Arnd Bergmann, Greg KH,
	Masahiro Yamada, Joe Perches, Dominique Martinet, LKML

Hi Nick,

On Mon, Aug 27, 2018 at 7:48 PM, Nick Desaulniers
<ndesaulniers@google.com> wrote:
> On Mon, Aug 27, 2018 at 10:43 AM Nick Desaulniers
>> > +
>> > +/*
>> > + * Optional attributes: your compiler may or may not support them.
>> > + *
>> > + * To check for them, we use __has_attribute, which is supported on gcc >= 5,
>> > + * clang >= 2.9 and icc >= 17. In the meantime, to support 4.6 <= gcc < 5,
>> > + * we implement it by hand.
>> > + */
>> > +#ifndef __has_attribute
>> > +#define __has_attribute(x) __GCC46_has_attribute_##x
>> > +#define __GCC46_has_attribute_assume_aligned 0
>> > +#define __GCC46_has_attribute_designated_init 0
>> > +#define __GCC46_has_attribute_externally_visible 1
>> > +#define __GCC46_has_attribute_noclone 1
>> > +#define __GCC46_has_attribute_optimize 1
>> > +#define __GCC46_has_attribute_no_sanitize_address 0
>> > +#endif
>
> And a follow up; I'm trying to understand what will happen in the case
> of say gcc 4.9 here.  Were any of these supported between gcc 4.6 and
> 5.0?  If so, then this code will not use them.  It's simpler than
> explicit version checks, but it won't use features that are supported.
>

I addressed that in the email I sent afterwards:

"""
Note that:
  - assume_aligned came with gcc 4.9
  - no_sanitize_address came with gcc 4.8

So if we feel it is important to have them there (before gcc 5), we
would need here a quick version check here.
"""

The idea is that, in the future, whenever gcc 5 or later is the
minimum version, we just get rid of the #ifdef block without touching
the rest of the code :-)

Cheers,
Miguel

>> > +
>> > +/*
>> > + * __assume_aligned(n, k): Tell the optimizer that the returned
>> > + * pointer can be assumed to be k modulo n. The second argument is
>> > + * optional (default 0), so we use a variadic macro to make the
>> > + * shorthand.
>> > + *
>> > + * Beware: Do not apply this to functions which may return
>> > + * ERR_PTRs. Also, it is probably unwise to apply it to functions
>> > + * returning extra information in the low bits (but in that case the
>> > + * compiler should see some alignment anyway, when the return value is
>> > + * massaged by 'flags = ptr & 3; ptr &= ~3;').
>> > + */
>> > +#if __has_attribute(assume_aligned)
>> > +#define __assume_aligned(a, ...) __attribute__((assume_aligned(a, ## __VA_ARGS__)))
>> > +#else
>> > +#define __assume_aligned(a, ...)
>> > +#endif
>> > +
>> > +/*
>> > + * Mark structures as requiring designated initializers.
>> > + * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
>> > + */
>> > +#if __has_attribute(designated_init)
>> > +#define __designated_init __attribute__((designated_init))
>> > +#else
>> > +#define __designated_init
>> > +#endif
>> > +
>> > +/*
>> > + * When used with Link Time Optimization, gcc can optimize away C functions or
>> > + * variables which are referenced only from assembly code.  __visible tells the
>> > + * optimizer that something else uses this function or variable, thus preventing
>> > + * this.
>> > + */
>> > +#if __has_attribute(externally_visible)
>> > +#define __visible __attribute__((externally_visible))
>> > +#else
>> > +#define __visible
>> > +#endif
>> > +
>> > +/* Mark a function definition as prohibited from being cloned. */
>> > +#if __has_attribute(noclone) && __has_attribute(optimize)
>> > +#define __noclone __attribute__((noclone, optimize("no-tracer")))
>> > +#else
>> > +#define __noclone
>> > +#endif
>> > +
>> > +/*
>> > + * Tell the compiler that address safety instrumentation (KASAN)
>> > + * should not be applied to that function.
>> > + * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
>> > + */
>> > +#if __has_attribute(no_sanitize_address)
>> > +#define __no_sanitize_address __attribute__((no_sanitize_address))
>> > +#else
>> > +#define __no_sanitize_address
>> > +#endif
>> > +
>> > +#endif /* __LINUX_COMPILER_ATTRIBUTES_H */
>> > diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
>> > index 3525c179698c..8cd622bedec4 100644
>> > --- a/include/linux/compiler_types.h
>> > +++ b/include/linux/compiler_types.h
>> > @@ -54,6 +54,9 @@ extern void __chk_io_ptr(const volatile void __iomem *);
>> >
>> >  #ifdef __KERNEL__
>> >
>> > +/* Attributes */
>> > +#include <linux/compiler_attributes.h>
>> > +
>> >  /* Compiler specific macros. */
>> >  #ifdef __clang__
>> >  #include <linux/compiler-clang.h>
>> > @@ -78,12 +81,6 @@ extern void __chk_io_ptr(const volatile void __iomem *);
>> >  #include <asm/compiler.h>
>> >  #endif
>> >
>> > -/*
>> > - * Generic compiler-independent macros required for kernel
>> > - * build go below this comment. Actual compiler/compiler version
>> > - * specific implementations come from the above header files
>> > - */
>> > -
>> >  struct ftrace_branch_data {
>> >         const char *func;
>> >         const char *file;
>> > @@ -119,10 +116,6 @@ struct ftrace_likely_data {
>> >   * compilers. We don't consider that to be an error, so set them to nothing.
>> >   * For example, some of them are for compiler specific plugins.
>> >   */
>> > -#ifndef __designated_init
>> > -# define __designated_init
>> > -#endif
>> > -
>> >  #ifndef __latent_entropy
>> >  # define __latent_entropy
>> >  #endif
>> > @@ -140,17 +133,6 @@ struct ftrace_likely_data {
>> >  # define randomized_struct_fields_end
>> >  #endif
>> >
>> > -#ifndef __visible
>> > -#define __visible
>> > -#endif
>> > -
>> > -/*
>> > - * Assume alignment of return value.
>> > - */
>> > -#ifndef __assume_aligned
>> > -#define __assume_aligned(a, ...)
>> > -#endif
>> > -
>> >  /* Are two types/vars the same type (ignoring qualifiers)? */
>> >  #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
>> >
>> > @@ -159,14 +141,6 @@ struct ftrace_likely_data {
>> >         (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
>> >          sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
>> >
>> > -#ifndef __attribute_const__
>> > -#define __attribute_const__    __attribute__((__const__))
>> > -#endif
>> > -
>> > -#ifndef __noclone
>> > -#define __noclone
>> > -#endif
>> > -
>> >  /* Helpers for emitting diagnostics in pragmas. */
>> >  #ifndef __diag
>> >  #define __diag(string)
>> > @@ -186,34 +160,6 @@ struct ftrace_likely_data {
>> >  #define __diag_error(compiler, version, option, comment) \
>> >         __diag_ ## compiler(version, error, option)
>> >
>> > -/*
>> > - * From the GCC manual:
>> > - *
>> > - * Many functions have no effects except the return value and their
>> > - * return value depends only on the parameters and/or global
>> > - * variables.  Such a function can be subject to common subexpression
>> > - * elimination and loop optimization just as an arithmetic operator
>> > - * would be.
>> > - * [...]
>> > - */
>> > -#define __pure                 __attribute__((pure))
>> > -#define __aligned(x)           __attribute__((aligned(x)))
>> > -#define __aligned_largest      __attribute__((aligned))
>> > -#define __printf(a, b)         __attribute__((format(printf, a, b)))
>> > -#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
>> > -#define __maybe_unused         __attribute__((unused))
>> > -#define __always_unused                __attribute__((unused))
>> > -#define __mode(x)              __attribute__((mode(x)))
>> > -#define __malloc               __attribute__((__malloc__))
>> > -#define __used                 __attribute__((__used__))
>> > -#define __noreturn             __attribute__((noreturn))
>> > -#define __packed               __attribute__((packed))
>> > -#define __weak                 __attribute__((weak))
>> > -#define __alias(symbol)                __attribute__((alias(#symbol)))
>> > -#define __cold                 __attribute__((cold))
>> > -#define __section(S)           __attribute__((__section__(#S)))
>> > -
>> > -
>> >  #ifdef CONFIG_ENABLE_MUST_CHECK
>> >  #define __must_check           __attribute__((warn_unused_result))
>> >  #else
>> > @@ -228,18 +174,6 @@ struct ftrace_likely_data {
>> >
>> >  #define __compiler_offsetof(a, b)      __builtin_offsetof(a, b)
>> >
>> > -/*
>> > - * Feature detection for gnu_inline (gnu89 extern inline semantics). Either
>> > - * __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics,
>> > - * and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not
>> > - * defined so the gnu89 semantics are the default.
>> > - */
>> > -#ifdef __GNUC_STDC_INLINE__
>> > -# define __gnu_inline  __attribute__((gnu_inline))
>> > -#else
>> > -# define __gnu_inline
>> > -#endif
>> > -
>> >  /*
>> >   * Force always-inline if the user requests it so via the .config.
>> >   * GCC does not warn about unused static inline functions for
>> > @@ -254,19 +188,13 @@ struct ftrace_likely_data {
>> >   */
>> >  #if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
>> >         !defined(CONFIG_OPTIMIZE_INLINING)
>> > -#define inline \
>> > -       inline __attribute__((always_inline, unused)) notrace __gnu_inline
>> > +#define inline inline __attribute__((always_inline, unused)) notrace __gnu_inline
>> >  #else
>> > -#define inline inline  __attribute__((unused)) notrace __gnu_inline
>> > +#define inline inline __attribute__((unused)) notrace __gnu_inline
>> >  #endif
>> >
>> >  #define __inline__ inline
>> > -#define __inline inline
>> > -#define noinline       __attribute__((noinline))
>> > -
>> > -#ifndef __always_inline
>> > -#define __always_inline inline __attribute__((always_inline))
>> > -#endif
>> > +#define __inline   inline
>>
>> All of the changes to inline should not be removed, see above.  It's
>> important to make this work correctly regardless of C standard used.
>>
>> >
>> >  /*
>> >   * Rather then using noinline to prevent stack consumption, use
>> > @@ -274,4 +202,11 @@ struct ftrace_likely_data {
>> >   */
>> >  #define noinline_for_stack noinline
>> >
>> > +#ifdef __CHECKER__
>> > +#define __must_be_array(a) 0
>> > +#else
>> > +/* &a[0] degrades to a pointer: a different type from an array */
>> > +#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
>> > +#endif
>> > +
>> >  #endif /* __LINUX_COMPILER_TYPES_H */
>> > --
>> > 2.17.1
>> >
>>
>> With the above changes requested, I'm super happy with the spirit of
>> this patch, and look forward to a v2.  Thanks again Miguel!
>> --
>> Thanks,
>> ~Nick Desaulniers
>
>
>
> --
> Thanks,
> ~Nick Desaulniers

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-28 15:03   ` Miguel Ojeda
@ 2018-08-28 16:53     ` Nick Desaulniers
  2018-08-28 20:41       ` Miguel Ojeda
  0 siblings, 1 reply; 12+ messages in thread
From: Nick Desaulniers @ 2018-08-28 16:53 UTC (permalink / raw)
  To: miguel.ojeda.sandonis
  Cc: Linus Torvalds, efriedma, sparse, Kees Cook, Ingo Molnar,
	Geert Uytterhoeven, Arnd Bergmann, Greg KH, Masahiro Yamada, joe,
	asmadeus, LKML

On Tue, Aug 28, 2018 at 8:04 AM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> Hi Nick,
>
> On Mon, Aug 27, 2018 at 7:43 PM, Nick Desaulniers
> <ndesaulniers@google.com> wrote:
> > On Sun, Aug 26, 2018 at 10:58 AM Miguel Ojeda
> > <miguel.ojeda.sandonis@gmail.com> wrote:
> >>
> >> Instead of using version checks per-compiler to define (or not) each attribute,
> >> use __has_attribute to test for them, following the cleanup started with
> >> commit 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive").
> >>
> >> All the attributes that are fairly common/standard (i.e. those that do not
> >> require extra logic to define them) have been moved to a new file
> >> include/linux/compiler_attributes.h. The attributes have been sorted
> >> and divided between "required" and "optional".
> >
> > Nice! Thanks Miguel.  Regarding sorting, I'm happy with that.  In
> > fact, some of the comments can be removed IMO, as the attributes have
> > common definitions in the docs (maybe an added link to the gcc and
> > clang attribute docs at the top of the file rather than per attribute
> > comments).
>
> Thanks for the review!
>
> I thought about that, although there isn't a single page with them in
> GCC (we could group them by type though: function ones, variable
> ones... and then link to those).
> On the other hand, maybe writing a
> Doc/ file is better and allows us to write as much as one would like
> about each of them (and a link to each page compiler's page about it,
> etc.). I think in the end the Doc/ file might be the best, in order
> not to crowd the header.

A comment is closer to the source, but I guess that's bytes for each
inclusion for every file.  I don't feel passionate about this point
one way or the other.

>
> >
> >>
> >> Further, attributes that are already supported in gcc >= 4.6 and recent clang
> >> were simply made to be required (instead of testing for them):
> >>   * always_inline
> >>   * const (pure was already "required", by the way)
> >>   * gnu_inline
> >
> > There's an important test for gnu_inline that isn't checking that it's
> > supported, but rather what the implicit behavior is depending on which
> > C standard is being used.  It's important not to remove that.
>
> Hm... I actually thought it was not available at some point before 4.6
> and removed the #ifdef. The comment even says it is featuring
> detecting it so that the old GCC inlining is used; but it shouldn't
> matter if you always use it, no?

Good point.  Rather than defining it only if GNU inline is not the
current behavior is a bit more verbose than just always defining it.
This seems to confirm that that should work:
https://godbolt.org/z/igwh32.

>
> I just went looking for more info in d03db2bc2 ("compiler-gcc.h: Add
> __attribute__((gnu_inline)) to all inline declarations") and if I
> understood the commit message, the problem is compiling with implicit
> new standard in newer compilers which trigger the C90 behavior, while
> we need the old one --- but if we use gnu_inline, we are getting it
> regardless.
>
> I am sure I am missing something, but I think a clarification is
> needed (and in the code comment as well) -- a bit off-topic, anyway.
>
> [Also, I wouldn't define an attribute or not depending on some other
> condition. I would, instead, define something some other symbol with
> that logic (i.e. instead of using "__gnu_inline", because that is
> lying -- it is not using the attribute even if the compiler supports
> it).]
>
> >
> >>
> >> Finally, some other bits were cleaned up in the process:
> >>   * __optimize: removed (unused in the whole kernel tree)
> >
> > A+ for removing dead code.  I also don't see it used anywhere.
> >
> >>   * __must_be_array: removed from -gcc and -clang (identical), moved to _types
> >
> > Yep, uses a builtin (we should add guards for that, later, in a
> > similar style change that guards the use of builtins). Looks good.
> >
> >>     (it depends on the unconditionally used  __builtin_types_compatible_p
> >>   * Removes unneeded underscores on the attributes' names
> >
> > That doesn't sound right, but lets see what you mean by that.
>
> Some attributes used the __name__ syntax (i.e. inside the double
> parenthesis), others didn't. I simplified by removing all the extra
> underscores.

A+

>
> >
> >>
> >> There are some things that can be further cleaned up afterwards:
> >>   * __attribute_const__: rename to __const
> >
> > This doesn't look correct to me; the kernel is full of call sites for
> > __attribute_const__. You can't rename the definition without renaming
>
> Of course it is full of use sites! That is why I said it is a possible
> cleanup for *afterwards* this patch :-)
>
> > all of the call sites (and that would be too big a change for this
> > patch, IMO).  Skip the rename, and it also looks like you just removed
> > it outright (Oops).
>
> Not sure what you mean by this (?). The attribute is still there unchanged.

Nevermind, I misinterpretered this part of the patch.

>
> >
> >>   * __noretpoline: avoid checking for defined(__notrepoline)
> >>   * __compiletime_warning/error: they are in two different places,
> >>     -gcc and compiler.h.
> >>   * sparse' attributes could potentially go into the end of attributes.h
> >>     too (as another separate section).
> >>
> >> Compile-tested an x86 allmodconfig for a while with gcc 8.2.0 and 4.6.4.
> >
> > It's important to test changes to compiler-clang.h with clang. ;)
>
> I would agree if the clang build wasn't broken to begin with. ;)
>
> >
> >>
> >> Cc: Eli Friedman <efriedma@codeaurora.org>
> >> Cc: Christopher Li <sparse@chrisli.org>
> >> Cc: Kees Cook <keescook@chromium.org>
> >> Cc: Ingo Molnar <mingo@kernel.org>
> >> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> >> Cc: Arnd Bergmann <arnd@arndb.de>
> >> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> >> Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
> >> Cc: Joe Perches <joe@perches.com>
> >> Cc: Dominique Martinet <asmadeus@codewreck.org>
> >> Cc: Nick Desaulniers <ndesaulniers@google.com>
> >> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> >> Signed-off-by: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
> >> ---
> >> *Seems* to work, but note that I did not finish the entire allmodconfig :)
> >>
> >> A few things could be splitted into their own patch, but I kept it
> >> as one for simplicity for a first review.
> >>
> >> These files are becoming no-headaches-readable again, yay.
> >
> > A+
> >
> >>
> >>  include/linux/compiler-clang.h      |   5 --
> >>  include/linux/compiler-gcc.h        |  60 ----------------
> >>  include/linux/compiler-intel.h      |   6 --
> >>  include/linux/compiler.h            |   4 --
> >>  include/linux/compiler_attributes.h | 105 ++++++++++++++++++++++++++++
> >>  include/linux/compiler_types.h      |  91 ++++--------------------
> >>  6 files changed, 118 insertions(+), 153 deletions(-)
> >>  create mode 100644 include/linux/compiler_attributes.h
> >>
> >> diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
> >> index b1ce500fe8b3..3e7dafb3ea80 100644
> >> --- a/include/linux/compiler-clang.h
> >> +++ b/include/linux/compiler-clang.h
> >> @@ -21,8 +21,6 @@
> >>  #define __SANITIZE_ADDRESS__
> >>  #endif
> >>
> >> -#define __no_sanitize_address __attribute__((no_sanitize("address")))
> >> -
> >>  /*
> >>   * Not all versions of clang implement the the type-generic versions
> >>   * of the builtin overflow checkers. Fortunately, clang implements
> >> @@ -41,6 +39,3 @@
> >>   * compilers, like ICC.
> >>   */
> >>  #define barrier() __asm__ __volatile__("" : : : "memory")
> >> -#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
> >> -#define __assume_aligned(a, ...)       \
> >> -       __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
> >> diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
> >> index 763bbad1e258..dde3daae6287 100644
> >> --- a/include/linux/compiler-gcc.h
> >> +++ b/include/linux/compiler-gcc.h
> >> @@ -68,13 +68,6 @@
> >>   */
> >>  #define uninitialized_var(x) x = x
> >>
> >> -#ifdef __CHECKER__
> >> -#define __must_be_array(a)     0
> >> -#else
> >> -/* &a[0] degrades to a pointer: a different type from an array */
> >> -#define __must_be_array(a)     BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
> >> -#endif
> >> -
> >>  #ifdef RETPOLINE
> >>  #define __noretpoline __attribute__((indirect_branch("keep")))
> >>  #endif
> >> @@ -95,8 +88,6 @@
> >>
> >>  #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
> >>
> >> -#define __optimize(level)      __attribute__((__optimize__(level)))
> >> -
> >>  #define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
> >>
> >>  #ifndef __CHECKER__
> >> @@ -133,9 +124,6 @@
> >>                 __builtin_unreachable();        \
> >>         } while (0)
> >>
> >> -/* Mark a function definition as prohibited from being cloned. */
> >> -#define __noclone      __attribute__((__noclone__, __optimize__("no-tracer")))
> >> -
> >>  #if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
> >>  #define __randomize_layout __attribute__((randomize_layout))
> >>  #define __no_randomize_layout __attribute__((no_randomize_layout))
> >> @@ -144,32 +132,6 @@
> >>  #define randomized_struct_fields_end   } __randomize_layout;
> >>  #endif
> >>
> >> -/*
> >> - * When used with Link Time Optimization, gcc can optimize away C functions or
> >> - * variables which are referenced only from assembly code.  __visible tells the
> >> - * optimizer that something else uses this function or variable, thus preventing
> >> - * this.
> >> - */
> >> -#define __visible      __attribute__((externally_visible))
> >> -
> >> -/* gcc version specific checks */
> >> -
> >> -#if GCC_VERSION >= 40900 && !defined(__CHECKER__)
> >> -/*
> >> - * __assume_aligned(n, k): Tell the optimizer that the returned
> >> - * pointer can be assumed to be k modulo n. The second argument is
> >> - * optional (default 0), so we use a variadic macro to make the
> >> - * shorthand.
> >> - *
> >> - * Beware: Do not apply this to functions which may return
> >> - * ERR_PTRs. Also, it is probably unwise to apply it to functions
> >> - * returning extra information in the low bits (but in that case the
> >> - * compiler should see some alignment anyway, when the return value is
> >> - * massaged by 'flags = ptr & 3; ptr &= ~3;').
> >> - */
> >> -#define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
> >> -#endif
> >> -
> >>  /*
> >>   * GCC 'asm goto' miscompiles certain code sequences:
> >>   *
> >> @@ -201,32 +163,10 @@
> >>  #define KASAN_ABI_VERSION 3
> >>  #endif
> >>
> >> -#if GCC_VERSION >= 40902
> >> -/*
> >> - * Tell the compiler that address safety instrumentation (KASAN)
> >> - * should not be applied to that function.
> >> - * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
> >> - */
> >> -#define __no_sanitize_address __attribute__((no_sanitize_address))
> >> -#endif
> >> -
> >>  #if GCC_VERSION >= 50100
> >> -/*
> >> - * Mark structures as requiring designated initializers.
> >> - * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
> >> - */
> >> -#define __designated_init __attribute__((designated_init))
> >>  #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
> >>  #endif
> >>
> >> -#if !defined(__noclone)
> >> -#define __noclone      /* not needed */
> >> -#endif
> >> -
> >> -#if !defined(__no_sanitize_address)
> >> -#define __no_sanitize_address
> >> -#endif
> >> -
> >>  /*
> >>   * Turn individual warnings and errors on and off locally, depending
> >>   * on version.
> >> diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h
> >> index 4c7f9befa9f6..fb9e77fc65ec 100644
> >> --- a/include/linux/compiler-intel.h
> >> +++ b/include/linux/compiler-intel.h
> >> @@ -37,9 +37,3 @@
> >>  /* icc has this, but it's called _bswap16 */
> >>  #define __HAVE_BUILTIN_BSWAP16__
> >>  #define __builtin_bswap16 _bswap16
> >> -
> >> -/* The following are for compatibility with GCC, from compiler-gcc.h,
> >> - * and may be redefined here because they should not be shared with other
> >> - * compilers, like clang.
> >> - */
> >> -#define __visible      __attribute__((externally_visible))
> >> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> >> index 681d866efb1e..7c0157d50964 100644
> >> --- a/include/linux/compiler.h
> >> +++ b/include/linux/compiler.h
> >> @@ -301,10 +301,6 @@ static inline void *offset_to_ptr(const int *off)
> >>
> >>  #endif /* __ASSEMBLY__ */
> >>
> >> -#ifndef __optimize
> >> -# define __optimize(level)
> >> -#endif
> >> -
> >>  /* Compile time object size, -1 for unknown */
> >>  #ifndef __compiletime_object_size
> >>  # define __compiletime_object_size(obj) -1
> >> diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
> >> new file mode 100644
> >> index 000000000000..af8c8413d136
> >> --- /dev/null
> >> +++ b/include/linux/compiler_attributes.h
> >> @@ -0,0 +1,105 @@
> >> +#ifndef __LINUX_COMPILER_ATTRIBUTES_H
> >> +#define __LINUX_COMPILER_ATTRIBUTES_H
> >> +
> >> +/* This file is meant to be sorted. */
> >> +
> >> +/*
> >> + * Required attributes: your compiler must support these.
> >> + */
> >> +#define __alias(symbol)                __attribute__((alias(#symbol)))
> >> +#define __aligned(x)           __attribute__((aligned(x)))
> >> +#define __aligned_largest      __attribute__((aligned))
> >> +#define __always_inline         inline __attribute__((always_inline))
> >> +#define __always_unused                __attribute__((unused))
> >> +#define __attribute_const__     __attribute__((const))
> >> +#define __cold                 __attribute__((cold))
> >> +#define __gnu_inline            __attribute__((gnu_inline))
> >> +#define __malloc               __attribute__((malloc))
> >> +#define __maybe_unused         __attribute__((unused))
> >> +#define __mode(x)              __attribute__((mode(x)))
> >> +#define   noinline              __attribute__((noinline))
> >> +#define __noreturn             __attribute__((noreturn))
> >> +#define __packed               __attribute__((packed))
> >> +#define __printf(a, b)         __attribute__((format(printf, a, b)))
> >> +#define __pure                 __attribute__((pure))
> >> +#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
> >> +#define __section(S)           __attribute__((section(#S)))
> >> +#define __used                 __attribute__((used))
> >> +#define __weak                 __attribute__((weak))
> >> +
> >> +/*
> >> + * Optional attributes: your compiler may or may not support them.
> >> + *
> >> + * To check for them, we use __has_attribute, which is supported on gcc >= 5,
> >> + * clang >= 2.9 and icc >= 17. In the meantime, to support 4.6 <= gcc < 5,
> >> + * we implement it by hand.
> >> + */
> >> +#ifndef __has_attribute
> >> +#define __has_attribute(x) __GCC46_has_attribute_##x
> >> +#define __GCC46_has_attribute_assume_aligned 0
> >> +#define __GCC46_has_attribute_designated_init 0
> >> +#define __GCC46_has_attribute_externally_visible 1
> >> +#define __GCC46_has_attribute_noclone 1
> >> +#define __GCC46_has_attribute_optimize 1
> >> +#define __GCC46_has_attribute_no_sanitize_address 0
> >> +#endif
> >> +
> >> +/*
> >> + * __assume_aligned(n, k): Tell the optimizer that the returned
> >> + * pointer can be assumed to be k modulo n. The second argument is
> >> + * optional (default 0), so we use a variadic macro to make the
> >> + * shorthand.
> >> + *
> >> + * Beware: Do not apply this to functions which may return
> >> + * ERR_PTRs. Also, it is probably unwise to apply it to functions
> >> + * returning extra information in the low bits (but in that case the
> >> + * compiler should see some alignment anyway, when the return value is
> >> + * massaged by 'flags = ptr & 3; ptr &= ~3;').
> >> + */
> >> +#if __has_attribute(assume_aligned)
> >> +#define __assume_aligned(a, ...) __attribute__((assume_aligned(a, ## __VA_ARGS__)))
> >> +#else
> >> +#define __assume_aligned(a, ...)
> >> +#endif
> >> +
> >> +/*
> >> + * Mark structures as requiring designated initializers.
> >> + * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
> >> + */
> >> +#if __has_attribute(designated_init)
> >> +#define __designated_init __attribute__((designated_init))
> >> +#else
> >> +#define __designated_init
> >> +#endif
> >> +
> >> +/*
> >> + * When used with Link Time Optimization, gcc can optimize away C functions or
> >> + * variables which are referenced only from assembly code.  __visible tells the
> >> + * optimizer that something else uses this function or variable, thus preventing
> >> + * this.
> >> + */
> >> +#if __has_attribute(externally_visible)
> >> +#define __visible __attribute__((externally_visible))
> >> +#else
> >> +#define __visible
> >> +#endif
> >> +
> >> +/* Mark a function definition as prohibited from being cloned. */
> >> +#if __has_attribute(noclone) && __has_attribute(optimize)
> >> +#define __noclone __attribute__((noclone, optimize("no-tracer")))
> >> +#else
> >> +#define __noclone
> >> +#endif
> >> +
> >> +/*
> >> + * Tell the compiler that address safety instrumentation (KASAN)
> >> + * should not be applied to that function.
> >> + * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
> >> + */
> >> +#if __has_attribute(no_sanitize_address)
> >> +#define __no_sanitize_address __attribute__((no_sanitize_address))
> >> +#else
> >> +#define __no_sanitize_address
> >> +#endif
> >> +
> >> +#endif /* __LINUX_COMPILER_ATTRIBUTES_H */
> >> diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
> >> index 3525c179698c..8cd622bedec4 100644
> >> --- a/include/linux/compiler_types.h
> >> +++ b/include/linux/compiler_types.h
> >> @@ -54,6 +54,9 @@ extern void __chk_io_ptr(const volatile void __iomem *);
> >>
> >>  #ifdef __KERNEL__
> >>
> >> +/* Attributes */
> >> +#include <linux/compiler_attributes.h>
> >> +
> >>  /* Compiler specific macros. */
> >>  #ifdef __clang__
> >>  #include <linux/compiler-clang.h>
> >> @@ -78,12 +81,6 @@ extern void __chk_io_ptr(const volatile void __iomem *);
> >>  #include <asm/compiler.h>
> >>  #endif
> >>
> >> -/*
> >> - * Generic compiler-independent macros required for kernel
> >> - * build go below this comment. Actual compiler/compiler version
> >> - * specific implementations come from the above header files
> >> - */
> >> -
> >>  struct ftrace_branch_data {
> >>         const char *func;
> >>         const char *file;
> >> @@ -119,10 +116,6 @@ struct ftrace_likely_data {
> >>   * compilers. We don't consider that to be an error, so set them to nothing.
> >>   * For example, some of them are for compiler specific plugins.
> >>   */
> >> -#ifndef __designated_init
> >> -# define __designated_init
> >> -#endif
> >> -
> >>  #ifndef __latent_entropy
> >>  # define __latent_entropy
> >>  #endif
> >> @@ -140,17 +133,6 @@ struct ftrace_likely_data {
> >>  # define randomized_struct_fields_end
> >>  #endif
> >>
> >> -#ifndef __visible
> >> -#define __visible
> >> -#endif
> >> -
> >> -/*
> >> - * Assume alignment of return value.
> >> - */
> >> -#ifndef __assume_aligned
> >> -#define __assume_aligned(a, ...)
> >> -#endif
> >> -
> >>  /* Are two types/vars the same type (ignoring qualifiers)? */
> >>  #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
> >>
> >> @@ -159,14 +141,6 @@ struct ftrace_likely_data {
> >>         (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
> >>          sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
> >>
> >> -#ifndef __attribute_const__
> >> -#define __attribute_const__    __attribute__((__const__))
> >> -#endif
> >> -
> >> -#ifndef __noclone
> >> -#define __noclone
> >> -#endif
> >> -
> >>  /* Helpers for emitting diagnostics in pragmas. */
> >>  #ifndef __diag
> >>  #define __diag(string)
> >> @@ -186,34 +160,6 @@ struct ftrace_likely_data {
> >>  #define __diag_error(compiler, version, option, comment) \
> >>         __diag_ ## compiler(version, error, option)
> >>
> >> -/*
> >> - * From the GCC manual:
> >> - *
> >> - * Many functions have no effects except the return value and their
> >> - * return value depends only on the parameters and/or global
> >> - * variables.  Such a function can be subject to common subexpression
> >> - * elimination and loop optimization just as an arithmetic operator
> >> - * would be.
> >> - * [...]
> >> - */
> >> -#define __pure                 __attribute__((pure))
> >> -#define __aligned(x)           __attribute__((aligned(x)))
> >> -#define __aligned_largest      __attribute__((aligned))
> >> -#define __printf(a, b)         __attribute__((format(printf, a, b)))
> >> -#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
> >> -#define __maybe_unused         __attribute__((unused))
> >> -#define __always_unused                __attribute__((unused))
> >> -#define __mode(x)              __attribute__((mode(x)))
> >> -#define __malloc               __attribute__((__malloc__))
> >> -#define __used                 __attribute__((__used__))
> >> -#define __noreturn             __attribute__((noreturn))
> >> -#define __packed               __attribute__((packed))
> >> -#define __weak                 __attribute__((weak))
> >> -#define __alias(symbol)                __attribute__((alias(#symbol)))
> >> -#define __cold                 __attribute__((cold))
> >> -#define __section(S)           __attribute__((__section__(#S)))
> >> -
> >> -
> >>  #ifdef CONFIG_ENABLE_MUST_CHECK
> >>  #define __must_check           __attribute__((warn_unused_result))
> >>  #else
> >> @@ -228,18 +174,6 @@ struct ftrace_likely_data {
> >>
> >>  #define __compiler_offsetof(a, b)      __builtin_offsetof(a, b)
> >>
> >> -/*
> >> - * Feature detection for gnu_inline (gnu89 extern inline semantics). Either
> >> - * __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics,
> >> - * and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not
> >> - * defined so the gnu89 semantics are the default.
> >> - */
> >> -#ifdef __GNUC_STDC_INLINE__
> >> -# define __gnu_inline  __attribute__((gnu_inline))
> >> -#else
> >> -# define __gnu_inline
> >> -#endif
> >> -
> >>  /*
> >>   * Force always-inline if the user requests it so via the .config.
> >>   * GCC does not warn about unused static inline functions for
> >> @@ -254,19 +188,13 @@ struct ftrace_likely_data {
> >>   */
> >>  #if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
> >>         !defined(CONFIG_OPTIMIZE_INLINING)
> >> -#define inline \
> >> -       inline __attribute__((always_inline, unused)) notrace __gnu_inline
> >> +#define inline inline __attribute__((always_inline, unused)) notrace __gnu_inline
> >>  #else
> >> -#define inline inline  __attribute__((unused)) notrace __gnu_inline
> >> +#define inline inline __attribute__((unused)) notrace __gnu_inline
> >>  #endif
> >>
> >>  #define __inline__ inline
> >> -#define __inline inline
> >> -#define noinline       __attribute__((noinline))
> >> -
> >> -#ifndef __always_inline
> >> -#define __always_inline inline __attribute__((always_inline))
> >> -#endif
> >> +#define __inline   inline
> >
> > All of the changes to inline should not be removed, see above.  It's
> > important to make this work correctly regardless of C standard used.
> >
>
> See above.
>
> >>
> >>  /*
> >>   * Rather then using noinline to prevent stack consumption, use
> >> @@ -274,4 +202,11 @@ struct ftrace_likely_data {
> >>   */
> >>  #define noinline_for_stack noinline
> >>
> >> +#ifdef __CHECKER__
> >> +#define __must_be_array(a) 0
> >> +#else
> >> +/* &a[0] degrades to a pointer: a different type from an array */
> >> +#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
> >> +#endif
> >> +
> >>  #endif /* __LINUX_COMPILER_TYPES_H */
> >> --
> >> 2.17.1
> >>
> >
> > With the above changes requested, I'm super happy with the spirit of
> > this patch, and look forward to a v2.  Thanks again Miguel!
>
> Thanks again for the very thorough review!

Thanks for the patch! I'm almost ready to sign off, just a few more
comments on the other thread.

-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-28 15:10     ` Miguel Ojeda
@ 2018-08-28 17:05       ` Nick Desaulniers
  2018-08-28 20:33         ` Miguel Ojeda
  0 siblings, 1 reply; 12+ messages in thread
From: Nick Desaulniers @ 2018-08-28 17:05 UTC (permalink / raw)
  To: miguel.ojeda.sandonis
  Cc: Linus Torvalds, efriedma, sparse, Kees Cook, Ingo Molnar,
	Geert Uytterhoeven, Arnd Bergmann, Greg KH, Masahiro Yamada, joe,
	asmadeus, LKML

On Tue, Aug 28, 2018 at 8:10 AM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> Hi Nick,
>
> On Mon, Aug 27, 2018 at 7:48 PM, Nick Desaulniers
> <ndesaulniers@google.com> wrote:
> > On Mon, Aug 27, 2018 at 10:43 AM Nick Desaulniers
> >> > +
> >> > +/*
> >> > + * Optional attributes: your compiler may or may not support them.
> >> > + *
> >> > + * To check for them, we use __has_attribute, which is supported on gcc >= 5,
> >> > + * clang >= 2.9 and icc >= 17. In the meantime, to support 4.6 <= gcc < 5,
> >> > + * we implement it by hand.
> >> > + */
> >> > +#ifndef __has_attribute
> >> > +#define __has_attribute(x) __GCC46_has_attribute_##x
> >> > +#define __GCC46_has_attribute_assume_aligned 0
> >> > +#define __GCC46_has_attribute_designated_init 0
> >> > +#define __GCC46_has_attribute_externally_visible 1
> >> > +#define __GCC46_has_attribute_noclone 1
> >> > +#define __GCC46_has_attribute_optimize 1
> >> > +#define __GCC46_has_attribute_no_sanitize_address 0
> >> > +#endif
> >
> > And a follow up; I'm trying to understand what will happen in the case
> > of say gcc 4.9 here.  Were any of these supported between gcc 4.6 and
> > 5.0?  If so, then this code will not use them.  It's simpler than
> > explicit version checks, but it won't use features that are supported.
> >
>
> I addressed that in the email I sent afterwards:
>
> """
> Note that:
>   - assume_aligned came with gcc 4.9
>   - no_sanitize_address came with gcc 4.8
>
> So if we feel it is important to have them there (before gcc 5), we
> would need here a quick version check here.
> """
>
> The idea is that, in the future, whenever gcc 5 or later is the
> minimum version, we just get rid of the #ifdef block without touching
> the rest of the code :-)

So if __has_attribute came with gcc 5, then that means that this patch
will break assume_aligned for gcc-4.9 users and no_sanitize_address
for gcc-4.8 and gcc-4.9 users?  The slab allocator uses
assume_aligned, and no_sanitize_address for CONFIG_KASAN.  Should this
patch ever come back through stable, Android and ChromeOS
gcc-4.9/KASAN builds will break.

I don't think we should leave that for a follow up; I would like to
see it as part of this patch.  It's ok to have explicit version checks
for those 2 attributes since it's not possible to feature detect them
for the versions of gcc that we support in this code base.  I think
you should add them in a v2 of this patch.  Then we can point to this
commit as the *shining example* of how to do proper feature detection,
falling back to version checks only as a last resort.

-- 
Thanks,
~Nick Desaulniers

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-28 17:05       ` Nick Desaulniers
@ 2018-08-28 20:33         ` Miguel Ojeda
  0 siblings, 0 replies; 12+ messages in thread
From: Miguel Ojeda @ 2018-08-28 20:33 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Linus Torvalds, Eli Friedman, Christopher Li, Kees Cook,
	Ingo Molnar, Geert Uytterhoeven, Arnd Bergmann, Greg KH,
	Masahiro Yamada, Joe Perches, Dominique Martinet, LKML

Hi Nick,

On Tue, Aug 28, 2018 at 7:05 PM, Nick Desaulniers
<ndesaulniers@google.com> wrote:
> On Tue, Aug 28, 2018 at 8:10 AM Miguel Ojeda
> <miguel.ojeda.sandonis@gmail.com> wrote:
>>
>> I addressed that in the email I sent afterwards:
>>
>> """
>> Note that:
>>   - assume_aligned came with gcc 4.9
>>   - no_sanitize_address came with gcc 4.8
>>
>> So if we feel it is important to have them there (before gcc 5), we
>> would need here a quick version check here.
>> """
>>
>> The idea is that, in the future, whenever gcc 5 or later is the
>> minimum version, we just get rid of the #ifdef block without touching
>> the rest of the code :-)
>
> So if __has_attribute came with gcc 5, then that means that this patch
> will break assume_aligned for gcc-4.9 users and no_sanitize_address
> for gcc-4.8 and gcc-4.9 users?  The slab allocator uses
> assume_aligned, and no_sanitize_address for CONFIG_KASAN.  Should this
> patch ever come back through stable, Android and ChromeOS
> gcc-4.9/KASAN builds will break.
>

Indeed, KASAN requires it:

          This is strictly a debugging feature and it requires a gcc version
          of 4.9.2 or later. Detection of out of bounds accesses to stack or
          global variables requires gcc 5.0 or later.

So we should just support it. However, __no_sanitize_address is only
used when CONFIG_KASAN is enabled (to define __no_kasan_or_inline). So
I would say it is an attribute for a particular CONFIG (like those of
sparse). Therefore, I think we should simply remove
__no_sanitize_address for general use (let's see how it looks).

For __assume_aligned, it is "only" an optimization, but I think it is
a general one, so we should keep it in attributes.h; I will simply add
the gcc 4.9 support knowledge.

On that topic: actually, some of the attributes that we have that are
"required" are not really "required" in the strict sense: we could
test for them; but I wanted to minimize the amount of noise for gcc <
5 since we have to manually write the support table (and anyway most
compilers support them). Whenever we are past gcc 5 in a few years, we
could actually test for the non-strictly-required attribute if we want
to be extra nice to new compilers :-)

> I don't think we should leave that for a follow up; I would like to
> see it as part of this patch.  It's ok to have explicit version checks
> for those 2 attributes since it's not possible to feature detect them
> for the versions of gcc that we support in this code base.  I think
> you should add them in a v2 of this patch.  Then we can point to this
> commit as the *shining example* of how to do proper feature detection,
> falling back to version checks only as a last resort.

Thanks for the kind words!

I also read your other comments in the previous email -- no comments
on those. I will prepare v2.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes
  2018-08-28 16:53     ` Nick Desaulniers
@ 2018-08-28 20:41       ` Miguel Ojeda
  0 siblings, 0 replies; 12+ messages in thread
From: Miguel Ojeda @ 2018-08-28 20:41 UTC (permalink / raw)
  To: Nick Desaulniers
  Cc: Linus Torvalds, Eli Friedman, Christopher Li, Kees Cook,
	Ingo Molnar, Geert Uytterhoeven, Arnd Bergmann, Greg KH,
	Masahiro Yamada, Joe Perches, Dominique Martinet, LKML

Hi Nick,

Actually, to acknowledge the comments to the other email...

On Tue, Aug 28, 2018 at 6:53 PM, Nick Desaulniers
<ndesaulniers@google.com> wrote:
> On Tue, Aug 28, 2018 at 8:04 AM Miguel Ojeda
> <miguel.ojeda.sandonis@gmail.com> wrote:
>>
>> Hi Nick,
>>
>> On Mon, Aug 27, 2018 at 7:43 PM, Nick Desaulniers
>> <ndesaulniers@google.com> wrote:
>> > On Sun, Aug 26, 2018 at 10:58 AM Miguel Ojeda
>> > <miguel.ojeda.sandonis@gmail.com> wrote:
>> >>
>> >> Instead of using version checks per-compiler to define (or not) each attribute,
>> >> use __has_attribute to test for them, following the cleanup started with
>> >> commit 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive").
>> >>
>> >> All the attributes that are fairly common/standard (i.e. those that do not
>> >> require extra logic to define them) have been moved to a new file
>> >> include/linux/compiler_attributes.h. The attributes have been sorted
>> >> and divided between "required" and "optional".
>> >
>> > Nice! Thanks Miguel.  Regarding sorting, I'm happy with that.  In
>> > fact, some of the comments can be removed IMO, as the attributes have
>> > common definitions in the docs (maybe an added link to the gcc and
>> > clang attribute docs at the top of the file rather than per attribute
>> > comments).
>>
>> Thanks for the review!
>>
>> I thought about that, although there isn't a single page with them in
>> GCC (we could group them by type though: function ones, variable
>> ones... and then link to those).
>> On the other hand, maybe writing a
>> Doc/ file is better and allows us to write as much as one would like
>> about each of them (and a link to each page compiler's page about it,
>> etc.). I think in the end the Doc/ file might be the best, in order
>> not to crowd the header.
>
> A comment is closer to the source, but I guess that's bytes for each
> inclusion for every file.  I don't feel passionate about this point
> one way or the other.
>

I think I will write a simple Doc/ file, link to it from the source,
and see if people like it.

>>
>> >
>> >>
>> >> Further, attributes that are already supported in gcc >= 4.6 and recent clang
>> >> were simply made to be required (instead of testing for them):
>> >>   * always_inline
>> >>   * const (pure was already "required", by the way)
>> >>   * gnu_inline
>> >
>> > There's an important test for gnu_inline that isn't checking that it's
>> > supported, but rather what the implicit behavior is depending on which
>> > C standard is being used.  It's important not to remove that.
>>
>> Hm... I actually thought it was not available at some point before 4.6
>> and removed the #ifdef. The comment even says it is featuring
>> detecting it so that the old GCC inlining is used; but it shouldn't
>> matter if you always use it, no?
>
> Good point.  Rather than defining it only if GNU inline is not the
> current behavior is a bit more verbose than just always defining it.
> This seems to confirm that that should work:
> https://godbolt.org/z/igwh32.
>

Great then! Thanks for confirming!

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2018-08-28 20:41 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-26 17:57 [PATCH] include/linux/compiler*.h: Use feature checking instead of version checks for attributes Miguel Ojeda
2018-08-26 18:30 ` Miguel Ojeda
2018-08-26 18:50 ` Joe Perches
2018-08-27 12:33   ` Miguel Ojeda
2018-08-27 17:43 ` Nick Desaulniers
2018-08-27 17:48   ` Nick Desaulniers
2018-08-28 15:10     ` Miguel Ojeda
2018-08-28 17:05       ` Nick Desaulniers
2018-08-28 20:33         ` Miguel Ojeda
2018-08-28 15:03   ` Miguel Ojeda
2018-08-28 16:53     ` Nick Desaulniers
2018-08-28 20:41       ` Miguel Ojeda

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).