BugDriver.cpp revision 5073336cd4da5df4ae13a167582d1dc90f32e4e0
1afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner//===- BugDriver.cpp - Top-Level BugPoint class implementation ------------===// 2afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// 3afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// This class contains all of the shared state and information that is used by 4afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// the BugPoint tool to track down errors in optimizations. This class is the 5afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// main driver class that invokes all sub-functionality. 6afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// 7afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner//===----------------------------------------------------------------------===// 8afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 9afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "BugDriver.h" 105073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#include "SystemUtils.h" 11afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "llvm/Module.h" 12afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "llvm/Bytecode/Reader.h" 13afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "llvm/Assembly/Parser.h" 14afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "llvm/Transforms/Utils/Linker.h" 15afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "llvm/Pass.h" 165073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman#include "Support/CommandLine.h" 17afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include <memory> 18afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 195073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// Anonymous namespace to define command line options for debugging. 205073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman// 215073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmannamespace { 225073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Output - The user can specify a file containing the expected output of the 235073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // program. If this filename is set, it is used as the reference diff source, 245073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // otherwise the raw input run through an interpreter is used as the reference 255073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // source. 265073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // 275073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman cl::opt<std::string> 285073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman OutputFile("output", cl::desc("Specify a reference program output " 295073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman "(for miscompilation detection)")); 305073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 315073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman enum DebugType { DebugCompile, DebugCodegen }; 325073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman cl::opt<DebugType> 335073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman DebugMode("mode", cl::desc("Debug mode for bugpoint:"), cl::Prefix, 345073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman cl::values(clEnumValN(DebugCompile, "compile", " Compilation"), 355073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman clEnumValN(DebugCodegen, "codegen", " Code generation"), 365073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 0), 375073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman cl::init(DebugCompile)); 385073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 395073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 40640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner/// getPassesString - Turn a list of passes into a string which indicates the 41640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner/// command line options that must be passed to add the passes. 42640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner/// 43640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattnerstd::string getPassesString(const std::vector<const PassInfo*> &Passes) { 44640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner std::string Result; 45640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner for (unsigned i = 0, e = Passes.size(); i != e; ++i) { 46640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner if (i) Result += " "; 47640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner Result += "-"; 48640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner Result += Passes[i]->getPassArgument(); 49640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner } 50640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner return Result; 51640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner} 52640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner 53c8b27318a33d1fe2fbae553159a918ccee8fae29Misha Brukman// DeleteFunctionBody - "Remove" the function by deleting all of its basic 54ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattner// blocks, making it external. 55ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattner// 56ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattnervoid DeleteFunctionBody(Function *F) { 57ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattner // First, break circular use/def chain references... 58ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattner for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) 59ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattner I->dropAllReferences(); 60ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattner 61ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattner // Next, delete all of the basic blocks. 62ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattner F->getBasicBlockList().clear(); 63473a843f31af46de50e7b5747d0f3b41bbfe3fd8Chris Lattner F->setLinkage(GlobalValue::ExternalLinkage); 64ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattner assert(F->isExternal() && "This didn't make the function external!"); 65ff4aaf0010d11a4c42f58f839336669d5fd7ba03Chris Lattner} 66640f22e66d90439857a97a83896ee68c4f7128c9Chris Lattner 675073336cd4da5df4ae13a167582d1dc90f32e4e0Misha BrukmanBugDriver::BugDriver(const char *toolname) 685073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman : ToolName(toolname), ReferenceOutputFile(OutputFile), 695073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Program(0), Interpreter(0) {} 705073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 715073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 72afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// ParseInputFile - Given a bytecode or assembly input filename, parse and 73afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// return it, or return null if not possible. 74afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// 75afade9294af43c6b947b9aeaa1555883d5f853e3Chris LattnerModule *BugDriver::ParseInputFile(const std::string &InputFilename) const { 76afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner Module *Result = 0; 77afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner try { 78afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner Result = ParseBytecodeFile(InputFilename); 79afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (!Result && !(Result = ParseAssemblyFile(InputFilename))){ 80afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cerr << ToolName << ": could not read input file '" 81afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner << InputFilename << "'!\n"; 82afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 83afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } catch (const ParseException &E) { 84afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cerr << ToolName << ": " << E.getMessage() << "\n"; 85afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner Result = 0; 86afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 87afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return Result; 88afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner} 89afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 90afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// This method takes the specified list of LLVM input files, attempts to load 91dae7f92366311de2bfaff91f6e66ef3da2f2fcbcBrian Gaeke// them, either as assembly or bytecode, then link them together. It returns 92dae7f92366311de2bfaff91f6e66ef3da2f2fcbcBrian Gaeke// true on failure (if, for example, an input bytecode file could not be 93dae7f92366311de2bfaff91f6e66ef3da2f2fcbcBrian Gaeke// parsed), and false on success. 94afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner// 95afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattnerbool BugDriver::addSources(const std::vector<std::string> &Filenames) { 96afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner assert(Program == 0 && "Cannot call addSources multiple times!"); 97afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner assert(!Filenames.empty() && "Must specify at least on input filename!"); 98afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 99afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // Load the first input file... 100afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner Program = ParseInputFile(Filenames[0]); 101afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (Program == 0) return true; 102afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cout << "Read input file : '" << Filenames[0] << "'\n"; 103afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 104afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { 105afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::auto_ptr<Module> M(ParseInputFile(Filenames[i])); 106afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (M.get() == 0) return true; 107afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 108afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cout << "Linking in input file: '" << Filenames[i] << "'\n"; 109afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::string ErrorMessage; 110afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (LinkModules(Program, M.get(), &ErrorMessage)) { 111afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cerr << ToolName << ": error linking in '" << Filenames[i] << "': " 112afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner << ErrorMessage << "\n"; 113afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return true; 114afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 115afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner } 116afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 117afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cout << "*** All input ok\n"; 118afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 119afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // All input files read successfully! 120afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return false; 121afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner} 122afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 123afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 124afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner 125afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// run - The top level method that is invoked after all of the instance 126afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// variables are set up from command line arguments. 127afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/// 128afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattnerbool BugDriver::run() { 129afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // The first thing that we must do is determine what the problem is. Does the 130afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // optimization series crash the compiler, or does it produce illegal code? We 131afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // make the top-level decision by trying to run all of the passes on the the 132afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // input program, which should generate a bytecode file. If it does generate 133afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // a bytecode file, then we know the compiler didn't crash, so try to diagnose 134afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // a miscompilation. 135afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner // 136afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner std::cout << "Running selected passes on program to test for crash: "; 137afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner if (runPasses(PassesToRun)) 138afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner return debugCrash(); 1395073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1405073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "Checking for a miscompilation...\n"; 1415073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1425073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Set up the execution environment, selecting a method to run LLVM bytecode. 1435073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (initializeExecutionEnvironment()) return true; 1445073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1455073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // Run the raw input to see where we are coming from. If a reference output 1465073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // was specified, make sure that the raw output matches it. If not, it's a 1475073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // problem in the front-end or the code generator. 1485073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman // 1495073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman bool CreatedOutput = false, Result; 1505073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (ReferenceOutputFile.empty()) { 1515073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "Generating reference output from raw program..."; 1525073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (DebugCodegen) { 1535073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ReferenceOutputFile = executeProgramWithCBE("bugpoint.reference.out"); 1545073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } else { 1555073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman ReferenceOutputFile = executeProgram("bugpoint.reference.out"); 1565073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 1575073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman CreatedOutput = true; 1585073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "Reference output is: " << ReferenceOutputFile << "\n"; 1595073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 1605073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1615073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (DebugMode == DebugCompile) { 1625073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "\n*** Debugging miscompilation!\n"; 1635073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Result = debugMiscompilation(); 1645073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } else if (DebugMode == DebugCodegen) { 1655073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << "Debugging code generator problem!\n"; 1665073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman Result = debugCodeGenerator(); 1675073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 1685073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1695073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (CreatedOutput) removeFile(ReferenceOutputFile); 1705073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman return Result; 1715073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman} 1725073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman 1735073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukmanvoid BugDriver::PrintFunctionList(const std::vector<Function*> &Funcs) 1745073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman{ 1755073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman for (unsigned i = 0, e = Funcs.size(); i != e; ++i) { 1765073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman if (i) std::cout << ", "; 1775073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman std::cout << Funcs[i]->getName(); 1785073336cd4da5df4ae13a167582d1dc90f32e4e0Misha Brukman } 179afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner} 180