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