BeRTOS
|
00001 00039 #ifndef BERTOS_COMPILER_H 00040 #define BERTOS_COMPILER_H 00041 00042 #include <cpu/detect.h> 00043 00044 00045 #if defined __GNUC__ && defined __GNUC_MINOR__ 00046 #define GNUC_PREREQ(maj, min) \ 00047 ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) 00048 #else 00049 #define GNUC_PREREQ(maj, min) 0 00050 #endif 00051 00052 /* Some CW versions do not allow enabling C99 from the settings panel. */ 00053 #if defined(__MWERKS__) 00054 #pragma c99 on 00055 #endif 00056 00057 #if defined(__STDC_VERSION__) 00058 #if (__STDC_VERSION__ == 199409L) // IAR 00059 #define COMPILER_C99 1 // not true, because partial C99, avoid miscompilation 00060 #elif (__STDC_VERSION__ >= 199901L) // GCC 00061 #define COMPILER_C99 1 00062 #else 00063 #define COMPILER_C99 0 00064 #endif 00065 #endif 00066 00067 00069 #define PP_CAT(x,y) PP_CAT__(x,y) 00070 #define PP_CAT__(x,y) x ## y 00071 #define PP_CAT3(x,y,z) PP_CAT(PP_CAT(x,y),z) 00072 #define PP_CAT4(x,y,z,w) PP_CAT(PP_CAT3(x,y,z),w) 00073 #define PP_CAT5(x,y,z,w,j) PP_CAT(PP_CAT4(x,y,z,w),j) 00074 00076 #define PP_STRINGIZE(x) PP_STRINGIZE__(x) 00077 #define PP_STRINGIZE__(x) #x 00078 00079 00082 #if COMPILER_C99 00083 #define COUNT_PARMS2(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _, ...) _ 00084 #define COUNT_PARMS(...) \ 00085 COUNT_PARMS2(11 , ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) 00086 00094 #else 00095 #define COUNT_PARMS2(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _, ...) _ 00096 #define COUNT_PARMS(args...) \ 00097 COUNT_PARMS2(11 , ## args, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) 00098 00106 #endif 00107 00108 #if defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__) 00109 00110 #pragma language=extended 00111 00112 /* IAR iccarm specific functions */ 00113 #include <intrinsics.h> 00114 #pragma diag_suppress=Pe940 00115 #pragma inline = forced 00116 00117 #define MEMORY_BARRIER asm("") 00118 00119 #if CPU_ARM || CPU_CM3 00120 00121 #define COMPILER_VARIADIC_MACROS 1 00122 00123 #define INTERRUPT(x) __irq __arm void x (void) 00124 #define INLINE static inline 00125 #define NAKED 00126 00127 /* Include some standard C89/C99 stuff */ 00128 #include <stddef.h> 00129 #include <stdint.h> 00130 #include <stdbool.h> 00131 00132 #elif CPU_I196 00133 00134 // IAR has size_t as built-in type, but does not define this symbol. 00135 #define _SIZE_T_DEFINED 00136 00137 #define INTERRUPT(x) interrupt [x] 00138 #define REGISTER shortad 00139 #define INLINE /* unsupported */ 00140 00141 /* 00142 * Imported from <longjmp.h>. Unfortunately, we can't just include 00143 * this header because it typedefs jmp_buf to be an array of chars. 00144 * This would allow the compiler to place the buffer on an odd address. 00145 * The CPU _should_ be able to perform word accesses to 00146 * unaligned data, but there are *BUGS* in the 80196KC with 00147 * some combinations of opcodes and addressing modes. One of 00148 * these, "ST SP,[?GR]+" is used in the longjmp() implementation 00149 * provided by the IAR compiler ANSI C library. When ?GR contains 00150 * an odd address, surprisingly the CPU will copy the high order 00151 * byte of the source operand (SP) in the low order byte of the 00152 * destination operand (the memory location pointed to by ?GR). 00153 * 00154 * We also need to replace the library setjmp()/longjmp() with 00155 * our own versions because the IAR implementation "forgets" to 00156 * save the contents of local registers (?LR). 00157 */ 00158 struct _JMP_BUF 00159 { 00160 void *sp; /* Stack pointer */ 00161 void *return_addr; /* Return address */ 00162 int lr[6]; /* 6 local registers */ 00163 }; 00164 00165 typedef struct _JMP_BUF jmp_buf[1]; 00166 00167 int setjmp(jmp_buf env); 00168 void longjmp(jmp_buf env, int val); 00169 00170 /* Fake bool support */ 00171 #define true (1==1) 00172 #define false (1!=1) 00173 typedef unsigned char bool; 00174 00175 #else 00176 #error Unsupported CPU 00177 #endif 00178 00179 #elif defined(_MSC_VER) /* Win32 emulation support */ 00180 00181 /* MSVC doesn't provide <stdbool.h>. */ 00182 #ifndef __cplusplus 00183 #define true (1==1) 00184 #define false (1!=1) 00185 typedef int bool; 00186 #endif /* !__cplusplus */ 00187 00188 /* These C99 functions are oddly named in MSVCRT32.lib */ 00189 #define snprintf _snprintf 00190 #define vsnprintf _vsnprintf 00191 00192 /* MSVC doesn't support C99's __func__, but has a similar extension. */ 00193 #define __func__ __FUNCTION__ 00194 00195 /* MSVC doesn't support C99's inline keyword */ 00196 #ifndef __cplusplus 00197 #define INLINE __inline 00198 #endif 00199 00200 #elif defined(__GNUC__) 00201 00202 /* Compiler features */ 00203 #define COMPILER_VARIADIC_MACROS 1 /* Even in C++ */ 00204 #define COMPILER_TYPEOF 1 00205 #define COMPILER_STATEMENT_EXPRESSIONS 1 00206 00207 /* GCC attributes */ 00208 #define FORMAT(type,fmt,first) __attribute__((__format__(type, fmt, first))) 00209 #define NORETURN __attribute__((__noreturn__)) 00210 #define UNUSED_ARG(type,arg) __attribute__((__unused__)) type arg 00211 #define UNUSED_VAR(type,name) __attribute__((__unused__)) type name 00212 #define USED_VAR(type,name) __attribute__((__used__)) type name 00213 #define INLINE static inline __attribute__((__always_inline__)) 00214 #define NOINLINE __attribute__((noinline)) 00215 #define LIKELY(x) __builtin_expect(!!(x), 1) 00216 #define UNLIKELY(x) __builtin_expect(!!(x), 0) 00217 #define PURE_FUNC __attribute__((pure)) 00218 #define CONST_FUNC __attribute__((const)) 00219 #define UNUSED_FUNC __attribute__((unused)) 00220 #define USED_FUNC __attribute__((__used__)) 00221 #define RESTRICT __restrict__ 00222 #define MUST_CHECK __attribute__((warn_unused_result)) 00223 #define PACKED __attribute__((packed)) 00224 #define ALIGNED(x) __attribute__ ((__aligned__(x))) 00225 #if CPU_ARM | CPU_CM3 00226 #define NAKED __attribute__((naked)) 00227 #else 00228 #define NAKED 00229 #endif 00230 00234 #define MEMORY_BARRIER asm volatile ("" : : : "memory") 00235 00236 #if GNUC_PREREQ(3,1) 00237 #define DEPRECATED __attribute__((__deprecated__)) 00238 #endif 00239 00240 #if GNUC_PREREQ(4,5) 00241 #define UNREACHABLE() __builtin_unreachable() 00242 #endif 00243 00244 #ifndef __cplusplus 00245 #define ASSERT_TYPE_EQUAL(var1, var2) \ 00246 STATIC_ASSERT(__builtin_types_compatible_p(typeof(var1), typeof(var2))) 00247 #define ASSERT_TYPE_IS(var, type) \ 00248 STATIC_ASSERT(__builtin_types_compatible_p(typeof(var), type)) 00249 #endif 00250 00251 /* Include some standard C89/C99 stuff */ 00252 #include <stddef.h> 00253 #include <stdint.h> 00254 #include <stdbool.h> 00255 #if !CPU_AVR 00256 #include <sys/types.h> /* for ssize_t */ 00257 #endif 00258 00259 #ifndef __cplusplus 00260 /* 00261 * Disallow some C++ keywords as identifiers in C programs, 00262 * for improved portability. 00263 */ 00264 #pragma GCC poison new delete class template typename 00265 #pragma GCC poison private protected public operator 00266 #pragma GCC poison friend mutable using namespace 00267 #pragma GCC poison cin cout cerr clog 00268 #endif 00269 00270 00271 00272 #elif defined(__MWERKS__) 00273 00274 /* Compiler features */ 00275 #define COMPILER_VARIADIC_MACROS 1 00276 #define COMPILER_TYPEOF 1 00277 #define COMPILER_STATEMENT_EXPRESSIONS 1 00278 00279 #define typeof __typeof__ 00280 00281 #define UNUSED_ARG(type,arg) type 00282 00283 #include <stddef.h> 00284 #include <stdint.h> 00285 #include <stdbool.h> 00286 00287 // CodeWarrior has size_t as built-in type, but does not define this symbol. 00288 #define _SIZE_T_DEFINED 00289 00290 #else 00291 #error unknown compiler 00292 #endif 00293 00294 00295 /* Defaults for compiler extensions. */ 00296 00301 #ifndef COMPILER_VARIADIC_MACROS 00302 #define COMPILER_VARIADIC_MACROS (COMPILER_C99 != 0) 00303 #endif 00304 00309 #ifndef COMPILER_TYPEOF 00310 #define COMPILER_TYPEOF 0 00311 #endif 00312 00317 #ifndef COMPILER_STATEMENT_EXPRESSIONS 00318 #define COMPILER_STATEMENT_EXPRESSIONS 0 00319 #endif 00320 00321 /* A few defaults for missing compiler features. */ 00322 #ifndef INLINE 00323 #define INLINE static inline 00324 #endif 00325 #ifndef NOINLINE 00326 #define NOINLINE /* nothing */ 00327 #endif 00328 #ifndef NORETURN 00329 #define NORETURN /* nothing */ 00330 #endif 00331 #ifndef FORMAT 00332 #define FORMAT(type,fmt,first) /* nothing */ 00333 #endif 00334 #ifndef DEPRECATED 00335 #define DEPRECATED /* nothing */ 00336 #endif 00337 #ifndef UNUSED_ARG 00338 #define UNUSED_ARG(type,arg) type arg 00339 #endif 00340 #ifndef UNUSED_VAR 00341 #define UNUSED_VAR(type,name) type name 00342 #endif 00343 #ifndef USED_VAR 00344 #define USED_VAR(type,name) type name 00345 #endif 00346 #ifndef REGISTER 00347 #define REGISTER /* nothing */ 00348 #endif 00349 #ifndef LIKELY 00350 #define LIKELY(x) x 00351 #endif 00352 #ifndef UNLIKELY 00353 #define UNLIKELY(x) x 00354 #endif 00355 #ifndef PURE_FUNC 00356 #define PURE_FUNC /* nothing */ 00357 #endif 00358 #ifndef CONST_FUNC 00359 #define CONST_FUNC /* nothing */ 00360 #endif 00361 #ifndef UNUSED_FUNC 00362 #define UNUSED_FUNC /* nothing */ 00363 #endif 00364 #ifndef USED_FUNC 00365 #define USED_FUNC /* nothing */ 00366 #endif 00367 #ifndef RESTRICT 00368 #define RESTRICT /* nothing */ 00369 #endif 00370 #ifndef MUST_CHECK 00371 #define MUST_CHECK /* nothing */ 00372 #endif 00373 #ifndef PACKED 00374 #define PACKED /* nothing */ 00375 #endif 00376 #ifndef ALIGNED 00377 #define ALIGNED /* nothing */ 00378 #endif 00379 #ifndef MEMORY_BARRIER 00380 #define MEMORY_BARRIER /* nothing */ 00381 #warning No memory barrier defined for select compiler. If you use the kernel check it. 00382 #endif 00383 #ifndef UNREACHABLE 00384 #define UNREACHABLE() for (;;) 00385 #endif 00386 00387 00388 /* Misc definitions */ 00389 #ifndef NULL 00390 #define NULL (void *)0 00391 #endif 00392 #ifndef EOF 00393 #define EOF (-1) 00394 #endif 00395 00396 /* Support for hybrid C/C++ applications. */ 00397 #ifdef __cplusplus 00398 #define EXTERN_C extern "C" 00399 #define EXTERN_C_BEGIN extern "C" { 00400 #define EXTERN_C_END } 00401 #define EXTERN_CONST extern const 00402 #define CONST_CAST(TYPE,EXPR) (const_cast<TYPE>(EXPR)) 00403 #else 00404 #define EXTERN_C extern 00405 #define EXTERN_C_BEGIN /* nothing */ 00406 #define EXTERN_C_END /* nothing */ 00407 #define EXTERN_CONST const 00408 #define CONST_CAST(TYPE,EXPR) ((TYPE)(EXPR)) /* FIXME: How can we suppress the warning in C? */ 00409 #endif 00410 00411 00412 #if defined(_MSC_VER) \ 00413 || ((defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__)) && CPU_I196) 00414 00420 typedef signed char int8_t; 00421 typedef unsigned char uint8_t; 00422 typedef short int int16_t; 00423 typedef unsigned short int uint16_t; 00424 typedef long int int32_t; /* _WIN64 safe */ 00425 typedef unsigned long int uint32_t; /* _WIN64 safe */ 00426 00427 #ifdef _MSC_VER 00428 typedef __int64 int64_t; 00429 typedef unsigned __int64 uint64_t; 00430 #else 00431 typedef long long int64_t; 00432 typedef unsigned long long uint64_t; 00433 #endif 00434 /* \} */ 00435 #else 00436 /* This is the standard location. */ 00437 #include <stdint.h> 00438 #endif 00439 00440 #if CPU_AVR_ATMEGA8 00441 /* 00442 * The ATmega8 has a very small Flash, so we can't afford 00443 * to link in support routines for 32bit integer arithmetic. 00444 */ 00445 typedef int16_t ticks_t; 00446 typedef int16_t mtime_t; 00447 typedef int16_t utime_t; 00448 #define SIZEOF_MTIME_T (16 / CPU_BITS_PER_CHAR) 00449 #define SIZEOF_UTIME_T (16 / CPU_BITS_PER_CHAR) 00450 #define MTIME_INFINITE 0x7FFFL 00451 #else 00452 typedef int32_t ticks_t; 00454 typedef int32_t utime_t; 00455 #define SIZEOF_UTIME_T (32 / CPU_BITS_PER_CHAR) 00456 00457 #ifndef DEVLIB_MTIME_DEFINED 00458 #define DEVLIB_MTIME_DEFINED 1 /* Resolve conflict with <os/hptime.h> */ 00459 typedef int32_t mtime_t; 00460 #define SIZEOF_MTIME_T (32 / CPU_BITS_PER_CHAR) 00461 #define MTIME_INFINITE 0x7FFFFFFFL 00462 #endif 00463 #endif 00464 00466 typedef void (*Hook)(void *); 00467 00469 typedef void * iptr_t; 00470 00472 typedef const void * const_iptr_t; 00473 00474 typedef unsigned char sigbit_t; 00475 typedef unsigned char sigmask_t; 00480 typedef struct Signal 00481 { 00482 sigmask_t wait; 00483 sigmask_t recv; 00484 } Signal; 00485 00500 #if !(defined(size_t) || defined(_SIZE_T_DEFINED) || defined(_BSD_SIZE_T_DEFINED_) \ 00501 || defined(_SIZE_T)) 00502 #if CPU_X86 00503 /* 32bit or 64bit (32bit for _WIN64). */ 00504 typedef unsigned long size_t; 00505 #else 00506 #error Unknown CPU 00507 #endif 00508 #endif 00509 00510 #if !(defined(ssize_t) || defined(_SSIZE_T) || defined(__ssize_t_defined)) 00511 #if CPU_X86 00512 /* 32bit or 64bit (32bit for _WIN64). */ 00513 typedef long ssize_t; 00514 #elif CPU_ARM || CPU_CM3 00515 typedef int ssize_t; 00516 #elif CPU_AVR || CPU_MSP430 00517 /* 16bit (missing in avr-/msp430-libc's sys/types.h). */ 00518 typedef int ssize_t; 00519 #else 00520 #error Unknown CPU 00521 #endif 00522 #endif 00523 /*\}*/ 00524 00525 00534 #if CPU_DSP56K 00535 /* Registers can be accessed only through 16-bit pointers */ 00536 typedef volatile uint16_t reg16_t; 00537 #else 00538 typedef volatile uint8_t reg8_t; 00539 typedef volatile uint16_t reg16_t; 00540 typedef volatile uint32_t reg32_t; 00541 #endif 00542 /*\}*/ 00543 00544 00545 /* Quasi-ANSI macros */ 00546 #ifndef offsetof 00547 00553 #define offsetof(s,m) (size_t)&(((s *)0)->m) 00554 #endif 00555 #ifndef countof 00556 00561 #if defined(__GNUC__) && !defined(__cplusplus) 00562 /* 00563 * Perform a compile time type checking: countof() can only 00564 * work with static arrays, so throw a compile time error if a 00565 * pointer is passed as argument. 00566 * 00567 * NOTE: the construct __builtin_types_compatible_p() is only 00568 * available for C. 00569 */ 00570 #define countof(a) (sizeof(a) / sizeof(*(a)) + \ 00571 STATIC_ASSERT_EXPR( \ 00572 !__builtin_types_compatible_p( \ 00573 typeof(a), typeof(&a[0])))) 00574 #else 00575 #define countof(a) (sizeof(a) / sizeof(*(a))) 00576 #endif 00577 #endif 00578 #ifndef alignof 00579 00586 #define alignof(type) offsetof(struct { char c; type member; }, member) 00587 #endif 00588 00596 #if COMPILER_TYPEOF && COMPILER_STATEMENT_EXPRESSIONS 00597 #define containerof(ptr, type, member) ({ \ 00598 typeof( ((type *)0)->member ) *_mptr = (ptr); /* type check */ \ 00599 (type *)(void *)((char *)_mptr - offsetof(type, member)); \ 00600 }) 00601 #else 00602 #define containerof(ptr, type, member) \ 00603 ( (type *)(void *)((char *)(ptr) - offsetof(type, member)) ) 00604 #endif 00605 00607 #define STATIC_ASSERT(condition) \ 00608 UNUSED_VAR(extern char, STATIC_ASSERTION_FAILED__[(condition) ? 1 : -1]) 00609 00614 #define STATIC_ASSERT_EXPR(__cond) \ 00615 (sizeof(struct { int STATIC_ASSERTION_FAILED__:!!(__cond); }) * 0) 00616 00617 #ifndef ASSERT_TYPE_EQUAL 00618 00619 #define ASSERT_TYPE_EQUAL(var1, var2) \ 00620 do { (void)(&(var1) == &(var2)); } while(0) 00621 #endif 00622 00623 #ifndef ASSERT_TYPE_IS 00624 00625 #define ASSERT_TYPE_IS(var, type) \ 00626 do { (void)(&(var) == (type *)0); } while(0) 00627 #endif 00628 00634 #ifdef __ICCARM__ 00635 #define ACCESS_SAFE(x) x 00636 #else 00637 #define ACCESS_SAFE(x) (*(volatile typeof(x) *)&(x)) 00638 #endif 00639 00640 #endif /* BERTOS_COMPILER_H */