10b57cec5SDimitry Andric //===- BugDriver.cpp - Top-Level BugPoint class implementation ------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This class contains all of the shared state and information that is used by 100b57cec5SDimitry Andric // the BugPoint tool to track down errors in optimizations. This class is the 110b57cec5SDimitry Andric // main driver class that invokes all sub-functionality. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "BugDriver.h" 160b57cec5SDimitry Andric #include "ToolRunner.h" 170b57cec5SDimitry Andric #include "llvm/IR/Module.h" 180b57cec5SDimitry Andric #include "llvm/IR/Verifier.h" 190b57cec5SDimitry Andric #include "llvm/IRReader/IRReader.h" 200b57cec5SDimitry Andric #include "llvm/Linker/Linker.h" 210b57cec5SDimitry Andric #include "llvm/Pass.h" 220b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 230b57cec5SDimitry Andric #include "llvm/Support/FileUtilities.h" 240b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h" 250b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 2606c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 270b57cec5SDimitry Andric #include <memory> 280b57cec5SDimitry Andric using namespace llvm; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric namespace llvm { 310b57cec5SDimitry Andric Triple TargetTriple; 320b57cec5SDimitry Andric } 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric DiscardTemp::~DiscardTemp() { 350b57cec5SDimitry Andric if (SaveTemps) { 360b57cec5SDimitry Andric if (Error E = File.keep()) 370b57cec5SDimitry Andric errs() << "Failed to keep temp file " << toString(std::move(E)) << '\n'; 380b57cec5SDimitry Andric return; 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric if (Error E = File.discard()) 410b57cec5SDimitry Andric errs() << "Failed to delete temp file " << toString(std::move(E)) << '\n'; 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric // Anonymous namespace to define command line options for debugging. 450b57cec5SDimitry Andric // 460b57cec5SDimitry Andric namespace { 470b57cec5SDimitry Andric // Output - The user can specify a file containing the expected output of the 480b57cec5SDimitry Andric // program. If this filename is set, it is used as the reference diff source, 490b57cec5SDimitry Andric // otherwise the raw input run through an interpreter is used as the reference 500b57cec5SDimitry Andric // source. 510b57cec5SDimitry Andric // 520b57cec5SDimitry Andric cl::opt<std::string> OutputFile("output", 530b57cec5SDimitry Andric cl::desc("Specify a reference program output " 540b57cec5SDimitry Andric "(for miscompilation detection)")); 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric /// If we reduce or update the program somehow, call this method to update 580b57cec5SDimitry Andric /// bugdriver with it. This deletes the old module and sets the specified one 590b57cec5SDimitry Andric /// as the current program. 600b57cec5SDimitry Andric void BugDriver::setNewProgram(std::unique_ptr<Module> M) { 610b57cec5SDimitry Andric Program = std::move(M); 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric /// getPassesString - Turn a list of passes into a string which indicates the 650b57cec5SDimitry Andric /// command line options that must be passed to add the passes. 660b57cec5SDimitry Andric /// 670b57cec5SDimitry Andric std::string llvm::getPassesString(const std::vector<std::string> &Passes) { 680b57cec5SDimitry Andric std::string Result; 690b57cec5SDimitry Andric for (unsigned i = 0, e = Passes.size(); i != e; ++i) { 700b57cec5SDimitry Andric if (i) 710b57cec5SDimitry Andric Result += " "; 720b57cec5SDimitry Andric Result += "-"; 730b57cec5SDimitry Andric Result += Passes[i]; 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric return Result; 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric BugDriver::BugDriver(const char *toolname, bool find_bugs, unsigned timeout, 790b57cec5SDimitry Andric unsigned memlimit, bool use_valgrind, LLVMContext &ctxt) 800b57cec5SDimitry Andric : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile), 810b57cec5SDimitry Andric Program(nullptr), Interpreter(nullptr), SafeInterpreter(nullptr), 820b57cec5SDimitry Andric cc(nullptr), run_find_bugs(find_bugs), Timeout(timeout), 830b57cec5SDimitry Andric MemoryLimit(memlimit), UseValgrind(use_valgrind) {} 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric BugDriver::~BugDriver() { 860b57cec5SDimitry Andric if (Interpreter != SafeInterpreter) 870b57cec5SDimitry Andric delete Interpreter; 880b57cec5SDimitry Andric delete SafeInterpreter; 890b57cec5SDimitry Andric delete cc; 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric std::unique_ptr<Module> llvm::parseInputFile(StringRef Filename, 930b57cec5SDimitry Andric LLVMContext &Ctxt) { 940b57cec5SDimitry Andric SMDiagnostic Err; 950b57cec5SDimitry Andric std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt); 960b57cec5SDimitry Andric if (!Result) { 970b57cec5SDimitry Andric Err.print("bugpoint", errs()); 980b57cec5SDimitry Andric return Result; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric if (verifyModule(*Result, &errs())) { 1020b57cec5SDimitry Andric errs() << "bugpoint: " << Filename << ": error: input module is broken!\n"; 1030b57cec5SDimitry Andric return std::unique_ptr<Module>(); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric // If we don't have an override triple, use the first one to configure 1070b57cec5SDimitry Andric // bugpoint, or use the host triple if none provided. 1080b57cec5SDimitry Andric if (TargetTriple.getTriple().empty()) { 1090b57cec5SDimitry Andric Triple TheTriple(Result->getTargetTriple()); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric if (TheTriple.getTriple().empty()) 1120b57cec5SDimitry Andric TheTriple.setTriple(sys::getDefaultTargetTriple()); 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric TargetTriple.setTriple(TheTriple.getTriple()); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric Result->setTargetTriple(TargetTriple.getTriple()); // override the triple 1180b57cec5SDimitry Andric return Result; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric std::unique_ptr<Module> BugDriver::swapProgramIn(std::unique_ptr<Module> M) { 1220b57cec5SDimitry Andric std::unique_ptr<Module> OldProgram = std::move(Program); 1230b57cec5SDimitry Andric Program = std::move(M); 1240b57cec5SDimitry Andric return OldProgram; 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric // This method takes the specified list of LLVM input files, attempts to load 1280b57cec5SDimitry Andric // them, either as assembly or bitcode, then link them together. It returns 1290b57cec5SDimitry Andric // true on failure (if, for example, an input bitcode file could not be 1300b57cec5SDimitry Andric // parsed), and false on success. 1310b57cec5SDimitry Andric // 1320b57cec5SDimitry Andric bool BugDriver::addSources(const std::vector<std::string> &Filenames) { 1330b57cec5SDimitry Andric assert(!Program && "Cannot call addSources multiple times!"); 1340b57cec5SDimitry Andric assert(!Filenames.empty() && "Must specify at least on input filename!"); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric // Load the first input file. 1370b57cec5SDimitry Andric Program = parseInputFile(Filenames[0], Context); 1380b57cec5SDimitry Andric if (!Program) 1390b57cec5SDimitry Andric return true; 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric outs() << "Read input file : '" << Filenames[0] << "'\n"; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric for (unsigned i = 1, e = Filenames.size(); i != e; ++i) { 1440b57cec5SDimitry Andric std::unique_ptr<Module> M = parseInputFile(Filenames[i], Context); 145*0fca6ea1SDimitry Andric if (!M) 1460b57cec5SDimitry Andric return true; 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric outs() << "Linking in input file: '" << Filenames[i] << "'\n"; 1490b57cec5SDimitry Andric if (Linker::linkModules(*Program, std::move(M))) 1500b57cec5SDimitry Andric return true; 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric outs() << "*** All input ok\n"; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric // All input files read successfully! 1560b57cec5SDimitry Andric return false; 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric /// run - The top level method that is invoked after all of the instance 1600b57cec5SDimitry Andric /// variables are set up from command line arguments. 1610b57cec5SDimitry Andric /// 1620b57cec5SDimitry Andric Error BugDriver::run() { 1630b57cec5SDimitry Andric if (run_find_bugs) { 1640b57cec5SDimitry Andric // Rearrange the passes and apply them to the program. Repeat this process 1650b57cec5SDimitry Andric // until the user kills the program or we find a bug. 1660b57cec5SDimitry Andric return runManyPasses(PassesToRun); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric // If we're not running as a child, the first thing that we must do is 1700b57cec5SDimitry Andric // determine what the problem is. Does the optimization series crash the 1710b57cec5SDimitry Andric // compiler, or does it produce illegal code? We make the top-level 1720b57cec5SDimitry Andric // decision by trying to run all of the passes on the input program, 1730b57cec5SDimitry Andric // which should generate a bitcode file. If it does generate a bitcode 1740b57cec5SDimitry Andric // file, then we know the compiler didn't crash, so try to diagnose a 1750b57cec5SDimitry Andric // miscompilation. 1760b57cec5SDimitry Andric if (!PassesToRun.empty()) { 1770b57cec5SDimitry Andric outs() << "Running selected passes on program to test for crash: "; 1780b57cec5SDimitry Andric if (runPasses(*Program, PassesToRun)) 1790b57cec5SDimitry Andric return debugOptimizerCrash(); 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric // Set up the execution environment, selecting a method to run LLVM bitcode. 1830b57cec5SDimitry Andric if (Error E = initializeExecutionEnvironment()) 1840b57cec5SDimitry Andric return E; 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric // Test to see if we have a code generator crash. 1870b57cec5SDimitry Andric outs() << "Running the code generator to test for a crash: "; 1880b57cec5SDimitry Andric if (Error E = compileProgram(*Program)) { 1890b57cec5SDimitry Andric outs() << toString(std::move(E)); 1900b57cec5SDimitry Andric return debugCodeGeneratorCrash(); 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric outs() << '\n'; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric // Run the raw input to see where we are coming from. If a reference output 1950b57cec5SDimitry Andric // was specified, make sure that the raw output matches it. If not, it's a 1960b57cec5SDimitry Andric // problem in the front-end or the code generator. 1970b57cec5SDimitry Andric // 1980b57cec5SDimitry Andric bool CreatedOutput = false; 1990b57cec5SDimitry Andric if (ReferenceOutputFile.empty()) { 2000b57cec5SDimitry Andric outs() << "Generating reference output from raw program: "; 2010b57cec5SDimitry Andric if (Error E = createReferenceFile(*Program)) { 2020b57cec5SDimitry Andric errs() << toString(std::move(E)); 2030b57cec5SDimitry Andric return debugCodeGeneratorCrash(); 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric CreatedOutput = true; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric // Make sure the reference output file gets deleted on exit from this 2090b57cec5SDimitry Andric // function, if appropriate. 2100b57cec5SDimitry Andric std::string ROF(ReferenceOutputFile); 2110b57cec5SDimitry Andric FileRemover RemoverInstance(ROF, CreatedOutput && !SaveTemps); 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric // Diff the output of the raw program against the reference output. If it 2140b57cec5SDimitry Andric // matches, then we assume there is a miscompilation bug and try to 2150b57cec5SDimitry Andric // diagnose it. 2160b57cec5SDimitry Andric outs() << "*** Checking the code generator...\n"; 2170b57cec5SDimitry Andric Expected<bool> Diff = diffProgram(*Program, "", "", false); 2180b57cec5SDimitry Andric if (Error E = Diff.takeError()) { 2190b57cec5SDimitry Andric errs() << toString(std::move(E)); 2200b57cec5SDimitry Andric return debugCodeGeneratorCrash(); 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric if (!*Diff) { 2230b57cec5SDimitry Andric outs() << "\n*** Output matches: Debugging miscompilation!\n"; 2240b57cec5SDimitry Andric if (Error E = debugMiscompilation()) { 2250b57cec5SDimitry Andric errs() << toString(std::move(E)); 2260b57cec5SDimitry Andric return debugCodeGeneratorCrash(); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric return Error::success(); 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric outs() << "\n*** Input program does not match reference diff!\n"; 2320b57cec5SDimitry Andric outs() << "Debugging code generator problem!\n"; 2330b57cec5SDimitry Andric if (Error E = debugCodeGenerator()) { 2340b57cec5SDimitry Andric errs() << toString(std::move(E)); 2350b57cec5SDimitry Andric return debugCodeGeneratorCrash(); 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric return Error::success(); 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric void llvm::PrintFunctionList(const std::vector<Function *> &Funcs) { 2410b57cec5SDimitry Andric unsigned NumPrint = Funcs.size(); 2420b57cec5SDimitry Andric if (NumPrint > 10) 2430b57cec5SDimitry Andric NumPrint = 10; 2440b57cec5SDimitry Andric for (unsigned i = 0; i != NumPrint; ++i) 2450b57cec5SDimitry Andric outs() << " " << Funcs[i]->getName(); 2460b57cec5SDimitry Andric if (NumPrint < Funcs.size()) 2470b57cec5SDimitry Andric outs() << "... <" << Funcs.size() << " total>"; 2480b57cec5SDimitry Andric outs().flush(); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric void llvm::PrintGlobalVariableList(const std::vector<GlobalVariable *> &GVs) { 2520b57cec5SDimitry Andric unsigned NumPrint = GVs.size(); 2530b57cec5SDimitry Andric if (NumPrint > 10) 2540b57cec5SDimitry Andric NumPrint = 10; 2550b57cec5SDimitry Andric for (unsigned i = 0; i != NumPrint; ++i) 2560b57cec5SDimitry Andric outs() << " " << GVs[i]->getName(); 2570b57cec5SDimitry Andric if (NumPrint < GVs.size()) 2580b57cec5SDimitry Andric outs() << "... <" << GVs.size() << " total>"; 2590b57cec5SDimitry Andric outs().flush(); 2600b57cec5SDimitry Andric } 261