xref: /freebsd-src/contrib/llvm-project/llvm/tools/bugpoint/bugpoint.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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