llvm/tools/bugpoint/FindBugs.cpp
Justin Bogner d8090aef78 bugpoint: Return Errors instead of passing around strings
This replaces the threading of `std::string &Error` through all of
these APIs with checked Error returns instead. There are very few
places here that actually emit any errors right now, but threading the
APIs through will allow us to replace a bunch of exit(1)'s that are
scattered through this code with proper error handling.

This is more or less NFC, but does move around where a couple of error
messages are printed out.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@280720 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-06 17:18:22 +00:00

105 lines
3.1 KiB
C++

//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an interface that allows bugpoint to choose different
// combinations of optimizations to run on the selected input. Bugpoint will
// run these optimizations and record the success/failure of each. This way
// we can hopefully spot bugs in the optimizations.
//
//===----------------------------------------------------------------------===//
#include "BugDriver.h"
#include "ToolRunner.h"
#include "llvm/Pass.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <ctime>
using namespace llvm;
Error
BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) {
setPassesToRun(AllPasses);
outs() << "Starting bug finding procedure...\n\n";
// Creating a reference output if necessary
if (Error E = initializeExecutionEnvironment())
return E;
outs() << "\n";
if (ReferenceOutputFile.empty()) {
outs() << "Generating reference output from raw program: \n";
if (Error E = createReferenceFile(Program))
return E;
}
srand(time(nullptr));
unsigned num = 1;
while (1) {
//
// Step 1: Randomize the order of the optimizer passes.
//
std::random_shuffle(PassesToRun.begin(), PassesToRun.end());
//
// Step 2: Run optimizer passes on the program and check for success.
//
outs() << "Running selected passes on program to test for crash: ";
for (int i = 0, e = PassesToRun.size(); i != e; i++) {
outs() << "-" << PassesToRun[i] << " ";
}
std::string Filename;
if (runPasses(Program, PassesToRun, Filename, false)) {
outs() << "\n";
outs() << "Optimizer passes caused failure!\n\n";
return debugOptimizerCrash();
} else {
outs() << "Combination " << num << " optimized successfully!\n";
}
//
// Step 3: Compile the optimized code.
//
outs() << "Running the code generator to test for a crash: ";
if (Error E = compileProgram(Program)) {
outs() << "\n*** compileProgram threw an exception: ";
outs() << toString(std::move(E));
return debugCodeGeneratorCrash();
}
outs() << '\n';
//
// Step 4: Run the program and compare its output to the reference
// output (created above).
//
outs() << "*** Checking if passes caused miscompliation:\n";
Expected<bool> Diff = diffProgram(Program, Filename, "", false);
if (Error E = Diff.takeError()) {
errs() << toString(std::move(E));
return debugCodeGeneratorCrash();
}
if (*Diff) {
outs() << "\n*** diffProgram returned true!\n";
Error E = debugMiscompilation();
if (!E)
return Error::success();
}
outs() << "\n*** diff'd output matches!\n";
sys::fs::remove(Filename);
outs() << "\n\n";
num++;
} // end while
// Unreachable.
}