aboutsummaryrefslogtreecommitdiffstats
path: root/src/internals.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/internals.h')
-rw-r--r--src/internals.h51
1 files changed, 49 insertions, 2 deletions
diff --git a/src/internals.h b/src/internals.h
index c1153ea..c859ce1 100644
--- a/src/internals.h
+++ b/src/internals.h
@@ -4,7 +4,11 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
-#include <limits.h>
+
+/* clang pretends to be GCC... */
+#if defined(__GNUC__) && defined(__clang__)
+# undef __GNUC__
+#endif
#define BITS_PER_CHAR 64
#define LB_BITS_PER_CHAR 6
@@ -14,6 +18,32 @@
#define CEILING_BITS_TO_CHARS(bits) (((bits) + (BITS_PER_CHAR - 1)) >> LB_BITS_PER_CHAR)
#define BITS_IN_LAST_CHAR(bits) ((bits) & (BITS_PER_CHAR - 1))
+#if defined(__GNUC__)
+# define O0 __attribute__((optimize("O0")))
+# define O1 __attribute__((optimize("O1")))
+# define O2 __attribute__((optimize("O2")))
+# define O3 __attribute__((optimize("O3")))
+# define Ofast __attribute__((optimize("Ofast")))
+# define Os __attribute__((optimize("Os")))
+# define Oz __attribute__((optimize("Os")))
+#elif defined(__clang__)
+# define O0 __attribute__((optnone))
+# define O1 /* Don't know how. */
+# define O2 /* Don't know how. */
+# define O3 /* Don't know how. */
+# define Ofast /* Don't know how. */
+# define Os /* Don't know how. */
+# define Oz /* Don't know how. */
+#else
+# define O0 /* Don't know how. */
+# define O1 /* Don't know how. */
+# define O2 /* Don't know how. */
+# define O3 /* Don't know how. */
+# define Ofast /* Don't know how. */
+# define Os /* Don't know how. */
+# define Oz /* Don't know how. */
+#endif
+
#define LIST_TEMPS\
X(libzahl_tmp_cmp)\
X(libzahl_tmp_str_num)\
@@ -77,13 +107,14 @@ extern size_t libzahl_pool_alloc[sizeof(size_t) * 8];
#define TRIM(a) for (; (a)->used && !(a)->chars[(a)->used - 1]; (a)->used--)
#define TRIM_NONZERO(a) for (; !(a)->chars[(a)->used - 1]; (a)->used--)
#define TRIM_AND_ZERO(a) do { TRIM(a); if (!(a)->used) SET_SIGNUM(a, 0); } while (0)
+#define TRIM_AND_SIGN(a, s) do { TRIM(a); SET_SIGNUM(a, (a)->used ? (s) : 0); } while (0)
#define znegative(a) (zsignum(a) < 0)
#define znegative1(a, b) ((zsignum(a) | zsignum(b)) < 0)
#define znegative2(a, b) ((zsignum(a) & zsignum(b)) < 0)
#define zpositive(a) (zsignum(a) > 0)
#define zpositive1(a, b) (zpositive(a) + zpositive(b) > 0)
#define zpositive2(a, b) (zsignum(a) + zsignum(b) == 2)
-#define zzero1(a, b) (zzero(a) + zzero(b) > 0)
+#define zzero1(a, b) (zzero(a) || zzero(b))
#define zzero2(a, b) (!(zsignum(a) | zsignum(b)))
#define zmemmove(d, s, n) memmove((d), (s), (n) * sizeof(zahl_char_t))
@@ -138,3 +169,19 @@ libzahl_msb_nz_llu(unsigned long long int x)
return r;
}
#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+# if INT64_MAX == LONG_MAX
+# define libzahl_add_overflow(rp, a, b) __builtin_uaddl_overflow(a, b, rp)
+# else
+# define libzahl_add_overflow(rp, a, b) __builtin_uaddll_overflow(a, b, rp)
+# endif
+#else
+static inline int
+libzahl_add_overflow(zahl_char_t *rp, zahl_char_t a, zahl_char_t b)
+{
+ int carry = ZAHL_CHAR_MAX - a < b;
+ *rp = a + b;
+ return carry;
+}
+#endif