diff options
Diffstat (limited to 'llvm/tools/bugpoint')
-rw-r--r-- | llvm/tools/bugpoint/BugDriver.cpp | 14 | ||||
-rw-r--r-- | llvm/tools/bugpoint/BugDriver.h | 7 | ||||
-rw-r--r-- | llvm/tools/bugpoint/CrashDebugger.cpp | 72 | ||||
-rw-r--r-- | llvm/tools/bugpoint/FindBugs.cpp | 7 | ||||
-rw-r--r-- | llvm/tools/bugpoint/ListReducer.h | 27 | ||||
-rw-r--r-- | llvm/tools/bugpoint/Miscompilation.cpp | 67 | ||||
-rw-r--r-- | llvm/tools/bugpoint/bugpoint.cpp | 8 |
7 files changed, 112 insertions, 90 deletions
diff --git a/llvm/tools/bugpoint/BugDriver.cpp b/llvm/tools/bugpoint/BugDriver.cpp index 9bca91accba..dde552174b4 100644 --- a/llvm/tools/bugpoint/BugDriver.cpp +++ b/llvm/tools/bugpoint/BugDriver.cpp @@ -146,11 +146,11 @@ bool BugDriver::addSources(const std::vector<std::string> &Filenames) { /// run - The top level method that is invoked after all of the instance /// variables are set up from command line arguments. /// -bool BugDriver::run() { +bool BugDriver::run(std::string &ErrMsg) { 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); + return runManyPasses(PassesToRun, ErrMsg); } // If we're not running as a child, the first thing that we must do is @@ -176,7 +176,7 @@ bool BugDriver::run() { compileProgram(Program, &Error); if (!Error.empty()) { outs() << Error; - return debugCodeGeneratorCrash(); + return debugCodeGeneratorCrash(ErrMsg); } outs() << '\n'; @@ -188,7 +188,7 @@ bool BugDriver::run() { if (ReferenceOutputFile.empty()) { outs() << "Generating reference output from raw program: "; if (!createReferenceFile(Program)) { - return debugCodeGeneratorCrash(); + return debugCodeGeneratorCrash(ErrMsg); } CreatedOutput = true; } @@ -205,14 +205,14 @@ bool BugDriver::run() { bool Diff = diffProgram(Program, "", "", false, &Error); if (!Error.empty()) { errs() << Error; - return debugCodeGeneratorCrash(); + return debugCodeGeneratorCrash(ErrMsg); } if (!Diff) { outs() << "\n*** Output matches: Debugging miscompilation!\n"; debugMiscompilation(&Error); if (!Error.empty()) { errs() << Error; - return debugCodeGeneratorCrash(); + return debugCodeGeneratorCrash(ErrMsg); } return false; } @@ -222,7 +222,7 @@ bool BugDriver::run() { bool Failure = debugCodeGenerator(&Error); if (!Error.empty()) { errs() << Error; - return debugCodeGeneratorCrash(); + return debugCodeGeneratorCrash(ErrMsg); } return Failure; } diff --git a/llvm/tools/bugpoint/BugDriver.h b/llvm/tools/bugpoint/BugDriver.h index 7e03aa6512c..7ae2d5c2f99 100644 --- a/llvm/tools/bugpoint/BugDriver.h +++ b/llvm/tools/bugpoint/BugDriver.h @@ -85,7 +85,7 @@ public: /// variables are set up from command line arguments. The \p as_child argument /// indicates whether the driver is to run in parent mode or child mode. /// - bool run(); + bool run(std::string &ErrMsg); /// debugOptimizerCrash - This method is called when some optimizer pass /// crashes on input. It attempts to prune down the testcase to something @@ -96,7 +96,7 @@ public: /// 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(); + bool debugCodeGeneratorCrash(std::string &Error); /// debugMiscompilation - This method is used when the passes selected are not /// crashing, but the generated output is semantically different from the @@ -266,7 +266,8 @@ public: /// 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<std::string> &AllPasses); + bool runManyPasses(const std::vector<std::string> &AllPasses, + std::string &ErrMsg); /// writeProgramToFile - This writes the current "Program" to the named /// bitcode file. If an error occurs, true is returned. diff --git a/llvm/tools/bugpoint/CrashDebugger.cpp b/llvm/tools/bugpoint/CrashDebugger.cpp index 7a565c0140b..649cac7c681 100644 --- a/llvm/tools/bugpoint/CrashDebugger.cpp +++ b/llvm/tools/bugpoint/CrashDebugger.cpp @@ -71,13 +71,14 @@ public: // passes. If we return true, we update the current module of bugpoint. // TestResult doTest(std::vector<std::string> &Removed, - std::vector<std::string> &Kept) override; + std::vector<std::string> &Kept, + std::string &Error) override; }; } ReducePassList::TestResult ReducePassList::doTest(std::vector<std::string> &Prefix, - std::vector<std::string> &Suffix) { + std::vector<std::string> &Suffix, std::string &Error) { std::string PrefixOutput; Module *OrigProgram = nullptr; if (!Prefix.empty()) { @@ -128,7 +129,8 @@ public: : BD(bd), TestFn(testFn) {} TestResult doTest(std::vector<GlobalVariable *> &Prefix, - std::vector<GlobalVariable *> &Kept) override { + std::vector<GlobalVariable *> &Kept, + std::string &Error) override { if (!Kept.empty() && TestGlobalVariables(Kept)) return KeepSuffix; if (!Prefix.empty() && TestGlobalVariables(Prefix)) @@ -197,7 +199,8 @@ public: : BD(bd), TestFn(testFn) {} TestResult doTest(std::vector<Function *> &Prefix, - std::vector<Function *> &Kept) override { + std::vector<Function *> &Kept, + std::string &Error) override { if (!Kept.empty() && TestFuncs(Kept)) return KeepSuffix; if (!Prefix.empty() && TestFuncs(Prefix)) @@ -370,7 +373,8 @@ public: : BD(BD), TestFn(testFn) {} TestResult doTest(std::vector<const BasicBlock *> &Prefix, - std::vector<const BasicBlock *> &Kept) override { + std::vector<const BasicBlock *> &Kept, + std::string &Error) override { if (!Kept.empty() && TestBlocks(Kept)) return KeepSuffix; if (!Prefix.empty() && TestBlocks(Prefix)) @@ -491,7 +495,8 @@ public: : BD(bd), TestFn(testFn), Direction(Direction) {} TestResult doTest(std::vector<const BasicBlock *> &Prefix, - std::vector<const BasicBlock *> &Kept) override { + std::vector<const BasicBlock *> &Kept, + std::string &Error) override { if (!Kept.empty() && TestBlocks(Kept)) return KeepSuffix; if (!Prefix.empty() && TestBlocks(Prefix)) @@ -598,7 +603,8 @@ public: : BD(bd), TestFn(testFn), TTI(bd.getProgram()->getDataLayout()) {} TestResult doTest(std::vector<const BasicBlock *> &Prefix, - std::vector<const BasicBlock *> &Kept) override { + std::vector<const BasicBlock *> &Kept, + std::string &Error) override { if (!Kept.empty() && TestBlocks(Kept)) return KeepSuffix; if (!Prefix.empty() && TestBlocks(Prefix)) @@ -692,7 +698,8 @@ public: : BD(bd), TestFn(testFn) {} TestResult doTest(std::vector<const Instruction *> &Prefix, - std::vector<const Instruction *> &Kept) override { + std::vector<const Instruction *> &Kept, + std::string &Error) override { if (!Kept.empty() && TestInsts(Kept)) return KeepSuffix; if (!Prefix.empty() && TestInsts(Prefix)) @@ -768,7 +775,8 @@ public: : BD(bd), TestFn(testFn) {} TestResult doTest(std::vector<std::string> &Prefix, - std::vector<std::string> &Kept) override { + std::vector<std::string> &Kept, + std::string &Error) override { if (!Kept.empty() && TestNamedMDs(Kept)) return KeepSuffix; if (!Prefix.empty() && TestNamedMDs(Prefix)) @@ -837,7 +845,8 @@ public: : BD(bd), TestFn(testFn) {} TestResult doTest(std::vector<const MDNode *> &Prefix, - std::vector<const MDNode *> &Kept) override { + std::vector<const MDNode *> &Kept, + std::string &Error) override { if (!Kept.empty() && TestNamedMDOps(Kept)) return KeepSuffix; if (!Prefix.empty() && TestNamedMDOps(Prefix)) @@ -900,7 +909,8 @@ bool ReduceCrashingNamedMDOps::TestNamedMDOps( static void ReduceGlobalInitializers(BugDriver &BD, bool (*TestFn)(const BugDriver &, - Module *)) { + Module *), + std::string &Error) { if (BD.getProgram()->global_begin() != BD.getProgram()->global_end()) { // Now try to reduce the number of global variable initializers in the // module to something small. @@ -942,7 +952,8 @@ static void ReduceGlobalInitializers(BugDriver &BD, << "variables in the testcase\n"; unsigned OldSize = GVs.size(); - ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs); + ReduceCrashingGlobalVariables(BD, TestFn).reduceList(GVs, Error); + assert(!Error.empty()); if (GVs.size() < OldSize) BD.EmitProgressBitcode(BD.getProgram(), "reduced-global-variables"); @@ -953,7 +964,8 @@ static void ReduceGlobalInitializers(BugDriver &BD, } static void ReduceInsts(BugDriver &BD, - bool (*TestFn)(const BugDriver &, Module *)) { + bool (*TestFn)(const BugDriver &, Module *), + std::string &Error) { // Attempt to delete instructions using bisection. This should help out nasty // cases with large basic blocks where the problem is at one end. if (!BugpointIsInterrupted) { @@ -964,7 +976,7 @@ static void ReduceInsts(BugDriver &BD, if (!isa<TerminatorInst>(&I)) Insts.push_back(&I); - ReduceCrashingInstructions(BD, TestFn).reduceList(Insts); + ReduceCrashingInstructions(BD, TestFn).reduceList(Insts, Error); } unsigned Simplification = 2; @@ -1034,11 +1046,12 @@ static void ReduceInsts(BugDriver &BD, /// on a program, try to destructively reduce the program while still keeping /// the predicate true. static bool DebugACrash(BugDriver &BD, - bool (*TestFn)(const BugDriver &, Module *)) { + bool (*TestFn)(const BugDriver &, Module *), + std::string &Error) { // See if we can get away with nuking some of the global variable initializers // in the program... if (!NoGlobalRM) - ReduceGlobalInitializers(BD, TestFn); + ReduceGlobalInitializers(BD, TestFn, Error); // Now try to reduce the number of functions in the module to something small. std::vector<Function *> Functions; @@ -1051,7 +1064,7 @@ static bool DebugACrash(BugDriver &BD, "in the testcase\n"; unsigned OldSize = Functions.size(); - ReduceCrashingFunctions(BD, TestFn).reduceList(Functions); + ReduceCrashingFunctions(BD, TestFn).reduceList(Functions, Error); if (Functions.size() < OldSize) BD.EmitProgressBitcode(BD.getProgram(), "reduced-function"); @@ -1065,8 +1078,8 @@ static bool DebugACrash(BugDriver &BD, for (BasicBlock &BB : F) Blocks.push_back(&BB); unsigned OldSize = Blocks.size(); - ReduceCrashingConditionals(BD, TestFn, true).reduceList(Blocks); - ReduceCrashingConditionals(BD, TestFn, false).reduceList(Blocks); + ReduceCrashingConditionals(BD, TestFn, true).reduceList(Blocks, Error); + ReduceCrashingConditionals(BD, TestFn, false).reduceList(Blocks, Error); if (Blocks.size() < OldSize) BD.EmitProgressBitcode(BD.getProgram(), "reduced-conditionals"); } @@ -1082,7 +1095,7 @@ static bool DebugACrash(BugDriver &BD, for (BasicBlock &BB : F) Blocks.push_back(&BB); unsigned OldSize = Blocks.size(); - ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks); + ReduceCrashingBlocks(BD, TestFn).reduceList(Blocks, Error); if (Blocks.size() < OldSize) BD.EmitProgressBitcode(BD.getProgram(), "reduced-blocks"); } @@ -1093,7 +1106,7 @@ static bool DebugACrash(BugDriver &BD, for (BasicBlock &BB : F) Blocks.push_back(&BB); unsigned OldSize = Blocks.size(); - ReduceSimplifyCFG(BD, TestFn).reduceList(Blocks); + ReduceSimplifyCFG(BD, TestFn).reduceList(Blocks, Error); if (Blocks.size() < OldSize) BD.EmitProgressBitcode(BD.getProgram(), "reduced-simplifycfg"); } @@ -1101,7 +1114,7 @@ static bool DebugACrash(BugDriver &BD, // Attempt to delete instructions using bisection. This should help out nasty // cases with large basic blocks where the problem is at one end. if (!BugpointIsInterrupted) - ReduceInsts(BD, TestFn); + ReduceInsts(BD, TestFn, Error); if (!NoNamedMDRM) { if (!BugpointIsInterrupted) { @@ -1111,7 +1124,7 @@ static bool DebugACrash(BugDriver &BD, std::vector<std::string> NamedMDNames; for (auto &NamedMD : BD.getProgram()->named_metadata()) NamedMDNames.push_back(NamedMD.getName().str()); - ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames); + ReduceCrashingNamedMD(BD, TestFn).reduceList(NamedMDNames, Error); } if (!BugpointIsInterrupted) { @@ -1121,7 +1134,7 @@ static bool DebugACrash(BugDriver &BD, for (auto &NamedMD : BD.getProgram()->named_metadata()) for (auto op : NamedMD.operands()) NamedMDOps.push_back(op); - ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps); + ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps, Error); } BD.EmitProgressBitcode(BD.getProgram(), "reduced-named-md"); } @@ -1156,9 +1169,11 @@ static bool TestForOptimizerCrash(const BugDriver &BD, Module *M) { bool BugDriver::debugOptimizerCrash(const std::string &ID) { outs() << "\n*** Debugging optimizer crash!\n"; + std::string Error; // Reduce the list of passes which causes the optimizer to crash... if (!BugpointIsInterrupted && !DontReducePassList) - ReducePassList(*this).reduceList(PassesToRun); + ReducePassList(*this).reduceList(PassesToRun, Error); + assert(Error.empty()); outs() << "\n*** Found crashing pass" << (PassesToRun.size() == 1 ? ": " : "es: ") @@ -1166,7 +1181,8 @@ bool BugDriver::debugOptimizerCrash(const std::string &ID) { EmitProgressBitcode(Program, ID); - bool Success = DebugACrash(*this, TestForOptimizerCrash); + bool Success = DebugACrash(*this, TestForOptimizerCrash, Error); + assert(Error.empty()); return Success; } @@ -1187,8 +1203,8 @@ static bool TestForCodeGenCrash(const BugDriver &BD, Module *M) { /// 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() { +bool BugDriver::debugCodeGeneratorCrash(std::string &Error) { errs() << "*** Debugging code generator crash!\n"; - return DebugACrash(*this, TestForCodeGenCrash); + return DebugACrash(*this, TestForCodeGenCrash, Error); } diff --git a/llvm/tools/bugpoint/FindBugs.cpp b/llvm/tools/bugpoint/FindBugs.cpp index 818baf9e83f..3c345c5503c 100644 --- a/llvm/tools/bugpoint/FindBugs.cpp +++ b/llvm/tools/bugpoint/FindBugs.cpp @@ -30,7 +30,8 @@ using namespace llvm; /// 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 BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) { +bool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses, + std::string &ErrMsg) { setPassesToRun(AllPasses); outs() << "Starting bug finding procedure...\n\n"; @@ -81,7 +82,7 @@ bool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) { if (!Error.empty()) { outs() << "\n*** compileProgram threw an exception: "; outs() << Error; - return debugCodeGeneratorCrash(); + return debugCodeGeneratorCrash(ErrMsg); } outs() << '\n'; @@ -99,7 +100,7 @@ bool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses) { } if (!Error.empty()) { errs() << Error; - debugCodeGeneratorCrash(); + debugCodeGeneratorCrash(ErrMsg); return true; } outs() << "\n*** diff'd output matches!\n"; diff --git a/llvm/tools/bugpoint/ListReducer.h b/llvm/tools/bugpoint/ListReducer.h index 94e63e34200..78af1aeb6a2 100644 --- a/llvm/tools/bugpoint/ListReducer.h +++ b/llvm/tools/bugpoint/ListReducer.h @@ -15,6 +15,7 @@ #ifndef LLVM_TOOLS_BUGPOINT_LISTREDUCER_H #define LLVM_TOOLS_BUGPOINT_LISTREDUCER_H +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cstdlib> @@ -38,16 +39,16 @@ template <typename ElTy> struct ListReducer { /// test desired. The testcase is only required to test to see if the Kept /// list still satisfies the property, but if it is going to check the prefix /// anyway, it can. - virtual TestResult doTest(std::vector<ElTy> &Prefix, - std::vector<ElTy> &Kept) = 0; + virtual TestResult doTest(std::vector<ElTy> &Prefix, std::vector<ElTy> &Kept, + std::string &Error) = 0; /// This function attempts to reduce the length of the specified list while /// still maintaining the "test" property. This is the core of the "work" /// that bugpoint does. - bool reduceList(std::vector<ElTy> &TheList) { + bool reduceList(std::vector<ElTy> &TheList, std::string &Error) { std::vector<ElTy> empty; std::srand(0x6e5ea738); // Seed the random number generator - switch (doTest(TheList, empty)) { + switch (doTest(TheList, empty, Error)) { case KeepPrefix: if (TheList.size() == 1) // we are done, it's the base case and it fails return true; @@ -63,6 +64,7 @@ template <typename ElTy> struct ListReducer { return false; // there is no failure with the full set of passes/funcs! case InternalError: + assert(!Error.empty()); return true; } @@ -95,7 +97,7 @@ template <typename ElTy> struct ListReducer { std::random_shuffle(ShuffledList.begin(), ShuffledList.end()); errs() << "\n\n*** Testing shuffled set...\n\n"; // Check that random shuffle doesn't loose the bug - if (doTest(ShuffledList, empty) == KeepPrefix) { + if (doTest(ShuffledList, empty, Error) == KeepPrefix) { // If the bug is still here, use the shuffled list. TheList.swap(ShuffledList); MidTop = TheList.size(); @@ -114,7 +116,7 @@ template <typename ElTy> struct ListReducer { std::vector<ElTy> Prefix(TheList.begin(), TheList.begin() + Mid); std::vector<ElTy> Suffix(TheList.begin() + Mid, TheList.end()); - switch (doTest(Prefix, Suffix)) { + switch (doTest(Prefix, Suffix, Error)) { case KeepSuffix: // The property still holds. We can just drop the prefix elements, and // shorten the list to the "kept" elements. @@ -139,8 +141,9 @@ template <typename ElTy> struct ListReducer { NumOfIterationsWithoutProgress++; break; case InternalError: - return true; + return true; // Error was set by doTest. } + assert(Error.empty() && "doTest did not return InternalError for error"); } // Probability of backjumping from the trimming loop back to the binary @@ -176,18 +179,14 @@ template <typename ElTy> struct ListReducer { std::vector<ElTy> TestList(TheList); TestList.erase(TestList.begin() + i); - switch (doTest(EmptyList, TestList)) { - case KeepSuffix: + if (doTest(EmptyList, TestList, Error) == KeepSuffix) { // We can trim down the list! TheList.swap(TestList); --i; // Don't skip an element of the list Changed = true; - break; - case InternalError: - return true; - default: - break; } + if (!Error.empty()) + return true; } if (TrimIterations >= MaxTrimIterationsWithoutBackJump) break; diff --git a/llvm/tools/bugpoint/Miscompilation.cpp b/llvm/tools/bugpoint/Miscompilation.cpp index 62f28e2d1b8..9069e00acb9 100644 --- a/llvm/tools/bugpoint/Miscompilation.cpp +++ b/llvm/tools/bugpoint/Miscompilation.cpp @@ -46,14 +46,13 @@ static llvm::cl::opt<bool> DisableBlockExtraction( class ReduceMiscompilingPasses : public ListReducer<std::string> { BugDriver &BD; - std::string &Error; public: - ReduceMiscompilingPasses(BugDriver &bd, std::string &Error) - : BD(bd), Error(Error) {} + ReduceMiscompilingPasses(BugDriver &bd) : BD(bd) {} TestResult doTest(std::vector<std::string> &Prefix, - std::vector<std::string> &Suffix) override; + std::vector<std::string> &Suffix, + std::string &Error) override; }; } // end anonymous namespace @@ -62,7 +61,8 @@ public: /// ReduceMiscompilingPasses::TestResult ReduceMiscompilingPasses::doTest(std::vector<std::string> &Prefix, - std::vector<std::string> &Suffix) { + std::vector<std::string> &Suffix, + std::string &Error) { // First, run the program with just the Suffix passes. If it is still broken // with JUST the kept passes, discard the prefix passes. outs() << "Checking to see if '" << getPassesString(Suffix) @@ -181,26 +181,25 @@ class ReduceMiscompilingFunctions : public ListReducer<Function *> { BugDriver &BD; bool (*TestFn)(BugDriver &, std::unique_ptr<Module>, std::unique_ptr<Module>, std::string &); - std::string &Error; public: ReduceMiscompilingFunctions(BugDriver &bd, bool (*F)(BugDriver &, std::unique_ptr<Module>, - std::unique_ptr<Module>, std::string &), - std::string &Error) - : BD(bd), TestFn(F), Error(Error) {} + std::unique_ptr<Module>, std::string &)) + : BD(bd), TestFn(F) {} TestResult doTest(std::vector<Function *> &Prefix, - std::vector<Function *> &Suffix) override { + std::vector<Function *> &Suffix, + std::string &Error) override { if (!Suffix.empty()) { - bool Ret = TestFuncs(Suffix); + bool Ret = TestFuncs(Suffix, Error); if (!Error.empty()) return InternalError; if (Ret) return KeepSuffix; } if (!Prefix.empty()) { - bool Ret = TestFuncs(Prefix); + bool Ret = TestFuncs(Prefix, Error); if (!Error.empty()) return InternalError; if (Ret) @@ -209,7 +208,7 @@ public: return NoFailure; } - bool TestFuncs(const std::vector<Function *> &Prefix); + bool TestFuncs(const std::vector<Function *> &Prefix, std::string &Error); }; } // end anonymous namespace @@ -239,7 +238,7 @@ static std::unique_ptr<Module> testMergedProgram(const BugDriver &BD, /// accordingly. Each group of functions becomes a separate Module. /// bool ReduceMiscompilingFunctions::TestFuncs( - const std::vector<Function *> &Funcs) { + const std::vector<Function *> &Funcs, std::string &Error) { // Test to see if the function is misoptimized if we ONLY run it on the // functions listed in Funcs. outs() << "Checking to see if the program is misoptimized when " @@ -445,27 +444,26 @@ class ReduceMiscompiledBlocks : public ListReducer<BasicBlock *> { bool (*TestFn)(BugDriver &, std::unique_ptr<Module>, std::unique_ptr<Module>, std::string &); std::vector<Function *> FunctionsBeingTested; - std::string &Error; public: ReduceMiscompiledBlocks(BugDriver &bd, bool (*F)(BugDriver &, std::unique_ptr<Module>, std::unique_ptr<Module>, std::string &), - const std::vector<Function *> &Fns, - std::string &Error) - : BD(bd), TestFn(F), FunctionsBeingTested(Fns), Error(Error) {} + const std::vector<Function *> &Fns) + : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {} TestResult doTest(std::vector<BasicBlock *> &Prefix, - std::vector<BasicBlock *> &Suffix) override { + std::vector<BasicBlock *> &Suffix, + std::string &Error) override { if (!Suffix.empty()) { - bool Ret = TestFuncs(Suffix); + bool Ret = TestFuncs(Suffix, Error); if (!Error.empty()) return InternalError; if (Ret) return KeepSuffix; } if (!Prefix.empty()) { - bool Ret = TestFuncs(Prefix); + bool Ret = TestFuncs(Prefix, Error); if (!Error.empty()) return InternalError; if (Ret) @@ -474,14 +472,15 @@ public: return NoFailure; } - bool TestFuncs(const std::vector<BasicBlock *> &BBs); + bool TestFuncs(const std::vector<BasicBlock *> &BBs, std::string &Error); }; } // end anonymous namespace /// TestFuncs - Extract all blocks for the miscompiled functions except for the /// specified blocks. If the problem still exists, return true. /// -bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock *> &BBs) { +bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock *> &BBs, + std::string &Error) { // Test to see if the function is misoptimized if we ONLY run it on the // functions listed in Funcs. outs() << "Checking to see if the program is misoptimized when all "; @@ -551,15 +550,15 @@ static bool ExtractBlocks(BugDriver &BD, unsigned OldSize = Blocks.size(); // Check to see if all blocks are extractible first. - bool Ret = ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions, Error) - .TestFuncs(std::vector<BasicBlock *>()); + bool Ret = ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions) + .TestFuncs(std::vector<BasicBlock *>(), Error); if (!Error.empty()) return false; if (Ret) { Blocks.clear(); } else { - ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions, Error) - .reduceList(Blocks); + ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions) + .reduceList(Blocks, Error); if (!Error.empty()) return false; if (Blocks.size() == OldSize) @@ -629,8 +628,8 @@ DebugAMiscompilation(BugDriver &BD, // Do the reduction... if (!BugpointIsInterrupted) - ReduceMiscompilingFunctions(BD, TestFn, Error) - .reduceList(MiscompiledFunctions); + ReduceMiscompilingFunctions(BD, TestFn) + .reduceList(MiscompiledFunctions, Error); if (!Error.empty()) { errs() << "\n***Cannot reduce functions: "; return MiscompiledFunctions; @@ -655,8 +654,8 @@ DebugAMiscompilation(BugDriver &BD, // Do the reduction... if (!BugpointIsInterrupted) - ReduceMiscompilingFunctions(BD, TestFn, Error) - .reduceList(MiscompiledFunctions); + ReduceMiscompilingFunctions(BD, TestFn) + .reduceList(MiscompiledFunctions, Error); if (!Error.empty()) return MiscompiledFunctions; @@ -678,8 +677,8 @@ DebugAMiscompilation(BugDriver &BD, DisambiguateGlobalSymbols(BD.getProgram()); // Do the reduction... - ReduceMiscompilingFunctions(BD, TestFn, Error) - .reduceList(MiscompiledFunctions); + ReduceMiscompilingFunctions(BD, TestFn) + .reduceList(MiscompiledFunctions, Error); if (!Error.empty()) return MiscompiledFunctions; @@ -733,7 +732,7 @@ static bool TestOptimizer(BugDriver &BD, std::unique_ptr<Module> Test, void BugDriver::debugMiscompilation(std::string *Error) { // Make sure something was miscompiled... if (!BugpointIsInterrupted) - if (!ReduceMiscompilingPasses(*this, *Error).reduceList(PassesToRun)) { + if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun, *Error)) { if (Error->empty()) errs() << "*** Optimized program matches reference output! No problem" << " detected...\nbugpoint can't help you with your problem!\n"; diff --git a/llvm/tools/bugpoint/bugpoint.cpp b/llvm/tools/bugpoint/bugpoint.cpp index 46b7e6ef5a8..fa4243fd057 100644 --- a/llvm/tools/bugpoint/bugpoint.cpp +++ b/llvm/tools/bugpoint/bugpoint.cpp @@ -197,5 +197,11 @@ int main(int argc, char **argv) { sys::Process::PreventCoreFiles(); #endif - return D.run(); + std::string Error; + bool Failure = D.run(Error); + if (!Error.empty()) { + errs() << Error; + return 1; + } + return Failure; } |