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/raw_ostream.h" 21#include <algorithm> 22#include <ctime> 23using namespace llvm; 24 25/// runManyPasses - Take the specified pass list and create different 26/// combinations of passes to compile the program with. Compile the program with 27/// each set and mark test to see if it compiled correctly. If the passes 28/// compiled correctly output nothing and rearrange the passes into a new order. 29/// If the passes did not compile correctly, output the command required to 30/// recreate the failure. This returns true if a compiler error is found. 31/// 32bool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses, 33 std::string &ErrMsg) { 34 setPassesToRun(AllPasses); 35 outs() << "Starting bug finding procedure...\n\n"; 36 37 // Creating a reference output if necessary 38 if (initializeExecutionEnvironment()) return false; 39 40 outs() << "\n"; 41 if (ReferenceOutputFile.empty()) { 42 outs() << "Generating reference output from raw program: \n"; 43 if (!createReferenceFile(Program)) 44 return false; 45 } 46 47 srand(time(NULL)); 48 49 unsigned num = 1; 50 while(1) { 51 // 52 // Step 1: Randomize the order of the optimizer passes. 53 // 54 std::random_shuffle(PassesToRun.begin(), PassesToRun.end()); 55 56 // 57 // Step 2: Run optimizer passes on the program and check for success. 58 // 59 outs() << "Running selected passes on program to test for crash: "; 60 for(int i = 0, e = PassesToRun.size(); i != e; i++) { 61 outs() << "-" << PassesToRun[i] << " "; 62 } 63 64 std::string Filename; 65 if(runPasses(Program, PassesToRun, Filename, false)) { 66 outs() << "\n"; 67 outs() << "Optimizer passes caused failure!\n\n"; 68 debugOptimizerCrash(); 69 return true; 70 } else { 71 outs() << "Combination " << num << " optimized successfully!\n"; 72 } 73 74 // 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