1*06f32e7eSjoerg //===- BugDriver.h - Top-Level BugPoint class -------------------*- C++ -*-===//
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 #ifndef LLVM_TOOLS_BUGPOINT_BUGDRIVER_H
16*06f32e7eSjoerg #define LLVM_TOOLS_BUGPOINT_BUGDRIVER_H
17*06f32e7eSjoerg 
18*06f32e7eSjoerg #include "llvm/IR/ValueMap.h"
19*06f32e7eSjoerg #include "llvm/Support/Error.h"
20*06f32e7eSjoerg #include "llvm/Support/FileSystem.h"
21*06f32e7eSjoerg #include "llvm/Transforms/Utils/ValueMapper.h"
22*06f32e7eSjoerg #include <memory>
23*06f32e7eSjoerg #include <string>
24*06f32e7eSjoerg #include <vector>
25*06f32e7eSjoerg 
26*06f32e7eSjoerg namespace llvm {
27*06f32e7eSjoerg 
28*06f32e7eSjoerg class Value;
29*06f32e7eSjoerg class PassInfo;
30*06f32e7eSjoerg class Module;
31*06f32e7eSjoerg class GlobalVariable;
32*06f32e7eSjoerg class Function;
33*06f32e7eSjoerg class BasicBlock;
34*06f32e7eSjoerg class AbstractInterpreter;
35*06f32e7eSjoerg class Instruction;
36*06f32e7eSjoerg class LLVMContext;
37*06f32e7eSjoerg 
38*06f32e7eSjoerg class DebugCrashes;
39*06f32e7eSjoerg 
40*06f32e7eSjoerg class CC;
41*06f32e7eSjoerg 
42*06f32e7eSjoerg extern bool DisableSimplifyCFG;
43*06f32e7eSjoerg 
44*06f32e7eSjoerg /// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
45*06f32e7eSjoerg ///
46*06f32e7eSjoerg extern bool BugpointIsInterrupted;
47*06f32e7eSjoerg 
48*06f32e7eSjoerg class BugDriver {
49*06f32e7eSjoerg   LLVMContext &Context;
50*06f32e7eSjoerg   const char *ToolName;            // argv[0] of bugpoint
51*06f32e7eSjoerg   std::string ReferenceOutputFile; // Name of `good' output file
52*06f32e7eSjoerg   std::unique_ptr<Module> Program; // The raw program, linked together
53*06f32e7eSjoerg   std::vector<std::string> PassesToRun;
54*06f32e7eSjoerg   AbstractInterpreter *Interpreter;     // How to run the program
55*06f32e7eSjoerg   AbstractInterpreter *SafeInterpreter; // To generate reference output, etc.
56*06f32e7eSjoerg   CC *cc;
57*06f32e7eSjoerg   bool run_find_bugs;
58*06f32e7eSjoerg   unsigned Timeout;
59*06f32e7eSjoerg   unsigned MemoryLimit;
60*06f32e7eSjoerg   bool UseValgrind;
61*06f32e7eSjoerg 
62*06f32e7eSjoerg   // FIXME: sort out public/private distinctions...
63*06f32e7eSjoerg   friend class ReducePassList;
64*06f32e7eSjoerg   friend class ReduceMisCodegenFunctions;
65*06f32e7eSjoerg 
66*06f32e7eSjoerg public:
67*06f32e7eSjoerg   BugDriver(const char *toolname, bool find_bugs, unsigned timeout,
68*06f32e7eSjoerg             unsigned memlimit, bool use_valgrind, LLVMContext &ctxt);
69*06f32e7eSjoerg   ~BugDriver();
70*06f32e7eSjoerg 
getToolName()71*06f32e7eSjoerg   const char *getToolName() const { return ToolName; }
72*06f32e7eSjoerg 
getContext()73*06f32e7eSjoerg   LLVMContext &getContext() const { return Context; }
74*06f32e7eSjoerg 
75*06f32e7eSjoerg   // Set up methods... these methods are used to copy information about the
76*06f32e7eSjoerg   // command line arguments into instance variables of BugDriver.
77*06f32e7eSjoerg   //
78*06f32e7eSjoerg   bool addSources(const std::vector<std::string> &FileNames);
addPass(std::string p)79*06f32e7eSjoerg   void addPass(std::string p) { PassesToRun.push_back(std::move(p)); }
setPassesToRun(const std::vector<std::string> & PTR)80*06f32e7eSjoerg   void setPassesToRun(const std::vector<std::string> &PTR) {
81*06f32e7eSjoerg     PassesToRun = PTR;
82*06f32e7eSjoerg   }
getPassesToRun()83*06f32e7eSjoerg   const std::vector<std::string> &getPassesToRun() const { return PassesToRun; }
84*06f32e7eSjoerg 
85*06f32e7eSjoerg   /// run - The top level method that is invoked after all of the instance
86*06f32e7eSjoerg   /// variables are set up from command line arguments. The \p as_child argument
87*06f32e7eSjoerg   /// indicates whether the driver is to run in parent mode or child mode.
88*06f32e7eSjoerg   ///
89*06f32e7eSjoerg   Error run();
90*06f32e7eSjoerg 
91*06f32e7eSjoerg   /// debugOptimizerCrash - This method is called when some optimizer pass
92*06f32e7eSjoerg   /// crashes on input.  It attempts to prune down the testcase to something
93*06f32e7eSjoerg   /// reasonable, and figure out exactly which pass is crashing.
94*06f32e7eSjoerg   ///
95*06f32e7eSjoerg   Error debugOptimizerCrash(const std::string &ID = "passes");
96*06f32e7eSjoerg 
97*06f32e7eSjoerg   /// debugCodeGeneratorCrash - This method is called when the code generator
98*06f32e7eSjoerg   /// crashes on an input.  It attempts to reduce the input as much as possible
99*06f32e7eSjoerg   /// while still causing the code generator to crash.
100*06f32e7eSjoerg   Error debugCodeGeneratorCrash();
101*06f32e7eSjoerg 
102*06f32e7eSjoerg   /// debugMiscompilation - This method is used when the passes selected are not
103*06f32e7eSjoerg   /// crashing, but the generated output is semantically different from the
104*06f32e7eSjoerg   /// input.
105*06f32e7eSjoerg   Error debugMiscompilation();
106*06f32e7eSjoerg 
107*06f32e7eSjoerg   /// debugPassMiscompilation - This method is called when the specified pass
108*06f32e7eSjoerg   /// miscompiles Program as input.  It tries to reduce the testcase to
109*06f32e7eSjoerg   /// something that smaller that still miscompiles the program.
110*06f32e7eSjoerg   /// ReferenceOutput contains the filename of the file containing the output we
111*06f32e7eSjoerg   /// are to match.
112*06f32e7eSjoerg   ///
113*06f32e7eSjoerg   bool debugPassMiscompilation(const PassInfo *ThePass,
114*06f32e7eSjoerg                                const std::string &ReferenceOutput);
115*06f32e7eSjoerg 
116*06f32e7eSjoerg   /// compileSharedObject - This method creates a SharedObject from a given
117*06f32e7eSjoerg   /// BitcodeFile for debugging a code generator.
118*06f32e7eSjoerg   ///
119*06f32e7eSjoerg   Expected<std::string> compileSharedObject(const std::string &BitcodeFile);
120*06f32e7eSjoerg 
121*06f32e7eSjoerg   /// debugCodeGenerator - This method narrows down a module to a function or
122*06f32e7eSjoerg   /// set of functions, using the CBE as a ``safe'' code generator for other
123*06f32e7eSjoerg   /// functions that are not under consideration.
124*06f32e7eSjoerg   Error debugCodeGenerator();
125*06f32e7eSjoerg 
126*06f32e7eSjoerg   /// isExecutingJIT - Returns true if bugpoint is currently testing the JIT
127*06f32e7eSjoerg   ///
128*06f32e7eSjoerg   bool isExecutingJIT();
129*06f32e7eSjoerg 
getProgram()130*06f32e7eSjoerg   Module &getProgram() const { return *Program; }
131*06f32e7eSjoerg 
132*06f32e7eSjoerg   /// Set the current module to the specified module, returning the old one.
133*06f32e7eSjoerg   std::unique_ptr<Module> swapProgramIn(std::unique_ptr<Module> M);
134*06f32e7eSjoerg 
switchToSafeInterpreter()135*06f32e7eSjoerg   AbstractInterpreter *switchToSafeInterpreter() {
136*06f32e7eSjoerg     AbstractInterpreter *Old = Interpreter;
137*06f32e7eSjoerg     Interpreter = (AbstractInterpreter *)SafeInterpreter;
138*06f32e7eSjoerg     return Old;
139*06f32e7eSjoerg   }
140*06f32e7eSjoerg 
switchToInterpreter(AbstractInterpreter * AI)141*06f32e7eSjoerg   void switchToInterpreter(AbstractInterpreter *AI) { Interpreter = AI; }
142*06f32e7eSjoerg 
143*06f32e7eSjoerg   /// If we reduce or update the program somehow, call this method to update
144*06f32e7eSjoerg   /// bugdriver with it.  This deletes the old module and sets the specified one
145*06f32e7eSjoerg   /// as the current program.
146*06f32e7eSjoerg   void setNewProgram(std::unique_ptr<Module> M);
147*06f32e7eSjoerg 
148*06f32e7eSjoerg   /// Try to compile the specified module. This is used for code generation
149*06f32e7eSjoerg   /// crash testing.
150*06f32e7eSjoerg   Error compileProgram(Module &M) const;
151*06f32e7eSjoerg 
152*06f32e7eSjoerg   /// This method runs "Program", capturing the output of the program to a file.
153*06f32e7eSjoerg   /// A recommended filename may be optionally specified.
154*06f32e7eSjoerg   Expected<std::string> executeProgram(const Module &Program,
155*06f32e7eSjoerg                                        std::string OutputFilename,
156*06f32e7eSjoerg                                        std::string Bitcode,
157*06f32e7eSjoerg                                        const std::string &SharedObjects,
158*06f32e7eSjoerg                                        AbstractInterpreter *AI) const;
159*06f32e7eSjoerg 
160*06f32e7eSjoerg   /// Used to create reference output with the "safe" backend, if reference
161*06f32e7eSjoerg   /// output is not provided.  If there is a problem with the code generator
162*06f32e7eSjoerg   /// (e.g., llc crashes), this will return false and set Error.
163*06f32e7eSjoerg   Expected<std::string>
164*06f32e7eSjoerg   executeProgramSafely(const Module &Program,
165*06f32e7eSjoerg                        const std::string &OutputFile) const;
166*06f32e7eSjoerg 
167*06f32e7eSjoerg   /// Calls compileProgram and then records the output into ReferenceOutputFile.
168*06f32e7eSjoerg   /// Returns true if reference file created, false otherwise. Note:
169*06f32e7eSjoerg   /// initializeExecutionEnvironment should be called BEFORE this function.
170*06f32e7eSjoerg   Error createReferenceFile(Module &M, const std::string &Filename =
171*06f32e7eSjoerg                                            "bugpoint.reference.out-%%%%%%%");
172*06f32e7eSjoerg 
173*06f32e7eSjoerg   /// This method executes the specified module and diffs the output against the
174*06f32e7eSjoerg   /// file specified by ReferenceOutputFile.  If the output is different, 1 is
175*06f32e7eSjoerg   /// returned.  If there is a problem with the code generator (e.g., llc
176*06f32e7eSjoerg   /// crashes), this will return -1 and set Error.
177*06f32e7eSjoerg   Expected<bool> diffProgram(const Module &Program,
178*06f32e7eSjoerg                              const std::string &BitcodeFile = "",
179*06f32e7eSjoerg                              const std::string &SharedObj = "",
180*06f32e7eSjoerg                              bool RemoveBitcode = false) const;
181*06f32e7eSjoerg 
182*06f32e7eSjoerg   /// This function is used to output M to a file named "bugpoint-ID.bc".
183*06f32e7eSjoerg   void EmitProgressBitcode(const Module &M, const std::string &ID,
184*06f32e7eSjoerg                            bool NoFlyer = false) const;
185*06f32e7eSjoerg 
186*06f32e7eSjoerg   /// This method clones the current Program and deletes the specified
187*06f32e7eSjoerg   /// instruction from the cloned module.  It then runs a series of cleanup
188*06f32e7eSjoerg   /// passes (ADCE and SimplifyCFG) to eliminate any code which depends on the
189*06f32e7eSjoerg   /// value. The modified module is then returned.
190*06f32e7eSjoerg   ///
191*06f32e7eSjoerg   std::unique_ptr<Module> deleteInstructionFromProgram(const Instruction *I,
192*06f32e7eSjoerg                                                        unsigned Simp);
193*06f32e7eSjoerg 
194*06f32e7eSjoerg   /// This method clones the current Program and performs a series of cleanups
195*06f32e7eSjoerg   /// intended to get rid of extra cruft on the module. If the
196*06f32e7eSjoerg   /// MayModifySemantics argument is true, then the cleanups is allowed to
197*06f32e7eSjoerg   /// modify how the code behaves.
198*06f32e7eSjoerg   ///
199*06f32e7eSjoerg   std::unique_ptr<Module> performFinalCleanups(std::unique_ptr<Module> M,
200*06f32e7eSjoerg                                                bool MayModifySemantics = false);
201*06f32e7eSjoerg 
202*06f32e7eSjoerg   /// Given a module, extract up to one loop from it into a new function. This
203*06f32e7eSjoerg   /// returns null if there are no extractable loops in the program or if the
204*06f32e7eSjoerg   /// loop extractor crashes.
205*06f32e7eSjoerg   std::unique_ptr<Module> extractLoop(Module *M);
206*06f32e7eSjoerg 
207*06f32e7eSjoerg   /// Extract all but the specified basic blocks into their own functions. The
208*06f32e7eSjoerg   /// only detail is that M is actually a module cloned from the one the BBs are
209*06f32e7eSjoerg   /// in, so some mapping needs to be performed. If this operation fails for
210*06f32e7eSjoerg   /// some reason (ie the implementation is buggy), this function should return
211*06f32e7eSjoerg   /// null, otherwise it returns a new Module.
212*06f32e7eSjoerg   std::unique_ptr<Module>
213*06f32e7eSjoerg   extractMappedBlocksFromModule(const std::vector<BasicBlock *> &BBs,
214*06f32e7eSjoerg                                 Module *M);
215*06f32e7eSjoerg 
216*06f32e7eSjoerg   /// Carefully run the specified set of pass on the specified/ module,
217*06f32e7eSjoerg   /// returning the transformed module on success, or a null pointer on failure.
218*06f32e7eSjoerg   std::unique_ptr<Module> runPassesOn(Module *M,
219*06f32e7eSjoerg                                       const std::vector<std::string> &Passes,
220*06f32e7eSjoerg                                       ArrayRef<std::string> ExtraArgs = {});
221*06f32e7eSjoerg 
222*06f32e7eSjoerg   /// runPasses - Run the specified passes on Program, outputting a bitcode
223*06f32e7eSjoerg   /// file and writting the filename into OutputFile if successful.  If the
224*06f32e7eSjoerg   /// optimizations fail for some reason (optimizer crashes), return true,
225*06f32e7eSjoerg   /// otherwise return false.  If DeleteOutput is set to true, the bitcode is
226*06f32e7eSjoerg   /// deleted on success, and the filename string is undefined.  This prints to
227*06f32e7eSjoerg   /// outs() a single line message indicating whether compilation was successful
228*06f32e7eSjoerg   /// or failed, unless Quiet is set.  ExtraArgs specifies additional arguments
229*06f32e7eSjoerg   /// to pass to the child bugpoint instance.
230*06f32e7eSjoerg   ///
231*06f32e7eSjoerg   bool runPasses(Module &Program, const std::vector<std::string> &PassesToRun,
232*06f32e7eSjoerg                  std::string &OutputFilename, bool DeleteOutput = false,
233*06f32e7eSjoerg                  bool Quiet = false,
234*06f32e7eSjoerg                  ArrayRef<std::string> ExtraArgs = {}) const;
235*06f32e7eSjoerg 
236*06f32e7eSjoerg   /// runPasses - Just like the method above, but this just returns true or
237*06f32e7eSjoerg   /// false indicating whether or not the optimizer crashed on the specified
238*06f32e7eSjoerg   /// input (true = crashed).  Does not produce any output.
239*06f32e7eSjoerg   ///
runPasses(Module & M,const std::vector<std::string> & PassesToRun)240*06f32e7eSjoerg   bool runPasses(Module &M, const std::vector<std::string> &PassesToRun) const {
241*06f32e7eSjoerg     std::string Filename;
242*06f32e7eSjoerg     return runPasses(M, PassesToRun, Filename, true);
243*06f32e7eSjoerg   }
244*06f32e7eSjoerg 
245*06f32e7eSjoerg   /// Take the specified pass list and create different combinations of passes
246*06f32e7eSjoerg   /// to compile the program with. Compile the program with each set and mark
247*06f32e7eSjoerg   /// test to see if it compiled correctly. If the passes compiled correctly
248*06f32e7eSjoerg   /// output nothing and rearrange the passes into a new order. If the passes
249*06f32e7eSjoerg   /// did not compile correctly, output the command required to recreate the
250*06f32e7eSjoerg   /// failure.
251*06f32e7eSjoerg   Error runManyPasses(const std::vector<std::string> &AllPasses);
252*06f32e7eSjoerg 
253*06f32e7eSjoerg   /// This writes the current "Program" to the named bitcode file.  If an error
254*06f32e7eSjoerg   /// occurs, true is returned.
255*06f32e7eSjoerg   bool writeProgramToFile(const std::string &Filename, const Module &M) const;
256*06f32e7eSjoerg   bool writeProgramToFile(const std::string &Filename, int FD,
257*06f32e7eSjoerg                           const Module &M) const;
258*06f32e7eSjoerg   bool writeProgramToFile(int FD, const Module &M) const;
259*06f32e7eSjoerg 
260*06f32e7eSjoerg private:
261*06f32e7eSjoerg   /// initializeExecutionEnvironment - This method is used to set up the
262*06f32e7eSjoerg   /// environment for executing LLVM programs.
263*06f32e7eSjoerg   ///
264*06f32e7eSjoerg   Error initializeExecutionEnvironment();
265*06f32e7eSjoerg };
266*06f32e7eSjoerg 
267*06f32e7eSjoerg struct DiscardTemp {
268*06f32e7eSjoerg   sys::fs::TempFile &File;
269*06f32e7eSjoerg   ~DiscardTemp();
270*06f32e7eSjoerg };
271*06f32e7eSjoerg 
272*06f32e7eSjoerg ///  Given a bitcode or assembly input filename, parse and return it, or return
273*06f32e7eSjoerg ///  null if not possible.
274*06f32e7eSjoerg ///
275*06f32e7eSjoerg std::unique_ptr<Module> parseInputFile(StringRef InputFilename,
276*06f32e7eSjoerg                                        LLVMContext &ctxt);
277*06f32e7eSjoerg 
278*06f32e7eSjoerg /// getPassesString - Turn a list of passes into a string which indicates the
279*06f32e7eSjoerg /// command line options that must be passed to add the passes.
280*06f32e7eSjoerg ///
281*06f32e7eSjoerg std::string getPassesString(const std::vector<std::string> &Passes);
282*06f32e7eSjoerg 
283*06f32e7eSjoerg /// PrintFunctionList - prints out list of problematic functions
284*06f32e7eSjoerg ///
285*06f32e7eSjoerg void PrintFunctionList(const std::vector<Function *> &Funcs);
286*06f32e7eSjoerg 
287*06f32e7eSjoerg /// PrintGlobalVariableList - prints out list of problematic global variables
288*06f32e7eSjoerg ///
289*06f32e7eSjoerg void PrintGlobalVariableList(const std::vector<GlobalVariable *> &GVs);
290*06f32e7eSjoerg 
291*06f32e7eSjoerg // DeleteGlobalInitializer - "Remove" the global variable by deleting its
292*06f32e7eSjoerg // initializer, making it external.
293*06f32e7eSjoerg //
294*06f32e7eSjoerg void DeleteGlobalInitializer(GlobalVariable *GV);
295*06f32e7eSjoerg 
296*06f32e7eSjoerg // DeleteFunctionBody - "Remove" the function by deleting all of it's basic
297*06f32e7eSjoerg // blocks, making it external.
298*06f32e7eSjoerg //
299*06f32e7eSjoerg void DeleteFunctionBody(Function *F);
300*06f32e7eSjoerg 
301*06f32e7eSjoerg /// Given a module and a list of functions in the module, split the functions
302*06f32e7eSjoerg /// OUT of the specified module, and place them in the new module.
303*06f32e7eSjoerg std::unique_ptr<Module>
304*06f32e7eSjoerg SplitFunctionsOutOfModule(Module *M, const std::vector<Function *> &F,
305*06f32e7eSjoerg                           ValueToValueMapTy &VMap);
306*06f32e7eSjoerg 
307*06f32e7eSjoerg } // End llvm namespace
308*06f32e7eSjoerg 
309*06f32e7eSjoerg #endif
310