1 //===-- FindBugs.cpp - Run Many Different Optimizations -------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines an interface that allows bugpoint to choose different 11 // combinations of optimizations to run on the selected input. Bugpoint will 12 // run these optimizations and record the success/failure of each. This way 13 // we can hopefully spot bugs in the optimizations. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "BugDriver.h" 18 #include "ToolRunner.h" 19 #include "llvm/Pass.h" 20 #include "llvm/Support/FileSystem.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include <algorithm> 23 #include <ctime> 24 using namespace llvm; 25 26 /// runManyPasses - Take the specified pass list and create different 27 /// combinations of passes to compile the program with. Compile the program with 28 /// each set and mark test to see if it compiled correctly. If the passes 29 /// compiled correctly output nothing and rearrange the passes into a new order. 30 /// If the passes did not compile correctly, output the command required to 31 /// recreate the failure. This returns true if a compiler error is found. 32 /// 33 bool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses, 34 std::string &ErrMsg) { 35 setPassesToRun(AllPasses); 36 outs() << "Starting bug finding procedure...\n\n"; 37 38 // Creating a reference output if necessary 39 if (initializeExecutionEnvironment()) return false; 40 41 outs() << "\n"; 42 if (ReferenceOutputFile.empty()) { 43 outs() << "Generating reference output from raw program: \n"; 44 if (!createReferenceFile(Program)) 45 return false; 46 } 47 48 srand(time(nullptr)); 49 50 unsigned num = 1; 51 while(1) { 52 // 53 // Step 1: Randomize the order of the optimizer passes. 54 // 55 std::random_shuffle(PassesToRun.begin(), PassesToRun.end()); 56 57 // 58 // Step 2: Run optimizer passes on the program and check for success. 59 // 60 outs() << "Running selected passes on program to test for crash: "; 61 for(int i = 0, e = PassesToRun.size(); i != e; i++) { 62 outs() << "-" << PassesToRun[i] << " "; 63 } 64 65 std::string Filename; 66 if(runPasses(Program, PassesToRun, Filename, false)) { 67 outs() << "\n"; 68 outs() << "Optimizer passes caused failure!\n\n"; 69 debugOptimizerCrash(); 70 return true; 71 } else { 72 outs() << "Combination " << num << " optimized successfully!\n"; 73 } 74 75 // 76 // Step 3: Compile the optimized code. 77 // 78 outs() << "Running the code generator to test for a crash: "; 79 std::string Error; 80 compileProgram(Program, &Error); 81 if (!Error.empty()) { 82 outs() << "\n*** compileProgram threw an exception: "; 83 outs() << Error; 84 return debugCodeGeneratorCrash(ErrMsg); 85 } 86 outs() << '\n'; 87 88 // 89 // Step 4: Run the program and compare its output to the reference 90 // output (created above). 91 // 92 outs() << "*** Checking if passes caused miscompliation:\n"; 93 bool Diff = diffProgram(Program, Filename, "", false, &Error); 94 if (Error.empty() && Diff) { 95 outs() << "\n*** diffProgram returned true!\n"; 96 debugMiscompilation(&Error); 97 if (Error.empty()) 98 return true; 99 } 100 if (!Error.empty()) { 101 errs() << Error; 102 debugCodeGeneratorCrash(ErrMsg); 103 return true; 104 } 105 outs() << "\n*** diff'd output matches!\n"; 106 107 sys::fs::remove(Filename); 108 109 outs() << "\n\n"; 110 num++; 111 } //end while 112 113 // Unreachable. 114 } 115