GHC haskell support for arm64 and ppc64el

Colin Watson cjwatson at ubuntu.com
Fri Apr 4 16:04:18 UTC 2014


On Thu, Mar 27, 2014 at 12:28:54PM +0000, Colin Watson wrote:
> On Wed, Mar 26, 2014 at 10:34:04AM +0000, Gianfranco Costamagna wrote:
> >    Seems that fedora is bootstrapping ghc for ppc64
> >    http://pkgs.fedoraproject.org/cgit/ghc.git/log/?h=epel7
> > 
> >    Revert "bootstrap from ghc-7.4.2-11.2.fc19 x86_64 and ppc64"epel7
> >    use cpio --make-directories
> >    install ghc-base.ppc64 on ppc64
> >    bootstrap from ghc-7.4.2-11.2.fc19 x86_64 and ppc64
> >    do you think it is enough for trying in ubuntu?
> 
> ppc64 (i.e. big-endian) isn't the same as ppc64el (i.e. little-endian).
> The architecture isn't endian-switchable in userspace.  So no, I'm
> afraid that doesn't help much; it still leaves us bootstrapping from
> scratch.

OK, so I need to go round a couple more build passes to get everything
into a coherent state; but after a good deal of back-and-forward with
Karel (thanks!) I now have a fully-bootstrapped GHC 7.8 on arm64, and
based on that I've been able to get a stage1 GHC 7.6 and am most of the
way to stage2.  I had to disable profiling in my first pass, but I'm
hopeful that that's due to bootstrapping hacks and I'll be able to do a
more normal build next time round.  At this point there is a pretty good
chance that I'll be able to get arm64 GHC bootstrapped in the archive in
time for 14.04.


ppc64el is a different matter.  In that case I can't even get to a
working cross-compiled stage2: the compiler segfaults after child
processes return.  I've asked for help from toolchain engineers who know
their way around ppc64el, but I don't know what their schedules are like
and so I don't know when somebody will be available to help.  In the
absence of help, a bootstrap is not likely to happen.  For the record,
here's the report I sent with my procedure so far:

  1) Bootstrap a dedicated trusty chroot on a reasonably fast amd64
     system (e.g. with mk-sbuild).  Then, in that chroot:
  2) sudo apt-get build-dep ghc
  3) sudo dpkg --add-architecture ppc64el
  4) Make /etc/apt/sources.list look like this (modulo mirroring):
     deb [arch=amd64] http://archive.ubuntu.com/ubuntu trusty main restricted universe multiverse
     deb [arch=ppc64el] http://ports.ubuntu.com/ubuntu-ports trusty main restricted universe multiverse
     deb-src http://archive.ubuntu.com/ubuntu trusty main restricted universe multiverse
  5) sudo apt-get update
  6) sudo apt-get install libc6:ppc64el gcc-powerpc64le-linux-gnu
  7) Prepare ~/ppc64el-sysroot by creating it, changing to it, and
     running:
     apt-get download libncurses5-dev:ppc64el libtinfo-dev:ppc64el libffi-dev:ppc64el
     for x in *.deb; do dpkg -x "$x" .; done
     mv usr/include/powerpc64le-linux-gnu/* usr/include/
     rmdir usr/include/powerpc64le-linux-gnu
  8) Create ~/powerpc64le-linux-gnu-gccsysroot with the following
     contents:
     #! /bin/sh
     /usr/bin/powerpc64le-linux-gnu-gcc --sysroot="$HOME/ppc64el-sysroot" "$@"
  9) Get hold of the ghc-7.8 upstream git branch using something along
     the lines of
     https://ghc.haskell.org/trac/ghc/wiki/Building/GettingTheSources.
     Put it in ~/ghc-ppc64el (it's simplest for this to be near the top
     of your home directory to make things easier later).
 10) cd ~/ghc-ppc64el
 11) Copy mk/build.mk.sample to mk/build.mk and uncomment "BuildFlavour
     = quick-cross"; find the 'ifeq "$(BuildFlavour)" "quick-cross"'
     block, and in that, remove the three -fllvm options and comment out
     "Stage1Only = YES".
 12) Download libffi-3.0.13.tar.gz into libffi-tarballs/ and remove
     libffi-3.0.11.tar.gz from that directory.
 13) Apply ghc-ppc64el.patch attached to this bug (most of this is from
     the current Ubuntu libffi source package; the rts bit is my attempt
     to get started on ELF ABI v2 porting in GHC itself).
 14) perl boot
 15) ./configure --target=powerpc64le-linux-gnu --with-gcc="$HOME/powerpc64le-linux-gnu-gccsysroot" --enable-unregisterised
 16) make -j<whatever>.  If this works then it should finish up with an
     exec format error trying to execute ghc-stage2, which you can
     ignore.  If not, figure out what's wrong and fix it.
 17) rsync all this over to an Ubuntu ppc64el system, making sure that
     it goes in exactly the same path on the other side.  On the ppc64el
     system, in a chroot if necessary:
 18) Install all the build-dependencies of the ghc source package (as
     shown by "apt-get source ghc") except for ghc and hscolour.
 19) Edit ~/ghc-ppc64el/inplace/lib/settings and change "C compiler
     command" to "/usr/bin/gcc", "ld command" to "/usr/bin/ld", and "ar
     command" to "/usr/bin/ar".
 20) In ~/ghc-ppc64el/utils/unlit, run "gcc -o ../../inplace/lib/unlit
     unlit.c" to replace the amd64 binary previously in that location.
 21) In ~/ghc-ppc64el/bindisttest, run "LC_ALL=C.UTF-8
     ../inplace/lib/bin/ghc-stage2 +RTS -V0 -RTS
     -B$HOME/ghc-ppc64el/inplace/lib -v4 --make HelloWorld.lhs" (I've
     expanded this out a bit so that it's in a form that you can run gdb
     on it).

What I'm seeing at this point is that the compiler gets some way through
(so Haskell code is clearly at least somewhat working, which you can
also see by running "../inplace/bin/ghc-stage1 --make HelloWorld.lhs" on
the amd64 side and executing the resulting HelloWorld binary on
ppc64el), but I get a segfault immediately after its first child process
(unlit) returns.  If I manually run unlit to process HelloWorld.lhs into
HelloWorld.hs and try to compile that instead, then it instead fails
immediately after its readelf child process returns, so I think this
probably has something to do with signal handling or possibly with
foreign function calls.  This is reminiscent of
https://ghc.haskell.org/trac/ghc/ticket/8134 but clearly not quite the
same thing.  Getting a stack trace out of GHC-compiled code is
nigh-impossible as it effectively implements its own calling convention
which is not obliged to have anything particular to do with the normal
platform ABI and tends to use tail calls for everything.  The best I've
been able to do is to use "handle SIGCHLD stop" then "run" in gdb - the
"+RTS -V0 -RTS" bit is important here as it disables the interval timer
so that you can usefully single-step - and "stepi" until it crashes
shortly after leaving runInteractiveProcess, in a generated function
that for me is called "c8z6_entry".  I *think* this corresponds to
something in
libraries/process/dist-install/build/System/Process/Internals.o.

-- 
Colin Watson                                       [cjwatson at ubuntu.com]




More information about the Ubuntu-devel-discuss mailing list