FindBugs.cpp revision 193323
1183371Simp//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===//
2183371Simp//
3183371Simp//                     The LLVM Compiler Infrastructure
4183371Simp//
5183371Simp// This file is distributed under the University of Illinois Open Source
6183371Simp// License. See LICENSE.TXT for details.
7183371Simp//
8183371Simp//===----------------------------------------------------------------------===//
9183371Simp//
10183371Simp// This file defines an interface that allows bugpoint to choose different
11183371Simp// combinations of optimizations to run on the selected input. Bugpoint will
12183371Simp// run these optimizations and record the success/failure of each. This way
13183371Simp// we can hopefully spot bugs in the optimizations.
14183371Simp//
15183371Simp//===----------------------------------------------------------------------===//
16183371Simp
17183371Simp#include "BugDriver.h"
18183371Simp#include "ToolRunner.h"
19183371Simp#include "llvm/Pass.h"
20183371Simp#include <algorithm>
21183371Simp#include <ctime>
22183371Simp#include <iostream>
23183371Simpusing namespace llvm;
24183371Simp
25183371Simp/// runManyPasses - Take the specified pass list and create different
26183371Simp/// combinations of passes to compile the program with. Compile the program with
27183371Simp/// each set and mark test to see if it compiled correctly. If the passes
28183371Simp/// compiled correctly output nothing and rearrange the passes into a new order.
29183371Simp/// If the passes did not compile correctly, output the command required to
30183371Simp/// recreate the failure. This returns true if a compiler error is found.
31183371Simp///
32183371Simpbool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) {
33183371Simp  setPassesToRun(AllPasses);
34183371Simp  std::cout << "Starting bug finding procedure...\n\n";
35183371Simp
36183371Simp  // Creating a reference output if necessary
37183371Simp  if (initializeExecutionEnvironment()) return false;
38183371Simp
39183371Simp  std::cout << "\n";
40183371Simp  if (ReferenceOutputFile.empty()) {
41183371Simp    std::cout << "Generating reference output from raw program: \n";
42183371Simp    if (!createReferenceFile(Program))
43183371Simp      return false;
44183371Simp  }
45183371Simp
46183371Simp  srand(time(NULL));
47183371Simp
48183371Simp  unsigned num = 1;
49183371Simp  while(1) {
50183371Simp    //
51183371Simp    // Step 1: Randomize the order of the optimizer passes.
52183371Simp    //
53183371Simp    std::random_shuffle(PassesToRun.begin(), PassesToRun.end());
54183371Simp
55183371Simp    //
56183371Simp    // Step 2: Run optimizer passes on the program and check for success.
57183371Simp    //
58183371Simp    std::cout << "Running selected passes on program to test for crash: ";
59183371Simp    for(int i = 0, e = PassesToRun.size(); i != e; i++) {
60183371Simp      std::cout << "-" << PassesToRun[i]->getPassArgument( )<< " ";
61183371Simp    }
62183371Simp
63183371Simp    std::string Filename;
64183371Simp    if(runPasses(PassesToRun, Filename, false)) {
65183371Simp      std::cout << "\n";
66183371Simp      std::cout << "Optimizer passes caused failure!\n\n";
67183371Simp      debugOptimizerCrash();
68183371Simp      return true;
69183371Simp    } else {
70183371Simp      std::cout << "Combination " << num << " optimized successfully!\n";
71183371Simp    }
72183371Simp
73183371Simp    //
74    // Step 3: Compile the optimized code.
75    //
76    std::cout << "Running the code generator to test for a crash: ";
77    try {
78      compileProgram(Program);
79      std::cout << '\n';
80    } catch (ToolExecutionError &TEE) {
81      std::cout << "\n*** compileProgram threw an exception: ";
82      std::cout << TEE.what();
83      return debugCodeGeneratorCrash();
84    }
85
86    //
87    // Step 4: Run the program and compare its output to the reference
88    // output (created above).
89    //
90    std::cout << "*** Checking if passes caused miscompliation:\n";
91    try {
92      if (diffProgram(Filename, "", false)) {
93        std::cout << "\n*** diffProgram returned true!\n";
94        debugMiscompilation();
95        return true;
96      } else {
97        std::cout << "\n*** diff'd output matches!\n";
98      }
99    } catch (ToolExecutionError &TEE) {
100      std::cerr << TEE.what();
101      debugCodeGeneratorCrash();
102      return true;
103    }
104
105    sys::Path(Filename).eraseFromDisk();
106
107    std::cout << "\n\n";
108    num++;
109  } //end while
110
111  // Unreachable.
112}
113