Silen some warning.
[bertos.git] / bertos / cfg / compiler.h
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2003, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
30  * Copyright 2001, 2002, 2003 Bernie Innocenti <bernie@codewiz.org>
31  *
32  * -->
33  *
34  * \brief Additional support macros for compiler independance
35  *
36  * \author Bernie Innocenti <bernie@codewiz.org>
37  */
38
39 #ifndef BERTOS_COMPILER_H
40 #define BERTOS_COMPILER_H
41
42 #include <cpu/detect.h>
43
44
45 #if defined __GNUC__ && defined __GNUC_MINOR__
46         #define GNUC_PREREQ(maj, min) \
47                 ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
48 #else
49         #define GNUC_PREREQ(maj, min) 0
50 #endif
51
52 /* Some CW versions do not allow enabling C99 from the settings panel. */
53 #if defined(__MWERKS__)
54         #pragma c99 on
55 #endif
56
57 #if defined(__STDC_VERSION__)
58     #if (__STDC_VERSION__ == 199409L) // IAR
59             #define COMPILER_C99      1  // not true, because partial C99, avoid miscompilation
60     #elif (__STDC_VERSION__ >= 199901L) // GCC
61             #define COMPILER_C99      1
62     #else
63             #define COMPILER_C99      0
64     #endif
65 #endif
66
67
68 /** Concatenate two different preprocessor tokens (allowing macros to expand) */
69 #define PP_CAT(x,y)         PP_CAT__(x,y)
70 #define PP_CAT__(x,y)       x ## y
71 #define PP_CAT3(x,y,z)      PP_CAT(PP_CAT(x,y),z)
72 #define PP_CAT4(x,y,z,w)    PP_CAT(PP_CAT3(x,y,z),w)
73 #define PP_CAT5(x,y,z,w,j)  PP_CAT(PP_CAT4(x,y,z,w),j)
74
75 /** String-ize a token (allowing macros to expand) */
76 #define PP_STRINGIZE(x)     PP_STRINGIZE__(x)
77 #define PP_STRINGIZE__(x)   #x
78
79
80 /**
81  */
82 #if COMPILER_C99
83         #define COUNT_PARMS2(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _, ...) _
84         #define COUNT_PARMS(...) \
85                         COUNT_PARMS2(11 , ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
86
87         /**
88          * usage:
89          * \code
90          * #define foo_init(...) PP_CAT(foo_init_, COUNT_PARMS(__VA_ARGS__)) (__VA_ARGS__)
91          * \endcode
92          */
93
94 #else
95         #define COUNT_PARMS2(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _, ...) _
96         #define COUNT_PARMS(args...) \
97                         COUNT_PARMS2(11 , ## args, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
98
99         /**
100          * usage:
101          * \code
102          * #define foo_init(args...) PP_CAT(foo_init_, COUNT_PARMS(args)) (args)
103          * \endcode
104          */
105
106 #endif
107
108 #if defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__)
109
110         #pragma language=extended
111
112         /* IAR iccarm specific functions */
113         #include <intrinsics.h>
114         #pragma diag_suppress=Pe940
115         #pragma inline = forced
116
117         #define MEMORY_BARRIER          asm("")
118
119         #if CPU_ARM || CPU_CM3
120
121                 #define COMPILER_VARIADIC_MACROS 1
122
123                 #define INTERRUPT(x)  __irq __arm void x (void)
124                 #define INLINE        static inline
125                 #define NAKED
126
127                 /* Include some standard C89/C99 stuff */
128                 #include <stddef.h>
129                 #include <stdint.h>
130                 #include <stdbool.h>
131
132         #elif CPU_I196
133
134                 // IAR has size_t as built-in type, but does not define this symbol.
135                 #define _SIZE_T_DEFINED
136
137                 #define INTERRUPT(x)  interrupt [x]
138                 #define REGISTER      shortad
139                 #define INLINE        /* unsupported */
140
141                 /*
142                  * Imported from <longjmp.h>. Unfortunately, we can't just include
143                  * this header because it typedefs jmp_buf to be an array of chars.
144                  * This would allow the compiler to place the buffer on an odd address.
145                  * The CPU _should_ be able to perform word accesses to
146                  * unaligned data, but there are *BUGS* in the 80196KC with
147                  * some combinations of opcodes and addressing modes. One of
148                  * these, "ST SP,[?GR]+" is used in the longjmp() implementation
149                  * provided by the IAR compiler ANSI C library. When ?GR contains
150                  * an odd address, surprisingly the CPU will copy the high order
151                  * byte of the source operand (SP) in the low order byte of the
152                  * destination operand (the memory location pointed to by ?GR).
153                  *
154                  * We also need to replace the library setjmp()/longjmp() with
155                  * our own versions because the IAR implementation "forgets" to
156                  * save the contents of local registers (?LR).
157                  */
158                 struct _JMP_BUF
159                 {
160                         void *sp;           /* Stack pointer */
161                         void *return_addr;  /* Return address */
162                         int lr[6];          /* 6 local registers */
163                 };
164
165                 typedef struct _JMP_BUF jmp_buf[1];
166
167                 int setjmp(jmp_buf env);
168                 void longjmp(jmp_buf env, int val);
169
170                 /* Fake bool support */
171                 #define true (1==1)
172                 #define false (1!=1)
173                 typedef unsigned char bool;
174
175         #else
176                 #error Unsupported CPU
177         #endif
178
179 #elif defined(_MSC_VER) /* Win32 emulation support */
180
181         /* MSVC doesn't provide <stdbool.h>. */
182         #ifndef __cplusplus
183                 #define true (1==1)
184                 #define false (1!=1)
185                 typedef int bool;
186         #endif /* !__cplusplus */
187
188         /* These C99 functions are oddly named in MSVCRT32.lib */
189         #define snprintf _snprintf
190         #define vsnprintf _vsnprintf
191
192         /* MSVC doesn't support C99's __func__, but has a similar extension. */
193         #define __func__ __FUNCTION__
194
195         /* MSVC doesn't support C99's inline keyword */
196         #ifndef __cplusplus
197                 #define INLINE __inline
198         #endif
199
200 #elif defined(__GNUC__)
201
202         /* Compiler features */
203         #define COMPILER_VARIADIC_MACROS 1 /* Even in C++ */
204         #define COMPILER_TYPEOF 1
205         #define COMPILER_STATEMENT_EXPRESSIONS 1
206
207         /* GCC attributes */
208         #define FORMAT(type,fmt,first)  __attribute__((__format__(type, fmt, first)))
209         #define NORETURN                __attribute__((__noreturn__))
210         #define UNUSED_ARG(type,arg)    __attribute__((__unused__)) type arg
211         #define UNUSED_VAR(type,name)   __attribute__((__unused__)) type name
212         #define USED_VAR(type,name)     __attribute__((__used__)) type name
213         #define INLINE                  static inline __attribute__((__always_inline__))
214         #define NOINLINE                __attribute__((noinline))
215         #define LIKELY(x)               __builtin_expect(!!(x), 1)
216         #define UNLIKELY(x)             __builtin_expect(!!(x), 0)
217         #define PURE_FUNC               __attribute__((pure))
218         #define CONST_FUNC              __attribute__((const))
219         #define UNUSED_FUNC             __attribute__((unused))
220         #define USED_FUNC               __attribute__((__used__))
221         #define RESTRICT                __restrict__
222         #define MUST_CHECK              __attribute__((warn_unused_result))
223         #define PACKED                  __attribute__((packed))
224         #define ALIGNED(x)              __attribute__ ((__aligned__(x)))
225         #if CPU_ARM | CPU_CM3
226                 #define NAKED           __attribute__((naked))
227         #else
228                 #define NAKED
229         #endif
230
231         /**
232          * Force compiler to reload context variable.
233          */
234         #define MEMORY_BARRIER           asm volatile ("" : : : "memory")
235
236         #if GNUC_PREREQ(3,1)
237                 #define DEPRECATED  __attribute__((__deprecated__))
238         #endif
239
240         #if GNUC_PREREQ(4,5)
241                 #define UNREACHABLE() __builtin_unreachable()
242         #endif
243
244         #ifndef __cplusplus
245                 #define ASSERT_TYPE_EQUAL(var1, var2) \
246                         STATIC_ASSERT(__builtin_types_compatible_p(typeof(var1), typeof(var2)))
247                 #define ASSERT_TYPE_IS(var, type) \
248                         STATIC_ASSERT(__builtin_types_compatible_p(typeof(var), type))
249         #endif
250
251         /* Include some standard C89/C99 stuff */
252         #include <stddef.h>
253         #include <stdint.h>
254         #include <stdbool.h>
255         #if !CPU_AVR
256         #include <sys/types.h> /* for ssize_t */
257         #endif
258
259         #ifndef __cplusplus
260                 /*
261                  * Disallow some C++ keywords as identifiers in C programs,
262                  * for improved portability.
263                  */
264                 #pragma GCC poison new delete class template typename
265                 #pragma GCC poison private protected public operator
266                 #pragma GCC poison friend mutable using namespace
267                 #pragma GCC poison cin cout cerr clog
268         #endif
269
270
271
272 #elif defined(__MWERKS__)
273
274         /* Compiler features */
275         #define COMPILER_VARIADIC_MACROS 1
276         #define COMPILER_TYPEOF 1
277         #define COMPILER_STATEMENT_EXPRESSIONS 1
278
279         #define typeof __typeof__
280
281         #define UNUSED_ARG(type,arg)    type
282
283         #include <stddef.h>
284         #include <stdint.h>
285         #include <stdbool.h>
286
287         // CodeWarrior has size_t as built-in type, but does not define this symbol.
288         #define _SIZE_T_DEFINED
289
290 #else
291         #error unknown compiler
292 #endif
293
294
295 /* Defaults for compiler extensions. */
296
297 /**
298  * \def COMPILER_VARIADIC_MACROS
299  * Support for macros with variable arguments.
300  */
301 #ifndef COMPILER_VARIADIC_MACROS
302 #define COMPILER_VARIADIC_MACROS (COMPILER_C99 != 0)
303 #endif
304
305 /**
306  * \def COMPILER_TYPEOF
307  * Support for dynamic type identification.
308  */
309 #ifndef COMPILER_TYPEOF
310 #define COMPILER_TYPEOF 0
311 #endif
312
313 /**
314  * \def COMPILER_STATEMENT_EXPRESSIONS
315  * Support for statement expressions.
316  */
317 #ifndef COMPILER_STATEMENT_EXPRESSIONS
318 #define COMPILER_STATEMENT_EXPRESSIONS 0
319 #endif
320
321 /* A few defaults for missing compiler features. */
322 #ifndef INLINE
323 #define INLINE                 static inline
324 #endif
325 #ifndef NOINLINE
326 #define NOINLINE               /* nothing */
327 #endif
328 #ifndef NORETURN
329 #define NORETURN               /* nothing */
330 #endif
331 #ifndef FORMAT
332 #define FORMAT(type,fmt,first) /* nothing */
333 #endif
334 #ifndef DEPRECATED
335 #define DEPRECATED             /* nothing */
336 #endif
337 #ifndef UNUSED_ARG
338 #define UNUSED_ARG(type,arg)   type arg
339 #endif
340 #ifndef UNUSED_VAR
341 #define UNUSED_VAR(type,name)  type name
342 #endif
343 #ifndef USED_VAR
344 #define USED_VAR(type,name)    type name
345 #endif
346 #ifndef REGISTER
347 #define REGISTER               /* nothing */
348 #endif
349 #ifndef LIKELY
350 #define LIKELY(x)              x
351 #endif
352 #ifndef UNLIKELY
353 #define UNLIKELY(x)            x
354 #endif
355 #ifndef PURE_FUNC
356 #define PURE_FUNC              /* nothing */
357 #endif
358 #ifndef CONST_FUNC
359 #define CONST_FUNC             /* nothing */
360 #endif
361 #ifndef UNUSED_FUNC
362 #define UNUSED_FUNC            /* nothing */
363 #endif
364 #ifndef USED_FUNC
365 #define USED_FUNC              /* nothing */
366 #endif
367 #ifndef RESTRICT
368 #define RESTRICT               /* nothing */
369 #endif
370 #ifndef MUST_CHECK
371 #define MUST_CHECK             /* nothing */
372 #endif
373 #ifndef PACKED
374 #define PACKED                 /* nothing */
375 #endif
376 #ifndef ALIGNED
377 #define ALIGNED                /* nothing */
378 #endif
379 #ifndef MEMORY_BARRIER
380 #define MEMORY_BARRIER         /* nothing */
381 #warning No memory barrier defined for select compiler. If you use the kernel check it.
382 #endif
383 #ifndef UNREACHABLE
384 #define UNREACHABLE() for (;;)
385 #endif
386
387
388 /* Misc definitions */
389 #ifndef NULL
390 #define NULL  (void *)0
391 #endif
392 #ifndef EOF
393 #define EOF   (-1)
394 #endif
395
396 /* Support for hybrid C/C++ applications. */
397 #ifdef __cplusplus
398         #define EXTERN_C        extern "C"
399         #define EXTERN_C_BEGIN  extern "C" {
400         #define EXTERN_C_END    }
401         #define EXTERN_CONST    extern const
402         #define CONST_CAST(TYPE,EXPR)   (const_cast<TYPE>(EXPR))
403 #else
404         #define EXTERN_C        extern
405         #define EXTERN_C_BEGIN  /* nothing */
406         #define EXTERN_C_END    /* nothing */
407         #define EXTERN_CONST    const
408         #define CONST_CAST(TYPE,EXPR)   ((TYPE)(EXPR)) /* FIXME: How can we suppress the warning in C? */
409 #endif
410
411
412 #if defined(_MSC_VER) \
413         || ((defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__)) && CPU_I196)
414         /**
415          * \name ISO C99 fixed-size types
416          *
417          * These should be in <stdint.h>, but a few compilers lack them.
418          * \{
419          */
420         typedef signed char         int8_t;
421         typedef unsigned char       uint8_t;
422         typedef short int           int16_t;
423         typedef unsigned short int  uint16_t;
424         typedef long int            int32_t; /* _WIN64 safe */
425         typedef unsigned long int   uint32_t; /* _WIN64 safe */
426
427         #ifdef _MSC_VER
428                 typedef __int64              int64_t;
429                 typedef unsigned __int64     uint64_t;
430         #else
431                 typedef long long            int64_t;
432                 typedef unsigned long long   uint64_t;
433         #endif
434         /* \} */
435 #else
436         /* This is the standard location. */
437         #include <stdint.h>
438 #endif
439
440 #if CPU_AVR_ATMEGA8
441         /*
442          * The ATmega8 has a very small Flash, so we can't afford
443          * to link in support routines for 32bit integer arithmetic.
444          */
445         typedef int16_t ticks_t;  /**< Type for time expressed in ticks. */
446         typedef int16_t mtime_t;  /**< Type for time expressed in milliseconds. */
447         typedef int16_t utime_t;  /**< Type for time expressed in microseconds. */
448         #define SIZEOF_MTIME_T (16 / CPU_BITS_PER_CHAR)
449         #define SIZEOF_UTIME_T (16 / CPU_BITS_PER_CHAR)
450         #define MTIME_INFINITE 0x7FFFL
451 #else
452         typedef int32_t ticks_t;  /**< Type for time expressed in ticks. */
453
454         typedef int32_t utime_t;  /**< Type for time expressed in microseconds. */
455         #define SIZEOF_UTIME_T (32 / CPU_BITS_PER_CHAR)
456
457         #ifndef DEVLIB_MTIME_DEFINED
458                 #define DEVLIB_MTIME_DEFINED 1 /* Resolve conflict with <os/hptime.h> */
459                 typedef int32_t mtime_t;  /**< Type for time expressed in milliseconds. */
460                 #define SIZEOF_MTIME_T (32 / CPU_BITS_PER_CHAR)
461                 #define MTIME_INFINITE 0x7FFFFFFFL
462         #endif
463 #endif
464
465 /** User defined callback type */
466 typedef void (*Hook)(void *);
467
468 /** Bulk storage large enough for both pointers or integers. */
469 typedef void * iptr_t;
470
471 /** Bulk storage large enough for both pointers to constants or integers. */
472 typedef const void * const_iptr_t;
473
474 typedef unsigned char sigbit_t;  /**< Type for signal bits. */
475 typedef unsigned char sigmask_t; /**< Type for signal masks. */
476
477 /**
478  * Signal structure
479  */
480 typedef struct Signal
481 {
482         sigmask_t    wait;    /**< Signals the process is waiting for */
483         sigmask_t    recv;    /**< Received signals */
484 } Signal;
485
486 /**
487  * \name Standard type definitions.
488  *
489  * These should be in <sys/types.h> or <stddef.h>, but many compilers
490  * and C libraries lack them.
491  *
492  * We check for some common definitions to avoid redefinitions:
493  *
494  *    glibc, avr-libc: _SIZE_T_DEFINED, __ssize_t_defined
495  *    Darwin libc:     _BSD_SIZE_T_DEFINED_, _SIZE_T
496  *    IAR ARM:         _SIZE_T
497  *
498  * \{
499  */
500 #if !(defined(size_t) || defined(_SIZE_T_DEFINED) || defined(_BSD_SIZE_T_DEFINED_) \
501         || defined(_SIZE_T))
502         #if CPU_X86
503                 /* 32bit or 64bit (32bit for _WIN64). */
504                 typedef unsigned long size_t;
505         #else
506                 #error Unknown CPU
507         #endif
508 #endif
509
510 #if !(defined(ssize_t) || defined(_SSIZE_T) || defined(__ssize_t_defined))
511         #if CPU_X86
512                 /* 32bit or 64bit (32bit for _WIN64). */
513                 typedef long ssize_t;
514         #elif CPU_ARM || CPU_CM3
515                 typedef int ssize_t;
516         #elif CPU_AVR || CPU_MSP430
517                 /* 16bit (missing in avr-/msp430-libc's sys/types.h). */
518                 typedef int ssize_t;
519         #else
520                 #error Unknown CPU
521         #endif
522 #endif
523 /*\}*/
524
525
526 /**
527  * \name Types for hardware registers.
528  *
529  * Only use these types for registers whose contents can
530  * be changed asynchronously by external hardware.
531  *
532  * \{
533  */
534 #if CPU_DSP56K
535         /* Registers can be accessed only through 16-bit pointers */
536         typedef volatile uint16_t  reg16_t;
537 #else
538         typedef volatile uint8_t   reg8_t;
539         typedef volatile uint16_t  reg16_t;
540         typedef volatile uint32_t  reg32_t;
541 #endif
542 /*\}*/
543
544
545 /* Quasi-ANSI macros */
546 #ifndef offsetof
547         /**
548          * Return the byte offset of the member \a m in struct \a s.
549          *
550          * \note This macro should be defined in "stddef.h" and is sometimes
551          *       compiler-specific (g++ has a builtin for it).
552          */
553         #define offsetof(s,m)  (size_t)&(((s *)0)->m)
554 #endif
555 #ifndef countof
556         /**
557          * Count the number of elements in the static array \a a.
558          *
559          * \note This macro is non-standard, but implements a very common idiom
560          */
561         #if defined(__GNUC__) && !defined(__cplusplus)
562                 /*
563                  * Perform a compile time type checking: countof() can only
564                  * work with static arrays, so throw a compile time error if a
565                  * pointer is passed as argument.
566                  *
567                  * NOTE: the construct __builtin_types_compatible_p() is only
568                  * available for C.
569                  */
570                 #define countof(a) (sizeof(a) / sizeof(*(a)) +          \
571                                 STATIC_ASSERT_EXPR(                     \
572                                         !__builtin_types_compatible_p(  \
573                                                 typeof(a), typeof(&a[0]))))
574         #else
575                 #define countof(a)  (sizeof(a) / sizeof(*(a)))
576         #endif
577 #endif
578 #ifndef alignof
579         /**
580          * Return the alignment in memory of a generic data type.
581          *
582          * \note We need to worry about alignment when allocating memory that
583          * will be used later by unknown objects (e.g., malloc()) or, more
584          * generally, whenever creating generic container types.
585          */
586         #define alignof(type) offsetof(struct { char c; type member; }, member)
587 #endif
588
589 /**
590  * Cast a member of a structure out to the containing structure.
591  *
592  * \param ptr     the pointer to the member.
593  * \param type    the type of the container struct this is embedded in.
594  * \param member  the name of the member within the struct.
595  */
596 #if COMPILER_TYPEOF && COMPILER_STATEMENT_EXPRESSIONS
597         #define containerof(ptr, type, member) ({ \
598                 typeof( ((type *)0)->member ) *_mptr = (ptr); /* type check */ \
599                 (type *)(void *)((char *)_mptr - offsetof(type, member)); \
600         })
601 #else
602         #define containerof(ptr, type, member) \
603                 ( (type *)(void *)((char *)(ptr) - offsetof(type, member)) )
604 #endif
605
606 /** Issue a compilation error if the \a condition is false */
607 #define STATIC_ASSERT(condition)  \
608         UNUSED_VAR(extern char, STATIC_ASSERTION_FAILED__[(condition) ? 1 : -1])
609
610 /**
611  * Issue a compilation error if \a __cond is false (this can be used inside an
612  * expression).
613  */
614 #define STATIC_ASSERT_EXPR(__cond) \
615         (sizeof(struct { int STATIC_ASSERTION_FAILED__:!!(__cond); }) * 0)
616
617 #ifndef ASSERT_TYPE_EQUAL
618         /** Ensure two variables have the same type. */
619         #define ASSERT_TYPE_EQUAL(var1, var2)  \
620                         do { (void)(&(var1) == &(var2)); } while(0)
621 #endif
622
623 #ifndef ASSERT_TYPE_IS
624         /** Ensure variable is of specified type. */
625         #define ASSERT_TYPE_IS(var, type)  \
626                         do { (void)(&(var) == (type *)0); } while(0)
627 #endif
628
629 /**
630  * Prevent the compiler from optimizing access to the variable \a x, enforcing
631  * a refetch from memory. This also forbid from reordering successing instances
632  * of ACCESS_SAFE().
633  */
634 #ifdef __ICCARM__
635 #define ACCESS_SAFE(x) x
636 #else
637 #define ACCESS_SAFE(x) (*(volatile typeof(x) *)&(x))
638 #endif
639
640 #endif /* BERTOS_COMPILER_H */