3c4fa2dd47901845012a67cd7b79b18c5d7771d2
[oota-llvm.git] / tools / bugpoint / CrashDebugger.cpp
1 //===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//
2 //
3 // This file defines the bugpoint internals that narrow down compilation crashes
4 //
5 //===----------------------------------------------------------------------===//
6
7 #include "BugDriver.h"
8 #include "llvm/Module.h"
9 #include "llvm/Bytecode/Writer.h"
10 #include "llvm/Pass.h"
11 #include <fstream>
12
13 /// debugCrash - This method is called when some pass crashes on input.  It
14 /// attempts to prune down the testcase to something reasonable, and figure
15 /// out exactly which pass is crashing.
16 ///
17 bool BugDriver::debugCrash() {
18   std::cout << "\n*** Debugging optimizer crash!\n";
19
20   // Determine which pass causes the optimizer to crash... using binary search
21   unsigned LastToPass = 0, LastToCrash = PassesToRun.size();
22   while (LastToPass != LastToCrash) {
23     unsigned Mid = (LastToCrash+LastToPass+1) / 2;
24     std::vector<const PassInfo*> P(PassesToRun.begin(),
25                                    PassesToRun.begin()+Mid);
26     std::cout << "Checking to see if the first " << Mid << " passes crash: ";
27
28     if (runPasses(P))
29       LastToCrash = Mid-1;
30     else
31       LastToPass = Mid;
32   }
33
34   // Make sure something crashed.  :)
35   if (LastToCrash >= PassesToRun.size()) {
36     std::cerr << "ERROR: No passes crashed!\n";
37     return true;
38   }
39
40   // Calculate which pass it is that crashes...
41   const PassInfo *CrashingPass = PassesToRun[LastToCrash];
42   
43   std::cout << "\n*** Found crashing pass '-" << CrashingPass->getPassArgument()
44             << "': " << CrashingPass->getPassName() << "\n";
45
46   // Compile the program with just the passes that don't crash.
47   if (LastToPass != 0) {
48     // Don't bother doing this if the first pass crashes...
49     std::vector<const PassInfo*> P(PassesToRun.begin(), 
50                                    PassesToRun.begin()+LastToPass);
51     std::string Filename;
52     std::cout << "Running passes that don't crash to get input for pass: ";
53     if (runPasses(P, Filename)) {
54       std::cerr << "ERROR: Running the first " << LastToPass
55                 << " passes crashed this time!\n";
56       return true;
57     }
58
59     // Assuming everything was successful, we now have a valid bytecode file in
60     // OutputName.  Use it for "Program" Instead.
61     delete Program;
62     Program = ParseInputFile(Filename);
63
64     // Delete the file now.
65     removeFile(Filename);
66   }
67
68   return debugPassCrash(CrashingPass);
69 }
70
71 /// CountFunctions - return the number of non-external functions defined in the
72 /// module.
73 static unsigned CountFunctions(Module *M) {
74   unsigned N = 0;
75   for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
76     if (!I->isExternal())
77       ++N;
78   return N;
79 }
80
81 /// debugPassCrash - This method is called when the specified pass crashes on
82 /// Program as input.  It tries to reduce the testcase to something that still
83 /// crashes, but it smaller.
84 ///
85 bool BugDriver::debugPassCrash(const PassInfo *Pass) {
86   EmitProgressBytecode(Pass, "passinput");
87
88   if (CountFunctions(Program) > 1) {
89     // Attempt to reduce the input program down to a single function that still
90     // crashes.
91     //
92     std::cout << "\n*** Attempting to reduce the testcase to one function\n";
93
94     for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
95       if (!I->isExternal()) {
96         // Extract one function from the module...
97         Module *M = extractFunctionFromModule(I);
98
99         // Make the function the current program...
100         std::swap(Program, M);
101         
102         // Find out if the pass still crashes on this pass...
103         std::cout << "Checking function '" << I->getName() << "': ";
104         if (runPass(Pass)) {
105           // Yup, it does, we delete the old module, and continue trying to
106           // reduce the testcase...
107           delete M;
108
109           EmitProgressBytecode(Pass, "reduced-"+I->getName());
110           break;
111         }
112         
113         // This pass didn't crash on this function, try the next one.
114         delete Program;
115         Program = M;
116       }
117   }
118
119   return false;
120 }