[m-rev.] diff: more care careful with some GCC builtin functions

Julien Fischer jfischer at opturion.com
Thu Mar 15 17:53:19 AEDT 2018


Be more careful with some GCC builtin functions.

Our use of GCC's __builtin_{popcount,clz,ctz} functions in the uint32 module
assumes that sizeof(int) == sizeof(uint32_t).  While this is true on all of the
systems that we target that I am aware of, there's no reason it has to hold in
general.  Modify the macros guarding our use of these functions so that we
only use them if the above condition holds.

configure.ac:
runtime/mercury_conf.h.in:
     Add a new macro that if defined indicates that C's int type is
     exactly 32-bits in size.

library/uint32.m:
     Use the new macro to protect our use of the above builtin functions.

Julien.

diff --git a/configure.ac b/configure.ac
index 11c6929..148dafc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2080,6 +2080,22 @@ AC_SUBST(MR_ROBDD_LOG_BITS_PER_WORD)

  #-----------------------------------------------------------------------------#

+AC_MSG_CHECKING(whether int is 32-bit)
+AC_CACHE_VAL(mercury_cv_int_is_32_bit,
+    MERCURY_TRY_STATIC_ASSERT(
+        [#include <limits.h>],
+        [sizeof(int) * CHAR_BIT == 32],
+        [mercury_cv_int_is_32_bit=yes],
+        [mercury_cv_int_is_32_bit=no])
+)
+AC_MSG_RESULT($mercury_cv_int_is_32_bit)
+if test "$mercury_cv_int_is_32_bit" = yes; then
+    AC_DEFINE(MR_INT_IS_32_BIT)
+fi
+AC_SUBST(MR_INT_IS_32_BIT)
+
+#-----------------------------------------------------------------------------#
+
  AC_MSG_CHECKING(whether we can use unboxed floats)
  AC_CACHE_VAL(mercury_cv_unboxed_floats,
      MERCURY_TRY_STATIC_ASSERT(
diff --git a/library/uint32.m b/library/uint32.m
index 2890564..a215d5f 100644
--- a/library/uint32.m
+++ b/library/uint32.m
@@ -493,7 +493,7 @@ num_zeros(U) = 32 - num_ones(U).
      num_ones(U::in) = (N::out),
      [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
  "
-#if (defined(MR_GNUC) || defined(MR_CLANG))
+#if (defined(MR_GNUC) || defined(MR_CLANG)) && defined(MR_INT_IS_32_BIT)
      N = __builtin_popcount(U);
  #else
      U = U - ((U >> 1) & UINT32_C(0x55555555));
@@ -533,7 +533,7 @@ num_zeros(U) = 32 - num_ones(U).
      if (U == 0) {
          N = 32;
      } else {
-    #if defined(MR_GNUC) || defined(MR_CLANG)
+    #if (defined(MR_GNUC) || defined(MR_CLANG)) && defined(MR_INT_IS_32_BIT)
          // Note that __builtin_clz(0) is undefined.
          N = __builtin_clz(U);
      #else
@@ -579,7 +579,7 @@ num_zeros(U) = 32 - num_ones(U).
      if (U == 0) {
          N = 32;
      } else {
-    #if defined(MR_GNUC) || defined(MR_CLANG)
+    #if (defined(MR_GNUC) || defined(MR_CLANG)) && defined(MR_INT_IS_32_BIT)
          N = __builtin_ctz(U);
      #else
          int32_t     n = 31;
diff --git a/runtime/mercury_conf.h.in b/runtime/mercury_conf.h.in
index 89e52cc..8801b68 100644
--- a/runtime/mercury_conf.h.in
+++ b/runtime/mercury_conf.h.in
@@ -428,6 +428,10 @@

  #undef MR_HAVE_HWLOC

+// MR_INT_IS_32_BIT is defined if C's int type is exactly 32-bits.
+//
+#undef MR_INT_IS_32_BIT
+
  // The bytecode files represent floats in 64-bit IEEE format.
  //
  // MR_FLOAT_IS_64_BITS: defined iff the C type `float' is exactly 64 bits.


More information about the reviews mailing list