#!/bin/sh # vim: ft=sh 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), this script uses linear 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 everthing 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), or the successful execution of the all the test cases in # one or more subdirectories of the tests directory. usage="\ Usage: $0 [options] Options: -b-, --no-bootcheck Do not perform a bootcheck; check only the tests directory. -c, --compile-only Compile only. Do not compare stage2.ok and stage3. -d , --dir Confine the search to one directory, library or compiler. (Usually useful only after a previous search.) -f , --file Confine the search to the named file(s). (Usually useful only after a previous search.) -h, --help Display this usage message. -j , --jobs Run using different parallel processes. -m , --mmake-args Pass as options to \`mmake'. -n, --negative-search Look for the module that suppresses the bug, not causes it. -o , --output-file Output results to . -r, --copy-runtime Copy the runtime directory instead of linking it. -t , --test-dir 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 bootcheck="" compile_only="" jfactor= mmake_opts="" outfile="" copy_runtime=false testdirs="" negative=false alldirs="library compiler" allmodules="" while [ $# -gt 0 ]; do case "$1" in -b-|--no-bootcheck) bootcheck="-b-" ;; -c|--compile-only) compile_only="-c" ;; -d|--dir) alldirs="$2"; shift ;; -d*) alldirs="` expr $1 : '-d\(.*\)' `"; ;; -f|--file) allmodules="$2"; shift ;; -f*) 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\(.*\)' `" ;; -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 ;; -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 test "$negative" = true 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 echo "starting at `date`" root=`/bin/pwd` PATH=$root/tools:$PATH export PATH [ -d stage2 ] || mkdir stage2 /bin/rm -fr stage2/* cd stage2 mkdir compiler cd $root/stage2/compiler ln -s $root/compiler/*.m . cp $root/compiler/Mmake* . cd $root/stage2 mkdir library cd library ln -s $root/library/*.m . # ln -s $root/library/*.nl . ln -s $root/library/lib$STD_LIB_NAME.init . cp $root/library/Mmake* . cd $root/stage2 if test "$copy_runtime" = "true" then mkdir runtime cd runtime ln -s $root/runtime/*.h . ln -s $root/runtime/*.c . ln -s $root/runtime/*.mod . ln -s $root/runtime/*.in . ln -s $root/runtime/machdeps . cp $root/runtime/Mmake* . cd $root/stage2 else ln -s $root/runtime . fi ln -s $root/boehm_gc . ln -s $root/browser . ln -s $root/ssdb . ln -s $root/trace . ln -s $root/doc . ln -s $root/scripts . ln -s $root/util . ln -s $root/profiler . ln -s $root/conf* . 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/*.int stage2/library cp stage2.ok/library/*.int2 stage2/library cp stage2.ok/library/*.date stage2/library # cp stage2.ok/compiler/*.d stage2/compiler cp stage2.ok/compiler/*.dep 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.$base/library/*.[co] stage2/library cp stage2.$base/compiler/*.[co] stage2/compiler if test "$copy_runtime" = "true" 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 set -x normal= unusual= unusualparts= for testeddir in $alldirs do # find the set of modules to search, if not given on command line if test "$allmodules" = "" then cd stage2/$testeddir allmodules=`sub X.c X *.c` cd $root fi for testedmodule in $allmodules do # at this point, all the files in stage2 # should be from stage2.$base echo "testing module: $testedmodule" cp stage2.$trial/$testeddir/$testedmodule.[co] stage2/$testeddir if binary_step $bootcheck $compile_only $jfactor -m "$mmake_opts" $outfile $testdirs then echo "test succeeded" lasttest=success else echo "test failed" lasttest=failure fi if test "$lasttest" = "$expected" then normal="$normal $testeddir/$testedmodule" else unusual="$unusual $testeddir/$testedmodule" basecnt=`egrep '^MR_END_MODULE' stage2.$base/$testeddir/$testedmodule.c | wc -l` trialcnt=`egrep '^MR_END_MODULE' stage2.$trial/$testeddir/$testedmodule.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 unusual 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 $testedmodule.c $basecnt cd $root done allparts= i=0 while test $i -le $basecnt do allparts="$allparts $i" i=`expr $i + 1` done for testedpart in $allparts do echo testing part $testedpart in `/bin/pwd` assemble $base $trial $testeddir $testedmodule $basecnt $testedpart cd stage2/$testeddir /bin/rm $testedmodule.o mmake $testedmodule.o cd $root if binary_step $bootcheck $compile_only $jfactor -m "$mmake_opts" $outfile $testdirs then echo "test succeeded" lasttest=success else echo "test failed" lasttest=failure fi if test "$lasttest" != "$expected" then unusualparts="$unusualparts $testeddir/$testedmodule.part.$testedpart" fi done fi cp stage2.$base/$testeddir/$testedmodule.[co] stage2/$testeddir done done echo "modules whose stage.$trial versions behave as expected:" echo $normal echo "modules whose stage.$trial versions do not behave as expected:" echo $unusual echo "module parts whose stage.$trial versions do not behave as expected:" echo $unusualparts echo "finishing at `date`" exit 0