blob: 300ba950697ac3e99a01a374546a13421301bc8f [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"
Chris Lattnerf2bcccf2003-01-22 23:24:11 +000016#include "llvm/Target/TargetData.h"
Chris Lattnerafade922002-11-20 22:28:10 +000017#include <sys/types.h>
18#include <sys/wait.h>
19#include <unistd.h>
20#include <stdlib.h>
21#include <fstream>
22
Chris Lattnerafade922002-11-20 22:28:10 +000023/// writeProgramToFile - This writes the current "Program" to the named bytecode
24/// file. If an error occurs, true is returned.
25///
Chris Lattner218e26e2002-12-23 23:49:59 +000026bool BugDriver::writeProgramToFile(const std::string &Filename,
27 Module *M) const {
Chris Lattnerafade922002-11-20 22:28:10 +000028 std::ofstream Out(Filename.c_str());
29 if (!Out.good()) return true;
Chris Lattner218e26e2002-12-23 23:49:59 +000030 WriteBytecodeToFile(M ? M : Program, Out);
Chris Lattnerafade922002-11-20 22:28:10 +000031 return false;
32}
33
34
35/// EmitProgressBytecode - This function is used to output the current Program
36/// to a file named "bugpoing-ID.bc".
37///
38void BugDriver::EmitProgressBytecode(const PassInfo *Pass,
39 const std::string &ID) {
40 // Output the input to the current pass to a bytecode file, emit a message
41 // telling the user how to reproduce it: opt -foo blah.bc
42 //
43 std::string Filename = "bugpoint-" + ID + ".bc";
44 if (writeProgramToFile(Filename)) {
45 std::cerr << "Error opening file '" << Filename << "' for writing!\n";
46 return;
47 }
48
Chris Lattner218e26e2002-12-23 23:49:59 +000049 std::cout << "Emitted bytecode to '" << Filename << "'\n";
Chris Lattnerafade922002-11-20 22:28:10 +000050 std::cout << "\n*** You can reproduce the problem with: ";
51
52 unsigned PassType = Pass->getPassType();
53 if (PassType & PassInfo::Analysis)
54 std::cout << "analyze";
55 else if (PassType & PassInfo::Optimization)
56 std::cout << "opt";
57 else if (PassType & PassInfo::LLC)
58 std::cout << "llc";
59 else
60 std::cout << "bugpoint";
61 std::cout << " " << Filename << " -" << Pass->getPassArgument() << "\n";
62}
63
Chris Lattnerf2bcccf2003-01-22 23:24:11 +000064/// FIXME: This should be parameterizable!!
65static TargetData TD("bugpoint target");
Chris Lattnerafade922002-11-20 22:28:10 +000066
67static void RunChild(Module *Program,const std::vector<const PassInfo*> &Passes,
68 const std::string &OutFilename) {
69 std::ofstream OutFile(OutFilename.c_str());
70 if (!OutFile.good()) {
71 std::cerr << "Error opening bytecode file: " << OutFilename << "\n";
72 exit(1);
73 }
74
75 PassManager PM;
76 for (unsigned i = 0, e = Passes.size(); i != e; ++i) {
77 if (Passes[i]->getNormalCtor())
78 PM.add(Passes[i]->getNormalCtor()());
Chris Lattnerf2bcccf2003-01-22 23:24:11 +000079 else if (Passes[i]->getDataCtor())
80 PM.add(Passes[i]->getDataCtor()(TD)); // Provide dummy target data...
Chris Lattnerafade922002-11-20 22:28:10 +000081 else
82 std::cerr << "Cannot create pass yet: " << Passes[i]->getPassName()
83 << "\n";
84 }
85 // Check that the module is well formed on completion of optimization
86 PM.add(createVerifierPass());
87
88 // Write bytecode out to disk as the last step...
89 PM.add(new WriteBytecodePass(&OutFile));
90
91 // Run all queued passes.
92 PM.run(*Program);
93}
94
95/// runPasses - Run the specified passes on Program, outputting a bytecode file
96/// and writting the filename into OutputFile if successful. If the
97/// optimizations fail for some reason (optimizer crashes), return true,
98/// otherwise return false. If DeleteOutput is set to true, the bytecode is
99/// deleted on success, and the filename string is undefined. This prints to
100/// cout a single line message indicating whether compilation was successful or
101/// failed.
102///
103bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes,
Chris Lattner218e26e2002-12-23 23:49:59 +0000104 std::string &OutputFilename, bool DeleteOutput,
105 bool Quiet) const{
Chris Lattnerafade922002-11-20 22:28:10 +0000106 std::cout << std::flush;
Chris Lattner218e26e2002-12-23 23:49:59 +0000107 OutputFilename = getUniqueFilename("bugpoint-output.bc");
Chris Lattnerafade922002-11-20 22:28:10 +0000108
Chris Lattnerafade922002-11-20 22:28:10 +0000109 pid_t child_pid;
110 switch (child_pid = fork()) {
111 case -1: // Error occurred
112 std::cerr << ToolName << ": Error forking!\n";
113 exit(1);
114 case 0: // Child process runs passes.
115 RunChild(Program, Passes, OutputFilename);
116 exit(0); // If we finish successfully, return 0!
117 default: // Parent continues...
118 break;
119 }
120
121 // Wait for the child process to get done.
122 int Status;
123 if (wait(&Status) != child_pid) {
124 std::cerr << "Error waiting for child process!\n";
125 exit(1);
126 }
127
128 // If we are supposed to delete the bytecode file, remove it now
129 // unconditionally... this may fail if the file was never created, but that's
130 // ok.
131 if (DeleteOutput)
132 removeFile(OutputFilename);
133
Chris Lattner218e26e2002-12-23 23:49:59 +0000134 if (!Quiet) std::cout << (Status ? "Crashed!\n" : "Success!\n");
Chris Lattnerafade922002-11-20 22:28:10 +0000135
136 // Was the child successful?
137 return Status != 0;
138}