Files
mercury/tools/binary
Zoltan Somogyi 4fe703c7b9 Implement a more cache-friendly translation of lookup switches.
Estimated hours taken: 8
Branches: main

Implement a more cache-friendly translation of lookup switches. Previously,
for a switch such as the one in

	:- pred p(foo::in, string::out, bar::out, float::out) is semidet.

	p(d, "four", f1, 4.4).
	p(e, "five", f2, 5.5).
	p(f, "six", f4("hex"), 6.6).
	p(g, "seven", f5(77.7), 7.7).

we generated three static cells, one for each argument, and then indexed
into each one in turn to get the values of HeadVar__2, HeadVar__3 and
HeadVar__4. The different static cells each represent a column here.
Each of the loads accessing the columns will access a different cache block,
so with this technique we expect to get as many cache misses as there are
output variables.

This diff changes the code we generate to use a vector of static cells
where each cell represents a row. The assignments to the output variables
will now access the different fields of a row, which will be next to each
other. We thus expect only one cache miss irrespective of the number of output
variables, at least up to the number of variables that actually fit into one
cache block.

compiler/global_data.m:
	Provide a mechanism for creating not just single (scalar) static cells,
	but arrays (vectors) of them.

compiler/lookup_switch.m:
	Use the new mechanism to generate code along the lines described above.

	Put the information passed between the two halves of the lookup switch
	implementation (detection and code generation) into an opaque data
	structure.

compiler/switch_gen.m:
	Conform to the new interface of lookup_switch.m.

compiler/ll_pseudo_type_info.m:
compiler/stack_layout.m:
compiler/string_switch.m:
compiler/unify_gen.m:
compiler/var_locn.m:
	Conform to the change to global_data.m.

compiler/llds.m:
	Define the data structures for holding vectors of static cells. Rename
	the function symbols we used to use to refer to static cells to make
	clear that they apply to scalar cells only. Provide similar mechanisms
	for representing static cell vectors and references to them.

	Generalize heap_ref heap references to allow the index to be computed
	at runtime, not compile time. For symmetry's sake, do likewise
	for stack references.

compiler/llds_out.m:
	Add the code required to write out static cell vectors.

	Rename decl_ids to increase clarity and avoid ambiguity.

compiler/code_util.m:
compiler/exprn_aux.m:
	Modify code that traverses rvals to now also traverse the new rvals
	inside memory references.

compiler/name_mangle.m:
	Provide the prefix for static cell vectors.

compiler/layout_out.m:
compiler/rtti_out.m:
compiler/opt_debug.m:
	Conform to the change to data_addrs and decl_ids.

compiler/code_info.m:
	Provide access to the new functionality in global_data.m, and conform
	to the change to llds.m.

	Provide a utility predicate needed by lookup_switch.m.

compiler/hlds_llds.m:
	Fix the formatting of some comments.

tools/binary:
tools/binary_step:
	Fix the bit rot that has set in since they were last used (the rest
	of the system has changed quite a lot since then). I had to do so
	to debug one part of this change.

tests/hard_coded/dense_lookup_switch2.{m,exp}:
tests/hard_coded/dense_lookup_switch3.{m,exp}:
	New test cases to exercise the new algorithm.

tests/hard_coded/Mmakefile:
	Enable the new test cases, as well as an old one (from 1997!)
	that seems never to have been enabled.
2006-03-30 02:46:08 +00:00

786 lines
21 KiB
Bash
Executable File

#!/bin/sh
#
# vim: ts=4 sw=4 et
#
# This script finds miscompiled procedures.
#
# Given a stage2 directory that works (stage2.ok) and one that doesn't
# (stage2.bad), both of which must have their object files, this script
# uses binary search to try to find in stage2.bad first the C source file
# and then the module within that C source file that, when put together
# with everything else from the stage2.ok directory, still causes the
# compiler to fail.
#
# If the bad C source file has different numbers of modules in the bad and ok
# versions, then the script stops after identifying only the file.
#
# The test for the composite stage2 compiler is either bootstrap checking
# (the default), some initial part of bootstrap checking (making dependencies,
# compiling the library), the successful execution of all the test cases in
# one or more subdirectories of the tests directory, or the successful execution
# of a single command.
usage="\
Usage: $0 [options]
Options:
-b-, --no-bootcheck
Do not perform a bootcheck; check only the tests directory
or the single command.
-c, --compile-only
Check the successful creation of the stage3 .c files,
but do not compare stage2.ok and stage3.
-C, --compare-to-bad
Compile stage3 using the parameter settings in the stage2.bad
directory, and compare stage3 to stage2.bad, not stage2.ok.
-d, --dependency-only
Make dependencies for stage3 only. Do not compile stage3.
-D <dirname>, --dir <dirname>
Confine the search to one directory, library, mdbcomp, analysis
or compiler. (Usually useful only after a previous search.)
-f <modulename>, --file <modulename>
Confine the search to the named file(s).
(Usually useful only after a previous search.)
-h, --help
Display this usage message.
-j <num-jobs>, --jobs <num-jobs>
Run using <num-jobs> different parallel processes.
-l, --library-only
Check the successful creation of the stage3 .c files in the
library, but do not compile the compiler directory.
-m <mmake-args>, --mmake-args <mmake-args>
Pass <mmake-args> as options to \`mmake'.
-n, --negative-search
Look for the module that suppresses the bug, not causes it.
-o <filename>, --output-file <filename>
Output results to <filename>.
-r, --copy-runtime
Copy the runtime directory instead of linking it.
This is necessary if the test uses a compilation model option
that differs from the one used in the main runtime directory.
-s <command>, --single-command <command>
Execute the given command using each constructed compiler.
-t <testdir>, --test-dir <testdir>
Execute runtests from the named subdirectory of tests.
"
# If you change this, you will also need to change the files indicated
# in scripts/c2init.in.
STD_LIB_NAME=mer_std
set -x
bootcheck=""
compile_only=""
dependency_only=""
library_only=""
jfactor=
mmake_opts=""
outfile=""
copy_runtime=false
single_command=""
testdirs=""
negative=false
alldirs=""
allmodules=""
compare_to_bad=""
basis="ok"
while [ $# -gt 0 ]; do
case "$1" in
-b-|--no-bootcheck)
bootcheck="-b-" ;;
-c|--compile-only)
compile_only="-c" ;;
-C|--compare-to-bad)
compare_to_bad="-C"
basis="bad" ;;
-d|--dependency-only)
dependency_only="-d" ;;
-D|--dir)
alldirs="$2"; shift ;;
-D*)
alldirs="` expr $1 : '-d\(.*\)' `"; ;;
-f|--file)
allmodules="$allmodules $2"; shift ;;
-f*)
allmodules="$allmodules ` expr $1 : '-f\(.*\)' `"; ;;
-h|--help)
echo "$usage"
exit 0 ;;
-j|--jobs)
jfactor="-j$2"; shift ;;
-j*)
jfactor="-j` expr $1 : '-j\(.*\)' `" ;;
--jobs*)
jfactor="--jobs` expr $1 : '--jobs\(.*\)' `" ;;
-l|--library-only)
library_only="-l" ;;
-m|--mmake)
mmake_opts="$mmake_opts $2"; shift ;;
-n|--negative-search)
negative=true ;;
-o|--output-file)
outfile="-o $2"; shift ;;
-o*)
outfile="-o ` expr $1 : '-o\(.*\)' `"; ;;
-r|--copy-runtime)
copy_runtime=true ;;
-s|--single-command)
single_command="$2"; shift ;;
-s*)
single_command=` expr "$1" : '-s\(.*\)' ` ;;
--single-command*)
single_command=` expr "$1" : '--single-command\(.*\)' ` ;;
-t|--test-dir)
testdirs="$testdirs -t$2"; shift ;;
-t*)
testdirs="$testdirs ` expr $1 : '-t\(.*\)' `" ;;
-*)
echo "$0: unknown option \`$1'" 1>&2
echo "$usage" 1>&2
exit 1 ;;
*)
echo "$usage" 1>&2
exit 1 ;;
esac
shift
done
if "$negative"
then
base=bad
trial=ok
expected=failure
else
base=ok
trial=bad
expected=success
fi
if test -d stage2.ok -a -d stage2.bad
then
echo "stage2.ok and stage2.bad both present"
else
echo "at least one of stage2.ok and stage2.bad is missing"
exit 1
fi
root=`/bin/pwd`
trueroot=`echo $root | sed '
s:/mount/munkora/mercury:/home/mercury:
s:/mount/munkora/home/mercury:/home/mercury:
s:/mount/munkora/clp/mercury:/home/mercury:'`
PATH=$root/tools:$PATH
export PATH
if test "$RMSTAGECMD" = ""
then
RMSTAGECMD="/bin/rm -fr"
fi
echo "starting at `date`"
for dir in $base $trial
do
for subdir in library mdbcomp analysis compiler
do
case $subdir in
library) example_o=builtin.o ;;
mdbcomp) example_o=mdbcomp.prim_data.o ;;
analysis) example_o=analysis.o ;;
compiler) example_o=check_hlds.cse_detection.o ;;
esac
if test -f stage2.$dir/$subdir/$example_o
then
echo "stage2.$dir/$subdir seems to have its object files"
else
echo "reconstructing object files in stage2.$dir/$subdir"
cd stage2.$dir/$subdir
mmake
fi
done
done
echo "starting binary at `date`"
set +x
[ -d stage2 ] || mkdir stage2
$RMSTAGECMD $trueroot/stage2/compiler < /dev/null &
$RMSTAGECMD $trueroot/stage2/library < /dev/null &
wait
$RMSTAGECMD $trueroot/stage2/* < /dev/null
echo linking stage 2... 1>&2
cd stage2
ln -s $root/main.c .
mkdir compiler
cd compiler
ln -s $root/compiler/[a-h]*.m .
ln -s $root/compiler/[i-o]*.m .
ln -s $root/compiler/[p-s]*.m .
ln -s $root/compiler/[t-z]*.m .
ln -s $root/compiler/*.pp .
cp $root/compiler/Mmake* .
cp $root/compiler/Mercury* .
cp $root/compiler/*FLAGS* .
cp $root/compiler/.mgnuc* .
cd $root/stage2
mkdir library
cd library
ln -s $root/library/[a-l]*.m .
ln -s $root/library/[m-z]*.m .
ln -s $root/library/*.init .
cp $root/library/print_extra_inits .
cp $root/library/Mmake* .
cp $root/library/Mercury* .
cp $root/library/*FLAGS* .
cp $root/library/.mgnuc* .
cd $root/stage2
mkdir mdbcomp
cd mdbcomp
ln -s $root/mdbcomp/*.m .
ln -s $root/mdbcomp/*.init .
cp $root/mdbcomp/Mmake* .
cp $root/mdbcomp/Mercury* .
cp $root/mdbcomp/*FLAGS* .
cp $root/mdbcomp/.mgnuc* .
cd $root/stage2
mkdir analysis
cd analysis
ln -s $root/analysis/*.m .
ln -s $root/analysis/*.init .
cp $root/analysis/Mmake* .
cp $root/analysis/Mercury* .
cp $root/analysis/*FLAGS* .
cp $root/analysis/.mgnuc* .
cd $root/stage2
if "$copy_runtime"
then
mkdir runtime
cd runtime
ln -s $root/runtime/*.h .
ln -s $root/runtime/*.c .
ln -s $root/runtime/*.in .
ln -s $root/runtime/machdeps .
cp $root/runtime/Mmake* .
cd $root/stage2
else
# $root/runtime may be in a different grade from the stage2 directories.
ln -s $root/stage2.ok/runtime .
fi
ln -s $root/boehm_gc .
ln -s $root/browser .
ln -s $root/trace .
ln -s $root/doc .
ln -s $root/scripts .
ln -s $root/util .
ln -s $root/profiler .
ln -s $root/deep_profiler .
ln -s $root/tools .
ln -s $root/conf* .
ln -s $root/aclocal.m4 .
ln -s $root/VERSION .
ln -s $root/Mercury.options .
ln -s $root/.*.in .
rm -f config*.log
cp $root/stage2.ok/Mmake* .
cd $root
# We don't copy the .d files. This prevents mmake from trying to remake any
# of the .c and .o files, which we provide in the form they should be used.
# cp stage2.ok/library/*.d stage2/library
cp stage2.ok/library/*.dep stage2/library
cp stage2.ok/library/*.dv stage2/library
cp stage2.ok/library/*.int3 stage2/library
cp stage2.ok/library/*.date3 stage2/library
cp stage2.ok/library/*.int stage2/library
cp stage2.ok/library/*.int2 stage2/library
cp stage2.ok/library/*.date stage2/library
cp stage2.ok/library/*.opt stage2/library
cp stage2.ok/library/*.optdate stage2/library
cp stage2.ok/library/*.trans_opt stage2/library
cp stage2.ok/library/*.trans_opt_date stage2/library
cp stage2.ok/library/*.mh stage2/library
# cp stage2.ok/mdbcomp/*.d stage2/mdbcomp
cp stage2.ok/mdbcomp/*.dep stage2/mdbcomp
cp stage2.ok/mdbcomp/*.dv stage2/mdbcomp
cp stage2.ok/mdbcomp/*.int3 stage2/mdbcomp
cp stage2.ok/mdbcomp/*.date3 stage2/mdbcomp
cp stage2.ok/mdbcomp/*.int stage2/mdbcomp
cp stage2.ok/mdbcomp/*.int2 stage2/mdbcomp
cp stage2.ok/mdbcomp/*.date stage2/mdbcomp
cp stage2.ok/mdbcomp/*.mh stage2/mdbcomp
# cp stage2.ok/analysis/*.d stage2/analysis
cp stage2.ok/analysis/*.dep stage2/analysis
cp stage2.ok/analysis/*.dv stage2/analysis
cp stage2.ok/analysis/*.int3 stage2/analysis
cp stage2.ok/analysis/*.date3 stage2/analysis
cp stage2.ok/analysis/*.int stage2/analysis
cp stage2.ok/analysis/*.int2 stage2/analysis
cp stage2.ok/analysis/*.date stage2/analysis
cp stage2.ok/analysis/*.mh stage2/analysis
# cp stage2.ok/compiler/*.d stage2/compiler
cp stage2.ok/compiler/*.dep stage2/compiler
cp stage2.ok/compiler/*.dv stage2/compiler
cp stage2.ok/compiler/*.int3 stage2/compiler
cp stage2.ok/compiler/*.date3 stage2/compiler
cp stage2.ok/compiler/*.int stage2/compiler
cp stage2.ok/compiler/*.int2 stage2/compiler
cp stage2.ok/compiler/*.date stage2/compiler
cp stage2.ok/compiler/*.mh stage2/compiler
if test "$bootcheck" = ""
then
cd $root
[ -d stage3 ] || mkdir stage3
$RMSTAGECMD $trueroot/stage3/compiler < /dev/null &
$RMSTAGECMD $trueroot/stage3/library < /dev/null &
wait
$RMSTAGECMD $trueroot/stage3/* < /dev/null
echo linking stage 3... 1>&2
cd stage3
ln -s $root/main.c
mkdir compiler
cd compiler
# Break up the links into several chunks.
# This is needed to cope with small limits
# on the size of argument vectors.
ln -s $root/compiler/[a-h]*.m .
ln -s $root/compiler/[i-o]*.m .
ln -s $root/compiler/[p-s]*.m .
ln -s $root/compiler/[t-z]*.m .
ln -s $root/compiler/*.pp .
cp $root/compiler/Mmake* .
cp $root/compiler/Mercury* .
cp $root/compiler/*FLAGS* .
cp $root/compiler/.mgnuc* .
cd $root/stage3
mkdir library
cd library
ln -s $root/library/[a-l]*.m .
ln -s $root/library/[m-z]*.m .
ln -s $root/library/*.init .
cp $root/library/Mercury* .
cp $root/library/*FLAGS* .
cp $root/library/.mgnuc* .
cp $root/library/Mmake* .
cd $root/stage3
mkdir mdbcomp
cd mdbcomp
ln -s $root/mdbcomp/*.m .
ln -s $root/mdbcomp/*.init .
cp $root/mdbcomp/Mercury* .
cp $root/mdbcomp/*FLAGS* .
cp $root/mdbcomp/.mgnuc* .
cp $root/mdbcomp/Mmake* .
cd $root/stage3
mkdir analysis
cd analysis
ln -s $root/analysis/*.m .
ln -s $root/analysis/*.init .
cp $root/analysis/Mercury* .
cp $root/analysis/*FLAGS* .
cp $root/analysis/.mgnuc* .
cp $root/analysis/Mmake* .
cd $root/stage3
ln -s $root/boehm_gc .
ln -s $root/browser .
ln -s $root/trace .
ln -s $root/doc .
ln -s $root/scripts .
ln -s $root/util .
ln -s $root/profiler .
ln -s $root/deep_profiler .
ln -s $root/runtime .
ln -s $root/tools .
ln -s $root/conf* .
ln -s $root/aclocal.m4 .
ln -s $root/VERSION .
ln -s $root/Mercury.options .
ln -s $root/.*.in .
rm -f config*.log
/bin/rm -f Mmake*
cp $root/stage2.$basis/Mmake* .
# cp $root/stage2.ok/so_locations .
cd $root
fi
set -x
if "$copy_runtime"
then
if (cd stage2 ; mmake $mmake_opts $jfactor runtime)
then
echo "building of stage 2 runtime successful"
else
echo "building of stage 2 runtime not successful"
exit 1
fi
fi
cp stage2.ok/main.o stage2
if test "$alldirs" = ""
then
echo testing which directory the problem is in
/bin/rm .stage2_problem
found=false
for testsubdir in library mdbcomp analysis compiler
do
if $found
then
echo skipping test of $testsubdir
else
for subdir in library mdbcomp analysis compiler
do
if test "$subdir" = "$testsubdir"
then
echo linking stage2/$subdir from stage2.bad/$subdir 1>&2
cp stage2.bad/$subdir/*.[co] stage2/$subdir
cp stage2.bad/$subdir/*.pic_o stage2/$subdir
else
echo linking stage2/$subdir from stage2.ok/$subdir 1>&2
cp stage2.ok/$subdir/*.[co] stage2/$subdir
cp stage2.ok/$subdir/*.pic_o stage2/$subdir
fi
done
binary_step $bootcheck $compile_only $compare_to_bad \
$dependency_only $library_only $jfactor -m "$mmake_opts" \
$outfile $testdirs -s "$single_command"
step_status=$?
if test -f .stage2_problem
then
echo could not build stage 2 to test
exit 1
fi
if "$negative"
then
if test "$step_status" == 0
then
testeddir=$testsubdir
found=true
echo "solution seems to be in the $testeddir directory"
fi
else
if test "$step_status" != 0
then
testeddir=$testsubdir
found=true
echo "problem seems to be in the $testeddir directory"
fi
fi
fi
done
if test "$found" = false
then
echo "could not find problem"
exit 1
fi
else
testeddir=$alldirs
if test ! -d stage2/$testeddir
then
echo $stage2/$testeddir does not exist
exit 1
fi
fi
# start out with all files in stage2 coming from stage2.$base
set +x
echo linking stage2 from stage2.$base 1>&2
cp stage2.$base/library/*.[co] stage2/library
cp stage2.$base/library/*.pic_o stage2/library
cp stage2.$base/compiler/*.[co] stage2/compiler
set -x
# find the set of candidate modules
if test "$allmodules" = ""
then
cd stage2/$testeddir
allmodules=`sub X.c X *.c`
cd $root
else
for module in $allmodules
do
if test ! -f stage2/$testeddir/$module.c
then
echo $stage2/$testeddir/$module.c does not exist
exit 1
fi
done
fi
doubtful="$allmodules"
tested=`half $doubtful`
knowngood=
while test "$tested" != ""
do
# at this point, all the files in stage2 should be from stage2.$base
echo "doubtful modules: $doubtful"
echo "testing modules: $tested"
for module in $tested
do
cp stage2.$trial/$testeddir/$module.[co] stage2/$testeddir
if test $testeddir = library
then
cp stage2.$trial/library/$module.pic_o stage2/library
fi
done
if "$negative"
then
if binary_step $bootcheck $compile_only $compare_to_bad $dependency_only $library_only $jfactor -m "$mmake_opts" $outfile $testdirs -s "$single_command"
then
echo "test succeeded"
lasttest=success
doubtful="$tested"
else
echo "test failed"
lasttest=failure
set +x
newdoubtful=""
for module in $doubtful
do
if not appears $module $tested
then
newdoubtful="$newdoubtful $module"
fi
done
set -x
doubtful="$newdoubtful"
fi
else
if binary_step $bootcheck $compile_only $compare_to_bad $dependency_only $library_only $jfactor -m "$mmake_opts" $outfile $testdirs -s "$single_command"
then
echo "test succeeded"
lasttest=success
knowngood="$knowngood $tested"
set +x
newdoubtful=""
for module in $doubtful
do
if not appears $module $tested
then
newdoubtful="$newdoubtful $module"
fi
done
set -x
doubtful="$newdoubtful"
else
echo "test failed"
lasttest=failure
doubtful="$tested"
fi
fi
for module in $tested
do
cp stage2.$base/$testeddir/$module.[co] stage2/$testeddir
if test $testeddir = library
then
cp stage2.$base/library/$module.pic_o stage2/library
fi
done
tested=`half $doubtful`
if test "$tested" = "" -a "$lasttest" = "$expected"
then
tested="$doubtful"
fi
done
if test "$doubtful" = ""
then
echo "cannot find the problem; all modules behave as expected"
exit 1
fi
module=`echo $doubtful | tr -d ' '`
if "$negative"
then
true
else
echo "the modules known to be ok are: $knowngood"
fi
echo "there is a problem in $testeddir/$module"
echo
basecnt=`egrep '^MR_END_MODULE' stage2.$base/$testeddir/$module.c | wc -l`
trialcnt=`egrep '^MR_END_MODULE' stage2.$trial/$testeddir/$module.c | wc -l`
if test $basecnt -ne $trialcnt
then
basecnt=`echo $basecnt | tr -d ' '`
trialcnt=`echo $trialcnt | tr -d ' '`
echo "the two versions of the problem module"
echo "differ in the number of C modules they have"
echo "$base version: $basecnt vs $trial version: $trialcnt"
exit 1
fi
for dir in $base $trial
do
cd stage2.$dir/$testeddir
divide $module.c $basecnt
cd $root
done
set +x
doubtful=
knowngood=
i=0
while test $i -le $basecnt
do
# If two corresponding parts from stage2.ok and stage.bad are the same,
# then the bug cannot be in that part.
if cmp -s stage2.$base/$testeddir/$module.c.part.$i stage2.$trial/$testeddir/$module.c.part.$i
then
knowngood="$knowngood $i"
else
doubtful="$doubtful $i"
fi
i=`expr $i + 1`
done
set -x
tested=`half $doubtful`
/bin/rm -fr .stage2_problem
while test "$tested" != ""
do
echo "knowngood: $knowngood"
echo "doubtful: $doubtful"
echo "testing: $tested"
assemble $base $trial $testeddir $module $basecnt $tested
cd stage2/$testeddir
/bin/rm $module.o
mmake $module.o
cd $root
if "$negative"
then
if binary_step $bootcheck $compile_only $compare_to_bad $dependency_only $library_only $jfactor -m "$mmake_opts" $outfile $testdirs -s "$single_command"
then
echo "test succeeded"
lasttest=success
doubtful="$tested"
else
echo "test failed"
if test -f .stage2_problem
then
/bin/rm .stage2_problem
echo "problem with the creation of stage 2:"
echo "search of $testeddir/$module abandoned"
exit 1
fi
lasttest=failure
set +x
newdoubtful=""
for part in $doubtful
do
if not appears $part $tested
then
newdoubtful="$newdoubtful $part"
fi
done
set -x
doubtful="$newdoubtful"
fi
else
if binary_step $bootcheck $compile_only $compare_to_bad $dependency_only $library_only $jfactor -m "$mmake_opts" $outfile $testdirs -s "$single_command"
then
echo "test succeeded"
lasttest=success
knowngood="$knowngood $tested"
set +x
newdoubtful=""
for part in $doubtful
do
if not appears $part $tested
then
newdoubtful="$newdoubtful $part"
fi
done
set -x
doubtful="$newdoubtful"
else
echo "test failed"
if test -f .stage2_problem
then
/bin/rm .stage2_problem
echo "problem with the creation of stage 2:"
echo "search of $testeddir/$module abandoned"
exit 1
fi
lasttest=failure
doubtful="$tested"
fi
fi
tested=`half $doubtful`
if test "$tested" = "" -a "$lasttest" = "$expected"
then
tested="$doubtful"
fi
done
if test "$doubtful" = ""
then
echo "cannot find the problem; all parts behave as expected"
exit 1
fi
doubtful=`echo $doubtful | tr -d ' '`
if "$negative"
then
true
else
echo "the parts known to be ok are: $knowngood"
fi
echo "there is a problem in $testeddir/$module.c.part.$doubtful"
echo "the difference is:"
echo
diff -u stage2.$base/$testeddir/$module.c.part.$doubtful stage2.$trial/$testeddir/$module.c.part.$doubtful
echo
echo "finishing at `date`"
exit 0