blob: aae5791935ce483aa99b38b1c23234a6960382b4 [file] [log] [blame]
Chris Lattnerafade922002-11-20 22:28:10 +00001//===- OptimizerDriver.cpp - Allow BugPoint to run passes safely ----------===//
2//
3// This file defines an interface that allows bugpoint to run various passes
4// without the threat of a buggy pass corrupting bugpoint (of course bugpoint
5// may have it's own bugs, but that's another story...). It acheives this by
6// forking a copy of itself and having the child process do the optimizations.
7// If this client dies, we can always fork a new one. :)
8//
9//===----------------------------------------------------------------------===//
10
11#include "BugDriver.h"
Chris Lattner218e26e2002-12-23 23:49:59 +000012#include "SystemUtils.h"
Chris Lattnerafade922002-11-20 22:28:10 +000013#include "llvm/PassManager.h"
14#include "llvm/Analysis/Verifier.h"
15#include "llvm/Bytecode/WriteBytecodePass.h"
16#include <sys/types.h>
17#include <sys/wait.h>
18#include <unistd.h>
19#include <stdlib.h>
20#include <fstream>
21
Chris Lattnerafade922002-11-20 22:28:10 +000022/// writeProgramToFile - This writes the current "Program" to the named bytecode
23/// file. If an error occurs, true is returned.
24///
Chris Lattner218e26e2002-12-23 23:49:59 +000025bool BugDriver::writeProgramToFile(const std::string &Filename,
26 Module *M) const {
Chris Lattnerafade922002-11-20 22:28:10 +000027 std::ofstream Out(Filename.c_str());
28 if (!Out.good()) return true;
Chris Lattner218e26e2002-12-23 23:49:59 +000029 WriteBytecodeToFile(M ? M : Program, Out);
Chris Lattnerafade922002-11-20 22:28:10 +000030 return false;
31}
32
33
34/// EmitProgressBytecode - This function is used to output the current Program
35/// to a file named "bugpoing-ID.bc".
36///
37void BugDriver::EmitProgressBytecode(const PassInfo *Pass,
38 const std::string &ID) {
39 // Output the input to the current pass to a bytecode file, emit a message
40 // telling the user how to reproduce it: opt -foo blah.bc
41 //
42 std::string Filename = "bugpoint-" + ID + ".bc";
43 if (writeProgramToFile(Filename)) {
44 std::cerr << "Error opening file '" << Filename << "' for writing!\n";
45 return;
46 }
47
Chris Lattner218e26e2002-12-23 23:49:59 +000048 std::cout << "Emitted bytecode to '" << Filename << "'\n";
Chris Lattnerafade922002-11-20 22:28:10 +000049 std::cout << "\n*** You can reproduce the problem with: ";
50
51 unsigned PassType = Pass->getPassType();
52 if (PassType & PassInfo::Analysis)
53 std::cout << "analyze";
54 else if (PassType & PassInfo::Optimization)
55 std::cout << "opt";
56 else if (PassType & PassInfo::LLC)
57 std::cout << "llc";
58 else
59 std::cout << "bugpoint";
60 std::cout << " " << Filename << " -" << Pass->getPassArgument() << "\n";
61}
62
63
64static void RunChild(Module *Program,const std::vector<const PassInfo*> &Passes,
65 const std::string &OutFilename) {
66 std::ofstream OutFile(OutFilename.c_str());
67 if (!OutFile.good()) {
68 std::cerr << "Error opening bytecode file: " << OutFilename << "\n";
69 exit(1);
70 }
71
72 PassManager PM;
73 for (unsigned i = 0, e = Passes.size(); i != e; ++i) {
74 if (Passes[i]->getNormalCtor())
75 PM.add(Passes[i]->getNormalCtor()());
76 else
77 std::cerr << "Cannot create pass yet: " << Passes[i]->getPassName()
78 << "\n";
79 }
80 // Check that the module is well formed on completion of optimization
81 PM.add(createVerifierPass());
82
83 // Write bytecode out to disk as the last step...
84 PM.add(new WriteBytecodePass(&OutFile));
85
86 // Run all queued passes.
87 PM.run(*Program);
88}
89
90/// runPasses - Run the specified passes on Program, outputting a bytecode file
91/// and writting the filename into OutputFile if successful. If the
92/// optimizations fail for some reason (optimizer crashes), return true,
93/// otherwise return false. If DeleteOutput is set to true, the bytecode is
94/// deleted on success, and the filename string is undefined. This prints to
95/// cout a single line message indicating whether compilation was successful or
96/// failed.
97///
98bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
Chris Lattner218e26e2002-12-23 23:49:59 +000099 std::string &OutputFilename, bool DeleteOutput,
100 bool Quiet) const{
Chris Lattnerafade922002-11-20 22:28:10 +0000101 std::cout << std::flush;
Chris Lattner218e26e2002-12-23 23:49:59 +0000102 OutputFilename = getUniqueFilename("bugpoint-output.bc");
Chris Lattnerafade922002-11-20 22:28:10 +0000103
Chris Lattnerafade922002-11-20 22:28:10 +0000104 pid_t child_pid;
105 switch (child_pid = fork()) {
106 case -1: // Error occurred
107 std::cerr << ToolName << ": Error forking!\n";
108 exit(1);
109 case 0: // Child process runs passes.
110 RunChild(Program, Passes, OutputFilename);
111 exit(0); // If we finish successfully, return 0!
112 default: // Parent continues...
113 break;
114 }
115
116 // Wait for the child process to get done.
117 int Status;
118 if (wait(&Status) != child_pid) {
119 std::cerr << "Error waiting for child process!\n";
120 exit(1);
121 }
122
123 // If we are supposed to delete the bytecode file, remove it now
124 // unconditionally... this may fail if the file was never created, but that's
125 // ok.
126 if (DeleteOutput)
127 removeFile(OutputFilename);
128
Chris Lattner218e26e2002-12-23 23:49:59 +0000129 if (!Quiet) std::cout << (Status ? "Crashed!\n" : "Success!\n");
Chris Lattnerafade922002-11-20 22:28:10 +0000130
131 // Was the child successful?
132 return Status != 0;
133}