1 #ifndef __LINUX_COMPILER_H
2 #define __LINUX_COMPILER_H
3 
4 #if !defined(__GNUC__) || (__GNUC__ < 4)
5 #error Sorry, your compiler is too old/not recognized.
6 #elif CONFIG_CC_IS_GCC
7 # if defined(CONFIG_ARM_32) && CONFIG_GCC_VERSION < 40900
8 #  error Sorry, your version of GCC is too old - please use 4.9 or newer.
9 # elif defined(CONFIG_ARM_64) && CONFIG_GCC_VERSION < 50100
10 /*
11  * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63293
12  * https://lore.kernel.org/r/20210107111841.GN1551@shell.armlinux.org.uk
13  */
14 #  error Sorry, your version of GCC is too old - please use 5.1 or newer.
15 # endif
16 #endif
17 
18 #define barrier()     __asm__ __volatile__("": : :"memory")
19 
20 #define likely(x)     __builtin_expect(!!(x),1)
21 #define unlikely(x)   __builtin_expect(!!(x),0)
22 
23 #define always_inline inline __attribute__((__always_inline__))
24 #define gnu_inline    inline __attribute__((__gnu_inline__))
25 #define noinline      __attribute__((__noinline__))
26 
27 #define noreturn      __attribute__((__noreturn__))
28 
29 #define __packed      __attribute__((__packed__))
30 
31 #define __weak        __attribute__((__weak__))
32 
33 #if !defined(CONFIG_CC_IS_CLANG) || CONFIG_CLANG_VERSION >= 140000
34 # define nocall       __attribute__((__error__("Nonstandard ABI")))
35 #else
36 # define nocall
37 #endif
38 
39 #ifdef CONFIG_XEN_IBT
40 # define cf_check     __attribute__((__cf_check__))
41 #else
42 # define cf_check
43 #endif
44 
45 #if (!defined(__clang__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5))
46 #define unreachable() do {} while (1)
47 #else
48 #define unreachable() __builtin_unreachable()
49 #endif
50 
51 /*
52  * Add the pseudo keyword 'fallthrough' so case statement blocks
53  * must end with any of these keywords:
54  *   break;
55  *   fallthrough;
56  *   goto <label>;
57  *   return [expression];
58  *
59  *  gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#Statement-Attributes
60  */
61 #if (!defined(__clang__) && (__GNUC__ >= 7))
62 # define fallthrough        __attribute__((__fallthrough__))
63 #else
64 # define fallthrough        do {} while (0)  /* fallthrough */
65 #endif
66 
67 #ifdef __clang__
68 /* Clang can replace some vars with new automatic ones that go in .data;
69  * mark all explicit-segment vars 'used' to prevent that. */
70 #define __section(s)      __used __attribute__((__section__(s)))
71 #else
72 #define __section(s)      __attribute__((__section__(s)))
73 #endif
74 #define __used_section(s) __used __attribute__((__section__(s)))
75 #define __text_section(s) __attribute__((__section__(s)))
76 
77 #define __aligned(a) __attribute__((__aligned__(a)))
78 
79 #ifdef INIT_SECTIONS_ONLY
80 /*
81  * For sources indicated to have only init code, make sure even
82  * inline functions not expanded inline get placed in .init.text.
83  */
84 #include <xen/init.h>
85 /* SAF-3-safe MISRA C Rule 20.4: allow section checks to pass when not inlined */
86 #define inline inline __init
87 #endif
88 
89 #define __constructor       __attribute__((__constructor__)) cf_check
90 #define __pure              __attribute__((__pure__))
91 #define __attribute_const__ __attribute__((__const__))
92 #define __transparent__     __attribute__((__transparent_union__))
93 
94 /*
95  * The difference between the following two attributes is that __used is
96  * intended to be used in cases where a reference to an identifier may be
97  * invisible to the compiler (e.g. an inline assembly operand not listed
98  * in the asm()'s operands), preventing the compiler from eliminating the
99  * variable or function.
100  * __maybe_unused otoh is to be used to merely prevent warnings (e.g. when
101  * an identifier is used only inside a preprocessor conditional, yet putting
102  * its declaration/definition inside another conditional would harm code
103  * readability).
104  */
105 #define __used         __attribute__((__used__))
106 #define __maybe_unused __attribute__((__unused__))
107 
108 #define __must_check __attribute__((__warn_unused_result__))
109 #define __nonnull(...) __attribute__((__nonnull__(__VA_ARGS__)))
110 
111 #define offsetof(a,b) __builtin_offsetof(a,b)
112 
113 #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
114 #define alignof __alignof__
115 #endif
116 
117 /* &a[0] degrades to a pointer: a different type from an array */
118 #define __must_be_array(a) \
119   BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&(a)[0])))
120 
121 #ifdef CONFIG_CC_HAS_VISIBILITY_ATTRIBUTE
122 /* Results in more efficient PIC code (no indirections through GOT or PLT). */
123 #pragma GCC visibility push(hidden)
124 #endif
125 
126 /* Make the optimizer believe the variable can be manipulated arbitrarily. */
127 #define OPTIMIZER_HIDE_VAR(var) __asm__ ( "" : "+g" (var) )
128 
129 /* This macro obfuscates arithmetic on a variable address so that gcc
130    shouldn't recognize the original var, and make assumptions about it */
131 /*
132  * Versions of the ppc64 compiler before 4.1 had a bug where use of
133  * RELOC_HIDE could trash r30. The bug can be worked around by changing
134  * the inline assembly constraint from =g to =r, in this particular
135  * case either is valid.
136  */
137 #define RELOC_HIDE(ptr, off)                    \
138   ({ unsigned long __ptr;                       \
139     __asm__ ("" : "=r"(__ptr) : "0"(ptr));      \
140     (typeof(ptr)) (__ptr + (off)); })
141 
142 /* See gcc bug 100680. */
143 #if CONFIG_GCC_VERSION >= 110000 && CONFIG_GCC_VERSION < 110300
144 # define gcc11_wrap(x) RELOC_HIDE(x, 0)
145 #else
146 # define gcc11_wrap(x) (x)
147 #endif
148 
149 #ifdef __GCC_ASM_FLAG_OUTPUTS__
150 # define ASM_FLAG_OUT(yes, no) yes
151 #else
152 # define ASM_FLAG_OUT(yes, no) no
153 #endif
154 
155 /* Mark a function or variable as being used only to interface with asm */
156 #ifndef asmlinkage
157 #define asmlinkage
158 #endif
159 
160 /*
161  * NB: we need to disable the gcc-compat warnings for clang in some places or
162  * else it will complain with: "'break' is bound to loop, GCC binds it to
163  * switch" when a switch is used inside of a while expression inside of a
164  * switch statement, ie:
165  *
166  * switch ( ... )
167  * {
168  * case ...:
169  *      while ( ({ int x; switch ( foo ) { case 1: x = 1; break; } x }) )
170  *      {
171  *              ...
172  *
173  * This has already been reported upstream:
174  * http://bugs.llvm.org/show_bug.cgi?id=32595
175  */
176 #ifdef __clang__
177 # define CLANG_DISABLE_WARN_GCC_COMPAT_START                    \
178     _Pragma("clang diagnostic push")                            \
179     _Pragma("clang diagnostic ignored \"-Wgcc-compat\"")
180 # define CLANG_DISABLE_WARN_GCC_COMPAT_END                      \
181     _Pragma("clang diagnostic pop")
182 #else
183 # define CLANG_DISABLE_WARN_GCC_COMPAT_START
184 # define CLANG_DISABLE_WARN_GCC_COMPAT_END
185 #endif
186 
187 #endif /* __LINUX_COMPILER_H */
188