SERRF_TX, SERRF_RX: New macros; Enhance documentation.
[bertos.git] / compiler.h
1 /*!
2  * \file
3  * <!--
4  * Copyright 2003, 2004 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 devlib/README 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.25  2004/10/19 07:14:20  bernie
18  *#* Add macros to test for specific compiler features.
19  *#*
20  *#* Revision 1.24  2004/10/03 18:35:13  bernie
21  *#* Poison C++ keywords in C programs for better portability.
22  *#*
23  *#* Revision 1.23  2004/09/20 03:30:27  bernie
24  *#* Remove vsprintf_P() proto, no longer needed with avr-libc 1.0.4.
25  *#*
26  *#* Revision 1.22  2004/09/14 21:03:04  bernie
27  *#* PURE_FUNC, CONST_FUNC, MUST_CHECK: New function attributes; LIKELY()/UNLIKELY(): Fix for non-integral expressions.
28  *#*
29  *#* Revision 1.21  2004/09/06 21:38:31  bernie
30  *#* Misc documentation and style fixes.
31  *#*
32  *#* Revision 1.20  2004/08/29 21:57:58  bernie
33  *#* Move back STATIC_ASSERT() to compiler.h as it's needed in cpu.h;
34  *#* iptr_t, const_iptr_t: Replace IPTR macro with a real typedef.
35  *#*
36  *#* Revision 1.19  2004/08/25 14:12:08  rasky
37  *#* Aggiornato il comment block dei log RCS
38  *#*
39  *#* Revision 1.18  2004/08/24 16:32:37  bernie
40  *#* Document custom types.
41  *#*
42  *#* Revision 1.17  2004/08/24 13:32:14  bernie
43  *#* PP_CAT(), PP_STRINGIZE(): Move back to compiler.h to break circular dependency between cpu.h/compiler.h/macros.h;
44  *#* offsetof(), countof(): Move back to compiler.h to avoid including macros.h almost everywhere;
45  *#* Trim CVS log;
46  *#* Rename header guards;
47  *#* Don't include arch_config.h in compiler.h as it's not needed there.
48  *#*
49  *#* Revision 1.16  2004/08/14 19:37:57  rasky
50  *#* Merge da SC: macros.h, pool.h, BIT_CHANGE, nome dei processi, etc.
51  *#*
52  *#* Revision 1.15  2004/08/13 03:23:26  bernie
53  *#* Adjust a few MSVC tweaks from older projects.
54  *#*
55  *#* Revision 1.14  2004/08/10 06:56:29  bernie
56  *#* RESTRICT: New C99-like macro; STATIC_ASSERT: Fix warning for multiple invocation in one file.
57  *#*
58  *#* Revision 1.13  2004/08/02 20:20:29  aleph
59  *#* Merge from project_ks
60  *#*
61  *#* Revision 1.12  2004/08/01 01:21:17  bernie
62  *#* LIKELY(), UNLIKELY(): New compiler-specific macros.
63  *#*
64  *#* Revision 1.11  2004/07/30 14:34:10  rasky
65  *#* Vari fix per documentazione e commenti
66  *#* Aggiunte PP_CATn e STATIC_ASSERT
67  *#*
68  *#* Revision 1.10  2004/07/30 14:15:53  rasky
69  *#* Nuovo supporto unificato per detect della CPU
70  *#*
71  *#* Revision 1.9  2004/07/29 22:57:09  bernie
72  *#* vsprintf(): Remove prototype for backwards compatibility with GCC 3.4; ssize_t: Add definition for inferior compilers.
73  *#*/
74 #ifndef DEVLIB_COMPILER_H
75 #define DEVLIB_COMPILER_H
76
77 #include "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 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
88         #define COMPILER_C99      1
89 #else
90         #define COMPILER_C99      0
91 #endif
92
93
94 /*! Concatenate two different preprocessor tokens (allowing macros to expand) */
95 #define PP_CAT(x,y)         PP_CAT__(x,y)
96 #define PP_CAT__(x,y)       x ## y
97 #define PP_CAT3(x,y,z)      PP_CAT(PP_CAT(x,y),z)
98 #define PP_CAT4(x,y,z,w)    PP_CAT(PP_CAT3(x,y,z),w)
99 #define PP_CAT5(x,y,z,w,j)  PP_CAT(PP_CAT4(x,y,z,w),j)
100
101 /*! String-ize a token (allowing macros to expand) */
102 #define PP_STRINGIZE(x)     PP_STRINGIZE__(x)
103 #define PP_STRINGIZE__(x)   #x
104
105
106 #if defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__)
107         #pragma language=extended
108         #define INTERRUPT(x)  interrupt [x]
109         #define REGISTER      shortad
110         #define INLINE        /* unsupported */
111
112         /* Imported from <longjmp.h>. Unfortunately, we can't just include
113          * this header because it typedefs jmp_buf to be an array of chars.
114          * This would allow the compiler to place the buffer on an odd address.
115          * The CPU _should_ be able to perform word accesses to
116          * unaligned data, but there are *BUGS* in the 80196KC with
117          * some combinations of opcodes and addressing modes. One of
118          * these, "ST SP,[?GR]+" is used in the longjmp() implementation
119          * provided by the IAR compiler ANSI C library. When ?GR contains
120          * an odd address, surprisingly the CPU will copy the high order
121          * byte of the source operand (SP) in the low order byte of the
122          * destination operand (the memory location pointed to by ?GR).
123          *
124          * We also need to replace the library setjmp()/longjmp() with
125          * our own versions because the IAR implementation "forgets" to
126          * save the contents of local registers (?LR).
127          */
128         struct _JMP_BUF
129         {
130                 void *  sp;                             /* Stack pointer */
131                 void *  return_addr;    /* Return address */
132                 int             lr[6];                  /* 6 local registers */
133         };
134
135         typedef struct _JMP_BUF jmp_buf[1];
136
137         int setjmp(jmp_buf env);
138         void longjmp(jmp_buf env, int val);
139
140         /* Fake bool support */
141         #define true (1==1)
142         #define false (1!=1)
143         typedef unsigned char bool;
144
145 #elif defined(_MSC_VER) /* Win32 emulation support */
146
147         #include <setjmp.h>
148         #include <time.h> /* for time_t */
149
150         /* FIXME: I can't remember why exactly this was needed (NdBernie) */
151         #define float double
152
153         /* Fake bool support */
154         #ifndef __cplusplus
155                 #define true 1
156                 #define false 0
157                 typedef int bool;
158         #endif /* !__cplusplus */
159
160         /* These C99 functions are oddly named in MSVCRT32.lib */
161         #define snprintf _snprintf
162         #define vsnprintf _vsnprintf
163
164 #elif defined(__GNUC__)
165
166         /* Compiler features */
167         #define COMPILER_VARIADIC_MACROS 1 /* Even in C++ */
168         #define COMPILER_TYPEOF 1
169         #define COMPILER_STAEMENT_EXPRESSIONS 1
170
171         /* GCC attributes */
172         #define FORMAT(type,fmt,first)  __attribute__((__format__(type, fmt, first)))
173         #define NORETURN                __attribute__((__noreturn__))
174         #define UNUSED(type,arg)        __attribute__((__unused__)) type arg
175         #define INLINE                  static inline __attribute__((__always_inline__))
176         #define LIKELY(x)               __builtin_expect(!!(x), 1)
177         #define UNLIKELY(x)             __builtin_expect(!!(x), 0)
178         #define PURE_FUNC               __attribute__((pure))
179         #define CONST_FUNC              __attribute__((const))
180         #define RESTRICT                __restrict__
181         #define MUST_CHECK              __attribute__((warn_unused_result))
182         #if GNUC_PREREQ(3,1)
183                 #define DEPRECATED  __attribute__((__deprecated__))
184         #endif
185
186         #if CPU_X86
187
188                 /* Hack to avoid conflicts with system type */
189                 #define sigset_t system_sigset_t
190                 #include <stddef.h>
191                 #include <setjmp.h>
192                 #include <stdbool.h>
193                 #undef system_sigset_t
194
195         #elif CPU_AVR
196
197                 #include <stddef.h>
198                 #include <stdbool.h>
199
200                 /* Support for harvard architectures */
201                 #ifdef _PROGMEM
202                         #define PGM_READ_CHAR(s) pgm_read_byte(s)
203                         #define PGM_FUNC(x) x ## _P
204                         #define PGM_ATTR  PROGMEM
205                 #endif
206
207         #endif
208
209         #ifndef __cplusplus
210                 /*
211                  * Disallow some C++ keywords as identifiers in C programs,
212                  * for improved portability.
213                  */
214                 #pragma GCC poison new delete class template typename
215                 #pragma GCC poison private protected public operator
216                 #pragma GCC poison friend mutable using namespace
217                 #pragma GCC poison cin cout cerr clog
218         #endif
219
220 #elif defined(__MWERKS__) && CPU_DSP56K
221
222         /* Compiler features */
223         #define COMPILER_TYPEOF 1
224         #define COMPILER_STAEMENT_EXPRESSIONS 1
225
226         #include <stdint.h>
227         #include <stddef.h>
228         #include <stdbool.h>
229         #include <setjmp.h>
230
231         // CodeWarrior has size_t as built-in type, but does not define this symbol.
232         #define _SIZE_T_DEFINED
233
234 #else
235         #error unknown compiler
236 #endif
237
238
239 /* Defaults for compiler extensions. */
240
241 /*!
242  * \def COMPILER_VARIADIC_MACROS
243  * Support for macros with variable arguments.
244  */
245 #ifndef COMPILER_HAVE_VARIADIC_MACROS
246 #define COMPILER_HAVE_VARIADIC_MACROS (COMPILER_C99 != 0)
247 #endif
248
249 /*!
250  * \def COMPILER_TYPEOF
251  * Support for macros with variable arguments.
252  */
253 #ifndef COMPILER_TYPEOF
254 #define COMPILER_TYPEOF 0
255 #endif
256
257 /*!
258  * \def COMPILER_STATEMENT_EXPRESSIONS
259  * Support for macros with variable arguments.
260  */
261 #ifndef COMPILER_STATEMENT_EXPRESSIONS 0
262 #define COMPILER_STATEMENT_EXPRESSIONS 0
263 #endif
264
265 /* A few defaults for missing compiler features. */
266 #ifndef INLINE
267 #define INLINE                 static inline
268 #endif
269 #ifndef NORETURN
270 #define NORETURN               /* nothing */
271 #endif
272 #ifndef FORMAT
273 #define FORMAT(type,fmt,first) /* nothing */
274 #endif
275 #ifndef DEPRECATED
276 #define DEPRECATED             /* nothing */
277 #endif
278 #ifndef UNUSED
279 #define UNUSED(type,arg)       type arg
280 #endif
281 #ifndef REGISTER
282 #define REGISTER               /* nothing */
283 #endif
284 #ifndef INTERRUPT
285 #define INTERRUPT(x)           ERROR_NOT_IMPLEMENTED
286 #endif
287 #ifndef LIKELY
288 #define LIKELY(x)              x
289 #endif
290 #ifndef UNLIKELY
291 #define UNLIKELY(x)            x
292 #endif
293 #ifndef PURE_FUNC
294 #define PURE_FUNC              /* nothing */
295 #endif
296 #ifndef CONST_FUNC
297 #define CONST_FUNC             /* nothing */
298 #endif
299 #ifndef RESTRICT
300 #define RESTRICT               /* nothing */
301 #endif
302 #ifndef MUST_CHECK
303 #define MUST_CHECK             /* nothing */
304 #endif
305
306 /* Support for harvard architectures */
307 #ifndef PSTR
308 #define PSTR            /* nothing */
309 #endif
310 #ifndef PGM_READ_CHAR
311 #define PGM_READ_CHAR(s) (*(s))
312 #endif
313 #ifndef PGM_FUNC
314 #define PGM_FUNC(x) x
315 #endif
316 #ifndef PGM_ATTR
317 #define PGM_ATTR        /* nothing */
318 #endif
319
320
321 /* Misc definitions */
322 #ifndef NULL
323 #define NULL  (void *)0
324 #endif
325 #ifndef EOF
326 #define EOF   (-1)
327 #endif
328
329
330 /* Support for hybrid C/C++ applications. */
331 #ifdef __cplusplus
332         #define EXTERN_C        extern "C"
333         #define EXTERN_C_BEGIN  extern "C" {
334         #define EXTERN_C_END    }
335 #else
336         #define EXTERN_C        extern
337         #define EXTERN_C_BEGIN  /* nothing */
338         #define EXTERN_C_END    /* nothing */
339 #endif
340
341
342 /*
343  * Standard type definitions.
344  * These should be in <sys/types.h>, but many compilers lack them.
345  */
346 #if !(defined(size_t) || defined(_SIZE_T_DEFINED))
347         typedef unsigned int size_t;
348         typedef int ssize_t;
349 #endif
350 #if !(defined(_TIME_T_DEFINED) || defined(__time_t_defined))
351         typedef long time_t;
352 #endif /* _TIME_T_DEFINED || __time_t_defined */
353
354 /*! Bulk storage large enough for both pointers or integers */
355 typedef void * iptr_t;
356 typedef const void * const_iptr_t;
357 #define IPTR iptr_t  /* OBSOLETE */
358
359 typedef long utime_t;            /*!< Type for time expressed in microseconds */
360 typedef unsigned char sig_t;     /*!< Type for signal bits */
361 typedef unsigned char sigset_t;  /*!< Type for signal masks */
362 typedef unsigned char page_t;    /*!< Type for banked memory pages */
363
364 #if (defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__))
365         /*!
366          * \name ISO C99 fixed-size types
367          *
368          * These should be in <stdint.h>, but many compilers lack them.
369          * \{
370          */
371         typedef signed char         int8_t;
372         typedef short int           int16_t;
373         typedef long int            int32_t;
374         typedef unsigned char       uint8_t;
375         typedef unsigned short int  uint16_t;
376         typedef unsigned long int   uint32_t;
377         /* \} */
378 #elif defined(__GNUC__) && CPU_AVR
379         /* avr-libc is weird... */
380         #include <inttypes.h>
381 #else
382         /* This is the correct location. */
383         #include <stdint.h>
384 #endif
385
386 /*!
387  * \name Types for hardware registers.
388  *
389  * Only use these types for registers whose contents can
390  * be changed asynchronously by external hardware.
391  *
392  * \{
393  */
394 #if CPU_DSP56K
395         /* Registers can be accessed only through 16-bit pointers */
396         typedef volatile uint16_t  reg16_t;
397 #else
398         typedef volatile uint8_t   reg8_t;
399         typedef volatile uint16_t  reg16_t;
400         typedef volatile uint32_t  reg32_t;
401 #endif
402 /*\}*/
403
404
405 /* Quasi-ANSI macros */
406 #ifndef offsetof
407         /*!
408          * Return the byte offset of the member \a m in struct \a s.
409          *
410          * \note This macro should be defined in "stddef.h" and is sometimes
411          *       compiler-specific (g++ has a builtin for it).
412          */
413         #define offsetof(s,m)  (size_t)&(((s *)0)->m)
414 #endif
415 #ifndef countof
416         /*!
417          * Count the number of elements in the static array \a a.
418          *
419          * \note This macro is non-standard, but implements a very common idiom
420          */
421         #define countof(a)  (sizeof(a) / sizeof(*(a)))
422 #endif
423
424 /*! Issue a compilation error if the \a condition is false */
425 #define STATIC_ASSERT(condition)  \
426         extern char PP_CAT(CT_ASSERT___, __LINE__)[(condition) ? 1 : -1]
427
428 #endif /* DEVLIB_COMPILER_H */