FindBugs.cpp revision 198090
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"
20198090Srdivacky#include "llvm/Support/raw_ostream.h"
21193323Sed#include <algorithm>
22193323Sed#include <ctime>
23193323Sedusing namespace llvm;
24193323Sed
25193323Sed/// runManyPasses - Take the specified pass list and create different
26193323Sed/// combinations of passes to compile the program with. Compile the program with
27193323Sed/// each set and mark test to see if it compiled correctly. If the passes
28193323Sed/// compiled correctly output nothing and rearrange the passes into a new order.
29193323Sed/// If the passes did not compile correctly, output the command required to
30193323Sed/// recreate the failure. This returns true if a compiler error is found.
31193323Sed///
32212793Sdimbool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses) {
33207618Srdivacky  setPassesToRun(AllPasses);
34193323Sed  outs() << "Starting bug finding procedure...\n\n";
35198090Srdivacky
36193323Sed  // Creating a reference output if necessary
37193323Sed  if (initializeExecutionEnvironment()) return false;
38193323Sed
39193323Sed  outs() << "\n";
40198090Srdivacky  if (ReferenceOutputFile.empty()) {
41193323Sed    outs() << "Generating reference output from raw program: \n";
42198090Srdivacky    if (!createReferenceFile(Program))
43193323Sed      return false;
44193323Sed  }
45193323Sed
46193323Sed  srand(time(NULL));
47193323Sed
48193323Sed  unsigned num = 1;
49193323Sed  while(1) {
50193323Sed    //
51193323Sed    // Step 1: Randomize the order of the optimizer passes.
52193323Sed    //
53193323Sed    std::random_shuffle(PassesToRun.begin(), PassesToRun.end());
54193323Sed
55193323Sed    //
56193323Sed    // Step 2: Run optimizer passes on the program and check for success.
57193323Sed    //
58193323Sed    outs() << "Running selected passes on program to test for crash: ";
59198090Srdivacky    for(int i = 0, e = PassesToRun.size(); i != e; i++) {
60193323Sed      outs() << "-" << PassesToRun[i]->getPassArgument( )<< " ";
61212793Sdim    }
62193323Sed
63193323Sed    std::string Filename;
64193323Sed    if(runPasses(PassesToRun, Filename, false)) {
65212793Sdim      outs() << "\n";
66198090Srdivacky      outs() << "Optimizer passes caused failure!\n\n";
67198090Srdivacky      debugOptimizerCrash();
68193323Sed      return true;
69193323Sed    } else {
70193323Sed      outs() << "Combination " << num << " optimized successfully!\n";
71198090Srdivacky    }
72193323Sed
73193323Sed    //
74193323Sed    // Step 3: Compile the optimized code.
75193323Sed    //
76193323Sed    outs() << "Running the code generator to test for a crash: ";
77198090Srdivacky    try {
78207618Srdivacky      compileProgram(Program);
79207618Srdivacky      outs() << '\n';
80207618Srdivacky    } catch (ToolExecutionError &TEE) {
81198090Srdivacky      outs() << "\n*** compileProgram threw an exception: ";
82207618Srdivacky      outs() << TEE.what();
83207618Srdivacky      return debugCodeGeneratorCrash();
84193323Sed    }
85207618Srdivacky
86193323Sed    //
87193323Sed    // Step 4: Run the program and compare its output to the reference
88193323Sed    // output (created above).
89193323Sed    //
90193323Sed    outs() << "*** Checking if passes caused miscompliation:\n";
91198090Srdivacky    try {
92212793Sdim      if (diffProgram(Filename, "", false)) {
93207618Srdivacky        outs() << "\n*** diffProgram returned true!\n";
94207618Srdivacky        debugMiscompilation();
95207618Srdivacky        return true;
96207618Srdivacky      } else {
97193323Sed        outs() << "\n*** diff'd output matches!\n";
98207618Srdivacky      }
99207618Srdivacky    } catch (ToolExecutionError &TEE) {
100207618Srdivacky      errs() << TEE.what();
101207618Srdivacky      debugCodeGeneratorCrash();
102193323Sed      return true;
103193323Sed    }
104207618Srdivacky
105193323Sed    sys::Path(Filename).eraseFromDisk();
106193323Sed
107193323Sed    outs() << "\n\n";
108198090Srdivacky    num++;
109193323Sed  } //end while
110193323Sed
111193323Sed  // Unreachable.
112193323Sed}
113193323Sed