FindBugs.cpp revision 193323
1155131Srwatson//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===//
2155131Srwatson//
3155131Srwatson//                     The LLVM Compiler Infrastructure
4155131Srwatson//
5155131Srwatson// This file is distributed under the University of Illinois Open Source
6155131Srwatson// License. See LICENSE.TXT for details.
7155131Srwatson//
8155131Srwatson//===----------------------------------------------------------------------===//
9155131Srwatson//
10155131Srwatson// This file defines an interface that allows bugpoint to choose different
11155131Srwatson// combinations of optimizations to run on the selected input. Bugpoint will
12155131Srwatson// run these optimizations and record the success/failure of each. This way
13168777Srwatson// we can hopefully spot bugs in the optimizations.
14155131Srwatson//
15155131Srwatson//===----------------------------------------------------------------------===//
16155131Srwatson
17155131Srwatson#include "BugDriver.h"
18155131Srwatson#include "ToolRunner.h"
19155131Srwatson#include "llvm/Pass.h"
20155131Srwatson#include <algorithm>
21155131Srwatson#include <ctime>
22155131Srwatson#include <iostream>
23155131Srwatsonusing namespace llvm;
24155131Srwatson
25155131Srwatson/// runManyPasses - Take the specified pass list and create different
26155131Srwatson/// combinations of passes to compile the program with. Compile the program with
27155131Srwatson/// each set and mark test to see if it compiled correctly. If the passes
28155131Srwatson/// compiled correctly output nothing and rearrange the passes into a new order.
29155131Srwatson/// If the passes did not compile correctly, output the command required to
30155131Srwatson/// recreate the failure. This returns true if a compiler error is found.
31155131Srwatson///
32155131Srwatsonbool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) {
33168777Srwatson  setPassesToRun(AllPasses);
34155131Srwatson  std::cout << "Starting bug finding procedure...\n\n";
35155131Srwatson
36155131Srwatson  // Creating a reference output if necessary
37168777Srwatson  if (initializeExecutionEnvironment()) return false;
38155131Srwatson
39155131Srwatson  std::cout << "\n";
40155131Srwatson  if (ReferenceOutputFile.empty()) {
41155131Srwatson    std::cout << "Generating reference output from raw program: \n";
42155131Srwatson    if (!createReferenceFile(Program))
43155131Srwatson      return false;
44155131Srwatson  }
45155131Srwatson
46155131Srwatson  srand(time(NULL));
47155131Srwatson
48155131Srwatson  unsigned num = 1;
49155131Srwatson  while(1) {
50168777Srwatson    //
51155131Srwatson    // Step 1: Randomize the order of the optimizer passes.
52168777Srwatson    //
53155131Srwatson    std::random_shuffle(PassesToRun.begin(), PassesToRun.end());
54168777Srwatson
55155131Srwatson    //
56168777Srwatson    // Step 2: Run optimizer passes on the program and check for success.
57155131Srwatson    //
58168777Srwatson    std::cout << "Running selected passes on program to test for crash: ";
59155131Srwatson    for(int i = 0, e = PassesToRun.size(); i != e; i++) {
60155131Srwatson      std::cout << "-" << PassesToRun[i]->getPassArgument( )<< " ";
61155131Srwatson    }
62155131Srwatson
63155131Srwatson    std::string Filename;
64155131Srwatson    if(runPasses(PassesToRun, Filename, false)) {
65155131Srwatson      std::cout << "\n";
66168777Srwatson      std::cout << "Optimizer passes caused failure!\n\n";
67155131Srwatson      debugOptimizerCrash();
68155131Srwatson      return true;
69155131Srwatson    } else {
70155131Srwatson      std::cout << "Combination " << num << " optimized successfully!\n";
71155131Srwatson    }
72155131Srwatson
73155131Srwatson    //
74155131Srwatson    // Step 3: Compile the optimized code.
75155131Srwatson    //
76168777Srwatson    std::cout << "Running the code generator to test for a crash: ";
77155131Srwatson    try {
78168777Srwatson      compileProgram(Program);
79155131Srwatson      std::cout << '\n';
80155131Srwatson    } catch (ToolExecutionError &TEE) {
81168777Srwatson      std::cout << "\n*** compileProgram threw an exception: ";
82155131Srwatson      std::cout << TEE.what();
83168777Srwatson      return debugCodeGeneratorCrash();
84155131Srwatson    }
85168777Srwatson
86155131Srwatson    //
87168777Srwatson    // Step 4: Run the program and compare its output to the reference
88155131Srwatson    // output (created above).
89168777Srwatson    //
90155131Srwatson    std::cout << "*** Checking if passes caused miscompliation:\n";
91168777Srwatson    try {
92168777Srwatson      if (diffProgram(Filename, "", false)) {
93168777Srwatson        std::cout << "\n*** diffProgram returned true!\n";
94168777Srwatson        debugMiscompilation();
95155131Srwatson        return true;
96155131Srwatson      } else {
97168777Srwatson        std::cout << "\n*** diff'd output matches!\n";
98155131Srwatson      }
99155131Srwatson    } catch (ToolExecutionError &TEE) {
100155131Srwatson      std::cerr << TEE.what();
101168777Srwatson      debugCodeGeneratorCrash();
102168777Srwatson      return true;
103168777Srwatson    }
104168777Srwatson
105168777Srwatson    sys::Path(Filename).eraseFromDisk();
106168777Srwatson
107168777Srwatson    std::cout << "\n\n";
108155131Srwatson    num++;
109168777Srwatson  } //end while
110155131Srwatson
111168777Srwatson  // Unreachable.
112168777Srwatson}
113155131Srwatson