@@ -50,6 +50,7 @@ SUCH DAMAGE.
5050#endif
5151
5252#include <MachDeps.h>
53+ #include "Rts.h"
5354
5455#ifdef WORDS_BIGENDIAN
5556#define to_little_endian (x ) __builtin_bswap64(x)
@@ -66,6 +67,29 @@ static inline uint64_t read_uint64(const uint64_t *p) {
6667 return r ;
6768}
6869
70+ // stand-in for __builtin_ctzll, used because __builtin_ctzll can
71+ // cause runtime linker issues for GHC in some exotic situations (#601)
72+ //
73+ // See also these ghc issues:
74+ // * https://gitlab.haskell.org/ghc/ghc/-/issues/21787
75+ // * https://gitlab.haskell.org/ghc/ghc/-/issues/22011
76+ static inline int hs_bytestring_ctz64 (const uint64_t x ) {
77+ // These CPP conditions are taken from ghc-prim:
78+ // https://gitlab.haskell.org/ghc/ghc/-/blob/73b5c7ce33929e1f7c9283ed7c2860aa40f6d0ec/libraries/ghc-prim/cbits/ctz.c#L31-57
79+ // credit to Herbert Valerio Riedel, Erik de Castro Lopo
80+ #if defined(__GNUC__ ) && (defined(i386_HOST_ARCH ) || defined(powerpc_HOST_ARCH ))
81+ uint32_t xhi = (uint32_t )(x >> 32 );
82+ uint32_t xlo = (uint32_t ) x ;
83+ return xlo ? __builtin_ctz (xlo ) : 32 + __builtin_ctz (xhi );
84+ #elif SIZEOF_UNSIGNED_LONG == 8
85+ return __builtin_ctzl (x );
86+ #elif SIZEOF_UNSIGNED_LONG_LONG == 8
87+ return __builtin_ctzll (x );
88+ #else
89+ # error no suitable __builtin_ctz() found
90+ #endif
91+ }
92+
6993static inline int is_valid_utf8_fallback (uint8_t const * const src ,
7094 size_t const len ) {
7195 uint8_t const * ptr = (uint8_t const * )src ;
@@ -100,16 +124,16 @@ static inline int is_valid_utf8_fallback(uint8_t const *const src,
100124 if (results [3 ] == 0 ) {
101125 ptr += 8 ;
102126 } else {
103- ptr += (__builtin_ctzll (results [3 ]) / 8 );
127+ ptr += (hs_bytestring_ctz64 (results [3 ]) / 8 );
104128 }
105129 } else {
106- ptr += (__builtin_ctzll (results [2 ]) / 8 );
130+ ptr += (hs_bytestring_ctz64 (results [2 ]) / 8 );
107131 }
108132 } else {
109- ptr += (__builtin_ctzll (results [1 ]) / 8 );
133+ ptr += (hs_bytestring_ctz64 (results [1 ]) / 8 );
110134 }
111135 } else {
112- ptr += (__builtin_ctzll (results [0 ]) / 8 );
136+ ptr += (hs_bytestring_ctz64 (results [0 ]) / 8 );
113137 }
114138 }
115139 }
@@ -207,16 +231,16 @@ static inline int is_valid_utf8_sse2(uint8_t const *const src,
207231 if (result == 0 ) {
208232 ptr += 16 ;
209233 } else {
210- ptr += __builtin_ctzll (result );
234+ ptr += __builtin_ctz (result );
211235 }
212236 } else {
213- ptr += __builtin_ctzll (result );
237+ ptr += __builtin_ctz (result );
214238 }
215239 } else {
216- ptr += __builtin_ctzll (result );
240+ ptr += __builtin_ctz (result );
217241 }
218242 } else {
219- ptr += __builtin_ctzll (result );
243+ ptr += __builtin_ctz (result );
220244 }
221245 }
222246 }
0 commit comments