1*06f32e7eSjoerg //===- BugDriver.cpp - Top-Level BugPoint class implementation ------------===//
2*06f32e7eSjoerg //
3*06f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*06f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
5*06f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*06f32e7eSjoerg //
7*06f32e7eSjoerg //===----------------------------------------------------------------------===//
8*06f32e7eSjoerg //
9*06f32e7eSjoerg // This class contains all of the shared state and information that is used by
10*06f32e7eSjoerg // the BugPoint tool to track down errors in optimizations.  This class is the
11*06f32e7eSjoerg // main driver class that invokes all sub-functionality.
12*06f32e7eSjoerg //
13*06f32e7eSjoerg //===----------------------------------------------------------------------===//
14*06f32e7eSjoerg 
15*06f32e7eSjoerg #include "BugDriver.h"
16*06f32e7eSjoerg #include "ToolRunner.h"
17*06f32e7eSjoerg #include "llvm/IR/Module.h"
18*06f32e7eSjoerg #include "llvm/IR/Verifier.h"
19*06f32e7eSjoerg #include "llvm/IRReader/IRReader.h"
20*06f32e7eSjoerg #include "llvm/Linker/Linker.h"
21*06f32e7eSjoerg #include "llvm/Pass.h"
22*06f32e7eSjoerg #include "llvm/Support/CommandLine.h"
23*06f32e7eSjoerg #include "llvm/Support/FileUtilities.h"
24*06f32e7eSjoerg #include "llvm/Support/Host.h"
25*06f32e7eSjoerg #include "llvm/Support/SourceMgr.h"
26*06f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
27*06f32e7eSjoerg #include <memory>
28*06f32e7eSjoerg using namespace llvm;
29*06f32e7eSjoerg 
30*06f32e7eSjoerg namespace llvm {
31*06f32e7eSjoerg Triple TargetTriple;
32*06f32e7eSjoerg }
33*06f32e7eSjoerg 
~DiscardTemp()34*06f32e7eSjoerg DiscardTemp::~DiscardTemp() {
35*06f32e7eSjoerg   if (SaveTemps) {
36*06f32e7eSjoerg     if (Error E = File.keep())
37*06f32e7eSjoerg       errs() << "Failed to keep temp file " << toString(std::move(E)) << '\n';
38*06f32e7eSjoerg     return;
39*06f32e7eSjoerg   }
40*06f32e7eSjoerg   if (Error E = File.discard())
41*06f32e7eSjoerg     errs() << "Failed to delete temp file " << toString(std::move(E)) << '\n';
42*06f32e7eSjoerg }
43*06f32e7eSjoerg 
44*06f32e7eSjoerg // Anonymous namespace to define command line options for debugging.
45*06f32e7eSjoerg //
46*06f32e7eSjoerg namespace {
47*06f32e7eSjoerg // Output - The user can specify a file containing the expected output of the
48*06f32e7eSjoerg // program.  If this filename is set, it is used as the reference diff source,
49*06f32e7eSjoerg // otherwise the raw input run through an interpreter is used as the reference
50*06f32e7eSjoerg // source.
51*06f32e7eSjoerg //
52*06f32e7eSjoerg cl::opt<std::string> OutputFile("output",
53*06f32e7eSjoerg                                 cl::desc("Specify a reference program output "
54*06f32e7eSjoerg                                          "(for miscompilation detection)"));
55*06f32e7eSjoerg }
56*06f32e7eSjoerg 
57*06f32e7eSjoerg /// If we reduce or update the program somehow, call this method to update
58*06f32e7eSjoerg /// bugdriver with it.  This deletes the old module and sets the specified one
59*06f32e7eSjoerg /// as the current program.
setNewProgram(std::unique_ptr<Module> M)60*06f32e7eSjoerg void BugDriver::setNewProgram(std::unique_ptr<Module> M) {
61*06f32e7eSjoerg   Program = std::move(M);
62*06f32e7eSjoerg }
63*06f32e7eSjoerg 
64*06f32e7eSjoerg /// getPassesString - Turn a list of passes into a string which indicates the
65*06f32e7eSjoerg /// command line options that must be passed to add the passes.
66*06f32e7eSjoerg ///
getPassesString(const std::vector<std::string> & Passes)67*06f32e7eSjoerg std::string llvm::getPassesString(const std::vector<std::string> &Passes) {
68*06f32e7eSjoerg   std::string Result;
69*06f32e7eSjoerg   for (unsigned i = 0, e = Passes.size(); i != e; ++i) {
70*06f32e7eSjoerg     if (i)
71*06f32e7eSjoerg       Result += " ";
72*06f32e7eSjoerg     Result += "-";
73*06f32e7eSjoerg     Result += Passes[i];
74*06f32e7eSjoerg   }
75*06f32e7eSjoerg   return Result;
76*06f32e7eSjoerg }
77*06f32e7eSjoerg 
BugDriver(const char * toolname,bool find_bugs,unsigned timeout,unsigned memlimit,bool use_valgrind,LLVMContext & ctxt)78*06f32e7eSjoerg BugDriver::BugDriver(const char *toolname, bool find_bugs, unsigned timeout,
79*06f32e7eSjoerg                      unsigned memlimit, bool use_valgrind, LLVMContext &ctxt)
80*06f32e7eSjoerg     : Context(ctxt), ToolName(toolname), ReferenceOutputFile(OutputFile),
81*06f32e7eSjoerg       Program(nullptr), Interpreter(nullptr), SafeInterpreter(nullptr),
82*06f32e7eSjoerg       cc(nullptr), run_find_bugs(find_bugs), Timeout(timeout),
83*06f32e7eSjoerg       MemoryLimit(memlimit), UseValgrind(use_valgrind) {}
84*06f32e7eSjoerg 
~BugDriver()85*06f32e7eSjoerg BugDriver::~BugDriver() {
86*06f32e7eSjoerg   if (Interpreter != SafeInterpreter)
87*06f32e7eSjoerg     delete Interpreter;
88*06f32e7eSjoerg   delete SafeInterpreter;
89*06f32e7eSjoerg   delete cc;
90*06f32e7eSjoerg }
91*06f32e7eSjoerg 
parseInputFile(StringRef Filename,LLVMContext & Ctxt)92*06f32e7eSjoerg std::unique_ptr<Module> llvm::parseInputFile(StringRef Filename,
93*06f32e7eSjoerg                                              LLVMContext &Ctxt) {
94*06f32e7eSjoerg   SMDiagnostic Err;
95*06f32e7eSjoerg   std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt);
96*06f32e7eSjoerg   if (!Result) {
97*06f32e7eSjoerg     Err.print("bugpoint", errs());
98*06f32e7eSjoerg     return Result;
99*06f32e7eSjoerg   }
100*06f32e7eSjoerg 
101*06f32e7eSjoerg   if (verifyModule(*Result, &errs())) {
102*06f32e7eSjoerg     errs() << "bugpoint: " << Filename << ": error: input module is broken!\n";
103*06f32e7eSjoerg     return std::unique_ptr<Module>();
104*06f32e7eSjoerg   }
105*06f32e7eSjoerg 
106*06f32e7eSjoerg   // If we don't have an override triple, use the first one to configure
107*06f32e7eSjoerg   // bugpoint, or use the host triple if none provided.
108*06f32e7eSjoerg   if (TargetTriple.getTriple().empty()) {
109*06f32e7eSjoerg     Triple TheTriple(Result->getTargetTriple());
110*06f32e7eSjoerg 
111*06f32e7eSjoerg     if (TheTriple.getTriple().empty())
112*06f32e7eSjoerg       TheTriple.setTriple(sys::getDefaultTargetTriple());
113*06f32e7eSjoerg 
114*06f32e7eSjoerg     TargetTriple.setTriple(TheTriple.getTriple());
115*06f32e7eSjoerg   }
116*06f32e7eSjoerg 
117*06f32e7eSjoerg   Result->setTargetTriple(TargetTriple.getTriple()); // override the triple
118*06f32e7eSjoerg   return Result;
119*06f32e7eSjoerg }
120*06f32e7eSjoerg 
swapProgramIn(std::unique_ptr<Module> M)121*06f32e7eSjoerg std::unique_ptr<Module> BugDriver::swapProgramIn(std::unique_ptr<Module> M) {
122*06f32e7eSjoerg   std::unique_ptr<Module> OldProgram = std::move(Program);
123*06f32e7eSjoerg   Program = std::move(M);
124*06f32e7eSjoerg   return OldProgram;
125*06f32e7eSjoerg }
126*06f32e7eSjoerg 
127*06f32e7eSjoerg // This method takes the specified list of LLVM input files, attempts to load
128*06f32e7eSjoerg // them, either as assembly or bitcode, then link them together. It returns
129*06f32e7eSjoerg // true on failure (if, for example, an input bitcode file could not be
130*06f32e7eSjoerg // parsed), and false on success.
131*06f32e7eSjoerg //
addSources(const std::vector<std::string> & Filenames)132*06f32e7eSjoerg bool BugDriver::addSources(const std::vector<std::string> &Filenames) {
133*06f32e7eSjoerg   assert(!Program && "Cannot call addSources multiple times!");
134*06f32e7eSjoerg   assert(!Filenames.empty() && "Must specify at least on input filename!");
135*06f32e7eSjoerg 
136*06f32e7eSjoerg   // Load the first input file.
137*06f32e7eSjoerg   Program = parseInputFile(Filenames[0], Context);
138*06f32e7eSjoerg   if (!Program)
139*06f32e7eSjoerg     return true;
140*06f32e7eSjoerg 
141*06f32e7eSjoerg   outs() << "Read input file      : '" << Filenames[0] << "'\n";
142*06f32e7eSjoerg 
143*06f32e7eSjoerg   for (unsigned i = 1, e = Filenames.size(); i != e; ++i) {
144*06f32e7eSjoerg     std::unique_ptr<Module> M = parseInputFile(Filenames[i], Context);
145*06f32e7eSjoerg     if (!M.get())
146*06f32e7eSjoerg       return true;
147*06f32e7eSjoerg 
148*06f32e7eSjoerg     outs() << "Linking in input file: '" << Filenames[i] << "'\n";
149*06f32e7eSjoerg     if (Linker::linkModules(*Program, std::move(M)))
150*06f32e7eSjoerg       return true;
151*06f32e7eSjoerg   }
152*06f32e7eSjoerg 
153*06f32e7eSjoerg   outs() << "*** All input ok\n";
154*06f32e7eSjoerg 
155*06f32e7eSjoerg   // All input files read successfully!
156*06f32e7eSjoerg   return false;
157*06f32e7eSjoerg }
158*06f32e7eSjoerg 
159*06f32e7eSjoerg /// run - The top level method that is invoked after all of the instance
160*06f32e7eSjoerg /// variables are set up from command line arguments.
161*06f32e7eSjoerg ///
run()162*06f32e7eSjoerg Error BugDriver::run() {
163*06f32e7eSjoerg   if (run_find_bugs) {
164*06f32e7eSjoerg     // Rearrange the passes and apply them to the program. Repeat this process
165*06f32e7eSjoerg     // until the user kills the program or we find a bug.
166*06f32e7eSjoerg     return runManyPasses(PassesToRun);
167*06f32e7eSjoerg   }
168*06f32e7eSjoerg 
169*06f32e7eSjoerg   // If we're not running as a child, the first thing that we must do is
170*06f32e7eSjoerg   // determine what the problem is. Does the optimization series crash the
171*06f32e7eSjoerg   // compiler, or does it produce illegal code?  We make the top-level
172*06f32e7eSjoerg   // decision by trying to run all of the passes on the input program,
173*06f32e7eSjoerg   // which should generate a bitcode file.  If it does generate a bitcode
174*06f32e7eSjoerg   // file, then we know the compiler didn't crash, so try to diagnose a
175*06f32e7eSjoerg   // miscompilation.
176*06f32e7eSjoerg   if (!PassesToRun.empty()) {
177*06f32e7eSjoerg     outs() << "Running selected passes on program to test for crash: ";
178*06f32e7eSjoerg     if (runPasses(*Program, PassesToRun))
179*06f32e7eSjoerg       return debugOptimizerCrash();
180*06f32e7eSjoerg   }
181*06f32e7eSjoerg 
182*06f32e7eSjoerg   // Set up the execution environment, selecting a method to run LLVM bitcode.
183*06f32e7eSjoerg   if (Error E = initializeExecutionEnvironment())
184*06f32e7eSjoerg     return E;
185*06f32e7eSjoerg 
186*06f32e7eSjoerg   // Test to see if we have a code generator crash.
187*06f32e7eSjoerg   outs() << "Running the code generator to test for a crash: ";
188*06f32e7eSjoerg   if (Error E = compileProgram(*Program)) {
189*06f32e7eSjoerg     outs() << toString(std::move(E));
190*06f32e7eSjoerg     return debugCodeGeneratorCrash();
191*06f32e7eSjoerg   }
192*06f32e7eSjoerg   outs() << '\n';
193*06f32e7eSjoerg 
194*06f32e7eSjoerg   // Run the raw input to see where we are coming from.  If a reference output
195*06f32e7eSjoerg   // was specified, make sure that the raw output matches it.  If not, it's a
196*06f32e7eSjoerg   // problem in the front-end or the code generator.
197*06f32e7eSjoerg   //
198*06f32e7eSjoerg   bool CreatedOutput = false;
199*06f32e7eSjoerg   if (ReferenceOutputFile.empty()) {
200*06f32e7eSjoerg     outs() << "Generating reference output from raw program: ";
201*06f32e7eSjoerg     if (Error E = createReferenceFile(*Program)) {
202*06f32e7eSjoerg       errs() << toString(std::move(E));
203*06f32e7eSjoerg       return debugCodeGeneratorCrash();
204*06f32e7eSjoerg     }
205*06f32e7eSjoerg     CreatedOutput = true;
206*06f32e7eSjoerg   }
207*06f32e7eSjoerg 
208*06f32e7eSjoerg   // Make sure the reference output file gets deleted on exit from this
209*06f32e7eSjoerg   // function, if appropriate.
210*06f32e7eSjoerg   std::string ROF(ReferenceOutputFile);
211*06f32e7eSjoerg   FileRemover RemoverInstance(ROF, CreatedOutput && !SaveTemps);
212*06f32e7eSjoerg 
213*06f32e7eSjoerg   // Diff the output of the raw program against the reference output.  If it
214*06f32e7eSjoerg   // matches, then we assume there is a miscompilation bug and try to
215*06f32e7eSjoerg   // diagnose it.
216*06f32e7eSjoerg   outs() << "*** Checking the code generator...\n";
217*06f32e7eSjoerg   Expected<bool> Diff = diffProgram(*Program, "", "", false);
218*06f32e7eSjoerg   if (Error E = Diff.takeError()) {
219*06f32e7eSjoerg     errs() << toString(std::move(E));
220*06f32e7eSjoerg     return debugCodeGeneratorCrash();
221*06f32e7eSjoerg   }
222*06f32e7eSjoerg   if (!*Diff) {
223*06f32e7eSjoerg     outs() << "\n*** Output matches: Debugging miscompilation!\n";
224*06f32e7eSjoerg     if (Error E = debugMiscompilation()) {
225*06f32e7eSjoerg       errs() << toString(std::move(E));
226*06f32e7eSjoerg       return debugCodeGeneratorCrash();
227*06f32e7eSjoerg     }
228*06f32e7eSjoerg     return Error::success();
229*06f32e7eSjoerg   }
230*06f32e7eSjoerg 
231*06f32e7eSjoerg   outs() << "\n*** Input program does not match reference diff!\n";
232*06f32e7eSjoerg   outs() << "Debugging code generator problem!\n";
233*06f32e7eSjoerg   if (Error E = debugCodeGenerator()) {
234*06f32e7eSjoerg     errs() << toString(std::move(E));
235*06f32e7eSjoerg     return debugCodeGeneratorCrash();
236*06f32e7eSjoerg   }
237*06f32e7eSjoerg   return Error::success();
238*06f32e7eSjoerg }
239*06f32e7eSjoerg 
PrintFunctionList(const std::vector<Function * > & Funcs)240*06f32e7eSjoerg void llvm::PrintFunctionList(const std::vector<Function *> &Funcs) {
241*06f32e7eSjoerg   unsigned NumPrint = Funcs.size();
242*06f32e7eSjoerg   if (NumPrint > 10)
243*06f32e7eSjoerg     NumPrint = 10;
244*06f32e7eSjoerg   for (unsigned i = 0; i != NumPrint; ++i)
245*06f32e7eSjoerg     outs() << " " << Funcs[i]->getName();
246*06f32e7eSjoerg   if (NumPrint < Funcs.size())
247*06f32e7eSjoerg     outs() << "... <" << Funcs.size() << " total>";
248*06f32e7eSjoerg   outs().flush();
249*06f32e7eSjoerg }
250*06f32e7eSjoerg 
PrintGlobalVariableList(const std::vector<GlobalVariable * > & GVs)251*06f32e7eSjoerg void llvm::PrintGlobalVariableList(const std::vector<GlobalVariable *> &GVs) {
252*06f32e7eSjoerg   unsigned NumPrint = GVs.size();
253*06f32e7eSjoerg   if (NumPrint > 10)
254*06f32e7eSjoerg     NumPrint = 10;
255*06f32e7eSjoerg   for (unsigned i = 0; i != NumPrint; ++i)
256*06f32e7eSjoerg     outs() << " " << GVs[i]->getName();
257*06f32e7eSjoerg   if (NumPrint < GVs.size())
258*06f32e7eSjoerg     outs() << "... <" << GVs.size() << " total>";
259*06f32e7eSjoerg   outs().flush();
260*06f32e7eSjoerg }
261