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/Plugins/PassPlugin.h"
25#include "llvm/Support/AlwaysTrue.h"
26#include "llvm/Support/CommandLine.h"
27#include "llvm/Support/InitLLVM.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
35// Enable this macro to debug bugpoint itself.
36//#define DEBUG_BUGPOINT 1
37
38using namespace llvm;
39
40static cl::opt<bool>
41 FindBugs("find-bugs", cl::desc("Run many different optimization sequences "
42 "on program to find bugs"),
43 cl::init(Val: false));
44
45static cl::list<std::string>
46 InputFilenames(cl::Positional, cl::OneOrMore,
47 cl::desc("<input llvm ll/bc files>"));
48
49static cl::opt<unsigned> TimeoutValue(
50 "timeout", cl::init(Val: 300), cl::value_desc("seconds"),
51 cl::desc("Number of seconds program is allowed to run before it "
52 "is killed (default is 300s), 0 disables timeout"));
53
54static cl::opt<int> MemoryLimit(
55 "mlimit", cl::init(Val: -1), cl::value_desc("MBytes"),
56 cl::desc("Maximum amount of memory to use. 0 disables check. Defaults to "
57 "400MB (800MB under valgrind, 0 with sanitizers)."));
58
59static cl::opt<bool>
60 UseValgrind("enable-valgrind",
61 cl::desc("Run optimizations through valgrind"));
62
63// The AnalysesList is automatically populated with registered Passes by the
64// PassNameParser.
65//
66static cl::list<const PassInfo *, bool, PassNameParser>
67 PassList(cl::desc("Passes available:"));
68
69static cl::opt<std::string>
70 OverrideTriple("mtriple", cl::desc("Override target triple for module"));
71
72/// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
73bool llvm::BugpointIsInterrupted = false;
74
75#ifndef DEBUG_BUGPOINT
76static void BugpointInterruptFunction() { BugpointIsInterrupted = true; }
77#endif
78
79// Hack to capture a pass list.
80namespace {
81class AddToDriver : public legacy::FunctionPassManager {
82 BugDriver &D;
83
84public:
85 AddToDriver(BugDriver &_D) : FunctionPassManager(nullptr), D(_D) {}
86
87 void add(Pass *P) override {
88 const void *ID = P->getPassID();
89 const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(TI: ID);
90 D.addPass(p: std::string(PI->getPassArgument()));
91 }
92};
93} // namespace
94
95#define HANDLE_EXTENSION(Ext) \
96 llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
97#include "llvm/Support/Extension.def"
98
99int main(int argc, char **argv) {
100#ifndef DEBUG_BUGPOINT
101 InitLLVM X(argc, argv);
102#endif
103
104 // Initialize passes
105 PassRegistry &Registry = *PassRegistry::getPassRegistry();
106 initializeCore(Registry);
107 initializeScalarOpts(Registry);
108 initializeVectorization(Registry);
109 initializeIPO(Registry);
110 initializeAnalysis(Registry);
111 initializeTransformUtils(Registry);
112 initializeInstCombine(Registry);
113 initializeTarget(Registry);
114
115 if (!llvm::getNonFoldableAlwaysTrue()) {
116 InitializeAllTargets();
117 InitializeAllTargetMCs();
118 InitializeAllAsmPrinters();
119 InitializeAllAsmParsers();
120 }
121
122 cl::ParseCommandLineOptions(argc, argv,
123 Overview: "LLVM automatic testcase reducer. See\nhttp://"
124 "llvm.org/cmds/bugpoint.html"
125 " for more information.\n");
126#ifndef DEBUG_BUGPOINT
127 sys::SetInterruptFunction(BugpointInterruptFunction);
128#endif
129
130 LLVMContext Context;
131 // If we have an override, set it and then track the triple we want Modules
132 // to use.
133 if (!OverrideTriple.empty()) {
134 TargetTriple.setTriple(Triple::normalize(Str: OverrideTriple));
135 outs() << "Override triple set to '" << TargetTriple.getTriple() << "'\n";
136 }
137
138 if (MemoryLimit < 0) {
139 // Set the default MemoryLimit. Be sure to update the flag's description if
140 // you change this.
141 if (sys::RunningOnValgrind() || UseValgrind)
142 MemoryLimit = 800;
143 else
144 MemoryLimit = 400;
145#if (LLVM_ADDRESS_SANITIZER_BUILD || LLVM_MEMORY_SANITIZER_BUILD || \
146 LLVM_THREAD_SANITIZER_BUILD)
147 // Starting from kernel 4.9 memory allocated with mmap is counted against
148 // RLIMIT_DATA. Sanitizers need to allocate tens of terabytes for shadow.
149 MemoryLimit = 0;
150#endif
151 }
152
153 BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit, UseValgrind,
154 Context);
155 if (D.addSources(FileNames: InputFilenames))
156 return 1;
157
158 AddToDriver PM(D);
159
160 for (const PassInfo *PI : PassList)
161 D.addPass(p: std::string(PI->getPassArgument()));
162
163// Bugpoint has the ability of generating a plethora of core files, so to
164// avoid filling up the disk, we prevent it
165#ifndef DEBUG_BUGPOINT
166 sys::Process::PreventCoreFiles();
167#endif
168
169// Needed to pull in symbols from statically linked extensions, including static
170// registration. It is unused otherwise because bugpoint has no support for
171// NewPM.
172#define HANDLE_EXTENSION(Ext) \
173 (void)get##Ext##PluginInfo();
174#include "llvm/Support/Extension.def"
175
176 if (Error E = D.run()) {
177 errs() << toString(E: std::move(E));
178 return 1;
179 }
180 return 0;
181}
182