FindBugs.cpp revision 263508
160107Sobrien//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===// 242784Syokota// 3270114Sse// The LLVM Compiler Infrastructure 4270114Sse// 542784Syokota// This file is distributed under the University of Illinois Open Source 642784Syokota// License. See LICENSE.TXT for details. 742784Syokota// 842784Syokota//===----------------------------------------------------------------------===// 942784Syokota// 1042784Syokota// This file defines an interface that allows bugpoint to choose different 1142784Syokota// combinations of optimizations to run on the selected input. Bugpoint will 1242784Syokota// run these optimizations and record the success/failure of each. This way 1342784Syokota// we can hopefully spot bugs in the optimizations. 1442784Syokota// 1542784Syokota//===----------------------------------------------------------------------===// 1642784Syokota 1742784Syokota#include "BugDriver.h" 1842784Syokota#include "ToolRunner.h" 1942784Syokota#include "llvm/Pass.h" 20293047Semaste#include "llvm/Support/FileSystem.h" 2142784Syokota#include "llvm/Support/raw_ostream.h" 2242784Syokota#include <algorithm> 2342784Syokota#include <ctime> 2442784Syokotausing namespace llvm; 2542784Syokota 26270114Sse/// runManyPasses - Take the specified pass list and create different 2742784Syokota/// combinations of passes to compile the program with. Compile the program with 2842784Syokota/// each set and mark test to see if it compiled correctly. If the passes 2942784Syokota/// compiled correctly output nothing and rearrange the passes into a new order. 3042784Syokota/// If the passes did not compile correctly, output the command required to 3142784Syokota/// recreate the failure. This returns true if a compiler error is found. 3242784Syokota/// 3342784Syokotabool BugDriver::runManyPasses(const std::vector<std::string> &AllPasses, 3442784Syokota std::string &ErrMsg) { 3542784Syokota setPassesToRun(AllPasses); 3642784Syokota outs() << "Starting bug finding procedure...\n\n"; 3742784Syokota 3842784Syokota // Creating a reference output if necessary 3942784Syokota if (initializeExecutionEnvironment()) return false; 4042784Syokota 4142784Syokota outs() << "\n"; 4242784Syokota if (ReferenceOutputFile.empty()) { 4342784Syokota outs() << "Generating reference output from raw program: \n"; 4442784Syokota if (!createReferenceFile(Program)) 4542784Syokota return false; 4642784Syokota } 47270114Sse 4842784Syokota srand(time(NULL)); 4942784Syokota 5042784Syokota unsigned num = 1; 5142784Syokota while(1) { 5242784Syokota // 5342784Syokota // Step 1: Randomize the order of the optimizer passes. 5442784Syokota // 5542784Syokota std::random_shuffle(PassesToRun.begin(), PassesToRun.end()); 5642784Syokota 5742784Syokota // 5842784Syokota // Step 2: Run optimizer passes on the program and check for success. 5943334Syokota // 6042784Syokota outs() << "Running selected passes on program to test for crash: "; 6142784Syokota for(int i = 0, e = PassesToRun.size(); i != e; i++) { 6242784Syokota outs() << "-" << PassesToRun[i] << " "; 6343334Syokota } 6442784Syokota 65270114Sse std::string Filename; 6642784Syokota if(runPasses(Program, PassesToRun, Filename, false)) { 6742784Syokota outs() << "\n"; 6842784Syokota outs() << "Optimizer passes caused failure!\n\n"; 6942784Syokota debugOptimizerCrash(); 7042784Syokota return true; 7142784Syokota } else { 7242784Syokota outs() << "Combination " << num << " optimized successfully!\n"; 7342784Syokota } 7442784Syokota 7542784Syokota // 7642784Syokota // Step 3: Compile the optimized code. 7742784Syokota // 7842784Syokota outs() << "Running the code generator to test for a crash: "; 7942784Syokota std::string Error; 8042784Syokota compileProgram(Program, &Error); 8142784Syokota if (!Error.empty()) { 8242784Syokota outs() << "\n*** compileProgram threw an exception: "; 8342784Syokota outs() << Error; 8443334Syokota return debugCodeGeneratorCrash(ErrMsg); 8542784Syokota } 8642784Syokota outs() << '\n'; 8742784Syokota 8842784Syokota // 8942784Syokota // Step 4: Run the program and compare its output to the reference 9042784Syokota // output (created above). 9143334Syokota // 9243334Syokota outs() << "*** Checking if passes caused miscompliation:\n"; 9343334Syokota bool Diff = diffProgram(Program, Filename, "", false, &Error); 9442784Syokota if (Error.empty() && Diff) { 9542784Syokota outs() << "\n*** diffProgram returned true!\n"; 9642784Syokota debugMiscompilation(&Error); 9742784Syokota if (Error.empty()) 9842784Syokota return true; 9942784Syokota } 10074119Sache if (!Error.empty()) { 10142784Syokota errs() << Error; 10242784Syokota debugCodeGeneratorCrash(ErrMsg); 10342784Syokota return true; 10442784Syokota } 10542784Syokota outs() << "\n*** diff'd output matches!\n"; 10642784Syokota 10742784Syokota sys::fs::remove(Filename); 10842784Syokota 10942784Syokota outs() << "\n\n"; 11074119Sache num++; 11143334Syokota } //end while 11243334Syokota 11343334Syokota // Unreachable. 11443334Syokota} 11543334Syokota