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
39using namespace llvm;
40
41static 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
46static cl::list<std::string>
47    InputFilenames(cl::Positional, cl::OneOrMore,
48                   cl::desc("<input llvm ll/bc files>"));
49
50static 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
55static 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
60static 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//
67static cl::list<const PassInfo *, bool, PassNameParser>
68    PassList(cl::desc("Passes available:"), cl::ZeroOrMore);
69
70static cl::opt<bool>
71    StandardLinkOpts("std-link-opts",
72                     cl::desc("Include the standard link time optimizations"));
73
74static cl::opt<bool>
75    OptLevelO1("O1", cl::desc("Optimization level 1. Identical to 'opt -O1'"));
76
77static cl::opt<bool>
78    OptLevelO2("O2", cl::desc("Optimization level 2. Identical to 'opt -O2'"));
79
80static cl::opt<bool> OptLevelOs(
81    "Os",
82    cl::desc(
83        "Like -O2 with extra optimizations for size. Similar to clang -Os"));
84
85static cl::opt<bool>
86OptLevelOz("Oz",
87           cl::desc("Like -Os but reduces code size further. Similar to clang -Oz"));
88
89static cl::opt<bool>
90    OptLevelO3("O3", cl::desc("Optimization level 3. Identical to 'opt -O3'"));
91
92static cl::opt<std::string>
93    OverrideTriple("mtriple", cl::desc("Override target triple for module"));
94
95/// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
96bool llvm::BugpointIsInterrupted = false;
97
98#ifndef DEBUG_BUGPOINT
99static void BugpointInterruptFunction() { BugpointIsInterrupted = true; }
100#endif
101
102// Hack to capture a pass list.
103namespace {
104class AddToDriver : public legacy::FunctionPassManager {
105  BugDriver &D;
106
107public:
108  AddToDriver(BugDriver &_D) : FunctionPassManager(nullptr), D(_D) {}
109
110  void add(Pass *P) override {
111    const void *ID = P->getPassID();
112    const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID);
113    D.addPass(PI->getPassArgument());
114  }
115};
116}
117
118// This routine adds optimization passes based on selected optimization level,
119// OptLevel.
120//
121// OptLevel - Optimization Level
122static void AddOptimizationPasses(legacy::FunctionPassManager &FPM,
123                                  unsigned OptLevel,
124                                  unsigned SizeLevel) {
125  PassManagerBuilder Builder;
126  Builder.OptLevel = OptLevel;
127  Builder.SizeLevel = SizeLevel;
128
129  if (OptLevel > 1)
130    Builder.Inliner = createFunctionInliningPass(OptLevel, SizeLevel, false);
131  else
132    Builder.Inliner = createAlwaysInlinerLegacyPass();
133
134  Builder.populateFunctionPassManager(FPM);
135  Builder.populateModulePassManager(FPM);
136}
137
138#define HANDLE_EXTENSION(Ext)                                                  \
139  llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
140#include "llvm/Support/Extension.def"
141
142int main(int argc, char **argv) {
143#ifndef DEBUG_BUGPOINT
144  InitLLVM X(argc, argv);
145#endif
146
147  // Initialize passes
148  PassRegistry &Registry = *PassRegistry::getPassRegistry();
149  initializeCore(Registry);
150  initializeScalarOpts(Registry);
151  initializeObjCARCOpts(Registry);
152  initializeVectorization(Registry);
153  initializeIPO(Registry);
154  initializeAnalysis(Registry);
155  initializeTransformUtils(Registry);
156  initializeInstCombine(Registry);
157  initializeAggressiveInstCombine(Registry);
158  initializeInstrumentation(Registry);
159  initializeTarget(Registry);
160
161  if (std::getenv("bar") == (char*) -1) {
162    InitializeAllTargets();
163    InitializeAllTargetMCs();
164    InitializeAllAsmPrinters();
165    InitializeAllAsmParsers();
166  }
167
168  cl::ParseCommandLineOptions(argc, argv,
169                              "LLVM automatic testcase reducer. See\nhttp://"
170                              "llvm.org/cmds/bugpoint.html"
171                              " for more information.\n");
172#ifndef DEBUG_BUGPOINT
173  sys::SetInterruptFunction(BugpointInterruptFunction);
174#endif
175
176  LLVMContext Context;
177  // If we have an override, set it and then track the triple we want Modules
178  // to use.
179  if (!OverrideTriple.empty()) {
180    TargetTriple.setTriple(Triple::normalize(OverrideTriple));
181    outs() << "Override triple set to '" << TargetTriple.getTriple() << "'\n";
182  }
183
184  if (MemoryLimit < 0) {
185    // Set the default MemoryLimit.  Be sure to update the flag's description if
186    // you change this.
187    if (sys::RunningOnValgrind() || UseValgrind)
188      MemoryLimit = 800;
189    else
190      MemoryLimit = 400;
191#if (LLVM_ADDRESS_SANITIZER_BUILD || LLVM_MEMORY_SANITIZER_BUILD ||            \
192     LLVM_THREAD_SANITIZER_BUILD)
193    // Starting from kernel 4.9 memory allocated with mmap is counted against
194    // RLIMIT_DATA. Sanitizers need to allocate tens of terabytes for shadow.
195    MemoryLimit = 0;
196#endif
197  }
198
199  BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit, UseValgrind,
200              Context);
201  if (D.addSources(InputFilenames))
202    return 1;
203
204  AddToDriver PM(D);
205
206  if (StandardLinkOpts) {
207    PassManagerBuilder Builder;
208    Builder.Inliner = createFunctionInliningPass();
209    Builder.populateLTOPassManager(PM);
210  }
211
212  if (OptLevelO1)
213    AddOptimizationPasses(PM, 1, 0);
214  else if (OptLevelO2)
215    AddOptimizationPasses(PM, 2, 0);
216  else if (OptLevelO3)
217    AddOptimizationPasses(PM, 3, 0);
218  else if (OptLevelOs)
219    AddOptimizationPasses(PM, 2, 1);
220  else if (OptLevelOz)
221    AddOptimizationPasses(PM, 2, 2);
222
223  for (const PassInfo *PI : PassList)
224    D.addPass(PI->getPassArgument());
225
226// Bugpoint has the ability of generating a plethora of core files, so to
227// avoid filling up the disk, we prevent it
228#ifndef DEBUG_BUGPOINT
229  sys::Process::PreventCoreFiles();
230#endif
231
232// Needed to pull in symbols from statically linked extensions, including static
233// registration. It is unused otherwise because bugpoint has no support for
234// NewPM.
235#define HANDLE_EXTENSION(Ext)                                                  \
236  (void)get##Ext##PluginInfo();
237#include "llvm/Support/Extension.def"
238
239  if (Error E = D.run()) {
240    errs() << toString(std::move(E));
241    return 1;
242  }
243  return 0;
244}
245