bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

count-leading-zeros: Fix a link error on 32-bit MSVC and a test failure


From: Bruno Haible
Subject: count-leading-zeros: Fix a link error on 32-bit MSVC and a test failure
Date: Mon, 05 Sep 2022 01:36:24 +0200

On 32-bit MSVC, I see a compilation error:

/home/bruno/msvc/compile cl -nologo  -MD  -L/usr/local/msvc32/lib -o 
test-count-leading-zeros.exe test-count-leading-zeros.obj libtests.a 
../gllib/libgnu.a libtests.a ../gllib/libgnu.a libtests.a  
test-count-leading-zeros.obj : error LNK2019: unresolved external symbol 
__BitScanReverse64 referenced in function _count_leading_zeros_ll
test-count-leading-zeros.exe : fatal error LNK1120: 1 unresolved externals
make[4]: *** [Makefile:16525: test-count-leading-zeros.exe] Error 2

Additionally, on 64-bit MSVC, the test-count-leading-zeros.exe test fails.

This patch fixes both issues.


2022-09-04  Bruno Haible  <bruno@clisp.org>

        count-leading-zeros: Fix a link error on 32-bit MSVC and a test failure.
        * lib/count-leading-zeros.h: Correct syntax for #pragma intrinsic.
        (COUNT_LEADING_ZEROS): Fix the return value.
        (count_leading_zeros_ll): Use two _BitScanReverse invocations instead
        of a _BitScanReverse64 invocation.

diff --git a/lib/count-leading-zeros.h b/lib/count-leading-zeros.h
index 354641af0a..4b4f5d4f9a 100644
--- a/lib/count-leading-zeros.h
+++ b/lib/count-leading-zeros.h
@@ -43,13 +43,17 @@ extern "C" {
 # define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)                \
   return x ? BUILTIN (x) : CHAR_BIT * sizeof x;
 #elif _MSC_VER
-# pragma intrinsic _BitScanReverse
-# pragma intrinsic _BitScanReverse64
+# pragma intrinsic (_BitScanReverse)
+# if defined _M_X64
+#  pragma intrinsic (_BitScanReverse64)
+# endif
 # define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE)                \
     do                                                                  \
       {                                                                 \
         unsigned long result;                                           \
-        return MSC_BUILTIN (&result, x) ? result : CHAR_BIT * sizeof x; \
+        if (MSC_BUILTIN (&result, x))                                   \
+          return CHAR_BIT * sizeof x - 1 - result;                      \
+        return CHAR_BIT * sizeof x;                                     \
       }                                                                 \
     while (0)
 #else
@@ -109,8 +113,18 @@ count_leading_zeros_l (unsigned long int x)
 COUNT_LEADING_ZEROS_INLINE int
 count_leading_zeros_ll (unsigned long long int x)
 {
+#if (defined _MSC_VER && !defined __clang__) && !defined _M_X64
+  /* 32-bit MSVC does not have _BitScanReverse64, only _BitScanReverse.  */
+  unsigned long result;
+  if (_BitScanReverse (&result, (unsigned long) (x >> 32)))
+    return CHAR_BIT * sizeof x - 1 - 32 - result;
+  if (_BitScanReverse (&result, (unsigned long) x))
+    return CHAR_BIT * sizeof x - 1 - result;
+  return CHAR_BIT * sizeof x;
+#else
   COUNT_LEADING_ZEROS (__builtin_clzll, _BitScanReverse64,
                        unsigned long long int);
+#endif
 }
 
 #ifdef __cplusplus






reply via email to

[Prev in Thread] Current Thread [Next in Thread]