HRC uses GHC as a frontend to compile user programs or libraries to an intermediate representation (IR) called external core before it translates external core to HRC's set of internal IRs and eventually compiles down to binary via an external C compiler.
Moreover, GHC and its libraries have to be (slightly) patched in order to
produce external cores that is suitable for HRC to consume, mostly to remove
GHC-specific runtime references, and to insert additional primitives required
for immutable array and so on . Also, HRC has runtime support for arbitrary
precision integers, so GHC's integer-gmp
library is no longer compatible.
We've implemented a new library based on integer-simple
to integrate GHC's
big integer with HRC's.
However, recent GHC versions have dropped the support for external core (due to lack of maintainers), and therefore, HRC is stuck with an older version of GHC 7.6.3.
Because HRC does not support GHC-specific runtime calls or primitives, the
patched GHC 7.6 will not produce code containing them. So it does not work 100%
as a full compiler by itself. In particular, if you compile anything with this
patched compiler, the result binary will most likely fail to run. So you should
not install it to standard system location, but rather a place that is
isolated from other GHC installations. We'll refer to this location of your
choice as ${PREFIX}
in this guide.
Also, this guide only applies to x86 64-bit Linux installation.
First of all, you'll need an even older version to bootstrap GHC 7.6.3. For this purpose, we used GHC 7.4.2. You can either find a distro supported binary package that you can install on your own, or use Nix to get one.
Besides GHC 7.4.2, we also need a working binary of happy and alex. They do not have to be older versions, or even compiled by GHC 7.4.2. In theory, any working version that you can find for your distro should work just fine.
The following steps assumes we use bash
and we are in flrc
top directory,
otherwise the patches
directory needs to be spelled out in full path to refer
to flrc/patches
.
git clone http://git.haskell.org/ghc.git
cd ghc
git checkout ghc-7.6
patch -p1 < ../patches/ghc-7.6-hrc.patch
cp mk/build.mk.hrc mk/build.mk
perl sync-all --dph get
perl sync-all checkout ghc-7.6
pushd libraries/random && git checkout -b ghc-7.6 random-1.0.1.1-release && popd
pushd libraries/primitive && git checkout -b ghc-7.6 75c3379b && popd
pushd libraries/vector && git checkout -b ghc-7.6 c4c5a740 && popd
rm -rf libraries/dph
for libname in Cabal base integer-simple primitive vector; do
pushd libraries/${libname} && patch -p1 < ../../../patches/ghc-${libname}-7.6-hrc.patch && popd
done
perl boot
RELEASE=yes ./configure --prefix=${PREFIX}
make
make install
We usually prefer not to have the patched GHC in $PATH
, so the way
we run hrc
is as follows:
PATH=${PREFIX}/bin:$PATH hrc ...
or make
as:
PATH=${PREFIX}/bin:$PATH make
But you can set ${PREFIX}/bin
in $PATH
and save typing a few words.
The patched GHC comes with patched Cabal support that installs
the external core required by HRC along side the usual installation
of a Haskell package. The most convenient way to do this is with
the usual cabal
command, and any recent cabal
binary (from
cabal-install package) that comes with your
distro should work, even those that came with newer Haskell
Platform or installed from Stack.
To compile a package with HRC using cabal
, we have to add
a few extra flags as follows:
PATH=${PREFIX}/bin:$PATH cabal install --global \
--cabal-lib-version=1.16.1 \
--prefix=${PREFIX} \
--package-db=${PREFIX}/lib/ghc-7.6.3/lib/package.conf.d \
[package name]
This is because we need to instruct cabal to specifically choose a Cabal
library version of 1.16.1, and install to the DB files of our patched GHC 7.6.3,
instead of to the default user location such as ${HOME}/.cabal
. Please note
that the file path for the --package-db=
option might be different on your
machine, so you need to make sure the DB directory package.conf.d
it refers to
actually exists.
For example, we can use cabal
to install parsec-3.1.1
. We choose this
particular version because later parsec has a lot of extra dependencies, which
are not fully tested with HRC.
PATH=${PREFIX}/bin:$PATH cabal install --global \
--cabal-lib-version=1.16.1 --prefix=... --package-db=... \
parsec-3.1.1
For another example, we can install a patched Repa library for HRC.
Assume we are in flrc
top directory. We choose version 3.2.2.2 because later
versions will suck in a later version of vector, breaking the required
dependence on our patched vector library installed together with the patched
GHC.
curl https://hackage.haskell.org/package/repa-3.2.2.2/repa-3.2.2.2.tar.gz|tar zxf -
cd repa-3.2.2.2
patch -p1 < ../patches/ghc-repa-3.2.2.2-hrc.patch
PATH=${PREFIX}/bin:$PATH cabal install --global \
--cabal-lib-version=1.16.1 --prefix=... --package-db=...
People having trouble compiling with an existing cabal tool should double check
if there is any cached setup
program in ${HOME}/.cabal
directory, and if
so, please remove them and try again.
With the modified Repa installed, we can move on to compiling the benchmark programs from flrc-benchmarks. These Haskell programs are discussed in detail in the Measuring the Haskell Gap paper.
cd flrc-benchmarks
PATH=${PREFIX}/bin:$PATH cabal install --dependencies-only --global \
--cabal-lib-version=1.16.1 --prefix=... --package-db=...
The above command only installs dependencies. To actually compile the programs
with HRC, we'll instead use make
, either in the benchmarks directory, or in
each benchmark's own directory:
PATH=${PREFIX/bin:$PATH make
The verbosity setting of compiling these benchmarks are set to be 0, which
actually means some minimal information about the compilation process is
outputted. The last step in this compilation process is to use tools pilicl
and pilink' from
flrc-libto compile Pillar programs to C, and then use a C/C++ compiler (GCC by default) to compile and link to binary. If you want to use ICC, you can run
make` like this:
HRC_CC=icc PATH=${PREFIX/bin:$PATH make
For now, HRC can be used directly to compile haskell programs. There is no existing integration of choosing HRC as an alternative compiler when using cabal. Our patched Cabal package for GHC 7.6 is only intended to install GHC's external core together during package install, and to help with native library linking.
To run the benchmarks, go to each directory, and run the executables like this:
./<executable> @PPiler maxHeap 1024 --
The default settings for these benchmarks usually requires bigger memory, and
hence we use the @PPiler
runtime options, and sometimes increasing the
memory beyond 1024M also helps.
All benchmarks should also compile and install just fine with a regular GHC, although they were only tested with GHC 7.6 and older version of Repa.
If you use Nix, here is how you can spawn a sub-shell with needed tools and packages to work with all (the compilation) of FLRC-LIB, FLRC and HRC:
nix-shell -p git curl wget m4 autoconf automake gcc nasm yacc flex libtool gmp \
mlton pkgconfig which perl haskell.compiler.ghc742 haskell.packages.ghc742.happy \
haskell.packages.ghc742.alex cabal-install