1193323Sed//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file defines an interface that allows bugpoint to choose different 11193323Sed// combinations of optimizations to run on the selected input. Bugpoint will 12193323Sed// run these optimizations and record the success/failure of each. This way 13193323Sed// we can hopefully spot bugs in the optimizations. 14193323Sed// 15193323Sed//===----------------------------------------------------------------------===// 16193323Sed 17193323Sed#include "BugDriver.h" 18193323Sed#include "ToolRunner.h" 19193323Sed#include "llvm/Pass.h" 20263508Sdim#include "llvm/Support/FileSystem.h" 21198090Srdivacky#include "llvm/Support/raw_ostream.h" 22193323Sed#include <algorithm> 23193323Sed#include <ctime> 24193323Sedusing namespace llvm; 25193323Sed 26193323Sed/// runManyPasses - Take the specified pass list and create different 27193323Sed/// combinations of passes to compile the program with. Compile the program with 28193323Sed/// each set and mark test to see if it compiled correctly. If the passes 29193323Sed/// compiled correctly output nothing and rearrange the passes into a new order. 30193323Sed/// If the passes did not compile correctly, output the command required to 31193323Sed/// recreate the failure. This returns true if a compiler error is found. 32193323Sed/// 33212793Sdimbool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses, 34207618Srdivacky std::string &ErrMsg) { 35193323Sed setPassesToRun(AllPasses); 36198090Srdivacky outs() << "Starting bug finding procedure...\n\n"; 37193323Sed 38193323Sed // Creating a reference output if necessary 39193323Sed if (initializeExecutionEnvironment()) return false; 40193323Sed 41198090Srdivacky outs() << "\n"; 42193323Sed if (ReferenceOutputFile.empty()) { 43198090Srdivacky outs() << "Generating reference output from raw program: \n"; 44193323Sed if (!createReferenceFile(Program)) 45193323Sed return false; 46193323Sed } 47193323Sed 48193323Sed srand(time(NULL)); 49193323Sed 50193323Sed unsigned num = 1; 51193323Sed while(1) { 52193323Sed // 53193323Sed // Step 1: Randomize the order of the optimizer passes. 54193323Sed // 55193323Sed std::random_shuffle(PassesToRun.begin(), PassesToRun.end()); 56193323Sed 57193323Sed // 58193323Sed // Step 2: Run optimizer passes on the program and check for success. 59193323Sed // 60198090Srdivacky outs() << "Running selected passes on program to test for crash: "; 61193323Sed for(int i = 0, e = PassesToRun.size(); i != e; i++) { 62212793Sdim outs() << "-" << PassesToRun[i] << " "; 63193323Sed } 64193323Sed 65193323Sed std::string Filename; 66212793Sdim if(runPasses(Program, PassesToRun, Filename, false)) { 67198090Srdivacky outs() << "\n"; 68198090Srdivacky outs() << "Optimizer passes caused failure!\n\n"; 69193323Sed debugOptimizerCrash(); 70193323Sed return true; 71193323Sed } else { 72198090Srdivacky outs() << "Combination " << num << " optimized successfully!\n"; 73193323Sed } 74193323Sed 75193323Sed // 76193323Sed // Step 3: Compile the optimized code. 77193323Sed // 78198090Srdivacky outs() << "Running the code generator to test for a crash: "; 79207618Srdivacky std::string Error; 80207618Srdivacky compileProgram(Program, &Error); 81207618Srdivacky if (!Error.empty()) { 82198090Srdivacky outs() << "\n*** compileProgram threw an exception: "; 83207618Srdivacky outs() << Error; 84207618Srdivacky return debugCodeGeneratorCrash(ErrMsg); 85193323Sed } 86207618Srdivacky outs() << '\n'; 87193323Sed 88193323Sed // 89193323Sed // Step 4: Run the program and compare its output to the reference 90193323Sed // output (created above). 91193323Sed // 92198090Srdivacky outs() << "*** Checking if passes caused miscompliation:\n"; 93212793Sdim bool Diff = diffProgram(Program, Filename, "", false, &Error); 94207618Srdivacky if (Error.empty() && Diff) { 95207618Srdivacky outs() << "\n*** diffProgram returned true!\n"; 96207618Srdivacky debugMiscompilation(&Error); 97207618Srdivacky if (Error.empty()) 98193323Sed return true; 99207618Srdivacky } 100207618Srdivacky if (!Error.empty()) { 101207618Srdivacky errs() << Error; 102207618Srdivacky debugCodeGeneratorCrash(ErrMsg); 103193323Sed return true; 104193323Sed } 105207618Srdivacky outs() << "\n*** diff'd output matches!\n"; 106193323Sed 107263508Sdim sys::fs::remove(Filename); 108193323Sed 109198090Srdivacky outs() << "\n\n"; 110193323Sed num++; 111193323Sed } //end while 112193323Sed 113193323Sed // Unreachable. 114193323Sed} 115