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