X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcfg%2Fcompiler.h;h=0d401bcc42e27ba14997b4f1f8b73682050aad3b;hb=e25abecb6a6ff52917d44d1331e5af831aeceb9c;hp=87cdd9425a4159617880e40e2a803d929089a397;hpb=a0709949ddb69e5e28d79f7898c37ebf281696b0;p=bertos.git diff --git a/bertos/cfg/compiler.h b/bertos/cfg/compiler.h index 87cdd942..0d401bcc 100644 --- a/bertos/cfg/compiler.h +++ b/bertos/cfg/compiler.h @@ -33,7 +33,6 @@ * * \brief Additional support macros for compiler independance * - * \version $Id$ * \author Bernie Innocenti */ @@ -55,10 +54,14 @@ #pragma c99 on #endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - #define COMPILER_C99 1 -#else - #define COMPILER_C99 0 +#if defined(__STDC_VERSION__) + #if (__STDC_VERSION__ == 199409L) // IAR + #define COMPILER_C99 1 // not true, because partial C99, avoid miscompilation + #elif (__STDC_VERSION__ >= 199901L) // GCC + #define COMPILER_C99 1 + #else + #define COMPILER_C99 0 + #endif #endif @@ -74,16 +77,52 @@ #define PP_STRINGIZE__(x) #x +/** + */ +#if COMPILER_C99 + #define COUNT_PARMS2(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _, ...) _ + #define COUNT_PARMS(...) \ + COUNT_PARMS2(11 , ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + + /** + * usage: + * \code + * #define foo_init(...) PP_CAT(foo_init_, COUNT_PARMS(__VA_ARGS__)) (__VA_ARGS__) + * \endcode + */ + +#else + #define COUNT_PARMS2(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _, ...) _ + #define COUNT_PARMS(args...) \ + COUNT_PARMS2(11 , ## args, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + + /** + * usage: + * \code + * #define foo_init(args...) PP_CAT(foo_init_, COUNT_PARMS(args)) (args) + * \endcode + */ + +#endif + #if defined(__IAR_SYSTEMS_ICC) || defined(__IAR_SYSTEMS_ICC__) #pragma language=extended - #if CPU_ARM + /* IAR iccarm specific functions */ + #include + #pragma diag_suppress=Pe940 + #pragma inline = forced + + #define MEMORY_BARRIER asm("") + + #if CPU_ARM || CPU_CM3 #define COMPILER_VARIADIC_MACROS 1 #define INTERRUPT(x) __irq __arm void x (void) #define INLINE static inline + #define NAKED /* Include some standard C89/C99 stuff */ #include @@ -172,6 +211,7 @@ #define UNUSED_VAR(type,name) __attribute__((__unused__)) type name #define USED_VAR(type,name) __attribute__((__used__)) type name #define INLINE static inline __attribute__((__always_inline__)) + #define NOINLINE __attribute__((noinline)) #define LIKELY(x) __builtin_expect(!!(x), 1) #define UNLIKELY(x) __builtin_expect(!!(x), 0) #define PURE_FUNC __attribute__((pure)) @@ -181,8 +221,15 @@ #define RESTRICT __restrict__ #define MUST_CHECK __attribute__((warn_unused_result)) #define PACKED __attribute__((packed)) + #define ALIGNED(x) __attribute__ ((__aligned__(x))) + #if CPU_ARM | CPU_CM3 + #define NAKED __attribute__((naked)) + #else + #define NAKED + #endif + /** - * Force compiler to realod context variable. + * Force compiler to reload context variable. */ #define MEMORY_BARRIER asm volatile ("" : : : "memory") @@ -190,6 +237,10 @@ #define DEPRECATED __attribute__((__deprecated__)) #endif + #if GNUC_PREREQ(4,5) + #define UNREACHABLE() __builtin_unreachable() + #endif + #ifndef __cplusplus #define ASSERT_TYPE_EQUAL(var1, var2) \ STATIC_ASSERT(__builtin_types_compatible_p(typeof(var1), typeof(var2))) @@ -271,6 +322,9 @@ #ifndef INLINE #define INLINE static inline #endif +#ifndef NOINLINE +#define NOINLINE /* nothing */ +#endif #ifndef NORETURN #define NORETURN /* nothing */ #endif @@ -319,10 +373,16 @@ #ifndef PACKED #define PACKED /* nothing */ #endif +#ifndef ALIGNED +#define ALIGNED /* nothing */ +#endif #ifndef MEMORY_BARRIER #define MEMORY_BARRIER /* nothing */ #warning No memory barrier defined for select compiler. If you use the kernel check it. #endif +#ifndef UNREACHABLE +#define UNREACHABLE() for (;;) +#endif /* Misc definitions */ @@ -402,6 +462,9 @@ #endif #endif +/** User defined callback type */ +typedef void (*Hook)(void *); + /** Bulk storage large enough for both pointers or integers. */ typedef void * iptr_t; @@ -410,8 +473,15 @@ typedef const void * const_iptr_t; typedef unsigned char sigbit_t; /**< Type for signal bits. */ typedef unsigned char sigmask_t; /**< Type for signal masks. */ -typedef unsigned char page_t; /**< Type for banked memory pages. */ +/** + * Signal structure + */ +typedef struct Signal +{ + sigmask_t wait; /**< Signals the process is waiting for */ + sigmask_t recv; /**< Received signals */ +} Signal; /** * \name Standard type definitions. @@ -441,10 +511,10 @@ typedef unsigned char page_t; /**< Type for banked memory pages. */ #if CPU_X86 /* 32bit or 64bit (32bit for _WIN64). */ typedef long ssize_t; - #elif CPU_ARM + #elif CPU_ARM || CPU_CM3 typedef int ssize_t; - #elif CPU_AVR - /* 16bit (missing in avr-libc's sys/types.h). */ + #elif CPU_AVR || CPU_MSP430 + /* 16bit (missing in avr-/msp430-libc's sys/types.h). */ typedef int ssize_t; #else #error Unknown CPU @@ -488,7 +558,32 @@ typedef unsigned char page_t; /**< Type for banked memory pages. */ * * \note This macro is non-standard, but implements a very common idiom */ - #define countof(a) (sizeof(a) / sizeof(*(a))) + #if defined(__GNUC__) && !defined(__cplusplus) + /* + * Perform a compile time type checking: countof() can only + * work with static arrays, so throw a compile time error if a + * pointer is passed as argument. + * + * NOTE: the construct __builtin_types_compatible_p() is only + * available for C. + */ + #define countof(a) (sizeof(a) / sizeof(*(a)) + \ + STATIC_ASSERT_EXPR( \ + !__builtin_types_compatible_p( \ + typeof(a), typeof(&a[0])))) + #else + #define countof(a) (sizeof(a) / sizeof(*(a))) + #endif +#endif +#ifndef alignof + /** + * Return the alignment in memory of a generic data type. + * + * \note We need to worry about alignment when allocating memory that + * will be used later by unknown objects (e.g., malloc()) or, more + * generally, whenever creating generic container types. + */ + #define alignof(type) offsetof(struct { char c; type member; }, member) #endif /** @@ -512,6 +607,13 @@ typedef unsigned char page_t; /**< Type for banked memory pages. */ #define STATIC_ASSERT(condition) \ UNUSED_VAR(extern char, STATIC_ASSERTION_FAILED__[(condition) ? 1 : -1]) +/** + * Issue a compilation error if \a __cond is false (this can be used inside an + * expression). + */ +#define STATIC_ASSERT_EXPR(__cond) \ + (sizeof(struct { int STATIC_ASSERTION_FAILED__:!!(__cond); }) * 0) + #ifndef ASSERT_TYPE_EQUAL /** Ensure two variables have the same type. */ #define ASSERT_TYPE_EQUAL(var1, var2) \ @@ -524,4 +626,15 @@ typedef unsigned char page_t; /**< Type for banked memory pages. */ do { (void)(&(var) == (type *)0); } while(0) #endif +/** + * Prevent the compiler from optimizing access to the variable \a x, enforcing + * a refetch from memory. This also forbid from reordering successing instances + * of ACCESS_SAFE(). + */ +#ifdef __ICCARM__ +#define ACCESS_SAFE(x) x +#else +#define ACCESS_SAFE(x) (*(volatile typeof(x) *)&(x)) +#endif + #endif /* BERTOS_COMPILER_H */