xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-extract/llvm-extract.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- llvm-extract.cpp - LLVM function extraction 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 utility changes the input module to only contain a single function,
100b57cec5SDimitry Andric // which is primarily used for debugging transformations.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
150b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
160b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeWriterPass.h"
170b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
180b57cec5SDimitry Andric #include "llvm/IR/IRPrintingPasses.h"
190b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
200b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
210b57cec5SDimitry Andric #include "llvm/IR/Module.h"
22bdd1243dSDimitry Andric #include "llvm/IRPrinter/IRPrintingPasses.h"
230b57cec5SDimitry Andric #include "llvm/IRReader/IRReader.h"
24bdd1243dSDimitry Andric #include "llvm/Passes/PassBuilder.h"
250b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
260b57cec5SDimitry Andric #include "llvm/Support/Error.h"
270b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
280b57cec5SDimitry Andric #include "llvm/Support/InitLLVM.h"
290b57cec5SDimitry Andric #include "llvm/Support/Regex.h"
300b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
310b57cec5SDimitry Andric #include "llvm/Support/SystemUtils.h"
320b57cec5SDimitry Andric #include "llvm/Support/ToolOutputFile.h"
330b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h"
34bdd1243dSDimitry Andric #include "llvm/Transforms/IPO/BlockExtractor.h"
35bdd1243dSDimitry Andric #include "llvm/Transforms/IPO/ExtractGV.h"
36bdd1243dSDimitry Andric #include "llvm/Transforms/IPO/GlobalDCE.h"
37bdd1243dSDimitry Andric #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
38bdd1243dSDimitry Andric #include "llvm/Transforms/IPO/StripSymbols.h"
390b57cec5SDimitry Andric #include <memory>
405ffd83dbSDimitry Andric #include <utility>
41bdd1243dSDimitry Andric 
420b57cec5SDimitry Andric using namespace llvm;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric cl::OptionCategory ExtractCat("llvm-extract Options");
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric // InputFilename - The filename to read from.
470b57cec5SDimitry Andric static cl::opt<std::string> InputFilename(cl::Positional,
480b57cec5SDimitry Andric                                           cl::desc("<input bitcode file>"),
490b57cec5SDimitry Andric                                           cl::init("-"),
500b57cec5SDimitry Andric                                           cl::value_desc("filename"));
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric static cl::opt<std::string> OutputFilename("o",
530b57cec5SDimitry Andric                                            cl::desc("Specify output filename"),
540b57cec5SDimitry Andric                                            cl::value_desc("filename"),
550b57cec5SDimitry Andric                                            cl::init("-"), cl::cat(ExtractCat));
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric static cl::opt<bool> Force("f", cl::desc("Enable binary output on terminals"),
580b57cec5SDimitry Andric                            cl::cat(ExtractCat));
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric static cl::opt<bool> DeleteFn("delete",
610b57cec5SDimitry Andric                               cl::desc("Delete specified Globals from Module"),
620b57cec5SDimitry Andric                               cl::cat(ExtractCat));
630b57cec5SDimitry Andric 
645ffd83dbSDimitry Andric static cl::opt<bool> KeepConstInit("keep-const-init",
655ffd83dbSDimitry Andric                               cl::desc("Keep initializers of constants"),
665ffd83dbSDimitry Andric                               cl::cat(ExtractCat));
675ffd83dbSDimitry Andric 
680b57cec5SDimitry Andric static cl::opt<bool>
690b57cec5SDimitry Andric     Recursive("recursive", cl::desc("Recursively extract all called functions"),
700b57cec5SDimitry Andric               cl::cat(ExtractCat));
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric // ExtractFuncs - The functions to extract from the module.
730b57cec5SDimitry Andric static cl::list<std::string>
740b57cec5SDimitry Andric     ExtractFuncs("func", cl::desc("Specify function to extract"),
7581ad6265SDimitry Andric                  cl::value_desc("function"), cl::cat(ExtractCat));
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric // ExtractRegExpFuncs - The functions, matched via regular expression, to
780b57cec5SDimitry Andric // extract from the module.
790b57cec5SDimitry Andric static cl::list<std::string>
800b57cec5SDimitry Andric     ExtractRegExpFuncs("rfunc",
810b57cec5SDimitry Andric                        cl::desc("Specify function(s) to extract using a "
820b57cec5SDimitry Andric                                 "regular expression"),
8381ad6265SDimitry Andric                        cl::value_desc("rfunction"), cl::cat(ExtractCat));
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric // ExtractBlocks - The blocks to extract from the module.
860b57cec5SDimitry Andric static cl::list<std::string> ExtractBlocks(
878bcb0991SDimitry Andric     "bb",
888bcb0991SDimitry Andric     cl::desc(
898bcb0991SDimitry Andric         "Specify <function, basic block1[;basic block2...]> pairs to extract.\n"
908bcb0991SDimitry Andric         "Each pair will create a function.\n"
918bcb0991SDimitry Andric         "If multiple basic blocks are specified in one pair,\n"
928bcb0991SDimitry Andric         "the first block in the sequence should dominate the rest.\n"
938bcb0991SDimitry Andric         "eg:\n"
948bcb0991SDimitry Andric         "  --bb=f:bb1;bb2 will extract one function with both bb1 and bb2;\n"
958bcb0991SDimitry Andric         "  --bb=f:bb1 --bb=f:bb2 will extract two functions, one with bb1, one "
968bcb0991SDimitry Andric         "with bb2."),
9781ad6265SDimitry Andric     cl::value_desc("function:bb1[;bb2...]"), cl::cat(ExtractCat));
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric // ExtractAlias - The alias to extract from the module.
1000b57cec5SDimitry Andric static cl::list<std::string>
1010b57cec5SDimitry Andric     ExtractAliases("alias", cl::desc("Specify alias to extract"),
10281ad6265SDimitry Andric                    cl::value_desc("alias"), cl::cat(ExtractCat));
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric // ExtractRegExpAliases - The aliases, matched via regular expression, to
1050b57cec5SDimitry Andric // extract from the module.
1060b57cec5SDimitry Andric static cl::list<std::string>
1070b57cec5SDimitry Andric     ExtractRegExpAliases("ralias",
1080b57cec5SDimitry Andric                          cl::desc("Specify alias(es) to extract using a "
1090b57cec5SDimitry Andric                                   "regular expression"),
11081ad6265SDimitry Andric                          cl::value_desc("ralias"), cl::cat(ExtractCat));
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric // ExtractGlobals - The globals to extract from the module.
1130b57cec5SDimitry Andric static cl::list<std::string>
1140b57cec5SDimitry Andric     ExtractGlobals("glob", cl::desc("Specify global to extract"),
11581ad6265SDimitry Andric                    cl::value_desc("global"), cl::cat(ExtractCat));
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric // ExtractRegExpGlobals - The globals, matched via regular expression, to
1180b57cec5SDimitry Andric // extract from the module...
1190b57cec5SDimitry Andric static cl::list<std::string>
1200b57cec5SDimitry Andric     ExtractRegExpGlobals("rglob",
1210b57cec5SDimitry Andric                          cl::desc("Specify global(s) to extract using a "
1220b57cec5SDimitry Andric                                   "regular expression"),
12381ad6265SDimitry Andric                          cl::value_desc("rglobal"), cl::cat(ExtractCat));
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric static cl::opt<bool> OutputAssembly("S",
1260b57cec5SDimitry Andric                                     cl::desc("Write output as LLVM assembly"),
1270b57cec5SDimitry Andric                                     cl::Hidden, cl::cat(ExtractCat));
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric static cl::opt<bool> PreserveBitcodeUseListOrder(
1300b57cec5SDimitry Andric     "preserve-bc-uselistorder",
1310b57cec5SDimitry Andric     cl::desc("Preserve use-list order when writing LLVM bitcode."),
1320b57cec5SDimitry Andric     cl::init(true), cl::Hidden, cl::cat(ExtractCat));
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric static cl::opt<bool> PreserveAssemblyUseListOrder(
1350b57cec5SDimitry Andric     "preserve-ll-uselistorder",
1360b57cec5SDimitry Andric     cl::desc("Preserve use-list order when writing LLVM assembly."),
1370b57cec5SDimitry Andric     cl::init(false), cl::Hidden, cl::cat(ExtractCat));
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric int main(int argc, char **argv) {
1400b57cec5SDimitry Andric   InitLLVM X(argc, argv);
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   LLVMContext Context;
1430b57cec5SDimitry Andric   cl::HideUnrelatedOptions(ExtractCat);
1440b57cec5SDimitry Andric   cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n");
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   // Use lazy loading, since we only care about selected global values.
1470b57cec5SDimitry Andric   SMDiagnostic Err;
1480b57cec5SDimitry Andric   std::unique_ptr<Module> M = getLazyIRFileModule(InputFilename, Err, Context);
1490b57cec5SDimitry Andric 
150*0fca6ea1SDimitry Andric   if (!M) {
1510b57cec5SDimitry Andric     Err.print(argv[0], errs());
1520b57cec5SDimitry Andric     return 1;
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   // Use SetVector to avoid duplicates.
1560b57cec5SDimitry Andric   SetVector<GlobalValue *> GVs;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   // Figure out which aliases we should extract.
1590b57cec5SDimitry Andric   for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) {
1600b57cec5SDimitry Andric     GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]);
1610b57cec5SDimitry Andric     if (!GA) {
1620b57cec5SDimitry Andric       errs() << argv[0] << ": program doesn't contain alias named '"
1630b57cec5SDimitry Andric              << ExtractAliases[i] << "'!\n";
1640b57cec5SDimitry Andric       return 1;
1650b57cec5SDimitry Andric     }
1660b57cec5SDimitry Andric     GVs.insert(GA);
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   // Extract aliases via regular expression matching.
1700b57cec5SDimitry Andric   for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) {
1710b57cec5SDimitry Andric     std::string Error;
1720b57cec5SDimitry Andric     Regex RegEx(ExtractRegExpAliases[i]);
1730b57cec5SDimitry Andric     if (!RegEx.isValid(Error)) {
1740b57cec5SDimitry Andric       errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' "
1750b57cec5SDimitry Andric         "invalid regex: " << Error;
1760b57cec5SDimitry Andric     }
1770b57cec5SDimitry Andric     bool match = false;
1780b57cec5SDimitry Andric     for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end();
1790b57cec5SDimitry Andric          GA != E; GA++) {
1800b57cec5SDimitry Andric       if (RegEx.match(GA->getName())) {
1810b57cec5SDimitry Andric         GVs.insert(&*GA);
1820b57cec5SDimitry Andric         match = true;
1830b57cec5SDimitry Andric       }
1840b57cec5SDimitry Andric     }
1850b57cec5SDimitry Andric     if (!match) {
1860b57cec5SDimitry Andric       errs() << argv[0] << ": program doesn't contain global named '"
1870b57cec5SDimitry Andric              << ExtractRegExpAliases[i] << "'!\n";
1880b57cec5SDimitry Andric       return 1;
1890b57cec5SDimitry Andric     }
1900b57cec5SDimitry Andric   }
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   // Figure out which globals we should extract.
1930b57cec5SDimitry Andric   for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) {
1940b57cec5SDimitry Andric     GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]);
1950b57cec5SDimitry Andric     if (!GV) {
1960b57cec5SDimitry Andric       errs() << argv[0] << ": program doesn't contain global named '"
1970b57cec5SDimitry Andric              << ExtractGlobals[i] << "'!\n";
1980b57cec5SDimitry Andric       return 1;
1990b57cec5SDimitry Andric     }
2000b57cec5SDimitry Andric     GVs.insert(GV);
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   // Extract globals via regular expression matching.
2040b57cec5SDimitry Andric   for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) {
2050b57cec5SDimitry Andric     std::string Error;
2060b57cec5SDimitry Andric     Regex RegEx(ExtractRegExpGlobals[i]);
2070b57cec5SDimitry Andric     if (!RegEx.isValid(Error)) {
2080b57cec5SDimitry Andric       errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' "
2090b57cec5SDimitry Andric         "invalid regex: " << Error;
2100b57cec5SDimitry Andric     }
2110b57cec5SDimitry Andric     bool match = false;
2120b57cec5SDimitry Andric     for (auto &GV : M->globals()) {
2130b57cec5SDimitry Andric       if (RegEx.match(GV.getName())) {
2140b57cec5SDimitry Andric         GVs.insert(&GV);
2150b57cec5SDimitry Andric         match = true;
2160b57cec5SDimitry Andric       }
2170b57cec5SDimitry Andric     }
2180b57cec5SDimitry Andric     if (!match) {
2190b57cec5SDimitry Andric       errs() << argv[0] << ": program doesn't contain global named '"
2200b57cec5SDimitry Andric              << ExtractRegExpGlobals[i] << "'!\n";
2210b57cec5SDimitry Andric       return 1;
2220b57cec5SDimitry Andric     }
2230b57cec5SDimitry Andric   }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   // Figure out which functions we should extract.
2260b57cec5SDimitry Andric   for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) {
2270b57cec5SDimitry Andric     GlobalValue *GV = M->getFunction(ExtractFuncs[i]);
2280b57cec5SDimitry Andric     if (!GV) {
2290b57cec5SDimitry Andric       errs() << argv[0] << ": program doesn't contain function named '"
2300b57cec5SDimitry Andric              << ExtractFuncs[i] << "'!\n";
2310b57cec5SDimitry Andric       return 1;
2320b57cec5SDimitry Andric     }
2330b57cec5SDimitry Andric     GVs.insert(GV);
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric   // Extract functions via regular expression matching.
2360b57cec5SDimitry Andric   for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) {
2370b57cec5SDimitry Andric     std::string Error;
2380b57cec5SDimitry Andric     StringRef RegExStr = ExtractRegExpFuncs[i];
2390b57cec5SDimitry Andric     Regex RegEx(RegExStr);
2400b57cec5SDimitry Andric     if (!RegEx.isValid(Error)) {
2410b57cec5SDimitry Andric       errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' "
2420b57cec5SDimitry Andric         "invalid regex: " << Error;
2430b57cec5SDimitry Andric     }
2440b57cec5SDimitry Andric     bool match = false;
2450b57cec5SDimitry Andric     for (Module::iterator F = M->begin(), E = M->end(); F != E;
2460b57cec5SDimitry Andric          F++) {
2470b57cec5SDimitry Andric       if (RegEx.match(F->getName())) {
2480b57cec5SDimitry Andric         GVs.insert(&*F);
2490b57cec5SDimitry Andric         match = true;
2500b57cec5SDimitry Andric       }
2510b57cec5SDimitry Andric     }
2520b57cec5SDimitry Andric     if (!match) {
2530b57cec5SDimitry Andric       errs() << argv[0] << ": program doesn't contain global named '"
2540b57cec5SDimitry Andric              << ExtractRegExpFuncs[i] << "'!\n";
2550b57cec5SDimitry Andric       return 1;
2560b57cec5SDimitry Andric     }
2570b57cec5SDimitry Andric   }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   // Figure out which BasicBlocks we should extract.
2605ffd83dbSDimitry Andric   SmallVector<std::pair<Function *, SmallVector<StringRef, 16>>, 2> BBMap;
2610b57cec5SDimitry Andric   for (StringRef StrPair : ExtractBlocks) {
2625ffd83dbSDimitry Andric     SmallVector<StringRef, 16> BBNames;
2630b57cec5SDimitry Andric     auto BBInfo = StrPair.split(':');
2640b57cec5SDimitry Andric     // Get the function.
2650b57cec5SDimitry Andric     Function *F = M->getFunction(BBInfo.first);
2660b57cec5SDimitry Andric     if (!F) {
2670b57cec5SDimitry Andric       errs() << argv[0] << ": program doesn't contain a function named '"
2680b57cec5SDimitry Andric              << BBInfo.first << "'!\n";
2690b57cec5SDimitry Andric       return 1;
2700b57cec5SDimitry Andric     }
2715ffd83dbSDimitry Andric     // Add the function to the materialize list, and store the basic block names
2725ffd83dbSDimitry Andric     // to check after materialization.
2730b57cec5SDimitry Andric     GVs.insert(F);
2745ffd83dbSDimitry Andric     BBInfo.second.split(BBNames, ';', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
2755ffd83dbSDimitry Andric     BBMap.push_back({F, std::move(BBNames)});
2760b57cec5SDimitry Andric   }
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   // Use *argv instead of argv[0] to work around a wrong GCC warning.
2790b57cec5SDimitry Andric   ExitOnError ExitOnErr(std::string(*argv) + ": error reading input: ");
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   if (Recursive) {
2820b57cec5SDimitry Andric     std::vector<llvm::Function *> Workqueue;
2830b57cec5SDimitry Andric     for (GlobalValue *GV : GVs) {
2840b57cec5SDimitry Andric       if (auto *F = dyn_cast<Function>(GV)) {
2850b57cec5SDimitry Andric         Workqueue.push_back(F);
2860b57cec5SDimitry Andric       }
2870b57cec5SDimitry Andric     }
2880b57cec5SDimitry Andric     while (!Workqueue.empty()) {
2890b57cec5SDimitry Andric       Function *F = &*Workqueue.back();
2900b57cec5SDimitry Andric       Workqueue.pop_back();
2910b57cec5SDimitry Andric       ExitOnErr(F->materialize());
2920b57cec5SDimitry Andric       for (auto &BB : *F) {
2930b57cec5SDimitry Andric         for (auto &I : BB) {
2940b57cec5SDimitry Andric           CallBase *CB = dyn_cast<CallBase>(&I);
2950b57cec5SDimitry Andric           if (!CB)
2960b57cec5SDimitry Andric             continue;
2970b57cec5SDimitry Andric           Function *CF = CB->getCalledFunction();
2980b57cec5SDimitry Andric           if (!CF)
2990b57cec5SDimitry Andric             continue;
3000b57cec5SDimitry Andric           if (CF->isDeclaration() || GVs.count(CF))
3010b57cec5SDimitry Andric             continue;
3020b57cec5SDimitry Andric           GVs.insert(CF);
3030b57cec5SDimitry Andric           Workqueue.push_back(CF);
3040b57cec5SDimitry Andric         }
3050b57cec5SDimitry Andric       }
3060b57cec5SDimitry Andric     }
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   auto Materialize = [&](GlobalValue &GV) { ExitOnErr(GV.materialize()); };
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   // Materialize requisite global values.
3120b57cec5SDimitry Andric   if (!DeleteFn) {
3130b57cec5SDimitry Andric     for (size_t i = 0, e = GVs.size(); i != e; ++i)
3140b57cec5SDimitry Andric       Materialize(*GVs[i]);
3150b57cec5SDimitry Andric   } else {
3160b57cec5SDimitry Andric     // Deleting. Materialize every GV that's *not* in GVs.
3170b57cec5SDimitry Andric     SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end());
3180b57cec5SDimitry Andric     for (auto &F : *M) {
3190b57cec5SDimitry Andric       if (!GVSet.count(&F))
3200b57cec5SDimitry Andric         Materialize(F);
3210b57cec5SDimitry Andric     }
3220b57cec5SDimitry Andric   }
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   {
3250b57cec5SDimitry Andric     std::vector<GlobalValue *> Gvs(GVs.begin(), GVs.end());
326bdd1243dSDimitry Andric     LoopAnalysisManager LAM;
327bdd1243dSDimitry Andric     FunctionAnalysisManager FAM;
328bdd1243dSDimitry Andric     CGSCCAnalysisManager CGAM;
329bdd1243dSDimitry Andric     ModuleAnalysisManager MAM;
330bdd1243dSDimitry Andric 
331bdd1243dSDimitry Andric     PassBuilder PB;
332bdd1243dSDimitry Andric 
333bdd1243dSDimitry Andric     PB.registerModuleAnalyses(MAM);
334bdd1243dSDimitry Andric     PB.registerCGSCCAnalyses(CGAM);
335bdd1243dSDimitry Andric     PB.registerFunctionAnalyses(FAM);
336bdd1243dSDimitry Andric     PB.registerLoopAnalyses(LAM);
337bdd1243dSDimitry Andric     PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
338bdd1243dSDimitry Andric 
339bdd1243dSDimitry Andric     ModulePassManager PM;
340bdd1243dSDimitry Andric     PM.addPass(ExtractGVPass(Gvs, DeleteFn, KeepConstInit));
341bdd1243dSDimitry Andric     PM.run(*M, MAM);
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric     // Now that we have all the GVs we want, mark the module as fully
3440b57cec5SDimitry Andric     // materialized.
3450b57cec5SDimitry Andric     // FIXME: should the GVExtractionPass handle this?
3460b57cec5SDimitry Andric     ExitOnErr(M->materializeAll());
3470b57cec5SDimitry Andric   }
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   // Extract the specified basic blocks from the module and erase the existing
3500b57cec5SDimitry Andric   // functions.
3510b57cec5SDimitry Andric   if (!ExtractBlocks.empty()) {
3525ffd83dbSDimitry Andric     // Figure out which BasicBlocks we should extract.
353bdd1243dSDimitry Andric     std::vector<std::vector<BasicBlock *>> GroupOfBBs;
3545ffd83dbSDimitry Andric     for (auto &P : BBMap) {
355bdd1243dSDimitry Andric       std::vector<BasicBlock *> BBs;
3565ffd83dbSDimitry Andric       for (StringRef BBName : P.second) {
3575ffd83dbSDimitry Andric         // The function has been materialized, so add its matching basic blocks
3585ffd83dbSDimitry Andric         // to the block extractor list, or fail if a name is not found.
3595ffd83dbSDimitry Andric         auto Res = llvm::find_if(*P.first, [&](const BasicBlock &BB) {
360*0fca6ea1SDimitry Andric           return BB.getName() == BBName;
3615ffd83dbSDimitry Andric         });
3625ffd83dbSDimitry Andric         if (Res == P.first->end()) {
3635ffd83dbSDimitry Andric           errs() << argv[0] << ": function " << P.first->getName()
3645ffd83dbSDimitry Andric                  << " doesn't contain a basic block named '" << BBName
3655ffd83dbSDimitry Andric                  << "'!\n";
3665ffd83dbSDimitry Andric           return 1;
3675ffd83dbSDimitry Andric         }
3685ffd83dbSDimitry Andric         BBs.push_back(&*Res);
3695ffd83dbSDimitry Andric       }
3705ffd83dbSDimitry Andric       GroupOfBBs.push_back(BBs);
3715ffd83dbSDimitry Andric     }
3725ffd83dbSDimitry Andric 
373bdd1243dSDimitry Andric     LoopAnalysisManager LAM;
374bdd1243dSDimitry Andric     FunctionAnalysisManager FAM;
375bdd1243dSDimitry Andric     CGSCCAnalysisManager CGAM;
376bdd1243dSDimitry Andric     ModuleAnalysisManager MAM;
377bdd1243dSDimitry Andric 
378bdd1243dSDimitry Andric     PassBuilder PB;
379bdd1243dSDimitry Andric 
380bdd1243dSDimitry Andric     PB.registerModuleAnalyses(MAM);
381bdd1243dSDimitry Andric     PB.registerCGSCCAnalyses(CGAM);
382bdd1243dSDimitry Andric     PB.registerFunctionAnalyses(FAM);
383bdd1243dSDimitry Andric     PB.registerLoopAnalyses(LAM);
384bdd1243dSDimitry Andric     PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
385bdd1243dSDimitry Andric 
386bdd1243dSDimitry Andric     ModulePassManager PM;
387bdd1243dSDimitry Andric     PM.addPass(BlockExtractorPass(std::move(GroupOfBBs), true));
388bdd1243dSDimitry Andric     PM.run(*M, MAM);
3890b57cec5SDimitry Andric   }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   // In addition to deleting all other functions, we also want to spiff it
3920b57cec5SDimitry Andric   // up a little bit.  Do this now.
3930b57cec5SDimitry Andric 
394bdd1243dSDimitry Andric   LoopAnalysisManager LAM;
395bdd1243dSDimitry Andric   FunctionAnalysisManager FAM;
396bdd1243dSDimitry Andric   CGSCCAnalysisManager CGAM;
397bdd1243dSDimitry Andric   ModuleAnalysisManager MAM;
398bdd1243dSDimitry Andric 
399bdd1243dSDimitry Andric   PassBuilder PB;
400bdd1243dSDimitry Andric 
401bdd1243dSDimitry Andric   PB.registerModuleAnalyses(MAM);
402bdd1243dSDimitry Andric   PB.registerCGSCCAnalyses(CGAM);
403bdd1243dSDimitry Andric   PB.registerFunctionAnalyses(FAM);
404bdd1243dSDimitry Andric   PB.registerLoopAnalyses(LAM);
405bdd1243dSDimitry Andric   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
406bdd1243dSDimitry Andric 
407bdd1243dSDimitry Andric   ModulePassManager PM;
4080b57cec5SDimitry Andric   if (!DeleteFn)
409bdd1243dSDimitry Andric     PM.addPass(GlobalDCEPass());
410bdd1243dSDimitry Andric   PM.addPass(StripDeadDebugInfoPass());
411bdd1243dSDimitry Andric   PM.addPass(StripDeadPrototypesPass());
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   std::error_code EC;
4148bcb0991SDimitry Andric   ToolOutputFile Out(OutputFilename, EC, sys::fs::OF_None);
4150b57cec5SDimitry Andric   if (EC) {
4160b57cec5SDimitry Andric     errs() << EC.message() << '\n';
4170b57cec5SDimitry Andric     return 1;
4180b57cec5SDimitry Andric   }
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   if (OutputAssembly)
421bdd1243dSDimitry Andric     PM.addPass(PrintModulePass(Out.os(), "", PreserveAssemblyUseListOrder));
4225ffd83dbSDimitry Andric   else if (Force || !CheckBitcodeOutputToConsole(Out.os()))
423bdd1243dSDimitry Andric     PM.addPass(BitcodeWriterPass(Out.os(), PreserveBitcodeUseListOrder));
4240b57cec5SDimitry Andric 
425bdd1243dSDimitry Andric   PM.run(*M, MAM);
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   // Declare success.
4280b57cec5SDimitry Andric   Out.keep();
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   return 0;
4310b57cec5SDimitry Andric }
432