1193323Sed//===- BugDriver.cpp - Top-Level BugPoint class implementation ------------===// 2193323Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193323Sed// 7193323Sed//===----------------------------------------------------------------------===// 8193323Sed// 9193323Sed// This class contains all of the shared state and information that is used by 10193323Sed// the BugPoint tool to track down errors in optimizations. This class is the 11193323Sed// main driver class that invokes all sub-functionality. 12193323Sed// 13193323Sed//===----------------------------------------------------------------------===// 14193323Sed 15193323Sed#include "BugDriver.h" 16193323Sed#include "ToolRunner.h" 17249423Sdim#include "llvm/IR/Module.h" 18288943Sdim#include "llvm/IR/Verifier.h" 19249423Sdim#include "llvm/IRReader/IRReader.h" 20276479Sdim#include "llvm/Linker/Linker.h" 21193323Sed#include "llvm/Pass.h" 22193323Sed#include "llvm/Support/CommandLine.h" 23193323Sed#include "llvm/Support/FileUtilities.h" 24249423Sdim#include "llvm/Support/Host.h" 25195340Sed#include "llvm/Support/SourceMgr.h" 26193323Sed#include "llvm/Support/raw_ostream.h" 27193323Sed#include <memory> 28193323Sedusing namespace llvm; 29193323Sed 30198090Srdivackynamespace llvm { 31314564SdimTriple TargetTriple; 32198090Srdivacky} 33198090Srdivacky 34327952SdimDiscardTemp::~DiscardTemp() { 35327952Sdim if (SaveTemps) { 36327952Sdim if (Error E = File.keep()) 37327952Sdim errs() << "Failed to keep temp file " << toString(std::move(E)) << '\n'; 38327952Sdim return; 39327952Sdim } 40327952Sdim if (Error E = File.discard()) 41327952Sdim errs() << "Failed to delete temp file " << toString(std::move(E)) << '\n'; 42327952Sdim} 43327952Sdim 44193323Sed// Anonymous namespace to define command line options for debugging. 45193323Sed// 46193323Sednamespace { 47314564Sdim// Output - The user can specify a file containing the expected output of the 48314564Sdim// program. If this filename is set, it is used as the reference diff source, 49314564Sdim// otherwise the raw input run through an interpreter is used as the reference 50314564Sdim// source. 51314564Sdim// 52314564Sdimcl::opt<std::string> OutputFile("output", 53314564Sdim cl::desc("Specify a reference program output " 54314564Sdim "(for miscompilation detection)")); 55193323Sed} 56193323Sed 57341825Sdim/// If we reduce or update the program somehow, call this method to update 58341825Sdim/// bugdriver with it. This deletes the old module and sets the specified one 59341825Sdim/// as the current program. 60341825Sdimvoid BugDriver::setNewProgram(std::unique_ptr<Module> M) { 61341825Sdim Program = std::move(M); 62193323Sed} 63193323Sed 64193323Sed/// getPassesString - Turn a list of passes into a string which indicates the 65193323Sed/// command line options that must be passed to add the passes. 66193323Sed/// 67212793Sdimstd::string llvm::getPassesString(const std::vector<std::string> &Passes) { 68193323Sed std::string Result; 69193323Sed for (unsigned i = 0, e = Passes.size(); i != e; ++i) { 70314564Sdim if (i) 71314564Sdim Result += " "; 72193323Sed Result += "-"; 73212793Sdim Result += Passes[i]; 74193323Sed } 75193323Sed return Result; 76193323Sed} 77193323Sed 78314564SdimBugDriver::BugDriver(const char *toolname, bool find_bugs, unsigned timeout, 79314564Sdim unsigned memlimit, bool use_valgrind, LLVMContext &ctxt) 80314564Sdim : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile), 81314564Sdim Program(nullptr), Interpreter(nullptr), SafeInterpreter(nullptr), 82314564Sdim cc(nullptr), run_find_bugs(find_bugs), Timeout(timeout), 83314564Sdim MemoryLimit(memlimit), UseValgrind(use_valgrind) {} 84193323Sed 85206083SrdivackyBugDriver::~BugDriver() { 86276479Sdim if (Interpreter != SafeInterpreter) 87276479Sdim delete Interpreter; 88276479Sdim delete SafeInterpreter; 89296417Sdim delete cc; 90206083Srdivacky} 91193323Sed 92280031Sdimstd::unique_ptr<Module> llvm::parseInputFile(StringRef Filename, 93280031Sdim LLVMContext &Ctxt) { 94195340Sed SMDiagnostic Err; 95280031Sdim std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt); 96288943Sdim if (!Result) { 97234353Sdim Err.print("bugpoint", errs()); 98288943Sdim return Result; 99288943Sdim } 100198090Srdivacky 101288943Sdim if (verifyModule(*Result, &errs())) { 102288943Sdim errs() << "bugpoint: " << Filename << ": error: input module is broken!\n"; 103288943Sdim return std::unique_ptr<Module>(); 104288943Sdim } 105288943Sdim 106198090Srdivacky // If we don't have an override triple, use the first one to configure 107198090Srdivacky // bugpoint, or use the host triple if none provided. 108288943Sdim if (TargetTriple.getTriple().empty()) { 109288943Sdim Triple TheTriple(Result->getTargetTriple()); 110198090Srdivacky 111288943Sdim if (TheTriple.getTriple().empty()) 112288943Sdim TheTriple.setTriple(sys::getDefaultTargetTriple()); 113221337Sdim 114288943Sdim TargetTriple.setTriple(TheTriple.getTriple()); 115288943Sdim } 116198090Srdivacky 117288943Sdim Result->setTargetTriple(TargetTriple.getTriple()); // override the triple 118193323Sed return Result; 119193323Sed} 120193323Sed 121341825Sdimstd::unique_ptr<Module> BugDriver::swapProgramIn(std::unique_ptr<Module> M) { 122341825Sdim std::unique_ptr<Module> OldProgram = std::move(Program); 123341825Sdim Program = std::move(M); 124341825Sdim return OldProgram; 125341825Sdim} 126341825Sdim 127193323Sed// This method takes the specified list of LLVM input files, attempts to load 128193323Sed// them, either as assembly or bitcode, then link them together. It returns 129193323Sed// true on failure (if, for example, an input bitcode file could not be 130193323Sed// parsed), and false on success. 131193323Sed// 132193323Sedbool BugDriver::addSources(const std::vector<std::string> &Filenames) { 133276479Sdim assert(!Program && "Cannot call addSources multiple times!"); 134193323Sed assert(!Filenames.empty() && "Must specify at least on input filename!"); 135193323Sed 136207618Srdivacky // Load the first input file. 137341825Sdim Program = parseInputFile(Filenames[0], Context); 138314564Sdim if (!Program) 139314564Sdim return true; 140221337Sdim 141212793Sdim outs() << "Read input file : '" << Filenames[0] << "'\n"; 142193323Sed 143207618Srdivacky for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { 144280031Sdim std::unique_ptr<Module> M = parseInputFile(Filenames[i], Context); 145314564Sdim if (!M.get()) 146314564Sdim return true; 147193323Sed 148212793Sdim outs() << "Linking in input file: '" << Filenames[i] << "'\n"; 149296417Sdim if (Linker::linkModules(*Program, std::move(M))) 150207618Srdivacky return true; 151193323Sed } 152193323Sed 153212793Sdim outs() << "*** All input ok\n"; 154193323Sed 155193323Sed // All input files read successfully! 156193323Sed return false; 157193323Sed} 158193323Sed 159193323Sed/// run - The top level method that is invoked after all of the instance 160193323Sed/// variables are set up from command line arguments. 161193323Sed/// 162314564SdimError BugDriver::run() { 163193323Sed if (run_find_bugs) { 164193323Sed // Rearrange the passes and apply them to the program. Repeat this process 165193323Sed // until the user kills the program or we find a bug. 166314564Sdim return runManyPasses(PassesToRun); 167193323Sed } 168193323Sed 169221337Sdim // If we're not running as a child, the first thing that we must do is 170221337Sdim // determine what the problem is. Does the optimization series crash the 171221337Sdim // compiler, or does it produce illegal code? We make the top-level 172239462Sdim // decision by trying to run all of the passes on the input program, 173221337Sdim // which should generate a bitcode file. If it does generate a bitcode 174221337Sdim // file, then we know the compiler didn't crash, so try to diagnose a 175193323Sed // miscompilation. 176193323Sed if (!PassesToRun.empty()) { 177198090Srdivacky outs() << "Running selected passes on program to test for crash: "; 178341825Sdim if (runPasses(*Program, PassesToRun)) 179193323Sed return debugOptimizerCrash(); 180193323Sed } 181193323Sed 182193323Sed // Set up the execution environment, selecting a method to run LLVM bitcode. 183314564Sdim if (Error E = initializeExecutionEnvironment()) 184314564Sdim return E; 185193323Sed 186193323Sed // Test to see if we have a code generator crash. 187198090Srdivacky outs() << "Running the code generator to test for a crash: "; 188341825Sdim if (Error E = compileProgram(*Program)) { 189314564Sdim outs() << toString(std::move(E)); 190314564Sdim return debugCodeGeneratorCrash(); 191193323Sed } 192207618Srdivacky outs() << '\n'; 193193323Sed 194193323Sed // Run the raw input to see where we are coming from. If a reference output 195193323Sed // was specified, make sure that the raw output matches it. If not, it's a 196193323Sed // problem in the front-end or the code generator. 197193323Sed // 198193323Sed bool CreatedOutput = false; 199193323Sed if (ReferenceOutputFile.empty()) { 200198090Srdivacky outs() << "Generating reference output from raw program: "; 201341825Sdim if (Error E = createReferenceFile(*Program)) { 202314564Sdim errs() << toString(std::move(E)); 203314564Sdim return debugCodeGeneratorCrash(); 204193323Sed } 205193323Sed CreatedOutput = true; 206193323Sed } 207193323Sed 208193323Sed // Make sure the reference output file gets deleted on exit from this 209193323Sed // function, if appropriate. 210261991Sdim std::string ROF(ReferenceOutputFile); 211261991Sdim FileRemover RemoverInstance(ROF, CreatedOutput && !SaveTemps); 212193323Sed 213193323Sed // Diff the output of the raw program against the reference output. If it 214221337Sdim // matches, then we assume there is a miscompilation bug and try to 215193323Sed // diagnose it. 216198090Srdivacky outs() << "*** Checking the code generator...\n"; 217341825Sdim Expected<bool> Diff = diffProgram(*Program, "", "", false); 218314564Sdim if (Error E = Diff.takeError()) { 219314564Sdim errs() << toString(std::move(E)); 220314564Sdim return debugCodeGeneratorCrash(); 221207618Srdivacky } 222314564Sdim if (!*Diff) { 223207618Srdivacky outs() << "\n*** Output matches: Debugging miscompilation!\n"; 224314564Sdim if (Error E = debugMiscompilation()) { 225314564Sdim errs() << toString(std::move(E)); 226314564Sdim return debugCodeGeneratorCrash(); 227193323Sed } 228314564Sdim return Error::success(); 229193323Sed } 230193323Sed 231198090Srdivacky outs() << "\n*** Input program does not match reference diff!\n"; 232198090Srdivacky outs() << "Debugging code generator problem!\n"; 233314564Sdim if (Error E = debugCodeGenerator()) { 234314564Sdim errs() << toString(std::move(E)); 235314564Sdim return debugCodeGeneratorCrash(); 236193323Sed } 237314564Sdim return Error::success(); 238193323Sed} 239193323Sed 240314564Sdimvoid llvm::PrintFunctionList(const std::vector<Function *> &Funcs) { 241193323Sed unsigned NumPrint = Funcs.size(); 242314564Sdim if (NumPrint > 10) 243314564Sdim NumPrint = 10; 244193323Sed for (unsigned i = 0; i != NumPrint; ++i) 245198090Srdivacky outs() << " " << Funcs[i]->getName(); 246193323Sed if (NumPrint < Funcs.size()) 247198090Srdivacky outs() << "... <" << Funcs.size() << " total>"; 248198090Srdivacky outs().flush(); 249193323Sed} 250193323Sed 251314564Sdimvoid llvm::PrintGlobalVariableList(const std::vector<GlobalVariable *> &GVs) { 252193323Sed unsigned NumPrint = GVs.size(); 253314564Sdim if (NumPrint > 10) 254314564Sdim NumPrint = 10; 255193323Sed for (unsigned i = 0; i != NumPrint; ++i) 256198090Srdivacky outs() << " " << GVs[i]->getName(); 257193323Sed if (NumPrint < GVs.size()) 258198090Srdivacky outs() << "... <" << GVs.size() << " total>"; 259198090Srdivacky outs().flush(); 260193323Sed} 261