1 //===- PrintPasses.cpp ----------------------------------------------------===// 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 #include "llvm/IR/PrintPasses.h" 10 #include "llvm/Support/CommandLine.h" 11 #include <unordered_set> 12 13 using namespace llvm; 14 15 // Print IR out before/after specified passes. 16 static cl::list<std::string> 17 PrintBefore("print-before", 18 llvm::cl::desc("Print IR before specified passes"), 19 cl::CommaSeparated, cl::Hidden); 20 21 static cl::list<std::string> 22 PrintAfter("print-after", llvm::cl::desc("Print IR after specified passes"), 23 cl::CommaSeparated, cl::Hidden); 24 25 static cl::opt<bool> PrintBeforeAll("print-before-all", 26 llvm::cl::desc("Print IR before each pass"), 27 cl::init(false), cl::Hidden); 28 static cl::opt<bool> PrintAfterAll("print-after-all", 29 llvm::cl::desc("Print IR after each pass"), 30 cl::init(false), cl::Hidden); 31 32 // Print out the IR after passes, similar to -print-after-all except that it 33 // only prints the IR after passes that change the IR. Those passes that do not 34 // make changes to the IR are reported as not making any changes. In addition, 35 // the initial IR is also reported. Other hidden options affect the output from 36 // this option. -filter-passes will limit the output to the named passes that 37 // actually change the IR and other passes are reported as filtered out. The 38 // specified passes will either be reported as making no changes (with no IR 39 // reported) or the changed IR will be reported. Also, the -filter-print-funcs 40 // and -print-module-scope options will do similar filtering based on function 41 // name, reporting changed IRs as functions(or modules if -print-module-scope is 42 // specified) for a particular function or indicating that the IR has been 43 // filtered out. The extra options can be combined, allowing only changed IRs 44 // for certain passes on certain functions to be reported in different formats, 45 // with the rest being reported as filtered out. The -print-before-changed 46 // option will print the IR as it was before each pass that changed it. The 47 // optional value of quiet will only report when the IR changes, suppressing all 48 // other messages, including the initial IR. The values "diff" and "diff-quiet" 49 // will present the changes in a form similar to a patch, in either verbose or 50 // quiet mode, respectively. The lines that are removed and added are prefixed 51 // with '-' and '+', respectively. The -filter-print-funcs and -filter-passes 52 // can be used to filter the output. This reporter relies on the linux diff 53 // utility to do comparisons and insert the prefixes. For systems that do not 54 // have the necessary facilities, the error message will be shown in place of 55 // the expected output. 56 cl::opt<ChangePrinter> llvm::PrintChanged( 57 "print-changed", cl::desc("Print changed IRs"), cl::Hidden, 58 cl::ValueOptional, cl::init(ChangePrinter::None), 59 cl::values( 60 clEnumValN(ChangePrinter::Quiet, "quiet", "Run in quiet mode"), 61 clEnumValN(ChangePrinter::DiffVerbose, "diff", 62 "Display patch-like changes"), 63 clEnumValN(ChangePrinter::DiffQuiet, "diff-quiet", 64 "Display patch-like changes in quiet mode"), 65 clEnumValN(ChangePrinter::ColourDiffVerbose, "cdiff", 66 "Display patch-like changes with color"), 67 clEnumValN(ChangePrinter::ColourDiffQuiet, "cdiff-quiet", 68 "Display patch-like changes in quiet mode with color"), 69 clEnumValN(ChangePrinter::DotCfgVerbose, "dot-cfg", 70 "Create a website with graphical changes"), 71 clEnumValN(ChangePrinter::DotCfgQuiet, "dot-cfg-quiet", 72 "Create a website with graphical changes in quiet mode"), 73 // Sentinel value for unspecified option. 74 clEnumValN(ChangePrinter::Verbose, "", ""))); 75 76 static cl::opt<bool> 77 PrintModuleScope("print-module-scope", 78 cl::desc("When printing IR for print-[before|after]{-all} " 79 "always print a module IR"), 80 cl::init(false), cl::Hidden); 81 82 static cl::list<std::string> 83 PrintFuncsList("filter-print-funcs", cl::value_desc("function names"), 84 cl::desc("Only print IR for functions whose name " 85 "match this for all print-[before|after][-all] " 86 "options"), 87 cl::CommaSeparated, cl::Hidden); 88 89 /// This is a helper to determine whether to print IR before or 90 /// after a pass. 91 92 bool llvm::shouldPrintBeforeSomePass() { 93 return PrintBeforeAll || !PrintBefore.empty(); 94 } 95 96 bool llvm::shouldPrintAfterSomePass() { 97 return PrintAfterAll || !PrintAfter.empty(); 98 } 99 100 static bool shouldPrintBeforeOrAfterPass(StringRef PassID, 101 ArrayRef<std::string> PassesToPrint) { 102 return llvm::is_contained(PassesToPrint, PassID); 103 } 104 105 bool llvm::shouldPrintBeforeAll() { return PrintBeforeAll; } 106 107 bool llvm::shouldPrintAfterAll() { return PrintAfterAll; } 108 109 bool llvm::shouldPrintBeforePass(StringRef PassID) { 110 return PrintBeforeAll || shouldPrintBeforeOrAfterPass(PassID, PrintBefore); 111 } 112 113 bool llvm::shouldPrintAfterPass(StringRef PassID) { 114 return PrintAfterAll || shouldPrintBeforeOrAfterPass(PassID, PrintAfter); 115 } 116 117 std::vector<std::string> llvm::printBeforePasses() { 118 return std::vector<std::string>(PrintBefore); 119 } 120 121 std::vector<std::string> llvm::printAfterPasses() { 122 return std::vector<std::string>(PrintAfter); 123 } 124 125 bool llvm::forcePrintModuleIR() { return PrintModuleScope; } 126 127 bool llvm::isFunctionInPrintList(StringRef FunctionName) { 128 static std::unordered_set<std::string> PrintFuncNames(PrintFuncsList.begin(), 129 PrintFuncsList.end()); 130 return PrintFuncNames.empty() || 131 PrintFuncNames.count(std::string(FunctionName)); 132 } 133