|  | #! /usr/bin/perl | 
|  | # Script to find regressions by binary-searching a time interval in the | 
|  | # CVS tree.  Written by Brian Gaeke on 2-Mar-2004. | 
|  | # | 
|  |  | 
|  | require 5.6.0;  # NOTE: This script not tested with earlier versions. | 
|  | use Getopt::Std; | 
|  | use POSIX; | 
|  | use Time::Local; | 
|  | use IO::Handle; | 
|  |  | 
|  | sub usage { | 
|  | print STDERR <<END; | 
|  | findRegression [-I] -w WTIME -d DTIME -t TOOLS -c SCRIPT | 
|  |  | 
|  | The -w, -d, -t, and -c options are required. | 
|  | Run findRegression in the top level of an LLVM tree. | 
|  | WTIME is a time when you are sure the regression does NOT exist ("Works"). | 
|  | DTIME is a time when you are sure the regression DOES exist ("Doesntwork"). | 
|  | WTIME and DTIME are both in the format: "YYYY/MM/DD HH:MM". | 
|  | -I means run builds at WTIME and DTIME first to make sure. | 
|  | TOOLS is a comma separated list of tools to rebuild before running SCRIPT. | 
|  | SCRIPT exits 1 if the regression is present in TOOLS; 0 otherwise. | 
|  | END | 
|  | exit 1; | 
|  | } | 
|  |  | 
|  | sub timeAsSeconds { | 
|  | my ($timestr) = @_; | 
|  |  | 
|  | if ( $timestr =~ /(\d\d\d\d)\/(\d\d)\/(\d\d) (\d\d):(\d\d)/ ) { | 
|  | my ( $year, $mon, $mday, $hour, $min ) = ( $1, $2, $3, $4, $5 ); | 
|  | return timegm( 0, $min, $hour, $mday, $mon - 1, $year ); | 
|  | } | 
|  | else { | 
|  | die "** Can't parse date + time: $timestr\n"; | 
|  | } | 
|  | } | 
|  |  | 
|  | sub timeAsString { | 
|  | my ($secs) = @_; | 
|  | return strftime( "%Y/%m/%d %H:%M", gmtime($secs) ); | 
|  | } | 
|  |  | 
|  | sub run { | 
|  | my ($cmdline) = @_; | 
|  | print LOG "** Running: $cmdline\n"; | 
|  | return system($cmdline); | 
|  | } | 
|  |  | 
|  | sub buildLibrariesAndTools { | 
|  | run("sh /home/vadve/gaeke/scripts/run-configure"); | 
|  | run("$MAKE -C lib/Support"); | 
|  | run("$MAKE -C utils"); | 
|  | run("$MAKE -C lib"); | 
|  | foreach my $tool (@TOOLS) { run("$MAKE -C tools/$tool"); } | 
|  | } | 
|  |  | 
|  | sub contains { | 
|  | my ( $file, $regex ) = @_; | 
|  | local (*FILE); | 
|  | open( FILE, "<$file" ) or die "** can't read $file: $!\n"; | 
|  | while (<FILE>) { | 
|  | if (/$regex/) { | 
|  | close FILE; | 
|  | return 1; | 
|  | } | 
|  | } | 
|  | close FILE; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | sub updateSources { | 
|  | my ($time) = @_; | 
|  | my $inst = "include/llvm/Instruction.h"; | 
|  | unlink($inst); | 
|  | run( "cvs update -D'" . timeAsString($time) . "'" ); | 
|  | if ( !contains( $inst, 'class Instruction.*Annotable' ) ) { | 
|  | run("patch -F100 -p0 < makeInstructionAnnotable.patch"); | 
|  | } | 
|  | } | 
|  |  | 
|  | sub regressionPresentAt { | 
|  | my ($time) = @_; | 
|  |  | 
|  | updateSources($time); | 
|  | buildLibrariesAndTools(); | 
|  | my $rc = run($SCRIPT); | 
|  | if ($rc) { | 
|  | print LOG "** Found that regression was PRESENT at " | 
|  | . timeAsString($time) . "\n"; | 
|  | return 1; | 
|  | } | 
|  | else { | 
|  | print LOG "** Found that regression was ABSENT at " | 
|  | . timeAsString($time) . "\n"; | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | sub regressionAbsentAt { | 
|  | my ($time) = @_; | 
|  | return !regressionPresentAt($time); | 
|  | } | 
|  |  | 
|  | sub closeTo { | 
|  | my ( $time1, $time2 ) = @_; | 
|  | return abs( $time1 - $time2 ) < 600;    # 10 minutes seems reasonable. | 
|  | } | 
|  |  | 
|  | sub halfWayPoint { | 
|  | my ( $time1, $time2 ) = @_; | 
|  | my $halfSpan = int( abs( $time1 - $time2 ) / 2 ); | 
|  | if ( $time1 < $time2 ) { | 
|  | return $time1 + $halfSpan; | 
|  | } | 
|  | else { | 
|  | return $time2 + $halfSpan; | 
|  | } | 
|  | } | 
|  |  | 
|  | sub checkBoundaryConditions { | 
|  | print LOG "** Checking for presence of regression at ", timeAsString($DTIME), | 
|  | "\n"; | 
|  | if ( !regressionPresentAt($DTIME) ) { | 
|  | die ( "** Can't help you; $SCRIPT says regression absent at dtime: " | 
|  | . timeAsString($DTIME) | 
|  | . "\n" ); | 
|  | } | 
|  | print LOG "** Checking for absence of regression at ", timeAsString($WTIME), | 
|  | "\n"; | 
|  | if ( !regressionAbsentAt($WTIME) ) { | 
|  | die ( "** Can't help you; $SCRIPT says regression present at wtime: " | 
|  | . timeAsString($WTIME) | 
|  | . "\n" ); | 
|  | } | 
|  | } | 
|  |  | 
|  | ############################################################################## | 
|  |  | 
|  | # Set up log files | 
|  | open (STDERR, ">&STDOUT") || die "** Can't redirect std.err: $!\n"; | 
|  | autoflush STDOUT 1; | 
|  | autoflush STDERR 1; | 
|  | open (LOG, ">RegFinder.log") || die "** can't write RegFinder.log: $!\n"; | 
|  | autoflush LOG 1; | 
|  | # Check command line arguments and environment variables | 
|  | getopts('Iw:d:t:c:'); | 
|  | if ( !( $opt_w && $opt_d && $opt_t && $opt_c ) ) { | 
|  | usage; | 
|  | } | 
|  | $MAKE  = $ENV{'MAKE'}; | 
|  | $MAKE  = 'gmake' unless $MAKE; | 
|  | $WTIME = timeAsSeconds($opt_w); | 
|  | print LOG "** Assuming worked at ", timeAsString($WTIME), "\n"; | 
|  | $DTIME = timeAsSeconds($opt_d); | 
|  | print LOG "** Assuming didn't work at ", timeAsString($DTIME), "\n"; | 
|  | $opt_t =~ s/\s*//g; | 
|  | $SCRIPT = $opt_c; | 
|  | die "** $SCRIPT is not executable or not found\n" unless -x $SCRIPT; | 
|  | print LOG "** Checking for the regression using $SCRIPT\n"; | 
|  | @TOOLS = split ( /,/, $opt_t ); | 
|  | print LOG ( | 
|  | "** Going to rebuild: ", | 
|  | ( join ", ", @TOOLS ), | 
|  | " before each $SCRIPT run\n" | 
|  | ); | 
|  | if ($opt_I) { checkBoundaryConditions(); } | 
|  | # do the dirty work: | 
|  | while ( !closeTo( $DTIME, $WTIME ) ) { | 
|  | my $halfPt = halfWayPoint( $DTIME, $WTIME ); | 
|  | print LOG "** Checking whether regression is present at ", | 
|  | timeAsString($halfPt), "\n"; | 
|  | if ( regressionPresentAt($halfPt) ) { | 
|  | $DTIME = $halfPt; | 
|  | } | 
|  | else { | 
|  | $WTIME = $halfPt; | 
|  | } | 
|  | } | 
|  | # Tell them what we found | 
|  | print LOG "** Narrowed it down to:\n"; | 
|  | print LOG "** Worked at: ",       timeAsString($WTIME), "\n"; | 
|  | print LOG "** Did not work at: ", timeAsString($DTIME), "\n"; | 
|  | close LOG; | 
|  | exit 0; |