Cleanup and simplify manipulation of the program, eliminate the need for so

many 'friends' of bugdriver.

llvm-svn: 11603
This commit is contained in:
Chris Lattner 2004-02-18 21:24:48 +00:00
parent ead1dff00b
commit 327019b495
3 changed files with 57 additions and 40 deletions

View File

@ -38,6 +38,15 @@ namespace {
"(for miscompilation detection)")); "(for miscompilation detection)"));
} }
/// setNewProgram - If we reduce or update the program somehow, call this method
/// to update bugdriver with it. This deletes the old module and sets the
/// specified one as the current program.
void BugDriver::setNewProgram(Module *M) {
delete Program;
Program = M;
}
/// getPassesString - Turn a list of passes into a string which indicates the /// getPassesString - Turn a list of passes into a string which indicates the
/// command line options that must be passed to add the passes. /// command line options that must be passed to add the passes.
/// ///
@ -174,7 +183,7 @@ bool BugDriver::run() {
return debugMiscompilation(); return debugMiscompilation();
} }
} catch (ToolExecutionError &TEE) { } catch (ToolExecutionError &TEE) {
std::cerr << TEE.getMessage() << "*** Debugging code generator crash!\n"; std::cerr << TEE.getMessage();
return debugCodeGeneratorCrash(); return debugCodeGeneratorCrash();
} }

View File

@ -48,12 +48,10 @@ class BugDriver {
GCC *gcc; GCC *gcc;
// FIXME: sort out public/private distinctions... // FIXME: sort out public/private distinctions...
friend class DebugCrashes; friend class ReducePassList;
friend class ReduceMiscompilingPasses; friend class ReduceMiscompilingPasses;
friend class ReduceMiscompilingFunctions; friend class ReduceMiscompilingFunctions;
friend class ReduceMisCodegenFunctions; friend class ReduceMisCodegenFunctions;
friend class ReduceCrashingFunctions;
friend class ReduceCrashingBlocks;
public: public:
BugDriver(const char *toolname); BugDriver(const char *toolname);
@ -114,6 +112,23 @@ public:
/// ///
bool isExecutingJIT(); bool isExecutingJIT();
/// runPasses - Run all of the passes in the "PassesToRun" list, discard the
/// output, and return true if any of the passes crashed.
bool runPasses(Module *M = 0) {
if (M == 0) M = Program;
std::swap(M, Program);
bool Result = runPasses(PassesToRun);
std::swap(M, Program);
return Result;
}
const Module *getProgram() const { return Program; }
/// setNewProgram - If we reduce or update the program somehow, call this
/// method to update bugdriver with it. This deletes the old module and sets
/// the specified one as the current program.
void setNewProgram(Module *M);
private: private:
/// ParseInputFile - Given a bytecode or assembly input filename, parse and /// ParseInputFile - Given a bytecode or assembly input filename, parse and
/// return it, or return null if not possible. /// return it, or return null if not possible.

View File

@ -31,10 +31,10 @@
using namespace llvm; using namespace llvm;
namespace llvm { namespace llvm {
class DebugCrashes : public ListReducer<const PassInfo*> { class ReducePassList : public ListReducer<const PassInfo*> {
BugDriver &BD; BugDriver &BD;
public: public:
DebugCrashes(BugDriver &bd) : BD(bd) {} ReducePassList(BugDriver &bd) : BD(bd) {}
// doTest - Return true iff running the "removed" passes succeeds, and // doTest - Return true iff running the "removed" passes succeeds, and
// running the "Kept" passes fail when run on the output of the "removed" // running the "Kept" passes fail when run on the output of the "removed"
@ -45,9 +45,9 @@ namespace llvm {
}; };
} }
DebugCrashes::TestResult ReducePassList::TestResult
DebugCrashes::doTest(std::vector<const PassInfo*> &Prefix, ReducePassList::doTest(std::vector<const PassInfo*> &Prefix,
std::vector<const PassInfo*> &Suffix) { std::vector<const PassInfo*> &Suffix) {
std::string PrefixOutput; std::string PrefixOutput;
Module *OrigProgram = 0; Module *OrigProgram = 0;
if (!Prefix.empty()) { if (!Prefix.empty()) {
@ -104,7 +104,7 @@ namespace llvm {
bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
// Clone the program to try hacking it apart... // Clone the program to try hacking it apart...
Module *M = CloneModule(BD.Program); Module *M = CloneModule(BD.getProgram());
// Convert list to set for fast lookup... // Convert list to set for fast lookup...
std::set<Function*> Functions; std::set<Function*> Functions;
@ -131,17 +131,15 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
DeleteFunctionBody(I); DeleteFunctionBody(I);
// Try running the hacked up program... // Try running the hacked up program...
std::swap(BD.Program, M); if (BD.runPasses(M)) {
if (BD.runPasses(BD.PassesToRun)) { BD.setNewProgram(M); // It crashed, keep the trimmed version...
delete M; // It crashed, keep the trimmed version...
// Make sure to use function pointers that point into the now-current // Make sure to use function pointers that point into the now-current
// module. // module.
Funcs.assign(Functions.begin(), Functions.end()); Funcs.assign(Functions.begin(), Functions.end());
return true; return true;
} }
delete BD.Program; // It didn't crash, revert... delete M;
BD.Program = M;
return false; return false;
} }
@ -172,7 +170,7 @@ namespace llvm {
bool ReduceCrashingBlocks::TestBlocks(std::vector<BasicBlock*> &BBs) { bool ReduceCrashingBlocks::TestBlocks(std::vector<BasicBlock*> &BBs) {
// Clone the program to try hacking it apart... // Clone the program to try hacking it apart...
Module *M = CloneModule(BD.Program); Module *M = CloneModule(BD.getProgram());
// Convert list to set for fast lookup... // Convert list to set for fast lookup...
std::set<BasicBlock*> Blocks; std::set<BasicBlock*> Blocks;
@ -237,9 +235,8 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<BasicBlock*> &BBs) {
Passes.run(*M); Passes.run(*M);
// Try running on the hacked up program... // Try running on the hacked up program...
std::swap(BD.Program, M); if (BD.runPasses(M)) {
if (BD.runPasses(BD.PassesToRun)) { BD.setNewProgram(M); // It crashed, keep the trimmed version...
delete M; // It crashed, keep the trimmed version...
// Make sure to use basic block pointers that point into the now-current // Make sure to use basic block pointers that point into the now-current
// module, and that they don't include any deleted blocks. // module, and that they don't include any deleted blocks.
@ -252,11 +249,15 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<BasicBlock*> &BBs) {
} }
return true; return true;
} }
delete BD.Program; // It didn't crash, revert... delete M; // It didn't crash, try something else.
BD.Program = M;
return false; return false;
} }
static bool TestForOptimizerCrash(BugDriver &BD) {
return BD.runPasses();
}
/// debugOptimizerCrash - This method is called when some pass crashes on input. /// debugOptimizerCrash - This method is called when some pass crashes on input.
/// It attempts to prune down the testcase to something reasonable, and figure /// It attempts to prune down the testcase to something reasonable, and figure
/// out exactly which pass is crashing. /// out exactly which pass is crashing.
@ -267,7 +268,7 @@ bool BugDriver::debugOptimizerCrash() {
// Reduce the list of passes which causes the optimizer to crash... // Reduce the list of passes which causes the optimizer to crash...
unsigned OldSize = PassesToRun.size(); unsigned OldSize = PassesToRun.size();
DebugCrashes(*this).reduceList(PassesToRun); ReducePassList(*this).reduceList(PassesToRun);
std::cout << "\n*** Found crashing pass" std::cout << "\n*** Found crashing pass"
<< (PassesToRun.size() == 1 ? ": " : "es: ") << (PassesToRun.size() == 1 ? ": " : "es: ")
@ -292,15 +293,13 @@ bool BugDriver::debugOptimizerCrash() {
} else { } else {
// See if the program still causes a crash... // See if the program still causes a crash...
std::cout << "\nChecking to see if we can delete global inits: "; std::cout << "\nChecking to see if we can delete global inits: ";
std::swap(Program, M); if (runPasses(M)) { // Still crashes?
if (runPasses(PassesToRun)) { // Still crashes? setNewProgram(M);
AnyReduction = true; AnyReduction = true;
delete M;
std::cout << "\n*** Able to remove all global initializers!\n"; std::cout << "\n*** Able to remove all global initializers!\n";
} else { // No longer crashes? } else { // No longer crashes?
delete Program; // Restore program.
Program = M;
std::cout << " - Removing all global inits hides problem!\n"; std::cout << " - Removing all global inits hides problem!\n";
delete M;
} }
} }
} }
@ -365,23 +364,19 @@ bool BugDriver::debugOptimizerCrash() {
I != E; ++I) { I != E; ++I) {
Module *M = deleteInstructionFromProgram(I, Simplification); Module *M = deleteInstructionFromProgram(I, Simplification);
// Make the function the current program...
std::swap(Program, M);
// Find out if the pass still crashes on this pass... // Find out if the pass still crashes on this pass...
std::cout << "Checking instruction '" << I->getName() << "': "; std::cout << "Checking instruction '" << I->getName() << "': ";
if (runPasses(PassesToRun)) { if (runPasses(M)) {
// Yup, it does, we delete the old module, and continue trying to // Yup, it does, we delete the old module, and continue trying to
// reduce the testcase... // reduce the testcase...
delete M; setNewProgram(M);
AnyReduction = true; AnyReduction = true;
goto TryAgain; // I wish I had a multi-level break here! goto TryAgain; // I wish I had a multi-level break here!
} }
// This pass didn't crash without this instruction, try the next // This pass didn't crash without this instruction, try the next
// one. // one.
delete Program; delete M;
Program = M;
} }
} }
} while (Simplification); } while (Simplification);
@ -390,16 +385,13 @@ bool BugDriver::debugOptimizerCrash() {
std::cout << "\n*** Attempting to perform final cleanups: "; std::cout << "\n*** Attempting to perform final cleanups: ";
Module *M = CloneModule(Program); Module *M = CloneModule(Program);
M = performFinalCleanups(M, true); M = performFinalCleanups(M, true);
std::swap(Program, M);
// Find out if the pass still crashes on the cleaned up program... // Find out if the pass still crashes on the cleaned up program...
if (runPasses(PassesToRun)) { if (runPasses(M)) {
// Yup, it does, keep the reduced version... setNewProgram(M); // Yup, it does, keep the reduced version...
delete M;
AnyReduction = true; AnyReduction = true;
} else { } else {
delete Program; // Otherwise, restore the original module... delete M;
Program = M;
} }
if (AnyReduction) if (AnyReduction)
@ -414,6 +406,7 @@ bool BugDriver::debugOptimizerCrash() {
/// crashes on an input. It attempts to reduce the input as much as possible /// crashes on an input. It attempts to reduce the input as much as possible
/// while still causing the code generator to crash. /// while still causing the code generator to crash.
bool BugDriver::debugCodeGeneratorCrash() { bool BugDriver::debugCodeGeneratorCrash() {
std::cerr << "*** Debugging code generator crash!\n";
return false; return false;
} }