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 // =========== TOOLCHAIN SELECTION : START ===========
114 
115 #if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM) || defined(__TI_ARM__)
116 
117 // https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
118 // http://www.keil.com/support/man/docs/armcc/armcc_chr1359124973480.htm
119 
120 #define OT_TOOL_PACKED_BEGIN
121 #define OT_TOOL_PACKED_FIELD __attribute__((packed))
122 #define OT_TOOL_PACKED_END __attribute__((packed))
123 #define OT_TOOL_WEAK __attribute__((weak))
124 
125 #elif defined(__ICCARM__) || defined(__ICC8051__)
126 
127 // http://supp.iar.com/FilesPublic/UPDINFO/004916/arm/doc/EWARM_DevelopmentGuide.ENU.pdf
128 
129 #include "intrinsics.h"
130 
131 #define OT_TOOL_PACKED_BEGIN __packed
132 #define OT_TOOL_PACKED_FIELD
133 #define OT_TOOL_PACKED_END
134 #define OT_TOOL_WEAK __weak
135 
136 #elif defined(__SDCC)
137 
138 // Structures are packed by default in sdcc, as it primarily targets 8-bit MCUs.
139 
140 #define OT_TOOL_PACKED_BEGIN
141 #define OT_TOOL_PACKED_FIELD
142 #define OT_TOOL_PACKED_END
143 #define OT_TOOL_WEAK
144 
145 #else
146 
147 #error "Error: No valid Toolchain specified"
148 
149 // Symbols for Doxygen
150 
151 #define OT_TOOL_PACKED_BEGIN
152 #define OT_TOOL_PACKED_FIELD
153 #define OT_TOOL_PACKED_END
154 #define OT_TOOL_WEAK
155 
156 #endif
157 
158 // =========== TOOLCHAIN SELECTION : END ===========
159 
160 /**
161  * @def OT_UNUSED_VARIABLE
162  *
163  * Suppress unused variable warning in specific toolchains.
164  *
165  */
166 
167 /**
168  * @def OT_UNREACHABLE_CODE
169  *
170  * Suppress Unreachable code warning in specific toolchains.
171  *
172  */
173 
174 #if defined(__ICCARM__)
175 
176 #include <stddef.h>
177 
178 #define OT_UNUSED_VARIABLE(VARIABLE) \
179     do                               \
180     {                                \
181         if (&VARIABLE == NULL)       \
182         {                            \
183         }                            \
184     } while (false)
185 
186 #define OT_UNREACHABLE_CODE(CODE)                                                                    \
187     _Pragma("diag_suppress=Pe111") _Pragma("diag_suppress=Pe128") CODE _Pragma("diag_default=Pe111") \
188         _Pragma("diag_default=Pe128")
189 
190 #elif defined(__CC_ARM)
191 
192 #include <stddef.h>
193 
194 #define OT_UNUSED_VARIABLE(VARIABLE) \
195     do                               \
196     {                                \
197         if (&VARIABLE == NULL)       \
198         {                            \
199         }                            \
200     } while (false)
201 
202 #define OT_UNREACHABLE_CODE(CODE) CODE
203 
204 #elif defined(__TI_ARM__)
205 
206 #include <stddef.h>
207 
208 #define OT_UNUSED_VARIABLE(VARIABLE) \
209     do                               \
210     {                                \
211         if (&VARIABLE == NULL)       \
212         {                            \
213         }                            \
214     } while (false)
215 
216 /*
217  * #112-D statement is unreachable
218  * #129-D loop is not reachable
219  */
220 #define OT_UNREACHABLE_CODE(CODE) \
221     _Pragma("diag_push") _Pragma("diag_suppress 112") _Pragma("diag_suppress 129") CODE _Pragma("diag_pop")
222 
223 #else
224 
225 #define OT_UNUSED_VARIABLE(VARIABLE) \
226     do                               \
227     {                                \
228         (void)(VARIABLE);            \
229     } while (false)
230 
231 #define OT_UNREACHABLE_CODE(CODE) CODE
232 
233 #endif
234 
235 /*
236  * Keil and IAR compiler doesn't provide type limits for C++.
237  */
238 #ifdef __cplusplus
239 #if defined(__CC_ARM) || defined(__ICCARM__)
240 
241 #ifndef UINT8_MAX
242 #define UINT8_MAX 0xff
243 #endif
244 
245 #ifndef UINT16_MAX
246 #define UINT16_MAX 0xffff
247 #endif
248 
249 #endif
250 #endif
251 
252 #ifdef __APPLE__
253 #define OT_APPLE_IGNORE_GNU_FOLDING_CONSTANT(...)                                               \
254     _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wgnu-folding-constant\"") \
255         __VA_ARGS__ _Pragma("GCC diagnostic pop")
256 #else
257 #define OT_APPLE_IGNORE_GNU_FOLDING_CONSTANT(...) __VA_ARGS__
258 #endif
259 
260 /**
261  * @def OT_FALL_THROUGH
262  *
263  * Suppress fall through warning in specific compiler.
264  *
265  */
266 #if defined(__cplusplus) && (__cplusplus >= 201703L)
267 #define OT_FALL_THROUGH [[fallthrough]]
268 #elif defined(__clang__)
269 #define OT_FALL_THROUGH [[clang::fallthrough]]
270 #elif defined(__GNUC__) && (__GNUC__ >= 7)
271 #define OT_FALL_THROUGH __attribute__((fallthrough))
272 #else
273 #define OT_FALL_THROUGH \
274     do                  \
275     {                   \
276     } while (false) /* fallthrough */
277 #endif
278 
279 /**
280  * @}
281  *
282  */
283 
284 #ifdef __cplusplus
285 } // extern "C"
286 #endif
287 
288 #endif // OPENTHREAD_PLATFORM_TOOLCHAIN_H_
289