diff options
author | Herbert Valerio Riedel <hvr@gnu.org> | 2014-08-17 12:19:45 +0200 |
---|---|---|
committer | Herbert Valerio Riedel <hvr@gnu.org> | 2014-08-17 13:09:42 +0200 |
commit | 6375934bfe64ca15eb215327629f9f07a185377a (patch) | |
tree | 227b943f81434abc23fbb410f970b939bab61248 /libraries | |
parent | 53cc943a62d790e5381133f95fd1994cd7a805aa (diff) | |
download | haskell-6375934bfe64ca15eb215327629f9f07a185377a.tar.gz |
Workaround GCC `__ctzdi2` intrinsic linker errors
On Linux/i386 the 64bit `__builtin_ctzll()` instrinsic doesn't get
inlined by GCC but rather a short `__ctzdi2` runtime function is
inserted when needed into compiled object files.
This causes failures for the four test-cases
TEST="T8639_api T8628 dynCompileExpr T5313"
with error messages of the kind
dynCompileExpr: .../libraries/ghc-prim/dist-install/build/libHSghcpr_BE58KUgBe9ELCsPXiJ1Q2r.a: unknown symbol `__ctzdi2'
dynCompileExpr: dynCompileExpr: unable to load package `ghc-prim'
This workaround forces GCC on 32bit x86 to to express `hs_ctz64` in
terms of the 32bit `__builtin_ctz()` (this is no loss, as there's no
64bit BSF instruction on i686 anyway) and thus avoid the problematic
out-of-line runtime function.
Note: `__builtin_ctzll()` is used since
e0c1767d0ea8d12e0a4badf43682a08784e379c6 (re #9340)
Diffstat (limited to 'libraries')
-rw-r--r-- | libraries/ghc-prim/cbits/ctz.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/libraries/ghc-prim/cbits/ctz.c b/libraries/ghc-prim/cbits/ctz.c index cc420b9acd..f68f628bd3 100644 --- a/libraries/ghc-prim/cbits/ctz.c +++ b/libraries/ghc-prim/cbits/ctz.c @@ -31,7 +31,23 @@ hs_ctz32(StgWord x) StgWord hs_ctz64(StgWord64 x) { -#if SIZEOF_UNSIGNED_LONG == 8 +#if defined(__GNUC__) && defined(i386_HOST_ARCH) + /* On Linux/i386, the 64bit `__builtin_ctzll()` instrinsic doesn't + get inlined by GCC but rather a short `__ctzdi2` runtime function + is inserted when needed into compiled object files. + + This workaround forces GCC on 32bit x86 to to express `hs_ctz64` in + terms of the 32bit `__builtin_ctz()` (this is no loss, as there's no + 64bit BSF instruction on i686 anyway) and thus avoid the problematic + out-of-line runtime function. + */ + + if (!x) return 64; + + return ((uint32_t)x ? __builtin_ctz((uint32_t)x) + : (__builtin_ctz(x >> 32) + 32)); + +#elif SIZEOF_UNSIGNED_LONG == 8 return x ? __builtin_ctzl(x) : 64; #elif SIZEOF_UNSIGNED_LONG_LONG == 8 return x ? __builtin_ctzll(x) : 64; |