#include "llvm/Assembly/Parser.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Transforms/Utils/Linker.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Transforms/Utils/Linker.h"
+#include "llvm/Support/ToolRunner.h"
#include "Support/CommandLine.h"
#include "Support/FileUtilities.h"
#include <memory>
#include "Support/CommandLine.h"
#include "Support/FileUtilities.h"
#include <memory>
if (!PassesToRun.empty()) {
std::cout << "Running selected passes on program to test for crash: ";
if (runPasses(PassesToRun))
if (!PassesToRun.empty()) {
std::cout << "Running selected passes on program to test for crash: ";
if (runPasses(PassesToRun))
+ return debugOptimizerCrash();
}
// Set up the execution environment, selecting a method to run LLVM bytecode.
}
// Set up the execution environment, selecting a method to run LLVM bytecode.
bool CreatedOutput = false;
if (ReferenceOutputFile.empty()) {
std::cout << "Generating reference output from raw program...";
bool CreatedOutput = false;
if (ReferenceOutputFile.empty()) {
std::cout << "Generating reference output from raw program...";
- ReferenceOutputFile = executeProgramWithCBE("bugpoint.reference.out");
- CreatedOutput = true;
- std::cout << "Reference output is: " << ReferenceOutputFile << "\n";
+ try {
+ ReferenceOutputFile = executeProgramWithCBE("bugpoint.reference.out");
+ CreatedOutput = true;
+ std::cout << "Reference output is: " << ReferenceOutputFile << "\n";
+ } catch (ToolExecutionError &TEE) {
+ std::cerr << TEE.getMessage();
+ 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();
+ }
}
// Make sure the reference output file gets deleted on exit from this
}
// Make sure the reference output file gets deleted on exit from this
// Diff the output of the raw program against the reference output. If it
// matches, then we have a miscompilation bug.
std::cout << "*** Checking the code generator...\n";
// Diff the output of the raw program against the reference output. If it
// matches, then we have a miscompilation bug.
std::cout << "*** Checking the code generator...\n";
- if (!diffProgram()) {
- std::cout << "\n*** Debugging miscompilation!\n";
- return debugMiscompilation();
+ try {
+ if (!diffProgram()) {
+ std::cout << "\n*** Debugging miscompilation!\n";
+ return debugMiscompilation();
+ }
+ } catch (ToolExecutionError &TEE) {
+ std::cerr << TEE.getMessage() << "*** Debugging code generator crash!\n";
+ return debugCodeGeneratorCrash();
}
std::cout << "\n*** Input program does not match reference diff!\n";
}
std::cout << "\n*** Input program does not match reference diff!\n";
- /// debugCrash - This method is called when some pass crashes on input. It
- /// attempts to prune down the testcase to something reasonable, and figure
- /// out exactly which pass is crashing.
+ /// debugOptimizerCrash - This method is called when some optimizer pass
+ /// crashes on input. It attempts to prune down the testcase to something
+ /// reasonable, and figure out exactly which pass is crashing.
+ bool debugOptimizerCrash();
+
+ /// debugCodeGeneratorCrash - This method is called when the code generator
+ /// crashes on an input. It attempts to reduce the input as much as possible
+ /// while still causing the code generator to crash.
+ bool debugCodeGeneratorCrash();
/// debugMiscompilation - This method is used when the passes selected are not
/// crashing, but the generated output is semantically different from the
/// debugMiscompilation - This method is used when the passes selected are not
/// crashing, but the generated output is semantically different from the
-/// debugCrash - This method is called when some pass crashes on input. It
-/// attempts to prune down the testcase to something reasonable, and figure
+/// debugOptimizerCrash - This method is called when some pass crashes on input.
+/// It attempts to prune down the testcase to something reasonable, and figure
/// out exactly which pass is crashing.
///
/// out exactly which pass is crashing.
///
-bool BugDriver::debugCrash() {
+bool BugDriver::debugOptimizerCrash() {
bool AnyReduction = false;
std::cout << "\n*** Debugging optimizer crash!\n";
bool AnyReduction = false;
std::cout << "\n*** Debugging optimizer crash!\n";
+
+
+/// debugCodeGeneratorCrash - This method is called when the code generator
+/// crashes on an input. It attempts to reduce the input as much as possible
+/// while still causing the code generator to crash.
+bool BugDriver::debugCodeGeneratorCrash() {
+
+ return false;
+}
<< " on the input program!\n";
BD.setPassesToRun(Suffix);
BD.EmitProgressBytecode("pass-error", false);
<< " on the input program!\n";
BD.setPassesToRun(Suffix);
BD.EmitProgressBytecode("pass-error", false);
+ exit(BD.debugOptimizerCrash());
}
// Check to see if the finished program matches the reference output...
}
// Check to see if the finished program matches the reference output...
<< " on the input program!\n";
BD.setPassesToRun(Prefix);
BD.EmitProgressBytecode("pass-error", false);
<< " on the input program!\n";
BD.setPassesToRun(Prefix);
BD.EmitProgressBytecode("pass-error", false);
+ exit(BD.debugOptimizerCrash());
}
// If the prefix maintains the predicate by itself, only keep the prefix!
}
// If the prefix maintains the predicate by itself, only keep the prefix!
<< " on the input program!\n";
BD.setPassesToRun(Suffix);
BD.EmitProgressBytecode("pass-error", false);
<< " on the input program!\n";
BD.setPassesToRun(Suffix);
BD.EmitProgressBytecode("pass-error", false);
+ exit(BD.debugOptimizerCrash());
std::cerr << " Error running this sequence of passes"
<< " on the input program!\n";
BD.EmitProgressBytecode("pass-error", false);
std::cerr << " Error running this sequence of passes"
<< " on the input program!\n";
BD.EmitProgressBytecode("pass-error", false);
+ exit(BD.debugOptimizerCrash());