[GHC] #10334: __ctzdi2/si2/__clzdi2/si2 unknown symbols in ghc-prim on non-shared libs platform

GHC ghc-devs at haskell.org
Tue Apr 21 11:54:34 UTC 2015


#10334: __ctzdi2/si2/__clzdi2/si2 unknown symbols in ghc-prim on non-shared libs
platform
-------------------------------------+-------------------------------------
              Reporter:  kgardas     |             Owner:  ekmett
                  Type:  bug         |            Status:  new
              Priority:  normal      |         Milestone:
             Component:  Core        |           Version:  7.11
  Libraries                          |  Operating System:  Unknown/Multiple
              Keywords:              |   Type of failure:  None/Unknown
          Architecture:              |        Blocked By:
  Unknown/Multiple                   |   Related Tickets:
             Test Case:              |
              Blocking:              |
Differential Revisions:              |
-------------------------------------+-------------------------------------
 Hello,
 ghc-prim is using GCC's {{{__builtin_ctz(ll)/clz(ll)}}} functions to
 implement functionality to count leading or trailing zeros in provided
 integer type variable.
 The problem with those GCC's builtins is that on platform which does not
 implement either of the operation in ISA, such function call can't be
 replaced by simple ISN, but needs to be replaced by the call to the libgcc
 library which then implements the missing operation in generic C. In ghc-
 prim you can already see a workaround for missing *ll functions on i386.
 The problem is that generic SPARC (v9) does not provide ISNs in its ISA to
 implement those builtins effectively so any call to builtins above is
 replaced by the call to the libgcc. The inserted functions calls are
 {{{__ctzsi2/__ctzdi2/__clzsi2/__clzdi2}}} in this case.
 Unfortunately this makes a lot of GHCi testcases (if not all!) failing
 with the error:
 {{{
 ghc-stage2: /home/karel/src/obj-ghc-sparc-reg_ncg-
 head-2015-04-07-debug/libraries/ghc-prim/dist-install/build/HSghc-
 prim-0.4.0.0-8TmvWUcS1U1IKHT0levwg3.o: unknown symbol `__clzdi2'
 ghc-stage2: unable to load package `ghc-prim-0.4.0.0'
 }}}
 Please note, this happens only on platforms which does not support shared
 libs for GHC. On platforms with GHC shared libs support, ghc-prim is
 shared library which is correctly linked against the libgcc shared library
 and such error does not happen. (example Solaris/i386). Unfortunately we
 can't link ghc-prim*.o with libgcc -- it does effectively nothing so there
 are two solution for this issue IMHO:

 1) on problematic platform implement hs_ctz*/hs_clz* functions in pure C
 without usage of GNU C builtin functions.

 or

 2) enforce linking of shared libgcc with produced application binary. Such
 linking needs to be enforced with -shared-libgcc parameter passed to the
 GNU C in linking step and also by usage of either builtins in the
 application C code (not library code). My experimental code below shows
 that this is possible (tested on Solaris/SPARC). Please note that by
 default on static platform, the static version of libgcc is used and this
 does not help here. Also please note that usage of builtin in let say RTS
 library does not help either. I've tested RtsMain.c. The reason is the
 same like why it's not working in ghc-prim. We can't link *.o or *.a
 against shared libgcc.
 {{{
 diff --git a/compiler/main/DriverPipeline.hs
 b/compiler/main/DriverPipeline.hs
 index c86667c..7c615d1 100644
 --- a/compiler/main/DriverPipeline.hs
 +++ b/compiler/main/DriverPipeline.hs
 @@ -1651,6 +1651,7 @@ mkExtraObjToLinkIntoBinary dflags = do
     | gopt Opt_NoHsMain dflags = Outputable.empty
     | otherwise = vcat [
        text "#include \"Rts.h\"",
 +      text "#include <stdio.h>",
        text "extern StgClosure ZCMain_main_closure;",
        text "int main(int argc, char *argv[])",
        char '{',
 @@ -1662,6 +1663,10 @@ mkExtraObjToLinkIntoBinary dflags = do
           Just opts -> ptext (sLit "    __conf.rts_opts= ") <>
                          text (show opts) <> semi,
        text " __conf.rts_hs_main = rtsTrue;",
 +      text " printf(\"ctz(argc): %d\\n\", __builtin_ctz(argc));",
        text " return hs_main(argc,argv,&ZCMain_main_closure,__conf);",
        char '}',
        char '\n' -- final newline, to keep gcc happy
 }}}
 of course this is just a proof of concept. For real code we would need
 some place to save the result of the called builtin to prevent GCC from
 removing the call as an unused value. I guess one added value in
 {{{__conf}}} just for this case should do the job here.

 I'm free to implement either of those two solutions or even completely
 different one, I just need to know your preference in this case.

 BTW: I'm ccing people from #9340 which looks really related to this issue.
 If you are not interested in this issue discussion, please un-cc yourself.

 Thanks!
 Karel
 PS: as this is IMHO general issue, I'm not setting SPARC/Solaris as
 Architecture/OS here...

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10334>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list