Skip to content

Commit 514f7d9

Browse files
authored
Avoid __builtin_ctzll on some platforms (#604)
Fixes #601
1 parent bb31ef1 commit 514f7d9

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

cbits/is-valid-utf8.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
6993
static 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

Comments
 (0)