From 3f7fbe696d8d9656b2250ab390a39516cfaaba90 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 16 May 2016 18:39:17 -0500 Subject: [PATCH] Added useful attributes supported by supported compilers Merges compiler-polyfill into hal/api/toolchain.h following the existing mbed conventions. tested on: - GCC - Clang - ARMCC (online compiler) - IAR attributes: - PACK - ALIGN - UNUSED - WEAK - PURE - FORCEINLINE - NORETURN - UNREACHABLE - DEPRECATED --- hal/api/toolchain.h | 217 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 211 insertions(+), 6 deletions(-) diff --git a/hal/api/toolchain.h b/hal/api/toolchain.h index 2cd588e6d1..b16d654f28 100644 --- a/hal/api/toolchain.h +++ b/hal/api/toolchain.h @@ -16,6 +16,214 @@ #ifndef MBED_TOOLCHAIN_H #define MBED_TOOLCHAIN_H + +// Warning for unsupported compilers +#if !defined(__GNUC__) /* GCC */ \ + && !defined(__CC_ARM) /* ARMCC */ \ + && !defined(__clang__) /* LLVM/Clang */ \ + && !defined(__ICCARM__) /* IAR */ +#warning "This compiler is not yet supported." +#endif + + +// Attributes + +/** PACKED + * Pack a structure, preventing any padding from being added between fields. + * + * @code + * #include "toolchain.h" + * + * typedef struct { + * char x; + * int y; + * } PACKED foo; + * @endcode + */ +#ifndef PACKED +#if defined(__ICCARM__) +#define PACKED __packed +#else +#define PACKED __attribute__((packed)) +#endif +#endif + +/** ALIGN(N) + * Declare a variable to be aligned on an N-byte boundary. + * + * @code + * #include "toolchain.h" + * + * ALIGN(16) char a; + * @endcode + */ +#ifndef ALIGN +#if defined(__ICCARM__) +#define _ALIGN(N) _Pragma(#N) +#define ALIGN(N) _ALIGN(data_alignment=N) +#else +#define ALIGN(N) __attribute__((aligned(N))) +#endif +#endif + +/** UNUSED + * Declare a function argument to be unused, suppressing compiler warnings + * + * @code + * #include "toolchain.h" + * + * void foo(UNUSED int arg) { + * + * } + * @endcode + */ +#ifndef UNUSED +#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM) +#define UNUSED __attribute__((__unused__)) +#else +#define UNUSED +#endif +#endif + +/** WEAK + * Mark a function as being weak. + * + * @note + * weak functions are not friendly to making code re-usable, as they can only + * be overridden once (and if they are multiply overridden the linker will emit + * no warning). You should not normally use weak symbols as part of the API to + * re-usable modules. + * + * @code + * #include "toolchain.h" + * + * WEAK void foo() { + * // a weak implementation of foo that can be overriden by a definition + * // without __weak + * } + * @endcode + */ +#ifndef WEAK +#if defined(__ICCARM__) +#define WEAK __weak +#else +#define WEAK __attribute__((weak)) +#endif +#endif + +/** PURE + * Hint to the compiler that a function depends only on parameters + * + * @code + * #include "toolchain.h" + * + * PURE int foo(int arg){ + * // no access to global variables + * } + * @endcode + */ +#ifndef PURE +#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM) +#define PURE __attribute__((const)) +#else +#define PURE +#endif +#endif + +/** FORCEINLINE + * Declare a function that must always be inlined. Failure to inline + * such a function will result in an error. + * + * @code + * #include "toolchain.h" + * + * FORCEINLINE void foo() { + * + * } + * @endcode + */ +#ifndef FORCEINLINE +#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM) +#define FORCEINLINE static inline __attribute__((always_inline)) +#elif defined(__ICCARM__) +#define FORCEINLINE _Pragma("inline=force") static +#else +#define FORCEINLINE static inline +#endif +#endif + +/** NORETURN + * Declare a function that will never return. + * + * @code + * #include "toolchain.h" + * + * NORETURN void foo() { + * // must never return + * while (1) {} + * } + * @endcode + */ +#ifndef NORETURN +#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM) +#define NORETURN __attribute__((noreturn)) +#elif defined(__ICCARM__) +#define NORETURN __noreturn +#else +#define NORETURN +#endif +#endif + +/** UNREACHABLE + * An unreachable statement. If the statement is reached, + * behaviour is undefined. Useful in situations where the compiler + * cannot deduce the unreachability of code. + * + * @code + * #include "toolchain.h" + * + * void foo(int arg) { + * switch (arg) { + * case 1: return 1; + * case 2: return 2; + * ... + * } + * UNREACHABLE; + * } + * @endcode + */ +#ifndef UNREACHABLE +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__CC_ARM) +#define UNREACHABLE __builtin_unreachable() +#else +#define UNREACHABLE while (1) +#endif +#endif + +/** DEPRECATED("message string") + * Mark a function declaration as deprecated, if it used then a warning will be + * issued by the compiler possibly including the provided message. Note that not + * all compilers are able to display the message. + * + * @code + * #include "toolchain.h" + * + * DEPRECATED("don't foo any more, bar instead") + * void foo(int arg); + * @endcode + */ +#ifndef DEPRECATED +#if defined(__GNUC__) || defined(__clang__) +#define DEPRECATED(M) __attribute__((deprecated(M))) +#elif defined(__CC_ARM) +#define DEPRECATED(M) __attribute__((deprecated)) +#else +#define DEPRECATED(M) +#endif +#endif + + +// FILEHANDLE declaration #if defined(TOOLCHAIN_ARM) #include #endif @@ -24,12 +232,9 @@ typedef int FILEHANDLE; #endif -#if defined (__ICCARM__) -# define WEAK __weak -# define PACKED __packed -#else -# define WEAK __attribute__((weak)) -# define PACKED __attribute__((packed)) +// Backwards compatibility +#ifndef EXTERN +#define EXTERN extern #endif // Backwards compatibility