blob: 385a35746f6cdb75b290d5971b0457ec06f526bc [file] [log] [blame]
Patrick Jenkins032091d2006-08-15 16:41:52 +00001//===-- FindBugs.cpp - Run Many Different Optimizations -------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Patrick Jenkins and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an interface that allows bugpoint to choose different
11// combinations of optimizations to run on the selected input. Bugpoint will
12// run these optimizations and record the success/failure of each. This way
13// we can hopefully spot bugs in the optimizations.
14//
15//===----------------------------------------------------------------------===//
16#include "BugDriver.h"
17#include "ToolRunner.h"
18
19#include "llvm/Bytecode/WriteBytecodePass.h"
20
21#include <algorithm>
22#include <ctime>
23using namespace llvm;
24
25/// runManyPasses - Take the specified pass list and create different
26/// combinations of passes to compile the program with. Compile the program with
27/// each set and mark test to see if it compiled correctly. If the passes
28/// compiled correctly output nothing and rearrange the passes into a new order.
29/// If the passes did not compile correctly, output the command required to
30/// recreate the failure. This returns true if a compiler error is found.
31///
32bool BugDriver::runManyPasses(const std::vector<const PassInfo*> &AllPasses)
33{
34 std::string Filename;
35 std::vector<const PassInfo*> TempPass(AllPasses);
36 std::cout << "Starting bug finding procedure...\n\n";
37
38 // Creating a reference output if necessary
39 if (initializeExecutionEnvironment()) return false;
40 std::cout << "\n";
41 if (ReferenceOutputFile.empty()) {
42 std::cout << "Generating reference output from raw program: \n";
43 if(!createReferenceFile(Program)){
44 return false;
45 }
46 }
47
48 srand(time(NULL));
49 std::vector<const PassInfo*>::iterator I = TempPass.begin();
50 std::vector<const PassInfo*>::iterator E = TempPass.end();
51
52 int num=1;
53 while(1){
54 //
55 // Step 1: Randomize the order of the optimizer passes.
56 //
57 std::random_shuffle(TempPass.begin(), TempPass.end());
58
59 //
60 // Step 2: Run optimizer passes on the program and check for success.
61 //
62 std::cout << "Running selected passes on program to test for crash: ";
63 for(int i=0, e=TempPass.size(); i!=e; i++) {
64 std::cout << "-" << TempPass[i]->getPassArgument( )<< " ";
65 }
66 std::string Filename;
67 if(runPasses(TempPass, Filename, false)) {
68 std::cout << "\n";
69 std::cout << "Optimizer passes caused failure!\n\n";
70 debugOptimizerCrash();
71 return true;
72 }
73 else{
74 std::cout << "Combination "<<num<<" optimized successfully!\n";
75 }
76
77 //
78 // Step 3: Compile the optimized code.
79 //
80 std::cout << "Running the code generator to test for a crash: ";
81 try {
82 compileProgram(Program);
83 std::cout << '\n';
84 } catch (ToolExecutionError &TEE) {
85 std::cout << "\n*** compileProgram threw an exception: ";
86 std::cout << TEE.what();
87 return debugCodeGeneratorCrash();
88 }
89
90 //
91 // Step 4: Run the program and compare its output to the reference
92 // output (created above).
93 //
94 std::cout << "*** Checking if passes caused miscompliation:\n";
95 try {
96 if (diffProgram(Filename, "", false)) {
97 std::cout << "\n*** diffProgram returned true!\n";
98 debugMiscompilation();
99 return true;
100 }
101 else{
102 std::cout << "\n*** diff'd output matches!\n";
103 }
104 } catch (ToolExecutionError &TEE) {
105 std::cerr << TEE.what();
106 debugCodeGeneratorCrash();
107 return true;
108 }
109
110 sys::Path(Filename).eraseFromDisk();
111
112 std::cout << "\n\n";
113 num++;
114 } //end while
115
116 // This will never be reached
117 std::cout << "Did not find any bugs :-( \n";
118 return false;
119}