Initial Commit, moving from dev-private and removing private stuff
diff --git a/bisect/bisect.pl b/bisect/bisect.pl
new file mode 100755
index 0000000..acf6c21
--- /dev/null
+++ b/bisect/bisect.pl
@@ -0,0 +1,145 @@
+#!/usr/bin/env perl
+
+# This script drives the bisection of LLVM/Clang/RT regressions
+# by receiving checkout, build and test commands.
+#
+# By default, the lines are:
+# checkout: './checkout.sh'
+# build: './run.sh'
+# test: ''
+#
+# Which means: success == builds.
+#
+# If you use a different checkout script, make sure it accepts one
+# parameter, the SVN revision.
+#
+# Since testing is the hard part, you should write your own
+# custom test script for each job, but you can reuse the checkout
+# and run scripts if you like.
+#
+# The test script should return 0 when the commit is GOOD and non-zero
+# when it is bad.
+#
+# The build script has a way to quickly test (check-all, test-suite)
+# and you can use that as well, as a shortcut for the testing.
+
+use strict;
+use warnings;
+use Getopt::Std;
+use Scalar::Util qw(looks_like_number);
+
+################################## Command line parsing and validation
+my ($prog) = ($0 =~ /\/([^\/]+)$/);
+my $syntax = "Syntax: $prog [-c checkout_script] [-b build_script] [-t test_script] good_rev bad_rev\n";
+die $syntax unless &getopts('c:b:t:');
+our($opt_c, $opt_b, $opt_t);
+# Job Statuses
+my $Good = 0;
+my $CompilerError = 1;
+my $TestError = 2;
+# Defaults
+my ($checkout, $build, $test) = ("./checkout.sh", "./run.sh", "");
+$checkout = $opt_c if defined $opt_c;
+$build = $opt_b if defined $opt_b;
+$test = $opt_t if defined $opt_t;
+# Validate
+die "Invalid checkout script '$checkout'\n" unless &validate_script(\$checkout);
+die "Invalid run script '$build'\n" unless &validate_script(\$build);
+die "Invalid test script '$test'\n" unless not $test or &validate_script(\$test);
+# Revs
+my $last = scalar @ARGV-1;
+die $syntax unless $last == 1;
+my $good_rev = $ARGV[$last-1];
+die $syntax unless looks_like_number $good_rev;
+my $bad_rev = $ARGV[$last];
+die $syntax unless looks_like_number $bad_rev;
+die "Bad rev '$bad_rev' is less than or equal good rev '$good_rev'\n"
+ unless $bad_rev > $good_rev;
+&main();
+exit;
+
+################################## Main bisect logic
+
+sub main () {
+ my ($good, $bad) = ($good_rev, $bad_rev);
+
+ # Header
+ print "\n==============================================\n".
+ " Checkout script: $checkout\n".
+ " Build script: $build\n".
+ " Test script: $test\n".
+ " Range: [ $good, $bad ]\n".
+ "\n==============================================\n";
+
+ # Iterations
+ my $step = 1;
+ my $range = $bad-$good;
+ my $forced_rev = 0;
+ while ($bad > $good and $bad != $good+1) {
+ my $rev = int($good+($bad-$good)/2);
+ # Use forced rev, from compilation error
+ if ($forced_rev) {
+ $rev = $forced_rev;
+ $forced_rev = 0;
+ }
+ print "\n---------------------------\n";
+ print "Step $step: $good -> $rev -> $bad\n";
+ my $result = &check($rev);
+ # All good
+ if ($result == $Good) {
+ print "Revision '$rev' is good\n";
+ rename "$rev.log", "$rev.good";
+ $good = $rev;
+ # Compiler error when test should run
+ } elsif ($result == $CompilerError and $test) {
+ print "Revision '$rev' has a compiler error\n".
+ "Since you're looking for a test error,\n".
+ "we'll skip a rev\n";
+ rename "$rev.log", "$rev.compile";
+ $forced_rev = $rev+1;
+ # Proper error
+ } else {
+ print "Revision '$rev' is bad\n";
+ rename "$rev.log", "$rev.bad";
+ $bad = $rev;
+ }
+ $step++;
+ }
+
+ # Final status
+ print "\n==============================================\n".
+ " First bad revision is '$bad'\n".
+ " Found in $step steps in a range of $range commits".
+ "\n==============================================\n";
+}
+
+################################## Checkout, run, test
+
+sub check ($) {
+ my ($rev) = @_;
+ unlink "$rev.log";
+ my $log = "2>&1 >> $rev.log";
+ print "Checking out rev '$rev'\n";
+ die "Error while checking out '$rev'\n" if system("$checkout $rev $log");
+ print "Building rev '$rev'\n";
+ return $CompilerError if system("$build $log");
+ if ($test) {
+ print "Testing rev '$rev'\n";
+ return $TestError if system("$test $log");
+ }
+ return $Good;
+}
+
+################################## Helpers
+
+sub validate_script($) {
+ my ($command) = @_;
+ my ($script) = split /\s+/, $$command;
+ return 0 if (! -x $script);
+ if ($script !~ /^[\/\.]/) {
+ $script = "./$script";
+ return 0 if (! -x $script);
+ $$command = "./$$command";
+ }
+ return 1;
+}