#define AO_TS_INITIALIZER ((AO_TS_t)AO_TS_CLEAR)
+/* Convenient internal macro to test version of GCC. */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define AO_GNUC_PREREQ(major, minor) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((major) << 16) + (minor))
+#else
+# define AO_GNUC_PREREQ(major, minor) 0 /* false */
+#endif
+
+/* Convenient internal macro to test version of Clang. */
+#if defined(__clang__) && defined(__clang_major__)
+# define AO_CLANG_PREREQ(major, minor) \
+ ((__clang_major__ << 16) + __clang_minor__ >= ((major) << 16) + (minor))
+#else
+# define AO_CLANG_PREREQ(major, minor) 0 /* false */
+#endif
+
/* Platform-dependent stuff: */
#if (defined(__GNUC__) || defined(_MSC_VER) || defined(__INTEL_COMPILER) \
|| defined(__DMC__) || defined(__WATCOMC__)) && !defined(AO_NO_INLINE)
# define AO_INLINE static
#endif
-#if __GNUC__ >= 3 && !defined(LINT2)
+#if AO_GNUC_PREREQ(3, 0) && !defined(LINT2)
# define AO_EXPECT_FALSE(expr) __builtin_expect(expr, 0)
/* Equivalent to (expr) but predict that usually (expr) == 0. */
#else
#ifndef AO_ATTR_NO_SANITIZE_MEMORY
# if defined(AO_MEMORY_SANITIZER) \
- && (!defined(__clang__) || __clang_major__ > 3 \
- || (__clang_major__ == 3 && __clang_minor__ >= 8))
+ && (!defined(__clang__) || AO_CLANG_PREREQ(3, 8))
# define AO_ATTR_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
# else
# define AO_ATTR_NO_SANITIZE_MEMORY /* empty */
# include "atomic_ops/sysdeps/gcc/x86.h"
# endif /* __i386__ */
# if defined(__x86_64__)
-# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) \
- && !defined(AO_USE_SYNC_CAS_BUILTIN)
+# if AO_GNUC_PREREQ(4, 2) && !defined(AO_USE_SYNC_CAS_BUILTIN)
/* It is safe to use __sync CAS built-in on this architecture. */
# define AO_USE_SYNC_CAS_BUILTIN
# endif
*
*/
-#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) \
- || __clang_major__ > 3 \
- || (__clang_major__ == 3 && __clang_minor__ >= 5)) \
+#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 5)) \
&& !defined(AO_DISABLE_GCC_ATOMICS)
/* Probably, it could be enabled even for earlier gcc/clang versions. */
# define AO_GCC_ATOMIC_TEST_AND_SET
# if (!defined(__thumb__) \
|| (defined(__thumb2__) && !defined(__ARM_ARCH_7__) \
&& !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__))) \
- && (!defined(__clang__) || (__clang_major__ > 3) \
- || (__clang_major__ == 3 && __clang_minor__ >= 3))
+ && (!defined(__clang__) || AO_CLANG_PREREQ(3, 3))
/* LDREXD/STREXD present in ARMv6K/M+ (see gas/config/tc-arm.c). */
/* In the Thumb mode, this works only starting from ARMv7 (except */
/* for the base and 'M' models). Clang3.2 (and earlier) does not */
/* #include "../standard_ao_double_t.h" */
/* TODO: Implement double-wide operations if available. */
-#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) \
- || __clang_major__ > 3 \
- || (__clang_major__ == 3 && __clang_minor__ >= 5)) \
+#if (AO_GNUC_PREREQ(4, 9) || AO_CLANG_PREREQ(3, 5)) \
&& !defined(AO_DISABLE_GCC_ATOMICS)
/* Probably, it could be enabled even for earlier gcc/clang versions. */
/* Minimal support for tile. */
-#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) \
- || __clang_major__ > 3 \
- || (__clang_major__ == 3 && __clang_minor__ >= 4)) \
+#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 4)) \
&& !defined(AO_DISABLE_GCC_ATOMICS)
# include "generic.h"
* Some of the machine specific code was borrowed from our GC distribution.
*/
-#if (((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) \
- && !defined(__INTEL_COMPILER)) /* TODO: test and enable icc */ \
- || __clang_major__ > 3 \
- || (__clang_major__ == 3 && __clang_minor__ >= 4)) \
+#if (AO_GNUC_PREREQ(4, 8) || AO_CLANG_PREREQ(3, 4)) \
+ && !defined(__INTEL_COMPILER) /* TODO: test and enable icc */ \
&& !defined(AO_DISABLE_GCC_ATOMICS)
# define AO_GCC_ATOMIC_TEST_AND_SET
&& (!(defined(__x86_64__) || defined(__APPLE_CC__) \
|| defined(__CYGWIN__) || defined(AO_PREFER_BUILTIN_ATOMICS)) \
|| (defined(__x86_64__) && !defined(__ILP32__) \
- && ((__clang_major__ == 3 && __clang_minor__ == 4 \
- && !defined(AO_PREFER_BUILTIN_ATOMICS)) \
+ && (!(AO_CLANG_PREREQ(3, 5) \
+ || defined(AO_PREFER_BUILTIN_ATOMICS)) \
|| defined(AO_ADDRESS_SANITIZER))))
/* As of clang-3.8 i686 (NDK r11c), it requires -latomic for all */
/* the double-wide operations. Same for clang-3.4/x64. For now, */
#if ((defined(__x86_64__) && defined(AO_GCC_ATOMIC_TEST_AND_SET)) \
|| defined(__aarch64__)) && !defined(__ILP32__)
/* x86-64: __m128 is not applicable to atomic intrinsics. */
-# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) \
- || __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
+# if AO_GNUC_PREREQ(4, 7) || AO_CLANG_PREREQ(3, 6)
# pragma GCC diagnostic push
/* Suppress warning about __int128 type. */
# if defined(__clang__)
# else /* pragma diagnostic is not supported */
typedef unsigned __int128 double_ptr_storage;
# endif
-#elif ((defined(__x86_64__) && __GNUC__ >= 4) || defined(_WIN64)) \
+#elif ((defined(__x86_64__) && AO_GNUC_PREREQ(4, 0)) || defined(_WIN64)) \
&& !defined(__ILP32__)
/* x86-64 (except for x32): __m128 serves as a placeholder which also */
/* requires the compiler to align it on 16-byte boundary (as required */