FindBugs.cpp revision 7f27570ae0cb716927f946f4e73a55f60d99b3e2
1032091d7f62774443c282915964189ea3d8930dePatrick Jenkins//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===// 2032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// 3032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// The LLVM Compiler Infrastructure 4032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// 5032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// This file was developed by Patrick Jenkins and is distributed under 6032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// the University of Illinois Open Source License. See LICENSE.TXT for details. 7032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// 8032091d7f62774443c282915964189ea3d8930dePatrick Jenkins//===----------------------------------------------------------------------===// 9032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// 10032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// This file defines an interface that allows bugpoint to choose different 11032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// combinations of optimizations to run on the selected input. Bugpoint will 12032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// run these optimizations and record the success/failure of each. This way 13032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// we can hopefully spot bugs in the optimizations. 14032091d7f62774443c282915964189ea3d8930dePatrick Jenkins// 15032091d7f62774443c282915964189ea3d8930dePatrick Jenkins//===----------------------------------------------------------------------===// 167f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner 17032091d7f62774443c282915964189ea3d8930dePatrick Jenkins#include "BugDriver.h" 18032091d7f62774443c282915964189ea3d8930dePatrick Jenkins#include "ToolRunner.h" 197f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner#include "llvm/Pass.h" 20032091d7f62774443c282915964189ea3d8930dePatrick Jenkins#include <algorithm> 21032091d7f62774443c282915964189ea3d8930dePatrick Jenkins#include <ctime> 227f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner#include <iostream> 23032091d7f62774443c282915964189ea3d8930dePatrick Jenkinsusing namespace llvm; 24032091d7f62774443c282915964189ea3d8930dePatrick Jenkins 25032091d7f62774443c282915964189ea3d8930dePatrick Jenkins/// runManyPasses - Take the specified pass list and create different 26032091d7f62774443c282915964189ea3d8930dePatrick Jenkins/// combinations of passes to compile the program with. Compile the program with 27032091d7f62774443c282915964189ea3d8930dePatrick Jenkins/// each set and mark test to see if it compiled correctly. If the passes 28032091d7f62774443c282915964189ea3d8930dePatrick Jenkins/// compiled correctly output nothing and rearrange the passes into a new order. 29032091d7f62774443c282915964189ea3d8930dePatrick Jenkins/// If the passes did not compile correctly, output the command required to 30032091d7f62774443c282915964189ea3d8930dePatrick Jenkins/// recreate the failure. This returns true if a compiler error is found. 31032091d7f62774443c282915964189ea3d8930dePatrick Jenkins/// 327f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattnerbool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) { 33032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::string Filename; 34032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::vector<const PassInfo*> TempPass(AllPasses); 35032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "Starting bug finding procedure...\n\n"; 36032091d7f62774443c282915964189ea3d8930dePatrick Jenkins 37032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // Creating a reference output if necessary 38032091d7f62774443c282915964189ea3d8930dePatrick Jenkins if (initializeExecutionEnvironment()) return false; 397f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner 40032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "\n"; 41032091d7f62774443c282915964189ea3d8930dePatrick Jenkins if (ReferenceOutputFile.empty()) { 427f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner std::cout << "Generating reference output from raw program: \n"; 437f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner if (!createReferenceFile(Program)) 447f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner return false; 45032091d7f62774443c282915964189ea3d8930dePatrick Jenkins } 46032091d7f62774443c282915964189ea3d8930dePatrick Jenkins 47032091d7f62774443c282915964189ea3d8930dePatrick Jenkins srand(time(NULL)); 48032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::vector<const PassInfo*>::iterator I = TempPass.begin(); 49032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::vector<const PassInfo*>::iterator E = TempPass.end(); 50032091d7f62774443c282915964189ea3d8930dePatrick Jenkins 517f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner unsigned num = 1; 527f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner while(1) { 53032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // 54032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // Step 1: Randomize the order of the optimizer passes. 55032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // 56032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::random_shuffle(TempPass.begin(), TempPass.end()); 57032091d7f62774443c282915964189ea3d8930dePatrick Jenkins 58032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // 59032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // Step 2: Run optimizer passes on the program and check for success. 60032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // 61032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "Running selected passes on program to test for crash: "; 627f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner for(int i = 0, e = TempPass.size(); i != e; i++) { 63032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "-" << TempPass[i]->getPassArgument( )<< " "; 64032091d7f62774443c282915964189ea3d8930dePatrick Jenkins } 657f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner 66032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::string Filename; 67032091d7f62774443c282915964189ea3d8930dePatrick Jenkins if(runPasses(TempPass, Filename, false)) { 68032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "\n"; 69032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "Optimizer passes caused failure!\n\n"; 70032091d7f62774443c282915964189ea3d8930dePatrick Jenkins debugOptimizerCrash(); 71032091d7f62774443c282915964189ea3d8930dePatrick Jenkins return true; 727f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner } else { 737f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner std::cout << "Combination " << num << " optimized successfully!\n"; 74032091d7f62774443c282915964189ea3d8930dePatrick Jenkins } 75032091d7f62774443c282915964189ea3d8930dePatrick Jenkins 76032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // 77032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // Step 3: Compile the optimized code. 78032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // 79032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "Running the code generator to test for a crash: "; 80032091d7f62774443c282915964189ea3d8930dePatrick Jenkins try { 81032091d7f62774443c282915964189ea3d8930dePatrick Jenkins compileProgram(Program); 82032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << '\n'; 83032091d7f62774443c282915964189ea3d8930dePatrick Jenkins } catch (ToolExecutionError &TEE) { 84032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "\n*** compileProgram threw an exception: "; 85032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << TEE.what(); 86032091d7f62774443c282915964189ea3d8930dePatrick Jenkins return debugCodeGeneratorCrash(); 87032091d7f62774443c282915964189ea3d8930dePatrick Jenkins } 88032091d7f62774443c282915964189ea3d8930dePatrick Jenkins 89032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // 90032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // Step 4: Run the program and compare its output to the reference 91032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // output (created above). 92032091d7f62774443c282915964189ea3d8930dePatrick Jenkins // 93032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "*** Checking if passes caused miscompliation:\n"; 94032091d7f62774443c282915964189ea3d8930dePatrick Jenkins try { 95032091d7f62774443c282915964189ea3d8930dePatrick Jenkins if (diffProgram(Filename, "", false)) { 96032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "\n*** diffProgram returned true!\n"; 97032091d7f62774443c282915964189ea3d8930dePatrick Jenkins debugMiscompilation(); 98032091d7f62774443c282915964189ea3d8930dePatrick Jenkins return true; 997f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner } else { 100032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "\n*** diff'd output matches!\n"; 101032091d7f62774443c282915964189ea3d8930dePatrick Jenkins } 102032091d7f62774443c282915964189ea3d8930dePatrick Jenkins } catch (ToolExecutionError &TEE) { 103032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cerr << TEE.what(); 104032091d7f62774443c282915964189ea3d8930dePatrick Jenkins debugCodeGeneratorCrash(); 105032091d7f62774443c282915964189ea3d8930dePatrick Jenkins return true; 106032091d7f62774443c282915964189ea3d8930dePatrick Jenkins } 107032091d7f62774443c282915964189ea3d8930dePatrick Jenkins 108032091d7f62774443c282915964189ea3d8930dePatrick Jenkins sys::Path(Filename).eraseFromDisk(); 109032091d7f62774443c282915964189ea3d8930dePatrick Jenkins 110032091d7f62774443c282915964189ea3d8930dePatrick Jenkins std::cout << "\n\n"; 111032091d7f62774443c282915964189ea3d8930dePatrick Jenkins num++; 112032091d7f62774443c282915964189ea3d8930dePatrick Jenkins } //end while 113032091d7f62774443c282915964189ea3d8930dePatrick Jenkins 1147f27570ae0cb716927f946f4e73a55f60d99b3e2Chris Lattner // Unreachable. 115032091d7f62774443c282915964189ea3d8930dePatrick Jenkins} 116