Updated copiright notice.
[bertos.git] / 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 Bernardo Innocenti <bernie@codewiz.org>
31  * This file is part of DevLib - See README.devlib for information.
32  * -->
33  *
34  * \brief Additional support macros for compiler independance
35  *
36  * \version $Id$
37  * \author Bernardo Innocenti <bernie@develer.com>
38  */
39
40 /*#*
41  *#* $Log$
42  *#* Revision 1.24  2007/01/09 08:58:14  bernie
43  *#* Avoid dependency on cfg/compiler.h
44  *#*
45  *#* Revision 1.23  2006/09/13 18:28:38  bernie
46  *#* Reformat.
47  *#*
48  *#* Revision 1.22  2006/07/19 12:56:25  bernie
49  *#* Convert to new Doxygen style.
50  *#*
51  *#* Revision 1.21  2006/07/19 12:53:43  bernie
52  *#* Prune log.
53  *#*
54  *#* Revision 1.20  2006/06/10 05:36:15  bernie
55  *#* Convert to new Doxygen comments.
56  *#*
57  *#* Revision 1.19  2006/04/11 00:07:33  bernie
58  *#* Implemenent MF_SAVESEL flag.
59  *#*
60  *#* Revision 1.18  2006/03/22 13:34:34  bernie
61  *#* MSVC support.
62  *#*
63  *#* Revision 1.17  2006/03/22 09:48:35  bernie
64  *#* Formatting.
65  *#*
66  *#* Revision 1.16  2006/03/20 17:48:09  bernie
67  *#* Fix for avr-libc; INTERRUPT(): Remove macro.
68  *#*
69  *#* Revision 1.15  2006/03/13 02:06:25  bernie
70  *#* containerof(): New macro.
71  *#*
72  *#* Revision 1.14  2006/02/23 08:36:33  bernie
73  *#* Emulate __func__ on MSVC.
74  *#*
75  *#* Revision 1.13  2006/02/23 07:37:37  bernie
76  *#* Compile fix for MSVC.
77  *#*
78  *#* Revision 1.12  2006/02/21 16:06:31  bernie
79  *#* Fix ssize_t redefinitions on glibc systems.
80  *#*
81  *#* Revision 1.11  2006/02/20 14:34:58  bernie
82  *#* Use portable type checking.
83  *#*
84  *#* Revision 1.10  2006/02/15 09:12:01  bernie
85  *#* Fixes for ARM/IAR support.
86  *#*
87  *#* Revision 1.9  2006/02/10 12:38:00  bernie
88  *#* Add support for ARM on IAR.
89  *#*
90  *#* Revision 1.8  2006/01/16 03:27:49  bernie
91  *#* Rename sig_t to sigbit_t to avoid clash with POSIX.
92  *#*
93  *#* Revision 1.7  2005/11/27 23:33:05  bernie
94  *#* Drop avr-libc hack for missing stdint.h.
95  *#*
96  *#* Revision 1.6  2005/07/19 07:27:31  bernie
97  *#* Don't use CPU_REG_BITS from cpu.h to avoid circular header dependendy.
98  *#*
99  *#* Revision 1.5  2005/06/27 21:24:37  bernie
100  *#* ticks_t: New typedef.
101  *#*
102  *#* Revision 1.4  2005/06/14 06:15:10  bernie
103  *#* Add X86_64 support.
104  *#*
105  *#* Revision 1.3  2005/04/12 01:37:01  bernie
106  *#* Metrowerks touchups from HeCo.
107  *#*
108  *#* Revision 1.2  2005/04/11 19:10:27  bernie
109  *#* Include top-level headers from cfg/ subdir.
110  *#*
111  *#* Revision 1.1  2005/04/11 19:04:13  bernie
112  *#* Move top-level headers to cfg/ subdir.
113  *#*/
114 #ifndef DEVLIB_COMPILER_H
115 #define DEVLIB_COMPILER_H
116
117 #include <cfg/cpu_detect.h>
118
119
120 #if defined __GNUC__ && defined __GNUC_MINOR__
121         #define GNUC_PREREQ(maj, min) \
122                 ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
123 #else
124         #define GNUC_PREREQ(maj, min) 0
125 #endif
126
127 /* Some CW versions do not allow enabling C99 from the settings panel. */
128 #if defined(__MWERKS__)
129         #pragma c99 on
130 #endif
131
132 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
133         #define COMPILER_C99      1
134 #else
135         #define COMPILER_C99      0
136 #endif
137
138
139 /** Concatenate two different preprocessor tokens (allowing macros to expand) */
140 #define PP_CAT(x,y)         PP_CAT__(x,y)
141 #define PP_CAT__(x,y)       x ## y
142 #define PP_CAT3(x,y,z)      PP_CAT(PP_CAT(x,y),z)
143 #define PP_CAT4(x,y,z,w)    PP_CAT(PP_CAT3(x,y,z),w)
144 #define PP_CAT5(x,y,z,w,j)  PP_CAT(PP_CAT4(x,y,z,w),j)
145
146 /** String-ize a token (allowing macros to expand) */
147 #define PP_STRINGIZE(x)     PP_STRINGIZE__(x)
148 #define PP_STRINGIZE__(x)   #x
149
150
151 #if defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__)
152
153         #pragma language=extended
154
155         #if CPU_ARM
156
157                 #define COMPILER_VARIADIC_MACROS 1
158
159                 #define INTERRUPT(x)  __irq __arm void x (void)
160                 #define INLINE        static inline
161
162                 /* Include some standard C89/C99 stuff */
163                 #include <stddef.h>
164                 #include <stdint.h>
165                 #include <stdbool.h>
166
167         #elif CPU_I196
168
169                 // IAR has size_t as built-in type, but does not define this symbol.
170                 #define _SIZE_T_DEFINED
171
172                 #define INTERRUPT(x)  interrupt [x]
173                 #define REGISTER      shortad
174                 #define INLINE        /* unsupported */
175
176                 /*
177                  * Imported from <longjmp.h>. Unfortunately, we can't just include
178                  * this header because it typedefs jmp_buf to be an array of chars.
179                  * This would allow the compiler to place the buffer on an odd address.
180                  * The CPU _should_ be able to perform word accesses to
181                  * unaligned data, but there are *BUGS* in the 80196KC with
182                  * some combinations of opcodes and addressing modes. One of
183                  * these, "ST SP,[?GR]+" is used in the longjmp() implementation
184                  * provided by the IAR compiler ANSI C library. When ?GR contains
185                  * an odd address, surprisingly the CPU will copy the high order
186                  * byte of the source operand (SP) in the low order byte of the
187                  * destination operand (the memory location pointed to by ?GR).
188                  *
189                  * We also need to replace the library setjmp()/longjmp() with
190                  * our own versions because the IAR implementation "forgets" to
191                  * save the contents of local registers (?LR).
192                  */
193                 struct _JMP_BUF
194                 {
195                         void *sp;           /* Stack pointer */
196                         void *return_addr;  /* Return address */
197                         int lr[6];          /* 6 local registers */
198                 };
199
200                 typedef struct _JMP_BUF jmp_buf[1];
201
202                 int setjmp(jmp_buf env);
203                 void longjmp(jmp_buf env, int val);
204
205                 /* Fake bool support */
206                 #define true (1==1)
207                 #define false (1!=1)
208                 typedef unsigned char bool;
209
210         #else
211                 #error Unsupported CPU
212         #endif
213
214 #elif defined(_MSC_VER) /* Win32 emulation support */
215
216         /* MSVC doesn't provide <stdbool.h>. */
217         #ifndef __cplusplus
218                 #define true (1==1)
219                 #define false (1!=1)
220                 typedef int bool;
221         #endif /* !__cplusplus */
222
223         /* These C99 functions are oddly named in MSVCRT32.lib */
224         #define snprintf _snprintf
225         #define vsnprintf _vsnprintf
226
227         /* MSVC doesn't support C99's __func__, but has a similar extension. */
228         #define __func__ __FUNCTION__
229
230         /* MSVC doesn't support C99's inline keyword */
231         #ifndef __cplusplus
232                 #define INLINE __inline
233         #endif
234
235 #elif defined(__GNUC__)
236
237         /* Compiler features */
238         #define COMPILER_VARIADIC_MACROS 1 /* Even in C++ */
239         #define COMPILER_TYPEOF 1
240         #define COMPILER_STATEMENT_EXPRESSIONS 1
241
242         /* GCC attributes */
243         #define FORMAT(type,fmt,first)  __attribute__((__format__(type, fmt, first)))
244         #define NORETURN                __attribute__((__noreturn__))
245         #define UNUSED_ARG(type,arg)    __attribute__((__unused__)) type arg
246         #define UNUSED_VAR(type,name)   __attribute__((__unused__)) type name
247         #define USED_VAR(type,name)     __attribute__((__used__)) type name
248         #define INLINE                  static inline __attribute__((__always_inline__))
249         #define LIKELY(x)               __builtin_expect(!!(x), 1)
250         #define UNLIKELY(x)             __builtin_expect(!!(x), 0)
251         #define PURE_FUNC               __attribute__((pure))
252         #define CONST_FUNC              __attribute__((const))
253         #define UNUSED_FUNC             __attribute__((unused))
254         #define USED_FUNC               __attribute__((__used__))
255         #define RESTRICT                __restrict__
256         #define MUST_CHECK              __attribute__((warn_unused_result))
257         #if GNUC_PREREQ(3,1)
258                 #define DEPRECATED  __attribute__((__deprecated__))
259         #endif
260
261         #ifndef __cplusplus
262                 #define ASSERT_TYPE_EQUAL(var1, var2) \
263                         STATIC_ASSERT(__builtin_types_compatible_p(typeof(var1), typeof(var2)))
264                 #define ASSERT_TYPE_IS(var, type) \
265                         STATIC_ASSERT(__builtin_types_compatible_p(typeof(var), type))
266         #endif
267
268         /* Include some standard C89/C99 stuff */
269         #include <stddef.h>
270         #include <stdint.h>
271         #include <stdbool.h>
272         #if !CPU_AVR
273         #include <sys/types.h> /* for ssize_t */
274         #endif
275
276         #ifndef __cplusplus
277                 /*
278                  * Disallow some C++ keywords as identifiers in C programs,
279                  * for improved portability.
280                  */
281                 #pragma GCC poison new delete class template typename
282                 #pragma GCC poison private protected public operator
283                 #pragma GCC poison friend mutable using namespace
284                 #pragma GCC poison cin cout cerr clog
285         #endif
286
287 #elif defined(__MWERKS__)
288
289         /* Compiler features */
290         #define COMPILER_VARIADIC_MACROS 1
291         #define COMPILER_TYPEOF 1
292         #define COMPILER_STATEMENT_EXPRESSIONS 1
293
294         #define typeof __typeof__
295
296         #define UNUSED_ARG(type,arg)    type
297
298         #include <stddef.h>
299         #include <stdint.h>
300         #include <stdbool.h>
301
302         // CodeWarrior has size_t as built-in type, but does not define this symbol.
303         #define _SIZE_T_DEFINED
304
305 #else
306         #error unknown compiler
307 #endif
308
309
310 /* Defaults for compiler extensions. */
311
312 /**
313  * \def COMPILER_VARIADIC_MACROS
314  * Support for macros with variable arguments.
315  */
316 #ifndef COMPILER_VARIADIC_MACROS
317 #define COMPILER_VARIADIC_MACROS (COMPILER_C99 != 0)
318 #endif
319
320 /**
321  * \def COMPILER_TYPEOF
322  * Support for dynamic type identification.
323  */
324 #ifndef COMPILER_TYPEOF
325 #define COMPILER_TYPEOF 0
326 #endif
327
328 /**
329  * \def COMPILER_STATEMENT_EXPRESSIONS
330  * Support for statement expressions.
331  */
332 #ifndef COMPILER_STATEMENT_EXPRESSIONS
333 #define COMPILER_STATEMENT_EXPRESSIONS 0
334 #endif
335
336 /* A few defaults for missing compiler features. */
337 #ifndef INLINE
338 #define INLINE                 static inline
339 #endif
340 #ifndef NORETURN
341 #define NORETURN               /* nothing */
342 #endif
343 #ifndef FORMAT
344 #define FORMAT(type,fmt,first) /* nothing */
345 #endif
346 #ifndef DEPRECATED
347 #define DEPRECATED             /* nothing */
348 #endif
349 #ifndef UNUSED_ARG
350 #define UNUSED_ARG(type,arg)   type arg
351 #endif
352 #define UNUSED                 UNUSED_ARG /* OBSOLETE */
353 #ifndef UNUSED_VAR
354 #define UNUSED_VAR(type,name)  type name
355 #endif
356 #ifndef USED_VAR
357 #define USED_VAR(type,name)    type name
358 #endif
359 #ifndef REGISTER
360 #define REGISTER               /* nothing */
361 #endif
362 #ifndef LIKELY
363 #define LIKELY(x)              x
364 #endif
365 #ifndef UNLIKELY
366 #define UNLIKELY(x)            x
367 #endif
368 #ifndef PURE_FUNC
369 #define PURE_FUNC              /* nothing */
370 #endif
371 #ifndef CONST_FUNC
372 #define CONST_FUNC             /* nothing */
373 #endif
374 #ifndef UNUSED_FUNC
375 #define UNUSED_FUNC            /* nothing */
376 #endif
377 #ifndef USED_FUNC
378 #define USED_FUNC              /* nothing */
379 #endif
380 #ifndef RESTRICT
381 #define RESTRICT               /* nothing */
382 #endif
383 #ifndef MUST_CHECK
384 #define MUST_CHECK             /* nothing */
385 #endif
386
387 /* Misc definitions */
388 #ifndef NULL
389 #define NULL  (void *)0
390 #endif
391 #ifndef EOF
392 #define EOF   (-1)
393 #endif
394
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 /** Bulk storage large enough for both pointers or integers. */
466 typedef void * iptr_t;
467
468 /** Bulk storage large enough for both pointers to constants or integers. */
469 typedef const void * const_iptr_t;
470
471 typedef unsigned char sigbit_t;  /**< Type for signal bits. */
472 typedef unsigned char sigmask_t; /**< Type for signal masks. */
473 typedef unsigned char page_t;    /**< Type for banked memory pages. */
474
475
476 /**
477  * \name Standard type definitions.
478  *
479  * These should be in <sys/types.h> or <stddef.h>, but many compilers
480  * and C libraries lack them.
481  *
482  * We check for some common definitions to avoid redefinitions:
483  *
484  *    glibc, avr-libc: _SIZE_T_DEFINED, __ssize_t_defined
485  *    Darwin libc:     _BSD_SIZE_T_DEFINED_, _SIZE_T
486  *    IAR ARM:         _SIZE_T
487  *
488  * \{
489  */
490 #if !(defined(size_t) || defined(_SIZE_T_DEFINED) || defined(_BSD_SIZE_T_DEFINED_) \
491         || defined(_SIZE_T))
492         #if CPU_X86
493                 /* 32bit or 64bit (32bit for _WIN64). */
494                 typedef unsigned long size_t;
495         #else
496                 #error Unknown CPU
497         #endif
498 #endif
499
500 #if !(defined(ssize_t) || defined(_SSIZE_T) || defined(__ssize_t_defined))
501         #if CPU_X86
502                 /* 32bit or 64bit (32bit for _WIN64). */
503                 typedef long ssize_t;
504         #elif CPU_ARM
505                 typedef int ssize_t;
506         #elif CPU_AVR
507                 /* 16bit (missing in avr-libc's sys/types.h). */
508                 typedef int ssize_t;
509         #else
510                 #error Unknown CPU
511         #endif
512 #endif
513 /*\}*/
514
515
516 /**
517  * \name Types for hardware registers.
518  *
519  * Only use these types for registers whose contents can
520  * be changed asynchronously by external hardware.
521  *
522  * \{
523  */
524 #if CPU_DSP56K
525         /* Registers can be accessed only through 16-bit pointers */
526         typedef volatile uint16_t  reg16_t;
527 #else
528         typedef volatile uint8_t   reg8_t;
529         typedef volatile uint16_t  reg16_t;
530         typedef volatile uint32_t  reg32_t;
531 #endif
532 /*\}*/
533
534
535 /* Quasi-ANSI macros */
536 #ifndef offsetof
537         /**
538          * Return the byte offset of the member \a m in struct \a s.
539          *
540          * \note This macro should be defined in "stddef.h" and is sometimes
541          *       compiler-specific (g++ has a builtin for it).
542          */
543         #define offsetof(s,m)  (size_t)&(((s *)0)->m)
544 #endif
545 #ifndef countof
546         /**
547          * Count the number of elements in the static array \a a.
548          *
549          * \note This macro is non-standard, but implements a very common idiom
550          */
551         #define countof(a)  (sizeof(a) / sizeof(*(a)))
552 #endif
553
554 /**
555  * Cast a member of a structure out to the containing structure.
556  *
557  * \param ptr     the pointer to the member.
558  * \param type    the type of the container struct this is embedded in.
559  * \param member  the name of the member within the struct.
560  */
561 #if COMPILER_TYPEOF && COMPILER_STATEMENT_EXPRESSIONS
562         #define containerof(ptr, type, member) ({ \
563                 const typeof( ((type *)0)->member ) *_mptr = (ptr); /* type check */ \
564                 (type *)((char *)_mptr - offsetof(type, member)); \
565         })
566 #else
567         #define containerof(ptr, type, member) \
568                 ( (type *)((char *)(ptr) - offsetof(type, member)) )
569 #endif
570
571 /** Issue a compilation error if the \a condition is false */
572 #define STATIC_ASSERT(condition)  \
573         UNUSED_VAR(extern char, STATIC_ASSERTION_FAILED__[(condition) ? 1 : -1])
574
575 #ifndef ASSERT_TYPE_EQUAL
576         /** Ensure two variables have the same type. */
577         #define ASSERT_TYPE_EQUAL(var1, var2)  \
578                         do { (void)(&(var1) == &(var2)); } while(0)
579 #endif
580
581 #ifndef ASSERT_TYPE_IS
582         /** Ensure variable is of specified type. */
583         #define ASSERT_TYPE_IS(var, type)  \
584                         do { (void)(&(var) == (type *)0); } while(0)
585 #endif
586
587 #endif /* DEVLIB_COMPILER_H */