1 //===- bugpoint.cpp - The LLVM Bugpoint utility ---------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This program is an automated compiler debugger tool.  It is used to narrow
10 // down miscompilations and crash problems to a specific pass in the compiler,
11 // and the specific Module or Function input that is causing the problem.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "BugDriver.h"
16 #include "ToolRunner.h"
17 #include "llvm/Config/llvm-config.h"
18 #include "llvm/IR/LLVMContext.h"
19 #include "llvm/IR/LegacyPassManager.h"
20 #include "llvm/IR/LegacyPassNameParser.h"
21 #include "llvm/InitializePasses.h"
22 #include "llvm/LinkAllIR.h"
23 #include "llvm/LinkAllPasses.h"
24 #include "llvm/Passes/PassPlugin.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/InitLLVM.h"
27 #include "llvm/Support/ManagedStatic.h"
28 #include "llvm/Support/PluginLoader.h"
29 #include "llvm/Support/PrettyStackTrace.h"
30 #include "llvm/Support/Process.h"
31 #include "llvm/Support/TargetSelect.h"
32 #include "llvm/Support/Valgrind.h"
33 #include "llvm/Transforms/IPO/AlwaysInliner.h"
34 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
35 
36 // Enable this macro to debug bugpoint itself.
37 //#define DEBUG_BUGPOINT 1
38 
39 using namespace llvm;
40 
41 static cl::opt<bool>
42     FindBugs("find-bugs", cl::desc("Run many different optimization sequences "
43                                    "on program to find bugs"),
44              cl::init(false));
45 
46 static cl::list<std::string>
47     InputFilenames(cl::Positional, cl::OneOrMore,
48                    cl::desc("<input llvm ll/bc files>"));
49 
50 static cl::opt<unsigned> TimeoutValue(
51     "timeout", cl::init(300), cl::value_desc("seconds"),
52     cl::desc("Number of seconds program is allowed to run before it "
53              "is killed (default is 300s), 0 disables timeout"));
54 
55 static cl::opt<int> MemoryLimit(
56     "mlimit", cl::init(-1), cl::value_desc("MBytes"),
57     cl::desc("Maximum amount of memory to use. 0 disables check. Defaults to "
58              "400MB (800MB under valgrind, 0 with sanitizers)."));
59 
60 static cl::opt<bool>
61     UseValgrind("enable-valgrind",
62                 cl::desc("Run optimizations through valgrind"));
63 
64 // The AnalysesList is automatically populated with registered Passes by the
65 // PassNameParser.
66 //
67 static cl::list<const PassInfo *, bool, PassNameParser>
68     PassList(cl::desc("Passes available:"), cl::ZeroOrMore);
69 
70 static cl::opt<bool>
71     OptLevelO1("O1", cl::desc("Optimization level 1. Identical to 'opt -O1'"));
72 
73 static cl::opt<bool>
74     OptLevelO2("O2", cl::desc("Optimization level 2. Identical to 'opt -O2'"));
75 
76 static cl::opt<bool> OptLevelOs(
77     "Os",
78     cl::desc(
79         "Like -O2 with extra optimizations for size. Similar to clang -Os"));
80 
81 static cl::opt<bool>
82 OptLevelOz("Oz",
83            cl::desc("Like -Os but reduces code size further. Similar to clang -Oz"));
84 
85 static cl::opt<bool>
86     OptLevelO3("O3", cl::desc("Optimization level 3. Identical to 'opt -O3'"));
87 
88 static cl::opt<std::string>
89     OverrideTriple("mtriple", cl::desc("Override target triple for module"));
90 
91 /// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
92 bool llvm::BugpointIsInterrupted = false;
93 
94 #ifndef DEBUG_BUGPOINT
95 static void BugpointInterruptFunction() { BugpointIsInterrupted = true; }
96 #endif
97 
98 // Hack to capture a pass list.
99 namespace {
100 class AddToDriver : public legacy::FunctionPassManager {
101   BugDriver &D;
102 
103 public:
104   AddToDriver(BugDriver &_D) : FunctionPassManager(nullptr), D(_D) {}
105 
106   void add(Pass *P) override {
107     const void *ID = P->getPassID();
108     const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID);
109     D.addPass(std::string(PI->getPassArgument()));
110   }
111 };
112 }
113 
114 // This routine adds optimization passes based on selected optimization level,
115 // OptLevel.
116 //
117 // OptLevel - Optimization Level
118 static void AddOptimizationPasses(legacy::FunctionPassManager &FPM,
119                                   unsigned OptLevel,
120                                   unsigned SizeLevel) {
121   PassManagerBuilder Builder;
122   Builder.OptLevel = OptLevel;
123   Builder.SizeLevel = SizeLevel;
124 
125   if (OptLevel > 1)
126     Builder.Inliner = createFunctionInliningPass(OptLevel, SizeLevel, false);
127   else
128     Builder.Inliner = createAlwaysInlinerLegacyPass();
129 
130   Builder.populateFunctionPassManager(FPM);
131   Builder.populateModulePassManager(FPM);
132 }
133 
134 #define HANDLE_EXTENSION(Ext)                                                  \
135   llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
136 #include "llvm/Support/Extension.def"
137 
138 int main(int argc, char **argv) {
139 #ifndef DEBUG_BUGPOINT
140   InitLLVM X(argc, argv);
141 #endif
142 
143   // Initialize passes
144   PassRegistry &Registry = *PassRegistry::getPassRegistry();
145   initializeCore(Registry);
146   initializeScalarOpts(Registry);
147   initializeObjCARCOpts(Registry);
148   initializeVectorization(Registry);
149   initializeIPO(Registry);
150   initializeAnalysis(Registry);
151   initializeTransformUtils(Registry);
152   initializeInstCombine(Registry);
153   initializeAggressiveInstCombine(Registry);
154   initializeInstrumentation(Registry);
155   initializeTarget(Registry);
156 
157   if (std::getenv("bar") == (char*) -1) {
158     InitializeAllTargets();
159     InitializeAllTargetMCs();
160     InitializeAllAsmPrinters();
161     InitializeAllAsmParsers();
162   }
163 
164   cl::ParseCommandLineOptions(argc, argv,
165                               "LLVM automatic testcase reducer. See\nhttp://"
166                               "llvm.org/cmds/bugpoint.html"
167                               " for more information.\n");
168 #ifndef DEBUG_BUGPOINT
169   sys::SetInterruptFunction(BugpointInterruptFunction);
170 #endif
171 
172   LLVMContext Context;
173   // If we have an override, set it and then track the triple we want Modules
174   // to use.
175   if (!OverrideTriple.empty()) {
176     TargetTriple.setTriple(Triple::normalize(OverrideTriple));
177     outs() << "Override triple set to '" << TargetTriple.getTriple() << "'\n";
178   }
179 
180   if (MemoryLimit < 0) {
181     // Set the default MemoryLimit.  Be sure to update the flag's description if
182     // you change this.
183     if (sys::RunningOnValgrind() || UseValgrind)
184       MemoryLimit = 800;
185     else
186       MemoryLimit = 400;
187 #if (LLVM_ADDRESS_SANITIZER_BUILD || LLVM_MEMORY_SANITIZER_BUILD ||            \
188      LLVM_THREAD_SANITIZER_BUILD)
189     // Starting from kernel 4.9 memory allocated with mmap is counted against
190     // RLIMIT_DATA. Sanitizers need to allocate tens of terabytes for shadow.
191     MemoryLimit = 0;
192 #endif
193   }
194 
195   BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit, UseValgrind,
196               Context);
197   if (D.addSources(InputFilenames))
198     return 1;
199 
200   AddToDriver PM(D);
201 
202   if (OptLevelO1)
203     AddOptimizationPasses(PM, 1, 0);
204   else if (OptLevelO2)
205     AddOptimizationPasses(PM, 2, 0);
206   else if (OptLevelO3)
207     AddOptimizationPasses(PM, 3, 0);
208   else if (OptLevelOs)
209     AddOptimizationPasses(PM, 2, 1);
210   else if (OptLevelOz)
211     AddOptimizationPasses(PM, 2, 2);
212 
213   for (const PassInfo *PI : PassList)
214     D.addPass(std::string(PI->getPassArgument()));
215 
216 // Bugpoint has the ability of generating a plethora of core files, so to
217 // avoid filling up the disk, we prevent it
218 #ifndef DEBUG_BUGPOINT
219   sys::Process::PreventCoreFiles();
220 #endif
221 
222 // Needed to pull in symbols from statically linked extensions, including static
223 // registration. It is unused otherwise because bugpoint has no support for
224 // NewPM.
225 #define HANDLE_EXTENSION(Ext)                                                  \
226   (void)get##Ext##PluginInfo();
227 #include "llvm/Support/Extension.def"
228 
229   if (Error E = D.run()) {
230     errs() << toString(std::move(E));
231     return 1;
232   }
233   return 0;
234 }
235