janestreet / base

Standard library for OCaml
MIT License
860 stars 125 forks source link

_BitScanForward64 intrinsic is not available on x86 #72

Open db4 opened 5 years ago

db4 commented 5 years ago

This function

https://github.com/janestreet/base/blob/aee79da69b1dd93870cbae78794b2679dfba3dfc/src/int_math_stubs.c#L25

is not supported by 32-bit MSVC (see https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64). So I get a link error.

db4 commented 5 years ago

The following patch should fix the bug:

--- a/src/int_math_stubs.c  2019-02-25 13:55:12.000000000 +0300
+++ b/src/int_math_stubs.c  2019-04-04 18:29:43.760643700 +0300
@@ -12,17 +12,24 @@
 #define __builtin_popcountll __popcnt64
 #define __builtin_popcount   __popcnt

-static uint32_t __inline __builtin_clz(uint32_t x)
+static int __inline __builtin_clz(uint32_t x)
 {
   int r = 0;
   _BitScanForward(&r, x);
   return r;
 }

-static uint64_t __inline __builtin_clzll(uint64_t x)
+static int __inline __builtin_clzll(uint64_t x)
 {
   int r = 0;
+#ifdef _WIN64
   _BitScanForward64(&r, x);
+#else
+  if (!_BitScanForward(&r, (uint32_t)x) &&
+      _BitScanForward(&r, (uint32_t)(x>>32))) {
+    r += 32;
+  }
+#endif
   return r;
 }