#!/bin/sh
# Regenerate compiler.

echo "Regenerating compiler on:"
date
echo
echo "Using this 'regen' script:"
cat regen
echo "And these Makefile.in additions:"
cat MAKEFILE_ADDITIONS
echo "================================================="

# Compiler to run for stage 1:
# export CC="icc"


# DEST is master result directory, to contain the source and object dirs
# NOTE: The full directory name that's used for (re)compilation is stored
# inside executables, so for executables to compare as equal, the DEST
# must the same directory name during all (re)compilations to be compared.
export DEST="$HOME/thesis/work"
export PATH="$DEST:$PATH"

# Make 'icc' compiler available on PATH (must install Intel C++ compiler):
export PATH="$PATH:/opt/intel/Compiler/11.0/074/bin/ia32/"

# Don't need to define target, since it's autodetermined as:
# export TARGET=i686-unknown-linux-gnu


# Notes about installation requirements:
# Be sure there's no compiler cache - uninstall it if there is one.
#
# Install package "kernel-headers", make sure it matches kernel.
# We need the icc library for programs compiled by icc to work.
# One approach would be to do this:
#  export LD_LIBRARY_PATH="/opt/intel/Compiler/11.0/074/lib/ia32/"
# But that's annoying.  Instead, as root install icc's libraries on Fedora:
#  echo /opt/intel/Compiler/11.0/074/lib/ia32/ > /etc/ld.so.conf.d/icc.conf 
#  /sbin/ldconfig
#
# If installing tcc, install "alloca86.o" to /usr/local/lib.
# (Not using tcc, so not relevant.)


# Specify version of gcc to recompile:
export VERSION=3.0.4

# Many versions cause problems of one kind or another.
#
# A complication with the Intel C++ compiler is that it wants to
# insert some routines, e.g., _intel_fast_memcpy and _intel_fast_memset,
# that are not expanded to __builtin_memcpy and __builtin_memset.
# There are solutions, e.g., adding -lirc, but adding the right order
# is tricky. More info here:
# http://www.jsw4.net/info/listserv_archives/mysql/04-wk25/msg00062.html
# http://software.intel.com/en-us/forums/intel-c-compiler/topic/52776
# It also needs access to 'libimf' library.
#   build/genattrtab: error while loading shared libraries:
#   libimf.so: cannot open shared object file: No such file or directory
# The option -static-intel slips in the Intel libraries statically.
#
# 2.95.3: gcc 2.95.3's stage2 != stage3, even when compiled by gcc (4.3).
# 3.4.4:  gcc 3.4.4 regenerates via gcc, but icc can't compile it.
#
# 3.0.4: gcc4 and icc can compile, but produce different results, even though
#        stage2 & stage3 are equal in each case.
#
# 3.1.1: icc compiles it, but gcc4 won't recompile it!
#                     Must remake target `read-rtl.o'.
#   gcc -c -DIN_GCC    -g  -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wtraditional -pedantic -Wno-long-long  -DHAVE_CONFIG_H -DGENERATOR_FILE    -I. -I. -I../../gcc-3.1.1/gcc -I../../gcc-3.1.1/gcc/. -I../../gcc-3.1.1/gcc/config -I../../gcc-3.1.1/gcc/../include ../../gcc-3.1.1/gcc/read-rtl.c -o read-rtl.o
#   Putting child 0x095bce10 (read-rtl.o) PID 24638 on the chain.
#   Live child 0x095bce10 (read-rtl.o) PID 24638 
#   In file included from ../../gcc-3.1.1/gcc/read-rtl.c:24:
#   ../../gcc-3.1.1/gcc/rtl.h:125: warning: type of bit-field ‘code’ is a GCC extension
#   ../../gcc-3.1.1/gcc/rtl.h:128: warning: type of bit-field ‘mode’ is a GCC extension
#   ../../gcc-3.1.1/gcc/read-rtl.c: In function ‘fatal_with_file_and_line’:
#   ../../gcc-3.1.1/gcc/read-rtl.c:62: warning: traditional C rejects ISO C style function definitions
#   ../../gcc-3.1.1/gcc/read-rtl.c: In function ‘read_rtx’:
#   ../../gcc-3.1.1/gcc/read-rtl.c:662: error: lvalue required as increment operand
#   Reaping losing child 0x095bce10 PID 24638 
#   make[2]: *** [read-rtl.o] Error 1
#
# 3.2.3: gcc4 won't compile (!).
# 4.0.4: icc won't compile it, gives error:
#   build/genattrtab: error while loading shared libraries: libimf.so:
#   cannot open shared object file: No such file or directory
# 4.1.2: icc won't compile, gives error:
#   build/genattrtab: error while loading shared libraries:
#   libimf.so: cannot open shared object file: No such file or directory
# NOTE: libimf.so errors from icc shouldn't happen. See:
#    http://lists.debian.org/debian-user/2005/07/msg04180.html
#    http://lists.debian.org/debian-user/2005/07/msg04204.html
# The 'icc' command should set LD_LIBRARY_PATH includes /opt.../lib .

# export CC="$HOME/thesis/tcc-trusted/tcc -D HAVE_SYS_ERRLIST -D HAVE_ALLOCA_H -B$HOME/thesis/tcc-trusted -I$HOME/thesis/tcc-trusted"
# export CC="tcc -D HAVE_ALLOCA_H -D PACKAGE=\"gcc\""
# For info on alloca for tcc 0.9.24, see:
# http://www.mail-archive.com/tinycc-devel@nongnu.org/msg01827.html
# For lcc: ftp://ftp.cs.princeton.edu/pub/packages/lcc/
# export CC="tcc -D HAVE_ALLOCA_H -D _ALLOCA_H -D PACKAGE=\"gcc\""
# export CC="icc -static-intel"
# export CC="icc -static"

# export LDFLAGS="-lirc -lsvml"
# export LDFLAGS_FOR_TARGET="-lirc -lsvml"
# export LDFLAGS_FOR_BUILD="-lirc -lsvml"
# export LD="-lirc -lsvml"
# export LD_FOR_TARGET="icc"
# export LD_FOR_BUILD="icc"

# Version 3.0.4 of gcc (in particular, "make compare") uses an obsolete
# format for the "tail" command, e.g, "tail +16c" to skip first 16 characters.
# In modern 'tail's, by default "tail +16c" reads a file named "+16c".
# We work around this by specifying _POSIX2_VERSION; the GNU tail will
# recognize this and use the older semantics.  For more info, see:
# http://www.gnu.org/software/coreutils/faq/coreutils-faq.html
export _POSIX2_VERSION=199209

rm -fr "$DEST"
mkdir "$DEST"
cp -p MAKEFILE_ADDITIONS "$DEST"
cd "$DEST"

untarred=0
TARFILE_PREFIX="$HOME/downloads/gcc-$VERSION"
for file in "${TARFILE_PREFIX}.tar.gz" \
            "${TARFILE_PREFIX}.tar.bz2" \
            "${TARFILE_PREFIX}.tar"
do
  echo "Trying $file"
  if [ -r "$file" ]
  then
    echo "GO!"
    tar xf "$file"
    untarred=1
    break
  fi
done

if [ $untarred -eq 0 ]
then
  echo "Failed to untar $TARFILE_PREFIX"
  exit 1
fi

if [ ! -r "gcc-$VERSION/Makefile.in" ]
then
  echo "Can't read gcc-$VERSION/Makefile.in"
  exit 1
fi

cat MAKEFILE_ADDITIONS >> "gcc-$VERSION/Makefile.in"

mkdir gcc-recompile
cd    gcc-recompile

# Don't use --target; self-compiling, so don't need it.
# No -Dinhibit_link
# ../gcc-2.95.3/configure --target=$TARGET --prefix=$DEST --with-headers=$DEST/include --enable-languages="c"

# By default, will install to prefix of /usr/local/;
# for our testing purposes that's good, since we won't accidentally install it
# and mess up the system configuration:

echo "===== Configuring gcc for recompilation"
../gcc-$VERSION/configure --enable-languages="c"

# OLD APPROACHES THAT DON'T WORK:
# make
# export MAKE="make -d"
# make -d bootstrap

# Can't just "make bootstrap", because it doesn't rebuild libiberty cleanly.
# One approach is to "make bootstrap", unstage twice, rebuild libiberty
# with the new compiler from stage 1, then rebuild stage 2 and 3.
# This does lots of useless work, but didn't require changing the makefile.
# Here are the old instructions:
#
#make bootstrap
#
#echo "UNSTAGING!"
#cd gcc
#make unstage3
#make unstage2
#cd ..
#
#echo "Regenerating libiberty.a using the newly-created gcc:"
#mv libiberty libiberty.first
#cp -pr libiberty.first libiberty
#cd libiberty
#rm *.o *.a
#sed --in-place -e 's/^CC = .*/CC = ..\/gcc\/xgcc -B..\/gcc\/ -isystem ..\/gcc\/include\//' -e 's/CFLAGS = .*/CFLAGS = -g -O2/' Makefile 
#make
#cd ..
#
#cd gcc
#echo "RESTAGING stage2"
#make stage2_build
#echo "RESTAGING stage3"
#make stage3_build


# But instead, for additional control, modify Makefile to permit finer
# control over building process.  This reduces the work, as well as making
# it much clearer exactly what happens.


# "all-bootstrap" builds libiberty using bootstrap compiler (CC)
# (it also builds texinfo, bison, byacc, binutils, gas, ld, zlib if available)

echo "===== make all-bootstrap (makes libiberty)"
make all-bootstrap

# Bootstrap compiler - build gcc using CC compiler.
echo "===== make stage1_build"
make stage1_build

# re-build libiberty, using the stage1 compiler; if other libraries
# get embedded, we'd need to recompile them too:
echo "==== Regenerating libiberty.a using the newly-created gcc:"
# We move and copy so that we can compare the libiberty files compiled by
# the two different compilers (bootstrapping compiler and the stage1 result):
mv libiberty libiberty.first
cp -pr libiberty.first libiberty
cd libiberty
rm *.o *.a  # This isn't necessary, but we do this to make sure we rebuild
# Override CC and CFLAGS so we recompile with the stage1 compiler:
make CC='../gcc/xgcc -B../gcc/ -isystem ../gcc/include/ ' CFLAGS="-g -O2"
cd ..

# This recompiles far too much, and isn't needed here:
# make runtime-libraries

echo "===== make stage2_build"
make stage2_build

# We actually don't need to do stage3 - we'll do stage3 so that
# we can do a "compare" and ensure that stage2 and stage3 are the same.
echo "===== make stage3_build"
make stage3_build

echo "===== make compare (stage2 and stage3 should be identical)"
make compare
echo "(Failure would have printed 'Bootstrap comparison failure')"

echo "===== DONE WITH RECOMPILATION"

# I have developed a number of tools to analyze binary files, e.g.,
# bdiff - "diff" binary files (ordinary "diff" only handles text files)
# cmpar - compares 2 .a archives, to report differences OTHER than
#         timestamps (.a includes timestamps, so direct comparison misleads)
# Useful pre-existing tools include:
# readelf, objdump - report ELF contents
# sha1sum/md5sum - report fingerprints of files (eases comparison)
# strings - report strings inside a binary.  Be sure to use option "--all".
#
# Can see what's going on by running under strace, e.g.,
#   strace -e trace=file  ....
#   Other useful strace options include "-v", "-f", "-e trace=process".


# Here are some other tar files that could be untarred as well; not necessary.
# binutils-2.15.tar.bz2
# gcc-2.95.3.tar.gz
# gdb-6.5.tar.bz2
# glibc-2.2.5.tar.gz
# glibc-linuxthreads-2.2.5.tar.gz
# linux-2.4.26.tar.bz2

############# END ################


