FindBugs.cpp revision 212793
1185573Srwatson//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===// 2155131Srwatson// 3168777Srwatson// The LLVM Compiler Infrastructure 4155131Srwatson// 5155131Srwatson// This file is distributed under the University of Illinois Open Source 6155131Srwatson// License. See LICENSE.TXT for details. 7155131Srwatson// 8168777Srwatson//===----------------------------------------------------------------------===// 9155131Srwatson// 10155131Srwatson// This file defines an interface that allows bugpoint to choose different 11168777Srwatson// combinations of optimizations to run on the selected input. Bugpoint will 12185573Srwatson// run these optimizations and record the success/failure of each. This way 13155131Srwatson// we can hopefully spot bugs in the optimizations. 14168777Srwatson// 15168777Srwatson//===----------------------------------------------------------------------===// 16155131Srwatson 17155131Srwatson#include "BugDriver.h" 18155131Srwatson#include "ToolRunner.h" 19155131Srwatson#include "llvm/Pass.h" 20155131Srwatson#include "llvm/Support/raw_ostream.h" 21155131Srwatson#include <algorithm> 22155131Srwatson#include <ctime> 23155131Srwatsonusing namespace llvm; 24155131Srwatson 25155131Srwatson/// runManyPasses - Take the specified pass list and create different 26155131Srwatson/// combinations of passes to compile the program with. Compile the program with 27155131Srwatson/// each set and mark test to see if it compiled correctly. If the passes 28155364Srwatson/// compiled correctly output nothing and rearrange the passes into a new order. 29155131Srwatson/// If the passes did not compile correctly, output the command required to 30155131Srwatson/// recreate the failure. This returns true if a compiler error is found. 31155131Srwatson/// 32155131Srwatsonbool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses, 33155131Srwatson std::string &ErrMsg) { 34155131Srwatson setPassesToRun(AllPasses); 35168777Srwatson outs() << "Starting bug finding procedure...\n\n"; 36168777Srwatson 37168777Srwatson // Creating a reference output if necessary 38168777Srwatson if (initializeExecutionEnvironment()) return false; 39155131Srwatson 40168777Srwatson outs() << "\n"; 41155131Srwatson if (ReferenceOutputFile.empty()) { 42168777Srwatson outs() << "Generating reference output from raw program: \n"; 43155131Srwatson if (!createReferenceFile(Program)) 44155131Srwatson return false; 45168777Srwatson } 46155131Srwatson 47155131Srwatson srand(time(NULL)); 48155131Srwatson 49155131Srwatson unsigned num = 1; 50168777Srwatson while(1) { 51155131Srwatson // 52168777Srwatson // Step 1: Randomize the order of the optimizer passes. 53155131Srwatson // 54155131Srwatson std::random_shuffle(PassesToRun.begin(), PassesToRun.end()); 55155131Srwatson 56155131Srwatson // 57168777Srwatson // Step 2: Run optimizer passes on the program and check for success. 58155131Srwatson // 59168777Srwatson outs() << "Running selected passes on program to test for crash: "; 60168777Srwatson for(int i = 0, e = PassesToRun.size(); i != e; i++) { 61168777Srwatson outs() << "-" << PassesToRun[i] << " "; 62168777Srwatson } 63168777Srwatson 64155131Srwatson std::string Filename; 65168777Srwatson if(runPasses(Program, PassesToRun, Filename, false)) { 66155131Srwatson outs() << "\n"; 67155131Srwatson outs() << "Optimizer passes caused failure!\n\n"; 68168777Srwatson debugOptimizerCrash(); 69168777Srwatson return true; 70168777Srwatson } else { 71168777Srwatson outs() << "Combination " << num << " optimized successfully!\n"; 72155131Srwatson } 73155131Srwatson 74155131Srwatson // 75 // Step 3: Compile the optimized code. 76 // 77 outs() << "Running the code generator to test for a crash: "; 78 std::string Error; 79 compileProgram(Program, &Error); 80 if (!Error.empty()) { 81 outs() << "\n*** compileProgram threw an exception: "; 82 outs() << Error; 83 return debugCodeGeneratorCrash(ErrMsg); 84 } 85 outs() << '\n'; 86 87 // 88 // Step 4: Run the program and compare its output to the reference 89 // output (created above). 90 // 91 outs() << "*** Checking if passes caused miscompliation:\n"; 92 bool Diff = diffProgram(Program, Filename, "", false, &Error); 93 if (Error.empty() && Diff) { 94 outs() << "\n*** diffProgram returned true!\n"; 95 debugMiscompilation(&Error); 96 if (Error.empty()) 97 return true; 98 } 99 if (!Error.empty()) { 100 errs() << Error; 101 debugCodeGeneratorCrash(ErrMsg); 102 return true; 103 } 104 outs() << "\n*** diff'd output matches!\n"; 105 106 sys::Path(Filename).eraseFromDisk(); 107 108 outs() << "\n\n"; 109 num++; 110 } //end while 111 112 // Unreachable. 113} 114