@@ -50,6 +50,7 @@ SUCH DAMAGE.
50
50
#endif
51
51
52
52
#include <MachDeps.h>
53
+ #include "Rts.h"
53
54
54
55
#ifdef WORDS_BIGENDIAN
55
56
#define to_little_endian (x ) __builtin_bswap64(x)
@@ -66,6 +67,29 @@ static inline uint64_t read_uint64(const uint64_t *p) {
66
67
return r ;
67
68
}
68
69
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
+
69
93
static inline int is_valid_utf8_fallback (uint8_t const * const src ,
70
94
size_t const len ) {
71
95
uint8_t const * ptr = (uint8_t const * )src ;
@@ -100,16 +124,16 @@ static inline int is_valid_utf8_fallback(uint8_t const *const src,
100
124
if (results [3 ] == 0 ) {
101
125
ptr += 8 ;
102
126
} else {
103
- ptr += (__builtin_ctzll (results [3 ]) / 8 );
127
+ ptr += (hs_bytestring_ctz64 (results [3 ]) / 8 );
104
128
}
105
129
} else {
106
- ptr += (__builtin_ctzll (results [2 ]) / 8 );
130
+ ptr += (hs_bytestring_ctz64 (results [2 ]) / 8 );
107
131
}
108
132
} else {
109
- ptr += (__builtin_ctzll (results [1 ]) / 8 );
133
+ ptr += (hs_bytestring_ctz64 (results [1 ]) / 8 );
110
134
}
111
135
} else {
112
- ptr += (__builtin_ctzll (results [0 ]) / 8 );
136
+ ptr += (hs_bytestring_ctz64 (results [0 ]) / 8 );
113
137
}
114
138
}
115
139
}
@@ -207,16 +231,16 @@ static inline int is_valid_utf8_sse2(uint8_t const *const src,
207
231
if (result == 0 ) {
208
232
ptr += 16 ;
209
233
} else {
210
- ptr += __builtin_ctzll (result );
234
+ ptr += __builtin_ctz (result );
211
235
}
212
236
} else {
213
- ptr += __builtin_ctzll (result );
237
+ ptr += __builtin_ctz (result );
214
238
}
215
239
} else {
216
- ptr += __builtin_ctzll (result );
240
+ ptr += __builtin_ctz (result );
217
241
}
218
242
} else {
219
- ptr += __builtin_ctzll (result );
243
+ ptr += __builtin_ctz (result );
220
244
}
221
245
}
222
246
}
0 commit comments