source: rtems/cpukit/include/rtems/score/basedefs.h @ 21275b58

Last change on this file since 21275b58 was e50b4bd, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 6, 2018 at 12:40:08 PM

score: Use typeof for strict ISO C compat

Enable the use of RTEMS_DEVOLATILE() and RTEMS_DECONST() in strict ISO C
environments.

  • Property mode set to 100644
File size: 13.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup Score
5 *
6 * @brief Basic Definitions
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2007.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  Copyright (c) 2010, 2018 embedded brains GmbH.
14 *
15 *  The license and distribution terms for this file may be
16 *  found in the file LICENSE in this distribution or at
17 *  http://www.rtems.org/license/LICENSE.
18 */
19
20#ifndef _RTEMS_BASEDEFS_H
21#define _RTEMS_BASEDEFS_H
22
23/**
24 *  @defgroup ScoreBaseDefs Basic Definitions
25 *
26 *  @ingroup Score
27 */
28/**@{*/
29
30#include <rtems/score/cpuopts.h>
31
32#ifndef ASM
33  #include <stddef.h>
34  #include <stdbool.h>
35  #include <stdint.h>
36#endif
37
38#ifndef TRUE
39  /**
40   *  This ensures that RTEMS has TRUE defined in all situations.
41   */
42  #define TRUE 1
43#endif
44
45#ifndef FALSE
46  /**
47   *  This ensures that RTEMS has FALSE defined in all situations.
48   */
49  #define FALSE 0
50#endif
51
52#if TRUE == FALSE
53  #error "TRUE equals FALSE"
54#endif
55
56/**
57 *  The following (in conjunction with compiler arguments) are used
58 *  to choose between the use of static inline functions and macro
59 *  functions.   The static inline implementation allows better
60 *  type checking with no cost in code size or execution speed.
61 */
62#ifdef __GNUC__
63  #define RTEMS_INLINE_ROUTINE static __inline__
64#else
65  #define RTEMS_INLINE_ROUTINE static inline
66#endif
67
68/**
69 *  The following macro is a compiler specific way to ensure that memory
70 *  writes are not reordered around certain points.  This specifically can
71 *  impact interrupt disable and thread dispatching critical sections.
72 */
73#ifdef __GNUC__
74  #define RTEMS_COMPILER_MEMORY_BARRIER() __asm__ volatile("" ::: "memory")
75#else
76  #define RTEMS_COMPILER_MEMORY_BARRIER()
77#endif
78
79/**
80 *  The following defines a compiler specific attribute which informs
81 *  the compiler that the method must not be inlined.
82 */
83#ifdef __GNUC__
84  #define RTEMS_NO_INLINE __attribute__((__noinline__))
85#else
86  #define RTEMS_NO_INLINE
87#endif
88
89/**
90 *  The following macro is a compiler specific way to indicate that
91 *  the method will NOT return to the caller.  This can assist the
92 *  compiler in code generation and avoid unreachable paths.  This
93 *  can impact the code generated following calls to
94 *  rtems_fatal_error_occurred and _Terminate.
95 */
96#if defined(RTEMS_SCHEDSIM)
97  #define RTEMS_NO_RETURN
98#elif defined(__GNUC__) && !defined(RTEMS_DEBUG)
99  #define RTEMS_NO_RETURN __attribute__((__noreturn__))
100#else
101  #define RTEMS_NO_RETURN
102#endif
103
104/* Provided for backward compatibility */
105#define RTEMS_COMPILER_NO_RETURN_ATTRIBUTE RTEMS_NO_RETURN
106
107/**
108 *  The following defines a compiler specific attribute which informs
109 *  the compiler that the method has no effect except the return value
110 *  and that the return value depends only on parameters and/or global
111 *  variables.
112 */
113#ifdef __GNUC__
114  #define RTEMS_PURE __attribute__((__pure__))
115#else
116  #define RTEMS_PURE
117#endif
118
119/* Provided for backward compatibility */
120#define RTEMS_COMPILER_PURE_ATTRIBUTE RTEMS_PURE
121
122/**
123 *  Instructs the compiler to issue a warning whenever a variable or function
124 *  with this attribute will be used.
125 */
126#ifdef __GNUC__
127  #define RTEMS_DEPRECATED __attribute__((__deprecated__))
128#else
129  #define RTEMS_DEPRECATED
130#endif
131
132/* Provided for backward compatibility */
133#define RTEMS_COMPILER_DEPRECATED_ATTRIBUTE RTEMS_DEPRECATED
134
135/**
136 * @brief Instructs the compiler to place a specific variable or function in
137 * the specified section.
138 */
139#if defined(__GNUC__)
140  #define RTEMS_SECTION( _section ) __attribute__((__section__(_section)))
141#else
142  #define RTEMS_SECTION( _section )
143#endif
144
145/**
146 * @brief Instructs the compiler that a specific variable or function is used.
147 */
148#if defined(__GNUC__)
149  #define RTEMS_USED __attribute__((__used__))
150#else
151  #define RTEMS_USED
152#endif
153
154/**
155 *  Instructs the compiler that a specific variable is deliberately unused.
156 *  This can occur when reading volatile device memory or skipping arguments
157 *  in a variable argument method.
158 */
159#if defined(__GNUC__)
160  #define RTEMS_UNUSED __attribute__((__unused__))
161#else
162  #define RTEMS_UNUSED
163#endif
164
165/* Provided for backward compatibility */
166#define RTEMS_COMPILER_UNUSED_ATTRIBUTE RTEMS_UNUSED
167
168/**
169 *  Instructs the compiler that a specific structure or union members will be
170 *  placed so that the least memory is used.
171 */
172#if defined(__GNUC__)
173  #define RTEMS_PACKED __attribute__((__packed__))
174#else
175  #define RTEMS_PACKED
176#endif
177
178/**
179 * @brief Instructs the compiler to generate an alias to the specified target
180 * function.
181 */
182#if defined(__GNUC__)
183  #define RTEMS_ALIAS( _target ) __attribute__((__alias__(#_target)))
184#else
185  #define RTEMS_ALIAS( _target )
186#endif
187
188/**
189 * @brief Instructs the compiler to generate a weak alias to the specified
190 * target function.
191 */
192#if defined(__GNUC__)
193  #define RTEMS_WEAK_ALIAS( _target ) __attribute__((__weak__, __alias__(#_target)))
194#else
195  #define RTEMS_WEAK_ALIAS( _target )
196#endif
197
198/**
199 * @brief Instructs the compiler to enforce the specified alignment.
200 */
201#if defined(__GNUC__)
202  #define RTEMS_ALIGNED( _alignment ) __attribute__((__aligned__(_alignment)))
203#else
204  #define RTEMS_ALIGNED( _alignment )
205#endif
206
207/* Provided for backward compatibility */
208#define RTEMS_COMPILER_PACKED_ATTRIBUTE RTEMS_PACKED
209
210#if defined(RTEMS_DEBUG) && !defined(RTEMS_SCHEDSIM)
211  #define _Assert_Unreachable() _Assert( 0 )
212#else
213  #define _Assert_Unreachable() do { } while ( 0 )
214#endif
215
216/**
217 * @brief Tells the compiler that this program point is unreachable.
218 */
219#if defined(__GNUC__) && !defined(RTEMS_SCHEDSIM)
220  #define RTEMS_UNREACHABLE() \
221    do { \
222      __builtin_unreachable(); \
223      _Assert_Unreachable(); \
224    } while ( 0 )
225#else
226  #define RTEMS_UNREACHABLE() _Assert_Unreachable()
227#endif
228
229/**
230 * @brief Tells the compiler that this function expects printf()-like
231 * arguments.
232 */
233#if defined(__GNUC__)
234  #define RTEMS_PRINTFLIKE( _format_pos, _ap_pos ) \
235    __attribute__((__format__(__printf__, _format_pos, _ap_pos)))
236#else
237  #define RTEMS_PRINTFLIKE( _format_pos, _ap_pos )
238#endif
239
240/**
241 * @brief Tells the compiler that this function is a memory allocation function
242 * similar to malloc().
243 */
244#if defined(__GNUC__)
245  #define RTEMS_MALLOCLIKE __attribute__((__malloc__))
246#else
247  #define RTEMS_MALLOCLIKE
248#endif
249
250/**
251 * @brief Tells the compiler the memory allocation size parameter of this
252 * function similar to malloc().
253 */
254#if defined(__GNUC__)
255  #define RTEMS_ALLOC_SIZE( _index ) __attribute__((__alloc_size__(_index)))
256#else
257  #define RTEMS_ALLOC_SIZE( _index )
258#endif
259
260/**
261 * @brief Tells the compiler the memory allocation item count and item size
262 * parameter of this function similar to calloc().
263 */
264#if defined(__GNUC__)
265  #define RTEMS_ALLOC_SIZE_2( _count_index, _size_index ) \
266     __attribute__((__alloc_size__(_count_index, _size_index)))
267#else
268  #define RTEMS_ALLOC_SIZE_2( _count_index, _size_index )
269#endif
270
271/**
272 * @brief Tells the compiler the memory allocation alignment parameter of this
273 * function similar to aligned_alloc().
274 */
275#if defined(__GNUC__)
276  #define RTEMS_ALLOC_ALIGN( _index ) __attribute__((__alloc_align__(_index)))
277#else
278  #define RTEMS_ALLOC_ALIGN( _index )
279#endif
280
281/**
282 * @brief Tells the compiler that the result of this function should be used.
283 */
284#if defined(__GNUC__)
285  #define RTEMS_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
286#else
287  #define RTEMS_WARN_UNUSED_RESULT
288#endif
289
290/**
291 * @brief Obfuscates the variable so that the compiler cannot perform
292 * optimizations based on the variable value.
293 *
294 * The variable must be simple enough to fit into a register.
295 */
296#if defined(__GNUC__)
297  #define RTEMS_OBFUSCATE_VARIABLE( _var ) __asm__("" : "+r" (_var))
298#else
299  #define RTEMS_OBFUSCATE_VARIABLE( _var ) (void) (_var)
300#endif
301
302/**
303 * @brief Declares a global symbol with the specified name.
304 *
305 * This macro must be placed at file scope.
306 *
307 * The name must be a valid designator.
308 */
309#define RTEMS_DECLARE_GLOBAL_SYMBOL( _name ) \
310  extern char _name[]
311
312/**
313 * @brief Defines a global symbol with the specified name and value.
314 *
315 * This macro must be placed at file scope.
316 *
317 * The name must be a valid designator.
318 *
319 * On the value parameters macro expansion is performed and afterwards it is
320 * stringified.  It must expand to an integer literal understood by the
321 * assembler.
322 */
323#if defined(__GNUC__)
324  #define RTEMS_DEFINE_GLOBAL_SYMBOL( _name, _value ) \
325    __asm__( \
326      "\t.globl " RTEMS_XSTRING( __USER_LABEL_PREFIX__ ) #_name \
327      "\n\t.set " RTEMS_XSTRING( __USER_LABEL_PREFIX__ ) #_name \
328      ", " RTEMS_STRING( _value ) "\n" \
329    )
330#else
331  #define RTEMS_DEFINE_GLOBAL_SYMBOL( _name, _value )
332#endif
333
334/**
335 * @brief Returns the value of the specified integral expression and tells the
336 * compiler that the predicted value is true (1).
337 *
338 * @param[in] _exp The expression.
339 *
340 * @return The value of the expression.
341 */
342#if defined(__GNUC__)
343  #define RTEMS_PREDICT_TRUE( _exp ) __builtin_expect( ( _exp ), 1 )
344#else
345  #define RTEMS_PREDICT_TRUE( _exp ) ( _exp )
346#endif
347
348/**
349 * @brief Returns the value of the specified integral expression and tells the
350 * compiler that the predicted value is false (0).
351 *
352 * @param[in] _exp The expression.
353 *
354 * @return The value of the expression.
355 */
356#if defined(__GNUC__)
357  #define RTEMS_PREDICT_FALSE( _exp ) __builtin_expect( ( _exp ), 0 )
358#else
359  #define RTEMS_PREDICT_FALSE( _exp ) ( _exp )
360#endif
361
362#if __cplusplus >= 201103L
363  #define RTEMS_STATIC_ASSERT(cond, msg) \
364    static_assert(cond, # msg)
365#elif __STDC_VERSION__ >= 201112L
366  #define RTEMS_STATIC_ASSERT(cond, msg) \
367    _Static_assert(cond, # msg)
368#else
369  #define RTEMS_STATIC_ASSERT(cond, msg) \
370    struct rtems_static_assert_ ## msg \
371      { int rtems_static_assert_ ## msg : (cond) ? 1 : -1; }
372#endif
373
374#define RTEMS_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
375
376/*
377 * Zero-length arrays are valid in C99 as flexible array members.  C++11
378 * doesn't allow flexible array members.  Use the GNU extension which is also
379 * supported by other compilers.
380 */
381#define RTEMS_ZERO_LENGTH_ARRAY 0
382
383/**
384 * @brief Returns a pointer to the container of a specified member pointer.
385 *
386 * @param[in] _m The pointer to a member of the container.
387 * @param[in] _type The type of the container.
388 * @param[in] _member_name The designator name of the container member.
389 */
390#define RTEMS_CONTAINER_OF( _m, _type, _member_name ) \
391  ( (_type *) ( (uintptr_t) ( _m ) - offsetof( _type, _member_name ) ) )
392
393#ifdef __cplusplus
394#define RTEMS_DEQUALIFY_DEPTHX( _ptr_level, _type, _var ) \
395            (const_cast<_type>( _var ))
396#else /* Standard C code */
397
398/* The reference type idea based on libHX by Jan Engelhardt */
399#define RTEMS_TYPEOF_REFX(_ptr_level, _ptr_type) \
400  __typeof__(_ptr_level(union { int z; __typeof__(_ptr_type) x; }){0}.x)
401
402#if defined(__GNUC__) && !defined(ASM)
403#if  ((__GNUC__ * 1000 + __GNUC_MINOR__) >= 4004)
404extern void* RTEMS_DEQUALIFY_types_not_compatible(void)
405  __attribute__((error ("RTEMS_DEQUALIFY types differ not only by volatile and const")));
406#else
407extern void RTEMS_DEQUALIFY_types_not_compatible(void);
408#endif
409#define RTEMS_DEQUALIFY_DEPTHX( _ptr_level, _type, _var ) ( \
410    __builtin_choose_expr( __builtin_types_compatible_p ( \
411        RTEMS_TYPEOF_REFX( _ptr_level, _var ), \
412        RTEMS_TYPEOF_REFX( _ptr_level, _type ) \
413      ) || __builtin_types_compatible_p ( _type, void * ), \
414    (_type)(_var), \
415    RTEMS_DEQUALIFY_types_not_compatible() \
416  ) \
417)
418#endif /*__GNUC__*/
419#endif /*__cplusplus*/
420
421#ifndef RTEMS_DECONST
422#ifdef RTEMS_DEQUALIFY_DEPTHX
423#define RTEMS_DECONST( _type, _var ) \
424  RTEMS_DEQUALIFY_DEPTHX( *, _type, _var )
425#else /*RTEMS_DEQUALIFY_DEPTHX*/
426/**
427 * @brief Removes the const qualifier from a type of a variable.
428 *
429 * @param[in] _type The target type for the variable.
430 * @param[in] _var The variable.
431 */
432#define RTEMS_DECONST( _type, _var ) \
433  ((_type)(uintptr_t)(const void *) ( _var ))
434
435#endif /*RTEMS_DEQUALIFY_DEPTHX*/
436#endif /*RTEMS_DECONST*/
437
438#ifndef RTEMS_DEVOLATILE
439#ifdef RTEMS_DEQUALIFY_DEPTHX
440#define RTEMS_DEVOLATILE( _type, _var ) \
441  RTEMS_DEQUALIFY_DEPTHX( *, _type, _var )
442#else /*RTEMS_DEQUALIFY_DEPTHX*/
443/**
444 * @brief Removes the volatile qualifier from a type of a variable.
445 *
446 * @param[in] _type The target type for the variable.
447 * @param[in] _var The variable.
448 */
449#define RTEMS_DEVOLATILE( _type, _var ) \
450  ((_type)(uintptr_t)(volatile void *) ( _var ))
451
452#endif /*RTEMS_DEQUALIFY_DEPTHX*/
453#endif /*RTEMS_DEVOLATILE*/
454
455#ifndef RTEMS_DEQUALIFY
456#ifdef RTEMS_DEQUALIFY_DEPTHX
457#define RTEMS_DEQUALIFY( _type, _var ) \
458  RTEMS_DEQUALIFY_DEPTHX( *, _type, _var )
459#else /*RTEMS_DEQUALIFY_DEPTHX*/
460/**
461 * @brief Removes the all qualifiers from a type of a variable.
462 *
463 * @param[in] _type The target type for the variable.
464 * @param[in] _var The variable.
465 */
466#define RTEMS_DEQUALIFY( _type, _var ) \
467  ((_type)(uintptr_t)(const volatile void *) ( _var ))
468
469#endif /*RTEMS_DEQUALIFY_DEPTHX*/
470#endif /*RTEMS_DEQUALIFY*/
471
472/**
473 * @brief Evaluates to true if the members of two types have the same type.
474 *
475 * @param[in] _t_lhs Left hand side type.
476 * @param[in] _m_lhs Left hand side member.
477 * @param[in] _t_rhs Right hand side type.
478 * @param[in] _m_rhs Right hand side member.
479 */
480#ifdef __GNUC__
481  #define RTEMS_HAVE_MEMBER_SAME_TYPE( _t_lhs, _m_lhs, _t_rhs, _m_rhs ) \
482    __builtin_types_compatible_p( \
483      __typeof__( ( (_t_lhs *) 0 )->_m_lhs ), \
484      __typeof__( ( (_t_rhs *) 0 )->_m_rhs ) \
485    )
486#else
487  #define RTEMS_HAVE_MEMBER_SAME_TYPE( _t_lhs, _m_lhs, _t_rhs, _m_rhs ) \
488    true
489#endif
490
491/**
492 * @brief Concatenates _x and _y without expanding.
493 */
494#define RTEMS_CONCAT( _x, _y ) _x##_y
495
496/**
497 * @brief Concatenates expansion of _x and expansion of _y.
498 */
499#define RTEMS_XCONCAT( _x, _y ) RTEMS_CONCAT( _x, _y )
500
501/**
502 * @brief Stringifies _x  without expanding.
503 */
504#define RTEMS_STRING( _x ) #_x
505
506/**
507 * @brief Stringifies expansion of _x.
508 */
509#define RTEMS_XSTRING( _x ) RTEMS_STRING( _x )
510
511#ifndef ASM
512  #ifdef RTEMS_DEPRECATED_TYPES
513    typedef bool boolean RTEMS_DEPRECATED;
514    typedef float single_precision RTEMS_DEPRECATED;
515    typedef double double_precision RTEMS_DEPRECATED;
516  #endif
517
518  /**
519   * XXX: Eventually proc_ptr needs to disappear!!!
520   */
521  typedef void * proc_ptr RTEMS_DEPRECATED;
522#endif
523
524/**@}*/
525
526#endif /* _RTEMS_BASEDEFS_H */
Note: See TracBrowser for help on using the repository browser.