1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @addtogroup plat-toolchain
31  *
32  * @brief
33  *   This module defines a toolchain abstraction layer through macros.
34  *
35  * Usage:
36  *
37  *    @code
38  *
39  *    typedef
40  *    OT_TOOL_PACKED_BEGIN
41  *    struct
42  *    {
43  *        char mField1;
44  *        union
45  *        {
46  *            char mField2;
47  *            long mField3;
48  *        } OT_TOOL_PACKED_FIELD;
49  *    } OT_TOOL_PACKED_END packed_struct_t;
50  *
51  *    @endcode
52  *
53  * @{
54  *
55  */
56 
57 #ifndef OPENTHREAD_PLATFORM_TOOLCHAIN_H_
58 #define OPENTHREAD_PLATFORM_TOOLCHAIN_H_
59 
60 #include <stdbool.h>
61 #include <stdint.h>
62 
63 #ifdef __cplusplus
64 extern "C" {
65 #endif
66 
67 /**
68  * @def OT_MUST_USE_RESULT
69  *
70  * Compiler-specific indication that a class or enum must be used when it is
71  * the return value of a function.
72  *
73  * @note This is currently only available with clang (C++17 implements it
74  *       as attribute [[nodiscard]]).
75  * @note To suppress the 'unused-result' warning/error, please use the
76  *       '-Wno-unused-result' compiler option.
77  *
78  */
79 #if defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ >= 3 && __clang_minor__ >= 9))
80 #define OT_MUST_USE_RESULT __attribute__((warn_unused_result))
81 #else
82 #define OT_MUST_USE_RESULT
83 #endif
84 
85 /**
86  * @def OT_TOOL_PACKED_BEGIN
87  *
88  * Compiler-specific indication that a class or struct must be byte packed.
89  *
90  */
91 
92 /**
93  * @def OT_TOOL_PACKED_FIELD
94  *
95  * Indicate to the compiler a nested struct or union to be packed
96  * within byte packed class or struct.
97  *
98  */
99 
100 /**
101  * @def OT_TOOL_PACKED_END
102  *
103  * Compiler-specific indication at the end of a byte packed class or struct.
104  *
105  */
106 
107 /**
108  * @def OT_TOOL_WEAK
109  *
110  * Compiler-specific weak symbol modifier.
111  *
112  */
113 
114 /**
115  * @def OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK
116  *
117  * Specifies that a function or method takes `printf` style arguments and should be type-checked against
118  * a format string.
119  *
120  * Must be added after the function/method declaration. For example:
121  *
122  *    `void MyPrintf(void *aObject, const char *aFormat, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(2, 3);`
123  *
124  * The two argument index values indicate format string and first argument to check against it. They start at index 1
125  * for the first parameter in a function and at index 2 for the first parameter in a method.
126  *
127  * @param[in] aFmtIndex    The argument index of the format string.
128  * @param[in] aStartIndex  The argument index of the first argument to check against the format string.
129  *
130  */
131 
132 // =========== TOOLCHAIN SELECTION : START ===========
133 
134 #if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM) || defined(__TI_ARM__)
135 
136 // https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
137 // http://www.keil.com/support/man/docs/armcc/armcc_chr1359124973480.htm
138 
139 #define OT_TOOL_PACKED_BEGIN
140 #define OT_TOOL_PACKED_FIELD __attribute__((packed))
141 #define OT_TOOL_PACKED_END __attribute__((packed))
142 #define OT_TOOL_WEAK __attribute__((weak))
143 
144 #define OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(aFmtIndex, aStartIndex) \
145     __attribute__((format(printf, aFmtIndex, aStartIndex)))
146 
147 #elif defined(__ICCARM__) || defined(__ICC8051__)
148 
149 // http://supp.iar.com/FilesPublic/UPDINFO/004916/arm/doc/EWARM_DevelopmentGuide.ENU.pdf
150 
151 #include "intrinsics.h"
152 
153 #define OT_TOOL_PACKED_BEGIN __packed
154 #define OT_TOOL_PACKED_FIELD
155 #define OT_TOOL_PACKED_END
156 #define OT_TOOL_WEAK __weak
157 
158 #define OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(aFmtIndex, aStartIndex)
159 
160 #elif defined(__SDCC)
161 
162 // Structures are packed by default in sdcc, as it primarily targets 8-bit MCUs.
163 
164 #define OT_TOOL_PACKED_BEGIN
165 #define OT_TOOL_PACKED_FIELD
166 #define OT_TOOL_PACKED_END
167 #define OT_TOOL_WEAK
168 
169 #define OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(aFmtIndex, aStartIndex)
170 
171 #else
172 
173 #error "Error: No valid Toolchain specified"
174 
175 // Symbols for Doxygen
176 
177 #define OT_TOOL_PACKED_BEGIN
178 #define OT_TOOL_PACKED_FIELD
179 #define OT_TOOL_PACKED_END
180 #define OT_TOOL_WEAK
181 
182 #define OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(aFmtIndex, aStartIndex)
183 
184 #endif
185 
186 // =========== TOOLCHAIN SELECTION : END ===========
187 
188 /**
189  * @def OT_UNUSED_VARIABLE
190  *
191  * Suppress unused variable warning in specific toolchains.
192  *
193  */
194 
195 /**
196  * @def OT_UNREACHABLE_CODE
197  *
198  * Suppress Unreachable code warning in specific toolchains.
199  *
200  */
201 
202 #if defined(__ICCARM__)
203 
204 #include <stddef.h>
205 
206 #define OT_UNUSED_VARIABLE(VARIABLE) \
207     do                               \
208     {                                \
209         if (&VARIABLE == NULL)       \
210         {                            \
211         }                            \
212     } while (false)
213 
214 #define OT_UNREACHABLE_CODE(CODE)                                                                    \
215     _Pragma("diag_suppress=Pe111") _Pragma("diag_suppress=Pe128") CODE _Pragma("diag_default=Pe111") \
216         _Pragma("diag_default=Pe128")
217 
218 #elif defined(__CC_ARM)
219 
220 #include <stddef.h>
221 
222 #define OT_UNUSED_VARIABLE(VARIABLE) \
223     do                               \
224     {                                \
225         if (&VARIABLE == NULL)       \
226         {                            \
227         }                            \
228     } while (false)
229 
230 #define OT_UNREACHABLE_CODE(CODE) CODE
231 
232 #elif defined(__TI_ARM__)
233 
234 #include <stddef.h>
235 
236 #define OT_UNUSED_VARIABLE(VARIABLE) \
237     do                               \
238     {                                \
239         if (&VARIABLE == NULL)       \
240         {                            \
241         }                            \
242     } while (false)
243 
244 /*
245  * #112-D statement is unreachable
246  * #129-D loop is not reachable
247  */
248 #define OT_UNREACHABLE_CODE(CODE) \
249     _Pragma("diag_push") _Pragma("diag_suppress 112") _Pragma("diag_suppress 129") CODE _Pragma("diag_pop")
250 
251 #else
252 
253 #define OT_UNUSED_VARIABLE(VARIABLE) \
254     do                               \
255     {                                \
256         (void)(VARIABLE);            \
257     } while (false)
258 
259 #define OT_UNREACHABLE_CODE(CODE) CODE
260 
261 #endif
262 
263 /*
264  * Keil and IAR compiler doesn't provide type limits for C++.
265  */
266 #ifdef __cplusplus
267 #if defined(__CC_ARM) || defined(__ICCARM__)
268 
269 #ifndef UINT8_MAX
270 #define UINT8_MAX 0xff
271 #endif
272 
273 #ifndef UINT16_MAX
274 #define UINT16_MAX 0xffff
275 #endif
276 
277 #endif
278 #endif
279 
280 #ifdef __APPLE__
281 #define OT_APPLE_IGNORE_GNU_FOLDING_CONSTANT(...)                                               \
282     _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wgnu-folding-constant\"") \
283         __VA_ARGS__ _Pragma("GCC diagnostic pop")
284 #else
285 #define OT_APPLE_IGNORE_GNU_FOLDING_CONSTANT(...) __VA_ARGS__
286 #endif
287 
288 /**
289  * @def OT_FALL_THROUGH
290  *
291  * Suppress fall through warning in specific compiler.
292  *
293  */
294 #if defined(__cplusplus) && (__cplusplus >= 201703L)
295 #define OT_FALL_THROUGH [[fallthrough]]
296 #elif defined(__clang__)
297 #define OT_FALL_THROUGH [[clang::fallthrough]]
298 #elif defined(__GNUC__) && (__GNUC__ >= 7)
299 #define OT_FALL_THROUGH __attribute__((fallthrough))
300 #else
301 #define OT_FALL_THROUGH \
302     do                  \
303     {                   \
304     } while (false) /* fallthrough */
305 #endif
306 
307 /**
308  * @}
309  *
310  */
311 
312 #ifdef __cplusplus
313 } // extern "C"
314 #endif
315 
316 #endif // OPENTHREAD_PLATFORM_TOOLCHAIN_H_
317