10b57cec5SDimitry Andric //===- bugpoint.cpp - The LLVM Bugpoint utility ---------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This program is an automated compiler debugger tool. It is used to narrow
100b57cec5SDimitry Andric // down miscompilations and crash problems to a specific pass in the compiler,
110b57cec5SDimitry Andric // and the specific Module or Function input that is causing the problem.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "BugDriver.h"
160b57cec5SDimitry Andric #include "ToolRunner.h"
170b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
180b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
190b57cec5SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
200b57cec5SDimitry Andric #include "llvm/IR/LegacyPassNameParser.h"
21480093f4SDimitry Andric #include "llvm/InitializePasses.h"
220b57cec5SDimitry Andric #include "llvm/LinkAllIR.h"
230b57cec5SDimitry Andric #include "llvm/LinkAllPasses.h"
24480093f4SDimitry Andric #include "llvm/Passes/PassPlugin.h"
250b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
260b57cec5SDimitry Andric #include "llvm/Support/InitLLVM.h"
270b57cec5SDimitry Andric #include "llvm/Support/PluginLoader.h"
280b57cec5SDimitry Andric #include "llvm/Support/PrettyStackTrace.h"
290b57cec5SDimitry Andric #include "llvm/Support/Process.h"
300b57cec5SDimitry Andric #include "llvm/Support/TargetSelect.h"
310b57cec5SDimitry Andric #include "llvm/Support/Valgrind.h"
320b57cec5SDimitry Andric #include "llvm/Transforms/IPO/AlwaysInliner.h"
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric // Enable this macro to debug bugpoint itself.
350b57cec5SDimitry Andric //#define DEBUG_BUGPOINT 1
360b57cec5SDimitry Andric
370b57cec5SDimitry Andric using namespace llvm;
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric static cl::opt<bool>
400b57cec5SDimitry Andric FindBugs("find-bugs", cl::desc("Run many different optimization sequences "
410b57cec5SDimitry Andric "on program to find bugs"),
420b57cec5SDimitry Andric cl::init(false));
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric static cl::list<std::string>
450b57cec5SDimitry Andric InputFilenames(cl::Positional, cl::OneOrMore,
460b57cec5SDimitry Andric cl::desc("<input llvm ll/bc files>"));
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric static cl::opt<unsigned> TimeoutValue(
490b57cec5SDimitry Andric "timeout", cl::init(300), cl::value_desc("seconds"),
500b57cec5SDimitry Andric cl::desc("Number of seconds program is allowed to run before it "
510b57cec5SDimitry Andric "is killed (default is 300s), 0 disables timeout"));
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric static cl::opt<int> MemoryLimit(
540b57cec5SDimitry Andric "mlimit", cl::init(-1), cl::value_desc("MBytes"),
550b57cec5SDimitry Andric cl::desc("Maximum amount of memory to use. 0 disables check. Defaults to "
560b57cec5SDimitry Andric "400MB (800MB under valgrind, 0 with sanitizers)."));
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric static cl::opt<bool>
590b57cec5SDimitry Andric UseValgrind("enable-valgrind",
600b57cec5SDimitry Andric cl::desc("Run optimizations through valgrind"));
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric // The AnalysesList is automatically populated with registered Passes by the
630b57cec5SDimitry Andric // PassNameParser.
640b57cec5SDimitry Andric //
650b57cec5SDimitry Andric static cl::list<const PassInfo *, bool, PassNameParser>
66*81ad6265SDimitry Andric PassList(cl::desc("Passes available:"));
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric static cl::opt<std::string>
690b57cec5SDimitry Andric OverrideTriple("mtriple", cl::desc("Override target triple for module"));
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric /// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
720b57cec5SDimitry Andric bool llvm::BugpointIsInterrupted = false;
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric #ifndef DEBUG_BUGPOINT
BugpointInterruptFunction()750b57cec5SDimitry Andric static void BugpointInterruptFunction() { BugpointIsInterrupted = true; }
760b57cec5SDimitry Andric #endif
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric // Hack to capture a pass list.
790b57cec5SDimitry Andric namespace {
800b57cec5SDimitry Andric class AddToDriver : public legacy::FunctionPassManager {
810b57cec5SDimitry Andric BugDriver &D;
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric public:
AddToDriver(BugDriver & _D)840b57cec5SDimitry Andric AddToDriver(BugDriver &_D) : FunctionPassManager(nullptr), D(_D) {}
850b57cec5SDimitry Andric
add(Pass * P)860b57cec5SDimitry Andric void add(Pass *P) override {
870b57cec5SDimitry Andric const void *ID = P->getPassID();
880b57cec5SDimitry Andric const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(ID);
895ffd83dbSDimitry Andric D.addPass(std::string(PI->getPassArgument()));
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric };
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric
94480093f4SDimitry Andric #define HANDLE_EXTENSION(Ext) \
95480093f4SDimitry Andric llvm::PassPluginLibraryInfo get##Ext##PluginInfo();
96480093f4SDimitry Andric #include "llvm/Support/Extension.def"
970b57cec5SDimitry Andric
main(int argc,char ** argv)980b57cec5SDimitry Andric int main(int argc, char **argv) {
990b57cec5SDimitry Andric #ifndef DEBUG_BUGPOINT
1000b57cec5SDimitry Andric InitLLVM X(argc, argv);
1010b57cec5SDimitry Andric #endif
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andric // Initialize passes
1040b57cec5SDimitry Andric PassRegistry &Registry = *PassRegistry::getPassRegistry();
1050b57cec5SDimitry Andric initializeCore(Registry);
1060b57cec5SDimitry Andric initializeScalarOpts(Registry);
1070b57cec5SDimitry Andric initializeVectorization(Registry);
1080b57cec5SDimitry Andric initializeIPO(Registry);
1090b57cec5SDimitry Andric initializeAnalysis(Registry);
1100b57cec5SDimitry Andric initializeTransformUtils(Registry);
1110b57cec5SDimitry Andric initializeInstCombine(Registry);
1120b57cec5SDimitry Andric initializeTarget(Registry);
1130b57cec5SDimitry Andric
1140b57cec5SDimitry Andric if (std::getenv("bar") == (char*) -1) {
1150b57cec5SDimitry Andric InitializeAllTargets();
1160b57cec5SDimitry Andric InitializeAllTargetMCs();
1170b57cec5SDimitry Andric InitializeAllAsmPrinters();
1180b57cec5SDimitry Andric InitializeAllAsmParsers();
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric cl::ParseCommandLineOptions(argc, argv,
1220b57cec5SDimitry Andric "LLVM automatic testcase reducer. See\nhttp://"
1230b57cec5SDimitry Andric "llvm.org/cmds/bugpoint.html"
1240b57cec5SDimitry Andric " for more information.\n");
1250b57cec5SDimitry Andric #ifndef DEBUG_BUGPOINT
1260b57cec5SDimitry Andric sys::SetInterruptFunction(BugpointInterruptFunction);
1270b57cec5SDimitry Andric #endif
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric LLVMContext Context;
1300b57cec5SDimitry Andric // If we have an override, set it and then track the triple we want Modules
1310b57cec5SDimitry Andric // to use.
1320b57cec5SDimitry Andric if (!OverrideTriple.empty()) {
1330b57cec5SDimitry Andric TargetTriple.setTriple(Triple::normalize(OverrideTriple));
1340b57cec5SDimitry Andric outs() << "Override triple set to '" << TargetTriple.getTriple() << "'\n";
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric if (MemoryLimit < 0) {
1380b57cec5SDimitry Andric // Set the default MemoryLimit. Be sure to update the flag's description if
1390b57cec5SDimitry Andric // you change this.
1400b57cec5SDimitry Andric if (sys::RunningOnValgrind() || UseValgrind)
1410b57cec5SDimitry Andric MemoryLimit = 800;
1420b57cec5SDimitry Andric else
1430b57cec5SDimitry Andric MemoryLimit = 400;
1440b57cec5SDimitry Andric #if (LLVM_ADDRESS_SANITIZER_BUILD || LLVM_MEMORY_SANITIZER_BUILD || \
1450b57cec5SDimitry Andric LLVM_THREAD_SANITIZER_BUILD)
1460b57cec5SDimitry Andric // Starting from kernel 4.9 memory allocated with mmap is counted against
1470b57cec5SDimitry Andric // RLIMIT_DATA. Sanitizers need to allocate tens of terabytes for shadow.
1480b57cec5SDimitry Andric MemoryLimit = 0;
1490b57cec5SDimitry Andric #endif
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit, UseValgrind,
1530b57cec5SDimitry Andric Context);
1540b57cec5SDimitry Andric if (D.addSources(InputFilenames))
1550b57cec5SDimitry Andric return 1;
1560b57cec5SDimitry Andric
1570b57cec5SDimitry Andric AddToDriver PM(D);
1580b57cec5SDimitry Andric
1590b57cec5SDimitry Andric for (const PassInfo *PI : PassList)
1605ffd83dbSDimitry Andric D.addPass(std::string(PI->getPassArgument()));
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric // Bugpoint has the ability of generating a plethora of core files, so to
1630b57cec5SDimitry Andric // avoid filling up the disk, we prevent it
1640b57cec5SDimitry Andric #ifndef DEBUG_BUGPOINT
1650b57cec5SDimitry Andric sys::Process::PreventCoreFiles();
1660b57cec5SDimitry Andric #endif
1670b57cec5SDimitry Andric
168480093f4SDimitry Andric // Needed to pull in symbols from statically linked extensions, including static
169480093f4SDimitry Andric // registration. It is unused otherwise because bugpoint has no support for
170480093f4SDimitry Andric // NewPM.
171480093f4SDimitry Andric #define HANDLE_EXTENSION(Ext) \
172480093f4SDimitry Andric (void)get##Ext##PluginInfo();
173480093f4SDimitry Andric #include "llvm/Support/Extension.def"
174480093f4SDimitry Andric
1750b57cec5SDimitry Andric if (Error E = D.run()) {
1760b57cec5SDimitry Andric errs() << toString(std::move(E));
1770b57cec5SDimitry Andric return 1;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric return 0;
1800b57cec5SDimitry Andric }
181