1 /*
2  * Copyright (c) 2010-2014, Wind River Systems, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Macros to abstract toolchain specific capabilities
10  *
11  * This file contains various macros to abstract compiler capabilities that
12  * utilize toolchain specific attributes and/or pragmas.
13  */
14 
15 #ifndef ZEPHYR_INCLUDE_TOOLCHAIN_H_
16 #define ZEPHYR_INCLUDE_TOOLCHAIN_H_
17 
18 /**
19  * @def HAS_BUILTIN(x)
20  * @brief Check if the compiler supports the built-in function \a x.
21  *
22  * This macro is for use with conditional compilation to enable code using a
23  * builtin function that may not be available in every compiler.
24  */
25 #ifdef __has_builtin
26 #define HAS_BUILTIN(x) __has_builtin(x)
27 #else
28 /*
29  * The compiler doesn't provide the __has_builtin() macro, so instead we depend
30  * on the toolchain-specific headers to define HAS_BUILTIN_x for the builtins
31  * supported.
32  */
33 #define HAS_BUILTIN(x) HAS_BUILTIN_##x
34 #endif
35 
36 #if defined(__TOOLCHAIN_CUSTOM__)
37 /* This include line exists for off-tree definitions of compilers,
38  * and therefore this header is not meant to exist in-tree
39  */
40 #include <toolchain/other.h>
41 #elif defined(__XCC__)
42 #include <zephyr/toolchain/xcc.h>
43 #elif defined(__CCAC__)
44 #include <zephyr/toolchain/mwdt.h>
45 #elif defined(__ARMCOMPILER_VERSION)
46 #include <zephyr/toolchain/armclang.h>
47 #elif defined(__llvm__)
48 #include <zephyr/toolchain/llvm.h>
49 #elif defined(__GNUC__) || (defined(_LINKER) && defined(__GCC_LINKER_CMD__))
50 #include <zephyr/toolchain/gcc.h>
51 #else
52 #error "Invalid/unknown toolchain configuration"
53 #endif
54 
55 /**
56  * @def __noasan
57  * @brief Disable address sanitizer
58  *
59  * When used in the definiton of a symbol, prevents that symbol (be it
60  * a function or data) from being instrumented by the address
61  * sanitizer feature of the compiler.  Most commonly, this is used to
62  * prevent padding around data that will be treated specially by the
63  * Zephyr link (c.f. SYS_INIT records, STRUCT_SECTION_ITERABLE
64  * definitions) in ways that don't understand the guard padding.
65  */
66 #ifndef __noasan
67 #define __noasan /**/
68 #endif
69 
70 /**
71  * @def TOOLCHAIN_GCC_VERSION
72  * @brief GCC version in xxyyzz for xx.yy.zz. Zero if not GCC compatible.
73  */
74 #ifndef TOOLCHAIN_GCC_VERSION
75 #define TOOLCHAIN_GCC_VERSION 0
76 #endif
77 
78 /**
79  * @def TOOLCHAIN_CLANG_VERSION
80  * @brief Clang version in xxyyzz for xx.yy.zz. Zero if not Clang compatible.
81  */
82 #ifndef TOOLCHAIN_CLANG_VERSION
83 #define TOOLCHAIN_CLANG_VERSION 0
84 #endif
85 
86 /**
87  * @def TOOLCHAIN_HAS_PRAGMA_DIAG
88  * @brief Indicate if toolchain supports \#pragma diagnostics.
89  */
90 #ifndef TOOLCHAIN_HAS_PRAGMA_DIAG
91 #define TOOLCHAIN_HAS_PRAGMA_DIAG 0
92 #endif
93 
94 /**
95  * @def TOOLCHAIN_HAS_C_GENERIC
96  * @brief Indicate if toolchain supports C Generic.
97  */
98 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
99 /* _Generic is introduced in C11, so it is supported. */
100 # ifdef TOOLCHAIN_HAS_C_GENERIC
101 #  undef TOOLCHAIN_HAS_C_GENERIC
102 # endif
103 # define TOOLCHAIN_HAS_C_GENERIC 1
104 #else
105 # ifndef TOOLCHAIN_HAS_C_GENERIC
106 #  define TOOLCHAIN_HAS_C_GENERIC 0
107 # endif
108 #endif
109 
110 /**
111  * @def TOOLCHAIN_HAS_C_AUTO_TYPE
112  * @brief Indicate if toolchain supports C __auto_type.
113  */
114 #ifndef TOOLCHAIN_HAS_C_AUTO_TYPE
115 #define TOOLCHAIN_HAS_C_AUTO_TYPE 0
116 #endif
117 
118 /*
119  * Ensure that __BYTE_ORDER__ and related preprocessor definitions are defined,
120  * and that they match the Kconfig option that is used in the code itself to
121  * check for endianness.
122  */
123 #ifndef _LINKER
124 #if !defined(__BYTE_ORDER__) || !defined(__ORDER_BIG_ENDIAN__) || \
125     !defined(__ORDER_LITTLE_ENDIAN__)
126 
127 /*
128  * Displaying values unfortunately requires #pragma message which can't
129  * be taken for granted + STRINGIFY() which is not available in this .h
130  * file.
131  */
132 #error "At least one byte _ORDER_ macro is not defined"
133 
134 #else
135 
136 #if (defined(CONFIG_BIG_ENDIAN) && (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__)) || \
137     (defined(CONFIG_LITTLE_ENDIAN) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__))
138 
139 #  error "Kconfig/toolchain endianness mismatch:"
140 
141 #  if (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
142 #    error "Unknown __BYTE_ORDER__ value"
143 #  else
144 #    ifdef CONFIG_BIG_ENDIAN
145 #      error "CONFIG_BIG_ENDIAN but __ORDER_LITTLE_ENDIAN__"
146 #    endif
147 #    ifdef CONFIG_LITTLE_ENDIAN
148 #      error "CONFIG_LITTLE_ENDIAN but __ORDER_BIG_ENDIAN__"
149 #   endif
150 # endif
151 
152 #endif  /* Endianness mismatch */
153 
154 #endif /* all _ORDER_ macros defined */
155 
156 #endif /* !_LINKER */
157 
158 #endif /* ZEPHYR_INCLUDE_TOOLCHAIN_H_ */
159