1 //===- BugDriver.cpp - Top-Level BugPoint class implementation ------------===// 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 class contains all of the shared state and information that is used by 11 // the BugPoint tool to track down errors in optimizations. This class is the 12 // main driver class that invokes all sub-functionality. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "BugDriver.h" 17 #include "llvm/Module.h" 18 #include "llvm/Pass.h" 19 #include "llvm/Assembly/Parser.h" 20 #include "llvm/Bytecode/Reader.h" 21 #include "llvm/Transforms/Utils/Linker.h" 22 #include "llvm/Support/ToolRunner.h" 23 #include "Support/CommandLine.h" 24 #include "Support/FileUtilities.h" 25 #include <memory> 26 using namespace llvm; 27 28 // Anonymous namespace to define command line options for debugging. 29 // 30 namespace { 31 // Output - The user can specify a file containing the expected output of the 32 // program. If this filename is set, it is used as the reference diff source, 33 // otherwise the raw input run through an interpreter is used as the reference 34 // source. 35 // 36 cl::opt<std::string> 37 OutputFile("output", cl::desc("Specify a reference program output " 38 "(for miscompilation detection)")); 39 } 40 41 /// setNewProgram - If we reduce or update the program somehow, call this method 42 /// to update bugdriver with it. This deletes the old module and sets the 43 /// specified one as the current program. 44 void BugDriver::setNewProgram(Module *M) { 45 delete Program; 46 Program = M; 47 } 48 49 50 /// getPassesString - Turn a list of passes into a string which indicates the 51 /// command line options that must be passed to add the passes. 52 /// 53 std::string llvm::getPassesString(const std::vector<const PassInfo*> &Passes) { 54 std::string Result; 55 for (unsigned i = 0, e = Passes.size(); i != e; ++i) { 56 if (i) Result += " "; 57 Result += "-"; 58 Result += Passes[i]->getPassArgument(); 59 } 60 return Result; 61 } 62 63 BugDriver::BugDriver(const char *toolname) 64 : ToolName(toolname), ReferenceOutputFile(OutputFile), 65 Program(0), Interpreter(0), cbe(0), gcc(0) {} 66 67 68 /// ParseInputFile - Given a bytecode or assembly input filename, parse and 69 /// return it, or return null if not possible. 70 /// 71 Module *llvm::ParseInputFile(const std::string &InputFilename) { 72 Module *Result = 0; 73 try { 74 Result = ParseBytecodeFile(InputFilename); 75 if (!Result && !(Result = ParseAssemblyFile(InputFilename))){ 76 std::cerr << "bugpoint: could not read input file '" 77 << InputFilename << "'!\n"; 78 } 79 } catch (const ParseException &E) { 80 std::cerr << "bugpoint: " << E.getMessage() << "\n"; 81 Result = 0; 82 } 83 return Result; 84 } 85 86 // This method takes the specified list of LLVM input files, attempts to load 87 // them, either as assembly or bytecode, then link them together. It returns 88 // true on failure (if, for example, an input bytecode file could not be 89 // parsed), and false on success. 90 // 91 bool BugDriver::addSources(const std::vector<std::string> &Filenames) { 92 assert(Program == 0 && "Cannot call addSources multiple times!"); 93 assert(!Filenames.empty() && "Must specify at least on input filename!"); 94 95 // Load the first input file... 96 Program = ParseInputFile(Filenames[0]); 97 if (Program == 0) return true; 98 std::cout << "Read input file : '" << Filenames[0] << "'\n"; 99 100 for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { 101 std::auto_ptr<Module> M(ParseInputFile(Filenames[i])); 102 if (M.get() == 0) return true; 103 104 std::cout << "Linking in input file: '" << Filenames[i] << "'\n"; 105 std::string ErrorMessage; 106 if (LinkModules(Program, M.get(), &ErrorMessage)) { 107 std::cerr << ToolName << ": error linking in '" << Filenames[i] << "': " 108 << ErrorMessage << "\n"; 109 return true; 110 } 111 } 112 113 std::cout << "*** All input ok\n"; 114 115 // All input files read successfully! 116 return false; 117 } 118 119 120 121 /// run - The top level method that is invoked after all of the instance 122 /// variables are set up from command line arguments. 123 /// 124 bool BugDriver::run() { 125 // The first thing that we must do is determine what the problem is. Does the 126 // optimization series crash the compiler, or does it produce illegal code? 127 // We make the top-level decision by trying to run all of the passes on the 128 // the input program, which should generate a bytecode file. If it does 129 // generate a bytecode file, then we know the compiler didn't crash, so try 130 // to diagnose a miscompilation. 131 if (!PassesToRun.empty()) { 132 std::cout << "Running selected passes on program to test for crash: "; 133 if (runPasses(PassesToRun)) 134 return debugOptimizerCrash(); 135 } 136 137 // Set up the execution environment, selecting a method to run LLVM bytecode. 138 if (initializeExecutionEnvironment()) return true; 139 140 // Test to see if we have a code generator crash. 141 std::cout << "Running the code generator to test for a crash: "; 142 try { 143 compileProgram(Program); 144 std::cout << "\n"; 145 } catch (ToolExecutionError &TEE) { 146 std::cout << TEE.what(); 147 return debugCodeGeneratorCrash(); 148 } 149 150 151 // Run the raw input to see where we are coming from. If a reference output 152 // was specified, make sure that the raw output matches it. If not, it's a 153 // problem in the front-end or the code generator. 154 // 155 bool CreatedOutput = false; 156 if (ReferenceOutputFile.empty()) { 157 std::cout << "Generating reference output from raw program..."; 158 try { 159 ReferenceOutputFile = executeProgramWithCBE("bugpoint.reference.out"); 160 CreatedOutput = true; 161 std::cout << "Reference output is: " << ReferenceOutputFile << "\n"; 162 } catch (ToolExecutionError &TEE) { 163 std::cerr << TEE.what(); 164 if (Interpreter != cbe) { 165 std::cerr << "*** There is a bug running the C backend. Either debug" 166 << " it (use the -run-cbe bugpoint option), or fix the error" 167 << " some other way.\n"; 168 return 1; 169 } 170 return debugCodeGeneratorCrash(); 171 } 172 } 173 174 // Make sure the reference output file gets deleted on exit from this 175 // function, if appropriate. 176 FileRemover RemoverInstance(ReferenceOutputFile, CreatedOutput); 177 178 // Diff the output of the raw program against the reference output. If it 179 // matches, then we have a miscompilation bug. 180 std::cout << "*** Checking the code generator...\n"; 181 try { 182 if (!diffProgram()) { 183 std::cout << "\n*** Debugging miscompilation!\n"; 184 return debugMiscompilation(); 185 } 186 } catch (ToolExecutionError &TEE) { 187 std::cerr << TEE.what(); 188 return debugCodeGeneratorCrash(); 189 } 190 191 std::cout << "\n*** Input program does not match reference diff!\n"; 192 std::cout << "Debugging code generator problem!\n"; 193 try { 194 return debugCodeGenerator(); 195 } catch (ToolExecutionError &TEE) { 196 std::cerr << TEE.what(); 197 return debugCodeGeneratorCrash(); 198 } 199 } 200 201 void llvm::PrintFunctionList(const std::vector<Function*> &Funcs) { 202 unsigned NumPrint = Funcs.size(); 203 if (NumPrint > 10) NumPrint = 10; 204 for (unsigned i = 0; i != NumPrint; ++i) 205 std::cout << " " << Funcs[i]->getName(); 206 if (NumPrint < Funcs.size()) 207 std::cout << "... <" << Funcs.size() << " total>"; 208 std::cout << std::flush; 209 } 210