Commit 815f0ddb authored by Nick Desaulniers's avatar Nick Desaulniers Committed by Linus Torvalds

include/linux/compiler*.h: make compiler-*.h mutually exclusive

Commit cafa0010 ("Raise the minimum required gcc version to 4.6")
recently exposed a brittle part of the build for supporting non-gcc
compilers.

Both Clang and ICC define __GNUC__, __GNUC_MINOR__, and
__GNUC_PATCHLEVEL__ for quick compatibility with code bases that haven't
added compiler specific checks for __clang__ or __INTEL_COMPILER.

This is brittle, as they happened to get compatibility by posing as a
certain version of GCC.  This broke when upgrading the minimal version
of GCC required to build the kernel, to a version above what ICC and
Clang claim to be.

Rather than always including compiler-gcc.h then undefining or
redefining macros in compiler-intel.h or compiler-clang.h, let's
separate out the compiler specific macro definitions into mutually
exclusive headers, do more proper compiler detection, and keep shared
definitions in compiler_types.h.

Fixes: cafa0010 ("Raise the minimum required gcc version to 4.6")
Reported-by: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
Suggested-by: default avatarEli Friedman <efriedma@codeaurora.org>
Suggested-by: default avatarJoe Perches <joe@perches.com>
Signed-off-by: default avatarNick Desaulniers <ndesaulniers@google.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 899fbc33
...@@ -38,25 +38,14 @@ ...@@ -38,25 +38,14 @@
#error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32 #error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32
#endif #endif
/* /*
* GCC 3.0, 3.1: general bad code generation.
* GCC 3.2.0: incorrect function argument offset calculation.
* GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
* (http://gcc.gnu.org/PR8896) and incorrect structure
* initialisation in fs/jffs2/erase.c
* GCC 4.8.0-4.8.2: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854 * GCC 4.8.0-4.8.2: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854
* miscompiles find_get_entry(), and can result in EXT3 and EXT4 * miscompiles find_get_entry(), and can result in EXT3 and EXT4
* filesystem corruption (possibly other FS too). * filesystem corruption (possibly other FS too).
*/ */
#ifdef __GNUC__ #if defined(GCC_VERSION) && GCC_VERSION >= 40800 && GCC_VERSION < 40803
#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
#error Your compiler is too buggy; it is known to miscompile kernels.
#error Known good compilers: 3.3, 4.x
#endif
#if GCC_VERSION >= 40800 && GCC_VERSION < 40803
#error Your compiler is too buggy; it is known to miscompile kernels #error Your compiler is too buggy; it is known to miscompile kernels
#error and result in filesystem corruption and oopses. #error and result in filesystem corruption and oopses.
#endif #endif
#endif
int main(void) int main(void)
{ {
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
#define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \ #define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \
__stringify(x), (long)(x)) __stringify(x), (long)(x))
#if GCC_VERSION >= 70000 #if defined(GCC_VERSION) && GCC_VERSION >= 70000
#define add_overflows(A, B) \ #define add_overflows(A, B) \
__builtin_add_overflow_p((A), (B), (typeof((A) + (B)))0) __builtin_add_overflow_p((A), (B), (typeof((A) + (B)))0)
#else #else
......
...@@ -146,12 +146,7 @@ static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data, ...@@ -146,12 +146,7 @@ static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data,
u32 remainder; u32 remainder;
u8 stage_cfg; u8 stage_cfg;
#if GCC_VERSION < 40400
/* work around a bug compiling do_div() */
prescaler = READ_ONCE(kempld_prescaler[PRESCALER_21]);
#else
prescaler = kempld_prescaler[PRESCALER_21]; prescaler = kempld_prescaler[PRESCALER_21];
#endif
if (!stage) if (!stage)
return -EINVAL; return -EINVAL;
......
...@@ -6,11 +6,7 @@ ...@@ -6,11 +6,7 @@
/* Some compiler specific definitions are overwritten here /* Some compiler specific definitions are overwritten here
* for Clang compiler * for Clang compiler
*/ */
#ifdef uninitialized_var
#undef uninitialized_var
#define uninitialized_var(x) x = *(&(x)) #define uninitialized_var(x) x = *(&(x))
#endif
/* same as gcc, this was present in clang-2.6 so we can assume it works /* same as gcc, this was present in clang-2.6 so we can assume it works
* with any version that can compile the kernel * with any version that can compile the kernel
...@@ -25,14 +21,8 @@ ...@@ -25,14 +21,8 @@
#define __SANITIZE_ADDRESS__ #define __SANITIZE_ADDRESS__
#endif #endif
#undef __no_sanitize_address
#define __no_sanitize_address __attribute__((no_sanitize("address"))) #define __no_sanitize_address __attribute__((no_sanitize("address")))
/* Clang doesn't have a way to turn it off per-function, yet. */
#ifdef __noretpoline
#undef __noretpoline
#endif
/* /*
* Not all versions of clang implement the the type-generic versions * Not all versions of clang implement the the type-generic versions
* of the builtin overflow checkers. Fortunately, clang implements * of the builtin overflow checkers. Fortunately, clang implements
...@@ -40,9 +30,17 @@ ...@@ -40,9 +30,17 @@
* checks. Unfortunately, we don't know which version of gcc clang * checks. Unfortunately, we don't know which version of gcc clang
* pretends to be, so the macro may or may not be defined. * pretends to be, so the macro may or may not be defined.
*/ */
#undef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
#if __has_builtin(__builtin_mul_overflow) && \ #if __has_builtin(__builtin_mul_overflow) && \
__has_builtin(__builtin_add_overflow) && \ __has_builtin(__builtin_add_overflow) && \
__has_builtin(__builtin_sub_overflow) __has_builtin(__builtin_sub_overflow)
#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
#endif #endif
/* 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 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__)))
...@@ -75,48 +75,6 @@ ...@@ -75,48 +75,6 @@
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
#endif #endif
/*
* 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,
* or if gcc is too old.
* GCC does not warn about unused static inline functions for
* -Wunused-function. This turns out to avoid the need for complex #ifdef
* directives. Suppress the warning in clang as well by using "unused"
* function attribute, which is redundant but not harmful for gcc.
* Prefer gnu_inline, so that extern inline functions do not emit an
* externally visible function. This makes extern inline behave as per gnu89
* semantics rather than c99. This prevents multiple symbol definition errors
* of extern inline functions at link time.
* A lot of inline functions can cause havoc with function tracing.
*/
#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
!defined(CONFIG_OPTIMIZE_INLINING)
#define inline \
inline __attribute__((always_inline, unused)) notrace __gnu_inline
#else
#define inline inline __attribute__((unused)) notrace __gnu_inline
#endif
#define __inline__ inline
#define __inline inline
#define __always_inline inline __attribute__((always_inline))
#define noinline __attribute__((noinline))
#define __packed __attribute__((packed))
#define __weak __attribute__((weak))
#define __alias(symbol) __attribute__((alias(#symbol)))
#ifdef RETPOLINE #ifdef RETPOLINE
#define __noretpoline __attribute__((indirect_branch("keep"))) #define __noretpoline __attribute__((indirect_branch("keep")))
#endif #endif
...@@ -135,55 +93,9 @@ ...@@ -135,55 +93,9 @@
*/ */
#define __naked __attribute__((naked)) noinline __noclone notrace #define __naked __attribute__((naked)) noinline __noclone notrace
#define __noreturn __attribute__((noreturn))
/*
* 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 __attribute_const__ __attribute__((__const__))
#define __maybe_unused __attribute__((unused))
#define __always_unused __attribute__((unused))
#define __mode(x) __attribute__((mode(x)))
#define __must_check __attribute__((warn_unused_result))
#define __malloc __attribute__((__malloc__))
#define __used __attribute__((__used__))
#define __compiler_offsetof(a, b) \
__builtin_offsetof(a, b)
/* Mark functions as cold. gcc will assume any path leading to a call
* to them will be unlikely. This means a lot of manual unlikely()s
* are unnecessary now for any paths leading to the usual suspects
* like BUG(), printk(), panic() etc. [but let's keep them for now for
* older compilers]
*
* Early snapshots of gcc 4.3 don't support this and we can't detect this
* in the preprocessor, but we can live with this because they're unreleased.
* Maketime probing would be overkill here.
*
* gcc also has a __attribute__((__hot__)) to move hot functions into
* a special section, but I don't see any sense in this right now in
* the kernel context
*/
#define __cold __attribute__((__cold__))
#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
#define __optimize(level) __attribute__((__optimize__(level))) #define __optimize(level) __attribute__((__optimize__(level)))
#define __nostackprotector __optimize("no-stack-protector")
#define __compiletime_object_size(obj) __builtin_object_size(obj, 0) #define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
......
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
/* Intel ECC compiler doesn't support gcc specific asm stmts. /* Intel ECC compiler doesn't support gcc specific asm stmts.
* It uses intrinsics to do the equivalent things. * It uses intrinsics to do the equivalent things.
*/ */
#undef barrier
#undef barrier_data
#undef RELOC_HIDE
#undef OPTIMIZER_HIDE_VAR
#define barrier() __memory_barrier() #define barrier() __memory_barrier()
#define barrier_data(ptr) barrier() #define barrier_data(ptr) barrier()
...@@ -38,13 +34,12 @@ ...@@ -38,13 +34,12 @@
#endif #endif
#ifndef __HAVE_BUILTIN_BSWAP16__
/* icc has this, but it's called _bswap16 */ /* icc has this, but it's called _bswap16 */
#define __HAVE_BUILTIN_BSWAP16__ #define __HAVE_BUILTIN_BSWAP16__
#define __builtin_bswap16 _bswap16 #define __builtin_bswap16 _bswap16
#endif
/* /* The following are for compatibility with GCC, from compiler-gcc.h,
* icc defines __GNUC__, but does not implement the builtin overflow checkers. * and may be redefined here because they should not be shared with other
* compilers, like clang.
*/ */
#undef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW #define __visible __attribute__((externally_visible))
...@@ -54,32 +54,20 @@ extern void __chk_io_ptr(const volatile void __iomem *); ...@@ -54,32 +54,20 @@ extern void __chk_io_ptr(const volatile void __iomem *);
#ifdef __KERNEL__ #ifdef __KERNEL__
#ifdef __GNUC__ /* Compiler specific macros. */
#include <linux/compiler-gcc.h>
#endif
#if defined(CC_USING_HOTPATCH) && !defined(__CHECKER__)
#define notrace __attribute__((hotpatch(0,0)))
#else
#define notrace __attribute__((no_instrument_function))
#endif
/* Intel compiler defines __GNUC__. So we will overwrite implementations
* coming from above header files here
*/
#ifdef __INTEL_COMPILER
# include <linux/compiler-intel.h>
#endif
/* Clang compiler defines __GNUC__. So we will overwrite implementations
* coming from above header files here
*/
#ifdef __clang__ #ifdef __clang__
#include <linux/compiler-clang.h> #include <linux/compiler-clang.h>
#elif defined(__INTEL_COMPILER)
#include <linux/compiler-intel.h>
#elif defined(__GNUC__)
/* The above compilers also define __GNUC__, so order is important here. */
#include <linux/compiler-gcc.h>
#else
#error "Unknown compiler"
#endif #endif
/* /*
* Generic compiler-dependent macros required for kernel * Generic compiler-independent macros required for kernel
* build go below this comment. Actual compiler/compiler version * build go below this comment. Actual compiler/compiler version
* specific implementations come from the above header files * specific implementations come from the above header files
*/ */
...@@ -106,93 +94,19 @@ struct ftrace_likely_data { ...@@ -106,93 +94,19 @@ struct ftrace_likely_data {
unsigned long constant; unsigned long constant;
}; };
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
#ifdef __KERNEL__
/* Don't. Just don't. */ /* Don't. Just don't. */
#define __deprecated #define __deprecated
#define __deprecated_for_modules #define __deprecated_for_modules
#ifndef __must_check
#define __must_check
#endif
#ifndef CONFIG_ENABLE_MUST_CHECK
#undef __must_check
#define __must_check
#endif
#ifndef __malloc
#define __malloc
#endif
/*
* Allow us to avoid 'defined but not used' warnings on functions and data,
* as well as force them to be emitted to the assembly file.
*
* As of gcc 3.4, static functions that are not marked with attribute((used))
* may be elided from the assembly file. As of gcc 3.4, static data not so
* marked will not be elided, but this may change in a future gcc version.
*
* NOTE: Because distributions shipped with a backported unit-at-a-time
* compiler in gcc 3.3, we must define __used to be __attribute__((used))
* for gcc >=3.3 instead of 3.4.
*
* In prior versions of gcc, such functions and data would be emitted, but
* would be warned about except with attribute((unused)).
*
* Mark functions that are referenced only in inline assembly as __used so
* the code is emitted even though it appears to be unreferenced.
*/
#ifndef __used
# define __used /* unimplemented */
#endif
#ifndef __maybe_unused
# define __maybe_unused /* unimplemented */
#endif
#ifndef __always_unused
# define __always_unused /* unimplemented */
#endif
#ifndef noinline
#define noinline
#endif
/*
* Rather then using noinline to prevent stack consumption, use
* noinline_for_stack instead. For documentation reasons.
*/
#define noinline_for_stack noinline
#ifndef __always_inline
#define __always_inline inline
#endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
/* /*
* From the GCC manual: * The below symbols may be defined for one or more, but not ALL, of the above
* * compilers. We don't consider that to be an error, so set them to nothing.
* Many functions do not examine any values except their arguments, * For example, some of them are for compiler specific plugins.
* and have no effects except the return value. Basically this is
* just slightly more strict class than the `pure' attribute above,
* since function is not allowed to read global memory.
*
* Note that a function that has pointer arguments and examines the
* data pointed to must _not_ be declared `const'. Likewise, a
* function that calls a non-`const' function usually must not be
* `const'. It does not make sense for a `const' function to return
* `void'.
*/ */
#ifndef __attribute_const__
# define __attribute_const__ /* unimplemented */
#endif
#ifndef __designated_init #ifndef __designated_init
# define __designated_init # define __designated_init
#endif #endif
...@@ -214,28 +128,10 @@ struct ftrace_likely_data { ...@@ -214,28 +128,10 @@ struct ftrace_likely_data {
# define randomized_struct_fields_end # define randomized_struct_fields_end
#endif #endif
/*
* Tell gcc if a function is cold. The compiler will assume any path
* directly leading to the call is unlikely.
*/
#ifndef __cold
#define __cold
#endif
/* Simple shorthand for a section definition */
#ifndef __section
# define __section(S) __attribute__ ((__section__(#S)))
#endif
#ifndef __visible #ifndef __visible
#define __visible #define __visible
#endif #endif
#ifndef __nostackprotector
# define __nostackprotector
#endif
/* /*
* Assume alignment of return value. * Assume alignment of return value.
*/ */
...@@ -243,17 +139,23 @@ struct ftrace_likely_data { ...@@ -243,17 +139,23 @@ struct ftrace_likely_data {
#define __assume_aligned(a, ...) #define __assume_aligned(a, ...)
#endif #endif
/* Are two types/vars the same type (ignoring qualifiers)? */ /* Are two types/vars the same type (ignoring qualifiers)? */
#ifndef __same_type #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#endif
/* Is this type a native word size -- useful for atomic operations */ /* Is this type a native word size -- useful for atomic operations */
#ifndef __native_word #define __native_word(t) \
# define __native_word(t) (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long)) (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 #endif
#ifndef __noclone
#define __noclone
#endif
/* Helpers for emitting diagnostics in pragmas. */
#ifndef __diag #ifndef __diag
#define __diag(string) #define __diag(string)
#endif #endif
...@@ -272,4 +174,92 @@ struct ftrace_likely_data { ...@@ -272,4 +174,92 @@ struct ftrace_likely_data {
#define __diag_error(compiler, version, option, comment) \ #define __diag_error(compiler, version, option, comment) \
__diag_ ## compiler(version, error, option) __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
#define __must_check
#endif
#if defined(CC_USING_HOTPATCH) && !defined(__CHECKER__)
#define notrace __attribute__((hotpatch(0, 0)))
#else
#define notrace __attribute__((no_instrument_function))
#endif
#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
* -Wunused-function. This turns out to avoid the need for complex #ifdef
* directives. Suppress the warning in clang as well by using "unused"
* function attribute, which is redundant but not harmful for gcc.
* Prefer gnu_inline, so that extern inline functions do not emit an
* externally visible function. This makes extern inline behave as per gnu89
* semantics rather than c99. This prevents multiple symbol definition errors
* of extern inline functions at link time.
* A lot of inline functions can cause havoc with function tracing.
*/
#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
!defined(CONFIG_OPTIMIZE_INLINING)
#define inline \
inline __attribute__((always_inline, unused)) notrace __gnu_inline
#else
#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
/*
* Rather then using noinline to prevent stack consumption, use
* noinline_for_stack instead. For documentation reasons.
*/
#define noinline_for_stack noinline
#endif /* __LINUX_COMPILER_TYPES_H */ #endif /* __LINUX_COMPILER_TYPES_H */
...@@ -652,9 +652,9 @@ static void remove_node_from_stable_tree(struct stable_node *stable_node) ...@@ -652,9 +652,9 @@ static void remove_node_from_stable_tree(struct stable_node *stable_node)
* list_head to stay clear from the rb_parent_color union * list_head to stay clear from the rb_parent_color union
* (aligned and different than any node) and also different * (aligned and different than any node) and also different
* from &migrate_nodes. This will verify that future list.h changes * from &migrate_nodes. This will verify that future list.h changes
* don't break STABLE_NODE_DUP_HEAD. * don't break STABLE_NODE_DUP_HEAD. Only recent gcc can handle it.
*/ */
#if GCC_VERSION >= 40903 /* only recent gcc can handle it */ #if defined(GCC_VERSION) && GCC_VERSION >= 40903
BUILD_BUG_ON(STABLE_NODE_DUP_HEAD <= &migrate_nodes); BUILD_BUG_ON(STABLE_NODE_DUP_HEAD <= &migrate_nodes);
BUILD_BUG_ON(STABLE_NODE_DUP_HEAD >= &migrate_nodes + 1); BUILD_BUG_ON(STABLE_NODE_DUP_HEAD >= &migrate_nodes + 1);
#endif #endif
......
...@@ -1131,7 +1131,8 @@ static int __unmap_and_move(struct page *page, struct page *newpage, ...@@ -1131,7 +1131,8 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
* gcc 4.7 and 4.8 on arm get an ICEs when inlining unmap_and_move(). Work * gcc 4.7 and 4.8 on arm get an ICEs when inlining unmap_and_move(). Work
* around it. * around it.
*/ */
#if (GCC_VERSION >= 40700 && GCC_VERSION < 40900) && defined(CONFIG_ARM) #if defined(CONFIG_ARM) && \
defined(GCC_VERSION) && GCC_VERSION < 40900 && GCC_VERSION >= 40700
#define ICE_noinline noinline #define ICE_noinline noinline
#else #else
#define ICE_noinline #define ICE_noinline
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment