1193323Sed//===- bugpoint.cpp - The LLVM Bugpoint utility ---------------------------===//
2193323Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193323Sed//
7193323Sed//===----------------------------------------------------------------------===//
8193323Sed//
9193323Sed// This program is an automated compiler debugger tool.  It is used to narrow
10193323Sed// down miscompilations and crash problems to a specific pass in the compiler,
11193323Sed// and the specific Module or Function input that is causing the problem.
12193323Sed//
13193323Sed//===----------------------------------------------------------------------===//
14193323Sed
15193323Sed#include "BugDriver.h"
16193323Sed#include "ToolRunner.h"
17341825Sdim#include "llvm/Config/llvm-config.h"
18249423Sdim#include "llvm/IR/LLVMContext.h"
19288943Sdim#include "llvm/IR/LegacyPassManager.h"
20276479Sdim#include "llvm/IR/LegacyPassNameParser.h"
21360784Sdim#include "llvm/InitializePasses.h"
22249423Sdim#include "llvm/LinkAllIR.h"
23193323Sed#include "llvm/LinkAllPasses.h"
24360784Sdim#include "llvm/Passes/PassPlugin.h"
25193323Sed#include "llvm/Support/CommandLine.h"
26341825Sdim#include "llvm/Support/InitLLVM.h"
27193323Sed#include "llvm/Support/ManagedStatic.h"
28193323Sed#include "llvm/Support/PluginLoader.h"
29193323Sed#include "llvm/Support/PrettyStackTrace.h"
30218885Sdim#include "llvm/Support/Process.h"
31321369Sdim#include "llvm/Support/TargetSelect.h"
32218885Sdim#include "llvm/Support/Valgrind.h"
33314564Sdim#include "llvm/Transforms/IPO/AlwaysInliner.h"
34226584Sdim#include "llvm/Transforms/IPO/PassManagerBuilder.h"
35218885Sdim
36314564Sdim// Enable this macro to debug bugpoint itself.
37218885Sdim//#define DEBUG_BUGPOINT 1
38218885Sdim
39193323Sedusing namespace llvm;
40193323Sed
41276479Sdimstatic cl::opt<bool>
42314564Sdim    FindBugs("find-bugs", cl::desc("Run many different optimization sequences "
43314564Sdim                                   "on program to find bugs"),
44314564Sdim             cl::init(false));
45193323Sed
46193323Sedstatic cl::list<std::string>
47314564Sdim    InputFilenames(cl::Positional, cl::OneOrMore,
48314564Sdim                   cl::desc("<input llvm ll/bc files>"));
49193323Sed
50314564Sdimstatic cl::opt<unsigned> TimeoutValue(
51314564Sdim    "timeout", cl::init(300), cl::value_desc("seconds"),
52314564Sdim    cl::desc("Number of seconds program is allowed to run before it "
53314564Sdim             "is killed (default is 300s), 0 disables timeout"));
54193323Sed
55327952Sdimstatic cl::opt<int> MemoryLimit(
56327952Sdim    "mlimit", cl::init(-1), cl::value_desc("MBytes"),
57327952Sdim    cl::desc("Maximum amount of memory to use. 0 disables check. Defaults to "
58327952Sdim             "400MB (800MB under valgrind, 0 with sanitizers)."));
59193323Sed
60205407Srdivackystatic cl::opt<bool>
61314564Sdim    UseValgrind("enable-valgrind",
62314564Sdim                cl::desc("Run optimizations through valgrind"));
63205407Srdivacky
64193323Sed// The AnalysesList is automatically populated with registered Passes by the
65193323Sed// PassNameParser.
66193323Sed//
67314564Sdimstatic cl::list<const PassInfo *, bool, PassNameParser>
68314564Sdim    PassList(cl::desc("Passes available:"), cl::ZeroOrMore);
69193323Sed
70198090Srdivackystatic cl::opt<bool>
71314564Sdim    StandardLinkOpts("std-link-opts",
72314564Sdim                     cl::desc("Include the standard link time optimizations"));
73198090Srdivacky
74223013Sdimstatic cl::opt<bool>
75314564Sdim    OptLevelO1("O1", cl::desc("Optimization level 1. Identical to 'opt -O1'"));
76223013Sdim
77223013Sdimstatic cl::opt<bool>
78314564Sdim    OptLevelO2("O2", cl::desc("Optimization level 2. Identical to 'opt -O2'"));
79223013Sdim
80314564Sdimstatic cl::opt<bool> OptLevelOs(
81314564Sdim    "Os",
82314564Sdim    cl::desc(
83314564Sdim        "Like -O2 with extra optimizations for size. Similar to clang -Os"));
84314564Sdim
85223013Sdimstatic cl::opt<bool>
86360784SdimOptLevelOz("Oz",
87360784Sdim           cl::desc("Like -Os but reduces code size further. Similar to clang -Oz"));
88360784Sdim
89360784Sdimstatic cl::opt<bool>
90314564Sdim    OptLevelO3("O3", cl::desc("Optimization level 3. Identical to 'opt -O3'"));
91223013Sdim
92198090Srdivackystatic cl::opt<std::string>
93314564Sdim    OverrideTriple("mtriple", cl::desc("Override target triple for module"));
94198090Srdivacky
95193323Sed/// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
96193323Sedbool llvm::BugpointIsInterrupted = false;
97193323Sed
98218885Sdim#ifndef DEBUG_BUGPOINT
99314564Sdimstatic void BugpointInterruptFunction() { BugpointIsInterrupted = true; }
100218885Sdim#endif
101193323Sed
102198090Srdivacky// Hack to capture a pass list.
103198090Srdivackynamespace {
104314564Sdimclass AddToDriver : public legacy::FunctionPassManager {
105314564Sdim  BugDriver &D;
106276479Sdim
107314564Sdimpublic:
108314564Sdim  AddToDriver(BugDriver &_D) : FunctionPassManager(nullptr), D(_D) {}
109314564Sdim
110314564Sdim  void add(Pass *P) override {
111314564Sdim    const void *ID = P->getPassID();
112314564Sdim    const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID);
113314564Sdim    D.addPass(PI->getPassArgument());
114314564Sdim  }
115314564Sdim};
116198090Srdivacky}
117198090Srdivacky
118360784Sdim// This routine adds optimization passes based on selected optimization level,
119360784Sdim// OptLevel.
120360784Sdim//
121360784Sdim// OptLevel - Optimization Level
122360784Sdimstatic void AddOptimizationPasses(legacy::FunctionPassManager &FPM,
123360784Sdim                                  unsigned OptLevel,
124360784Sdim                                  unsigned SizeLevel) {
125360784Sdim  PassManagerBuilder Builder;
126360784Sdim  Builder.OptLevel = OptLevel;
127360784Sdim  Builder.SizeLevel = SizeLevel;
128360784Sdim
129360784Sdim  if (OptLevel > 1)
130360784Sdim    Builder.Inliner = createFunctionInliningPass(OptLevel, SizeLevel, false);
131360784Sdim  else
132360784Sdim    Builder.Inliner = createAlwaysInlinerLegacyPass();
133360784Sdim
134360784Sdim  Builder.populateFunctionPassManager(FPM);
135360784Sdim  Builder.populateModulePassManager(FPM);
136276479Sdim}
137276479Sdim
138360784Sdim#define HANDLE_EXTENSION(Ext)                                                  \
139360784Sdim  llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
140360784Sdim#include "llvm/Support/Extension.def"
141360784Sdim
142193323Sedint main(int argc, char **argv) {
143218885Sdim#ifndef DEBUG_BUGPOINT
144341825Sdim  InitLLVM X(argc, argv);
145218885Sdim#endif
146276479Sdim
147218885Sdim  // Initialize passes
148218885Sdim  PassRegistry &Registry = *PassRegistry::getPassRegistry();
149218885Sdim  initializeCore(Registry);
150218885Sdim  initializeScalarOpts(Registry);
151249423Sdim  initializeObjCARCOpts(Registry);
152234353Sdim  initializeVectorization(Registry);
153218885Sdim  initializeIPO(Registry);
154218885Sdim  initializeAnalysis(Registry);
155218885Sdim  initializeTransformUtils(Registry);
156218885Sdim  initializeInstCombine(Registry);
157341825Sdim  initializeAggressiveInstCombine(Registry);
158218885Sdim  initializeInstrumentation(Registry);
159218885Sdim  initializeTarget(Registry);
160276479Sdim
161321369Sdim  if (std::getenv("bar") == (char*) -1) {
162321369Sdim    InitializeAllTargets();
163321369Sdim    InitializeAllTargetMCs();
164321369Sdim    InitializeAllAsmPrinters();
165321369Sdim    InitializeAllAsmParsers();
166321369Sdim  }
167321369Sdim
168193323Sed  cl::ParseCommandLineOptions(argc, argv,
169193323Sed                              "LLVM automatic testcase reducer. See\nhttp://"
170193323Sed                              "llvm.org/cmds/bugpoint.html"
171193323Sed                              " for more information.\n");
172218885Sdim#ifndef DEBUG_BUGPOINT
173193323Sed  sys::SetInterruptFunction(BugpointInterruptFunction);
174218885Sdim#endif
175195340Sed
176309124Sdim  LLVMContext Context;
177198090Srdivacky  // If we have an override, set it and then track the triple we want Modules
178198090Srdivacky  // to use.
179198090Srdivacky  if (!OverrideTriple.empty()) {
180212793Sdim    TargetTriple.setTriple(Triple::normalize(OverrideTriple));
181212793Sdim    outs() << "Override triple set to '" << TargetTriple.getTriple() << "'\n";
182198090Srdivacky  }
183198090Srdivacky
184205407Srdivacky  if (MemoryLimit < 0) {
185205407Srdivacky    // Set the default MemoryLimit.  Be sure to update the flag's description if
186205407Srdivacky    // you change this.
187205407Srdivacky    if (sys::RunningOnValgrind() || UseValgrind)
188205407Srdivacky      MemoryLimit = 800;
189205407Srdivacky    else
190288943Sdim      MemoryLimit = 400;
191327952Sdim#if (LLVM_ADDRESS_SANITIZER_BUILD || LLVM_MEMORY_SANITIZER_BUILD ||            \
192327952Sdim     LLVM_THREAD_SANITIZER_BUILD)
193327952Sdim    // Starting from kernel 4.9 memory allocated with mmap is counted against
194327952Sdim    // RLIMIT_DATA. Sanitizers need to allocate tens of terabytes for shadow.
195327952Sdim    MemoryLimit = 0;
196327952Sdim#endif
197205407Srdivacky  }
198205407Srdivacky
199314564Sdim  BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit, UseValgrind,
200314564Sdim              Context);
201314564Sdim  if (D.addSources(InputFilenames))
202314564Sdim    return 1;
203276479Sdim
204198090Srdivacky  AddToDriver PM(D);
205276479Sdim
206223013Sdim  if (StandardLinkOpts) {
207223013Sdim    PassManagerBuilder Builder;
208280031Sdim    Builder.Inliner = createFunctionInliningPass();
209280031Sdim    Builder.populateLTOPassManager(PM);
210223013Sdim  }
211198090Srdivacky
212360784Sdim  if (OptLevelO1)
213360784Sdim    AddOptimizationPasses(PM, 1, 0);
214360784Sdim  else if (OptLevelO2)
215360784Sdim    AddOptimizationPasses(PM, 2, 0);
216360784Sdim  else if (OptLevelO3)
217360784Sdim    AddOptimizationPasses(PM, 3, 0);
218360784Sdim  else if (OptLevelOs)
219360784Sdim    AddOptimizationPasses(PM, 2, 1);
220360784Sdim  else if (OptLevelOz)
221360784Sdim    AddOptimizationPasses(PM, 2, 2);
222223013Sdim
223296417Sdim  for (const PassInfo *PI : PassList)
224212793Sdim    D.addPass(PI->getPassArgument());
225212793Sdim
226314564Sdim// Bugpoint has the ability of generating a plethora of core files, so to
227314564Sdim// avoid filling up the disk, we prevent it
228218885Sdim#ifndef DEBUG_BUGPOINT
229193323Sed  sys::Process::PreventCoreFiles();
230218885Sdim#endif
231193323Sed
232360784Sdim// Needed to pull in symbols from statically linked extensions, including static
233360784Sdim// registration. It is unused otherwise because bugpoint has no support for
234360784Sdim// NewPM.
235360784Sdim#define HANDLE_EXTENSION(Ext)                                                  \
236360784Sdim  (void)get##Ext##PluginInfo();
237360784Sdim#include "llvm/Support/Extension.def"
238360784Sdim
239314564Sdim  if (Error E = D.run()) {
240314564Sdim    errs() << toString(std::move(E));
241207618Srdivacky    return 1;
242193323Sed  }
243314564Sdim  return 0;
244193323Sed}
245