OptimizerDriver.cpp revision ca005120082385026fd80fe76946fc446d3c9d33
1//===- OptimizerDriver.cpp - Allow BugPoint to run passes safely ----------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the LLVM research group 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 run various passes 11// without the threat of a buggy pass corrupting bugpoint (of course, bugpoint 12// may have its own bugs, but that's another story...). It achieves this by 13// forking a copy of itself and having the child process do the optimizations. 14// If this client dies, we can always fork a new one. :) 15// 16//===----------------------------------------------------------------------===// 17 18#include "BugDriver.h" 19#include "llvm/PassManager.h" 20#include "llvm/Analysis/Verifier.h" 21#include "llvm/Bytecode/WriteBytecodePass.h" 22#include "llvm/Target/TargetData.h" 23#include "Support/FileUtilities.h" 24#include <fstream> 25#include <unistd.h> 26#include <sys/types.h> 27#include <sys/wait.h> 28using namespace llvm; 29 30/// writeProgramToFile - This writes the current "Program" to the named bytecode 31/// file. If an error occurs, true is returned. 32/// 33bool BugDriver::writeProgramToFile(const std::string &Filename, 34 Module *M) const { 35 std::ofstream Out(Filename.c_str()); 36 if (!Out.good()) return true; 37 WriteBytecodeToFile(M ? M : Program, Out); 38 return false; 39} 40 41 42/// EmitProgressBytecode - This function is used to output the current Program 43/// to a file named "bugpoint-ID.bc". 44/// 45void BugDriver::EmitProgressBytecode(const std::string &ID, bool NoFlyer) { 46 // Output the input to the current pass to a bytecode file, emit a message 47 // telling the user how to reproduce it: opt -foo blah.bc 48 // 49 std::string Filename = "bugpoint-" + ID + ".bc"; 50 if (writeProgramToFile(Filename)) { 51 std::cerr << "Error opening file '" << Filename << "' for writing!\n"; 52 return; 53 } 54 55 std::cout << "Emitted bytecode to '" << Filename << "'\n"; 56 if (NoFlyer || PassesToRun.empty()) return; 57 std::cout << "\n*** You can reproduce the problem with: "; 58 59 unsigned PassType = PassesToRun[0]->getPassType(); 60 for (unsigned i = 1, e = PassesToRun.size(); i != e; ++i) 61 PassType &= PassesToRun[i]->getPassType(); 62 63 if (PassType & PassInfo::Analysis) 64 std::cout << "analyze"; 65 else if (PassType & PassInfo::Optimization) 66 std::cout << "opt"; 67 else if (PassType & PassInfo::LLC) 68 std::cout << "llc"; 69 else 70 std::cout << "bugpoint"; 71 std::cout << " " << Filename << " "; 72 std::cout << getPassesString(PassesToRun) << "\n"; 73} 74 75static void RunChild(Module *Program,const std::vector<const PassInfo*> &Passes, 76 const std::string &OutFilename) { 77 std::ofstream OutFile(OutFilename.c_str()); 78 if (!OutFile.good()) { 79 std::cerr << "Error opening bytecode file: " << OutFilename << "\n"; 80 exit(1); 81 } 82 83 PassManager PM; 84 // Make sure that the appropriate target data is always used... 85 PM.add(new TargetData("bugpoint", Program)); 86 87 for (unsigned i = 0, e = Passes.size(); i != e; ++i) { 88 if (Passes[i]->getNormalCtor()) 89 PM.add(Passes[i]->getNormalCtor()()); 90 else 91 std::cerr << "Cannot create pass yet: " << Passes[i]->getPassName() 92 << "\n"; 93 } 94 // Check that the module is well formed on completion of optimization 95 PM.add(createVerifierPass()); 96 97 // Write bytecode out to disk as the last step... 98 PM.add(new WriteBytecodePass(&OutFile)); 99 100 // Run all queued passes. 101 PM.run(*Program); 102} 103 104/// runPasses - Run the specified passes on Program, outputting a bytecode file 105/// and writing the filename into OutputFile if successful. If the 106/// optimizations fail for some reason (optimizer crashes), return true, 107/// otherwise return false. If DeleteOutput is set to true, the bytecode is 108/// deleted on success, and the filename string is undefined. This prints to 109/// cout a single line message indicating whether compilation was successful or 110/// failed. 111/// 112bool BugDriver::runPasses(const std::vector<const PassInfo*> &Passes, 113 std::string &OutputFilename, bool DeleteOutput, 114 bool Quiet) const{ 115 std::cout << std::flush; 116 OutputFilename = getUniqueFilename("bugpoint-output.bc"); 117 118 pid_t child_pid; 119 switch (child_pid = fork()) { 120 case -1: // Error occurred 121 std::cerr << ToolName << ": Error forking!\n"; 122 exit(1); 123 case 0: // Child process runs passes. 124 RunChild(Program, Passes, OutputFilename); 125 exit(0); // If we finish successfully, return 0! 126 default: // Parent continues... 127 break; 128 } 129 130 // Wait for the child process to get done. 131 int Status; 132 if (wait(&Status) != child_pid) { 133 std::cerr << "Error waiting for child process!\n"; 134 exit(1); 135 } 136 137 // If we are supposed to delete the bytecode file, remove it now 138 // unconditionally... this may fail if the file was never created, but that's 139 // ok. 140 if (DeleteOutput) 141 removeFile(OutputFilename); 142 143 bool ExitedOK = WIFEXITED(Status) && WEXITSTATUS(Status) == 0; 144 145 if (!Quiet) { 146 if (ExitedOK) 147 std::cout << "Success!\n"; 148 else if (WIFEXITED(Status)) 149 std::cout << "Exited with error code '" << WEXITSTATUS(Status) << "'\n"; 150 else if (WIFSIGNALED(Status)) 151 std::cout << "Crashed with signal #" << WTERMSIG(Status) << "\n"; 152#ifdef WCOREDUMP 153 else if (WCOREDUMP(Status)) 154 std::cout << "Dumped core\n"; 155#endif 156 else 157 std::cout << "Failed for unknown reason!\n"; 158 } 159 160 // Was the child successful? 161 return !ExitedOK; 162} 163 164