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