//===- Standard pass instrumentations handling ----------------*- C++ -*--===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// \file /// /// This file defines IR-printing pass instrumentation callbacks as well as /// StandardInstrumentations class that manages standard pass instrumentations. /// //===----------------------------------------------------------------------===// #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassInstrumentation.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { namespace PrintIR { //===----------------------------------------------------------------------===// // IR-printing instrumentation //===----------------------------------------------------------------------===// /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into /// llvm::Any and does actual print job. void unwrapAndPrint(StringRef Banner, Any IR) { SmallString<40> Extra{"\n"}; const Module *M = nullptr; if (any_isa(IR)) { M = any_cast(IR); } else if (any_isa(IR)) { const Function *F = any_cast(IR); if (!llvm::isFunctionInPrintList(F->getName())) return; if (!llvm::forcePrintModuleIR()) { dbgs() << Banner << Extra << static_cast(*F); return; } M = F->getParent(); Extra = formatv(" (function: {0})\n", F->getName()); } else if (any_isa(IR)) { const LazyCallGraph::SCC *C = any_cast(IR); assert(C); if (!llvm::forcePrintModuleIR()) { Extra = formatv(" (scc: {0})\n", C->getName()); bool BannerPrinted = false; for (const LazyCallGraph::Node &N : *C) { const Function &F = N.getFunction(); if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) { if (!BannerPrinted) { dbgs() << Banner << Extra; BannerPrinted = true; } F.print(dbgs()); } } return; } for (const LazyCallGraph::Node &N : *C) { const Function &F = N.getFunction(); if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) { M = F.getParent(); break; } } if (!M) return; Extra = formatv(" (for scc: {0})\n", C->getName()); } else if (any_isa(IR)) { const Loop *L = any_cast(IR); const Function *F = L->getHeader()->getParent(); if (!isFunctionInPrintList(F->getName())) return; if (!llvm::forcePrintModuleIR()) { llvm::printLoop(const_cast(*L), dbgs(), Banner); return; } M = F->getParent(); { std::string LoopName; raw_string_ostream ss(LoopName); L->getHeader()->printAsOperand(ss, false); Extra = formatv(" (loop: {0})\n", ss.str()); } } if (M) { dbgs() << Banner << Extra; M->print(dbgs(), nullptr, false); } else { llvm_unreachable("Unknown wrapped IR type"); } } bool printBeforePass(StringRef PassID, Any IR) { if (!llvm::shouldPrintBeforePass(PassID)) return true; if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) return true; SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID); unwrapAndPrint(Banner, IR); return true; } void printAfterPass(StringRef PassID, Any IR) { if (!llvm::shouldPrintAfterPass(PassID)) return; if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) return; SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID); unwrapAndPrint(Banner, IR); return; } } // namespace PrintIR } // namespace void StandardInstrumentations::registerCallbacks( PassInstrumentationCallbacks &PIC) { if (llvm::shouldPrintBeforePass()) PIC.registerBeforePassCallback(PrintIR::printBeforePass); if (llvm::shouldPrintAfterPass()) PIC.registerAfterPassCallback(PrintIR::printAfterPass); TimePasses.registerCallbacks(PIC); }