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 
62 #ifdef __cplusplus
63 extern "C" {
64 #endif
65 
66 /**
67  * @def OT_MUST_USE_RESULT
68  *
69  * Compiler-specific indication that a class or enum must be used when it is
70  * the return value of a function.
71  *
72  * @note This is currently only available with clang (C++17 implements it
73  *       as attribute [[nodiscard]]).
74  * @note To suppress the 'unused-result' warning/error, please use the
75  *       '-Wno-unused-result' compiler option.
76  *
77  */
78 #if defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ >= 3 && __clang_minor__ >= 9))
79 #define OT_MUST_USE_RESULT __attribute__((warn_unused_result))
80 #else
81 #define OT_MUST_USE_RESULT
82 #endif
83 
84 /**
85  * @def OT_TOOL_PACKED_BEGIN
86  *
87  * Compiler-specific indication that a class or struct must be byte packed.
88  *
89  */
90 
91 /**
92  * @def OT_TOOL_PACKED_FIELD
93  *
94  * Indicate to the compiler a nested struct or union to be packed
95  * within byte packed class or struct.
96  *
97  */
98 
99 /**
100  * @def OT_TOOL_PACKED_END
101  *
102  * Compiler-specific indication at the end of a byte packed class or struct.
103  *
104  */
105 
106 /**
107  * @def OT_TOOL_WEAK
108  *
109  * Compiler-specific weak symbol modifier.
110  *
111  */
112 
113 /**
114  * @def OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK
115  *
116  * This macro specifies that a function or method takes `printf` style arguments and should be type-checked against
117  * a format string.
118  *
119  * This macro must be added after the function/method declaration. For example:
120  *
121  *    `void MyPrintf(void *aObject, const char *aFormat, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(2, 3);`
122  *
123  * The two argument index values indicate format string and first argument to check against it. They start at index 1
124  * for the first parameter in a function and at index 2 for the first parameter in a method.
125  *
126  * @param[in] aFmtIndex    The argument index of the format string.
127  * @param[in] aStartIndex  The argument index of the first argument to check against the format string.
128  *
129  */
130 
131 // =========== TOOLCHAIN SELECTION : START ===========
132 
133 #if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM) || defined(__TI_ARM__)
134 
135 // https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
136 // http://www.keil.com/support/man/docs/armcc/armcc_chr1359124973480.htm
137 
138 #define OT_TOOL_PACKED_BEGIN
139 #define OT_TOOL_PACKED_FIELD __attribute__((packed))
140 #define OT_TOOL_PACKED_END __attribute__((packed))
141 #define OT_TOOL_WEAK __attribute__((weak))
142 
143 #define OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(aFmtIndex, aStartIndex) \
144     __attribute__((format(printf, aFmtIndex, aStartIndex)))
145 
146 #elif defined(__ICCARM__) || defined(__ICC8051__)
147 
148 // http://supp.iar.com/FilesPublic/UPDINFO/004916/arm/doc/EWARM_DevelopmentGuide.ENU.pdf
149 
150 #include "intrinsics.h"
151 
152 #define OT_TOOL_PACKED_BEGIN __packed
153 #define OT_TOOL_PACKED_FIELD
154 #define OT_TOOL_PACKED_END
155 #define OT_TOOL_WEAK __weak
156 
157 #define OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(aFmtIndex, aStartIndex)
158 
159 #elif defined(__SDCC)
160 
161 // Structures are packed by default in sdcc, as it primarily targets 8-bit MCUs.
162 
163 #define OT_TOOL_PACKED_BEGIN
164 #define OT_TOOL_PACKED_FIELD
165 #define OT_TOOL_PACKED_END
166 #define OT_TOOL_WEAK
167 
168 #define OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(aFmtIndex, aStartIndex)
169 
170 #else
171 
172 #error "Error: No valid Toolchain specified"
173 
174 // Symbols for Doxygen
175 
176 #define OT_TOOL_PACKED_BEGIN
177 #define OT_TOOL_PACKED_FIELD
178 #define OT_TOOL_PACKED_END
179 #define OT_TOOL_WEAK
180 
181 #define OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(aFmtIndex, aStartIndex)
182 
183 #endif
184 
185 // =========== TOOLCHAIN SELECTION : END ===========
186 
187 /**
188  * @def OT_UNUSED_VARIABLE
189  *
190  * Suppress unused variable warning in specific toolchains.
191  *
192  */
193 
194 /**
195  * @def OT_UNREACHABLE_CODE
196  *
197  * Suppress Unreachable code warning in specific toolchains.
198  *
199  */
200 
201 #if defined(__ICCARM__)
202 
203 #include <stddef.h>
204 
205 #define OT_UNUSED_VARIABLE(VARIABLE) \
206     do                               \
207     {                                \
208         if (&VARIABLE == NULL)       \
209         {                            \
210         }                            \
211     } while (false)
212 
213 #define OT_UNREACHABLE_CODE(CODE)                                                                    \
214     _Pragma("diag_suppress=Pe111") _Pragma("diag_suppress=Pe128") CODE _Pragma("diag_default=Pe111") \
215         _Pragma("diag_default=Pe128")
216 
217 #elif defined(__CC_ARM)
218 
219 #include <stddef.h>
220 
221 #define OT_UNUSED_VARIABLE(VARIABLE) \
222     do                               \
223     {                                \
224         if (&VARIABLE == NULL)       \
225         {                            \
226         }                            \
227     } while (false)
228 
229 #define OT_UNREACHABLE_CODE(CODE) CODE
230 
231 #elif defined(__TI_ARM__)
232 
233 #include <stddef.h>
234 
235 #define OT_UNUSED_VARIABLE(VARIABLE) \
236     do                               \
237     {                                \
238         if (&VARIABLE == NULL)       \
239         {                            \
240         }                            \
241     } while (false)
242 
243 /*
244  * #112-D statement is unreachable
245  * #129-D loop is not reachable
246  */
247 #define OT_UNREACHABLE_CODE(CODE) \
248     _Pragma("diag_push") _Pragma("diag_suppress 112") _Pragma("diag_suppress 129") CODE _Pragma("diag_pop")
249 
250 #else
251 
252 #define OT_UNUSED_VARIABLE(VARIABLE) \
253     do                               \
254     {                                \
255         (void)(VARIABLE);            \
256     } while (false)
257 
258 #define OT_UNREACHABLE_CODE(CODE) CODE
259 
260 #endif
261 
262 /*
263  * Keil and IAR compiler doesn't provide type limits for C++.
264  */
265 #ifdef __cplusplus
266 #if defined(__CC_ARM) || defined(__ICCARM__)
267 
268 #ifndef UINT8_MAX
269 #define UINT8_MAX 0xff
270 #endif
271 
272 #ifndef UINT16_MAX
273 #define UINT16_MAX 0xffff
274 #endif
275 
276 #endif
277 #endif
278 
279 #ifdef __APPLE__
280 #define OT_APPLE_IGNORE_GNU_FOLDING_CONSTANT(...)                                               \
281     _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wgnu-folding-constant\"") \
282         __VA_ARGS__ _Pragma("GCC diagnostic pop")
283 #else
284 #define OT_APPLE_IGNORE_GNU_FOLDING_CONSTANT(...) __VA_ARGS__
285 #endif
286 
287 /**
288  * @def OT_FALL_THROUGH
289  *
290  * Suppress fall through warning in specific compiler.
291  *
292  */
293 #if defined(__cplusplus) && (__cplusplus >= 201703L)
294 #define OT_FALL_THROUGH [[fallthrough]]
295 #elif defined(__clang__)
296 #define OT_FALL_THROUGH [[clang::fallthrough]]
297 #elif defined(__GNUC__) && (__GNUC__ >= 7)
298 #define OT_FALL_THROUGH __attribute__((fallthrough))
299 #else
300 #define OT_FALL_THROUGH \
301     do                  \
302     {                   \
303     } while (false) /* fallthrough */
304 #endif
305 
306 /**
307  * @}
308  *
309  */
310 
311 #ifdef __cplusplus
312 } // extern "C"
313 #endif
314 
315 #endif // OPENTHREAD_PLATFORM_TOOLCHAIN_H_
316