summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/bugpoint/BugDriver.cpp30
-rw-r--r--tools/bugpoint/BugDriver.h23
-rw-r--r--tools/bugpoint/CrashDebugger.cpp4
-rw-r--r--tools/bugpoint/ExecutionDriver.cpp32
-rw-r--r--tools/bugpoint/bugpoint.cpp10
5 files changed, 73 insertions, 26 deletions
diff --git a/tools/bugpoint/BugDriver.cpp b/tools/bugpoint/BugDriver.cpp
index f8beb2a64c..9d82e8b3cc 100644
--- a/tools/bugpoint/BugDriver.cpp
+++ b/tools/bugpoint/BugDriver.cpp
@@ -62,10 +62,11 @@ std::string llvm::getPassesString(const std::vector<const PassInfo*> &Passes) {
return Result;
}
-BugDriver::BugDriver(const char *toolname, bool as_child, unsigned timeout)
+BugDriver::BugDriver(const char *toolname, bool as_child, bool find_bugs,
+ unsigned timeout)
: ToolName(toolname), ReferenceOutputFile(OutputFile),
Program(0), Interpreter(0), cbe(0), gcc(0), run_as_child(as_child),
- Timeout(timeout) {}
+ run_find_bugs(find_bugs), Timeout(timeout) {}
/// ParseInputFile - Given a bytecode or assembly input filename, parse and
@@ -140,6 +141,12 @@ bool BugDriver::run() {
// Execute the passes
return runPassesAsChild(PassesToRun);
}
+
+ if (run_find_bugs) {
+ // Rearrange the passes and apply them to the program. Repeat this process
+ // until the user kills the program or we find a bug.
+ return runManyPasses(PassesToRun);
+ }
// If we're not running as a child, the first thing that we must do is
// determine what the problem is. Does the optimization series crash the
@@ -175,20 +182,10 @@ bool BugDriver::run() {
bool CreatedOutput = false;
if (ReferenceOutputFile.empty()) {
std::cout << "Generating reference output from raw program: ";
- try {
- ReferenceOutputFile = executeProgramWithCBE("bugpoint.reference.out");
- CreatedOutput = true;
- std::cout << "Reference output is: " << ReferenceOutputFile << '\n';
- } catch (ToolExecutionError &TEE) {
- std::cerr << TEE.what();
- if (Interpreter != cbe) {
- std::cerr << "*** There is a bug running the C backend. Either debug"
- << " it (use the -run-cbe bugpoint option), or fix the error"
- << " some other way.\n";
- return 1;
- }
- return debugCodeGeneratorCrash();
+ if(!createReferenceFile(Program)){
+ return debugCodeGeneratorCrash();
}
+ CreatedOutput = true;
}
// Make sure the reference output file gets deleted on exit from this
@@ -197,7 +194,8 @@ bool BugDriver::run() {
FileRemover RemoverInstance(ROF, CreatedOutput);
// Diff the output of the raw program against the reference output. If it
- // matches, then we have a miscompilation bug.
+ // matches, then we assume there is a miscompilation bug and try to
+ // diagnose it.
std::cout << "*** Checking the code generator...\n";
try {
if (!diffProgram()) {
diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h
index ec687b3c7b..ced7df81ba 100644
--- a/tools/bugpoint/BugDriver.h
+++ b/tools/bugpoint/BugDriver.h
@@ -48,6 +48,7 @@ class BugDriver {
CBE *cbe;
GCC *gcc;
bool run_as_child;
+ bool run_find_bugs;
unsigned Timeout;
// FIXME: sort out public/private distinctions...
@@ -55,7 +56,8 @@ class BugDriver {
friend class ReduceMisCodegenFunctions;
public:
- BugDriver(const char *toolname, bool as_child, unsigned timeout);
+ BugDriver(const char *toolname, bool as_child, bool find_bugs,
+ unsigned timeout);
const std::string &getToolName() const { return ToolName; }
@@ -82,7 +84,7 @@ public:
/// crashes on input. It attempts to prune down the testcase to something
/// reasonable, and figure out exactly which pass is crashing.
///
- bool debugOptimizerCrash();
+ bool debugOptimizerCrash(const std::string &ID = "passes");
/// debugCodeGeneratorCrash - This method is called when the code generator
/// crashes on an input. It attempts to reduce the input as much as possible
@@ -175,6 +177,13 @@ public:
///
std::string executeProgramWithCBE(std::string OutputFile = "");
+ /// createReferenceFile - calls compileProgram and then records the output
+ /// into ReferenceOutputFile. Returns true if reference file created, false
+ /// otherwise. Note: initializeExecutionEnvironment should be called BEFORE
+ /// this function.
+ ///
+ bool createReferenceFile(Module *M, const std::string &Filename = "bugpoint.reference.out");
+
/// diffProgram - This method executes the specified module and diffs the
/// output against the file specified by ReferenceOutputFile. If the output
/// is different, true is returned. If there is a problem with the code
@@ -183,6 +192,7 @@ public:
bool diffProgram(const std::string &BytecodeFile = "",
const std::string &SharedObj = "",
bool RemoveBytecode = false);
+
/// EmitProgressBytecode - This function is used to output the current Program
/// to a file named "bugpoint-ID.bc".
///
@@ -235,6 +245,15 @@ public:
bool runPasses(const std::vector<const PassInfo*> &PassesToRun,
std::string &OutputFilename, bool DeleteOutput = false,
bool Quiet = false) const;
+
+ /// runManyPasses - Take the specified pass list and create different
+ /// combinations of passes to compile the program with. Compile the program with
+ /// each set and mark test to see if it compiled correctly. If the passes
+ /// compiled correctly output nothing and rearrange the passes into a new order.
+ /// If the passes did not compile correctly, output the command required to
+ /// recreate the failure. This returns true if a compiler error is found.
+ ///
+ bool runManyPasses(const std::vector<const PassInfo*> &AllPasses);
/// writeProgramToFile - This writes the current "Program" to the named
/// bytecode file. If an error occurs, true is returned.
diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp
index 2e2ab20fa0..63926464e2 100644
--- a/tools/bugpoint/CrashDebugger.cpp
+++ b/tools/bugpoint/CrashDebugger.cpp
@@ -423,7 +423,7 @@ static bool TestForOptimizerCrash(BugDriver &BD, Module *M) {
/// It attempts to prune down the testcase to something reasonable, and figure
/// out exactly which pass is crashing.
///
-bool BugDriver::debugOptimizerCrash() {
+bool BugDriver::debugOptimizerCrash(const std::string &ID) {
std::cout << "\n*** Debugging optimizer crash!\n";
// Reduce the list of passes which causes the optimizer to crash...
@@ -435,7 +435,7 @@ bool BugDriver::debugOptimizerCrash() {
<< (PassesToRun.size() == 1 ? ": " : "es: ")
<< getPassesString(PassesToRun) << '\n';
- EmitProgressBytecode("passinput");
+ EmitProgressBytecode(ID);
return DebugACrash(*this, TestForOptimizerCrash);
}
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp
index 453833eb8d..93eef5dbc5 100644
--- a/tools/bugpoint/ExecutionDriver.cpp
+++ b/tools/bugpoint/ExecutionDriver.cpp
@@ -297,10 +297,36 @@ std::string BugDriver::compileSharedObject(const std::string &BytecodeFile) {
return "./" + SharedObjectFile;
}
+/// createReferenceFile - calls compileProgram and then records the output
+/// into ReferenceOutputFile. Returns true if reference file created, false
+/// otherwise. Note: initializeExecutionEnvironment should be called BEFORE
+/// this function.
+///
+bool BugDriver::createReferenceFile(Module *M, const std::string &Filename){
+ try {
+ compileProgram(Program);
+ } catch (ToolExecutionError &TEE) {
+ return false;
+ }
+ try {
+ ReferenceOutputFile = executeProgramWithCBE(Filename);
+ std::cout << "Reference output is: " << ReferenceOutputFile << "\n\n";
+ } catch (ToolExecutionError &TEE) {
+ std::cerr << TEE.what();
+ if (Interpreter != cbe) {
+ std::cerr << "*** There is a bug running the C backend. Either debug"
+ << " it (use the -run-cbe bugpoint option), or fix the error"
+ << " some other way.\n";
+ }
+ return false;
+ }
+ return true;
+}
-/// diffProgram - This method executes the specified module and diffs the output
-/// against the file specified by ReferenceOutputFile. If the output is
-/// different, true is returned.
+/// diffProgram - This method executes the specified module and diffs the
+/// output against the file specified by ReferenceOutputFile. If the output
+/// is different, true is returned. If there is a problem with the code
+/// generator (e.g., llc crashes), this will throw an exception.
///
bool BugDriver::diffProgram(const std::string &BytecodeFile,
const std::string &SharedObject,
diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp
index cc05fea650..353e117369 100644
--- a/tools/bugpoint/bugpoint.cpp
+++ b/tools/bugpoint/bugpoint.cpp
@@ -29,8 +29,12 @@ using namespace llvm;
// from a parent process. It is not intended to be used by users so the
// option is hidden.
static cl::opt<bool>
- AsChild("as-child", cl::desc("Run bugpoint as child process"),
- cl::ReallyHidden);
+AsChild("as-child", cl::desc("Run bugpoint as child process"),
+ cl::ReallyHidden);
+
+static cl::opt<bool>
+FindBugs("find-bugs", cl::desc("Run many different optimization sequences"
+ "on program to find bugs"), cl::init(false));
static cl::list<std::string>
InputFilenames(cl::Positional, cl::OneOrMore,
@@ -62,7 +66,7 @@ int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal();
sys::SetInterruptFunction(BugpointInterruptFunction);
- BugDriver D(argv[0],AsChild,TimeoutValue);
+ BugDriver D(argv[0],AsChild,FindBugs,TimeoutValue);
if (D.addSources(InputFilenames)) return 1;
D.addPasses(PassList.begin(), PassList.end());