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