llvm/llvm/lib/Passes/StandardInstrumentations.cpp

//===- Standard pass instrumentations handling ----------------*- C++ -*--===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \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/ADT/Any.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/MIRPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineVerifier.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/PrintPasses.h"
#include "llvm/IR/StructuralHash.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/xxhash.h"
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

usingnamespacellvm;

static cl::opt<bool> VerifyAnalysisInvalidation("verify-analysis-invalidation",
                                                cl::Hidden,
#ifdef EXPENSIVE_CHECKS
                                                cl::init(true)
#else
                                                cl::init(false)
#endif
);

// An option that supports the -print-changed option.  See
// the description for -print-changed for an explanation of the use
// of this option.  Note that this option has no effect without -print-changed.
static cl::opt<bool>
    PrintChangedBefore("print-before-changed",
                       cl::desc("Print before passes that change them"),
                       cl::init(false), cl::Hidden);

// An option for specifying the dot used by
// print-changed=[dot-cfg | dot-cfg-quiet]
static cl::opt<std::string>
    DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"),
              cl::desc("system dot used by change reporters"));

// An option that determines the colour used for elements that are only
// in the before part.  Must be a colour named in appendix J of
// https://graphviz.org/pdf/dotguide.pdf
static cl::opt<std::string>
    BeforeColour("dot-cfg-before-color",
                 cl::desc("Color for dot-cfg before elements"), cl::Hidden,
                 cl::init("red"));
// An option that determines the colour used for elements that are only
// in the after part.  Must be a colour named in appendix J of
// https://graphviz.org/pdf/dotguide.pdf
static cl::opt<std::string>
    AfterColour("dot-cfg-after-color",
                cl::desc("Color for dot-cfg after elements"), cl::Hidden,
                cl::init("forestgreen"));
// An option that determines the colour used for elements that are in both
// the before and after parts.  Must be a colour named in appendix J of
// https://graphviz.org/pdf/dotguide.pdf
static cl::opt<std::string>
    CommonColour("dot-cfg-common-color",
                 cl::desc("Color for dot-cfg common elements"), cl::Hidden,
                 cl::init("black"));

// An option that determines where the generated website file (named
// passes.html) and the associated pdf files (named diff_*.pdf) are saved.
static cl::opt<std::string> DotCfgDir(
    "dot-cfg-dir",
    cl::desc("Generate dot files into specified directory for changed IRs"),
    cl::Hidden, cl::init("./"));

// Options to print the IR that was being processed when a pass crashes.
static cl::opt<std::string> PrintOnCrashPath(
    "print-on-crash-path",
    cl::desc("Print the last form of the IR before crash to a file"),
    cl::Hidden);

static cl::opt<bool> PrintOnCrash(
    "print-on-crash",
    cl::desc("Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
    cl::Hidden);

static cl::opt<std::string> OptBisectPrintIRPath(
    "opt-bisect-print-ir-path",
    cl::desc("Print IR to path when opt-bisect-limit is reached"), cl::Hidden);

static cl::opt<bool> PrintPassNumbers(
    "print-pass-numbers", cl::init(false), cl::Hidden,
    cl::desc("Print pass names and their ordinals"));

static cl::opt<unsigned> PrintBeforePassNumber(
    "print-before-pass-number", cl::init(0), cl::Hidden,
    cl::desc("Print IR before the pass with this number as "
             "reported by print-pass-numbers"));

static cl::opt<unsigned>
    PrintAfterPassNumber("print-after-pass-number", cl::init(0), cl::Hidden,
                         cl::desc("Print IR after the pass with this number as "
                                  "reported by print-pass-numbers"));

static cl::opt<std::string> IRDumpDirectory(
    "ir-dump-directory",
    cl::desc("If specified, IR printed using the "
             "-print-[before|after]{-all} options will be dumped into "
             "files in this directory rather than written to stderr"),
    cl::Hidden, cl::value_desc("filename"));

template <typename IRUnitT> static const IRUnitT *unwrapIR(Any IR) {}

namespace {

// An option for specifying an executable that will be called with the IR
// everytime it changes in the opt pipeline.  It will also be called on
// the initial IR as it enters the pipeline.  The executable will be passed
// the name of a temporary file containing the IR and the PassID.  This may
// be used, for example, to call llc on the IR and run a test to determine
// which pass makes a change that changes the functioning of the IR.
// The usual modifier options work as expected.
static cl::opt<std::string>
    TestChanged("exec-on-ir-change", cl::Hidden, cl::init(""),
                cl::desc("exe called with module IR after each pass that "
                         "changes it"));

/// Extract Module out of \p IR unit. May return nullptr if \p IR does not match
/// certain global filters. Will never return nullptr if \p Force is true.
const Module *unwrapModule(Any IR, bool Force = false) {}

void printIR(raw_ostream &OS, const Function *F) {}

void printIR(raw_ostream &OS, const Module *M) {}

void printIR(raw_ostream &OS, const LazyCallGraph::SCC *C) {}

void printIR(raw_ostream &OS, const Loop *L) {}

void printIR(raw_ostream &OS, const MachineFunction *MF) {}

std::string getIRName(Any IR) {}

bool moduleContainsFilterPrintFunc(const Module &M) {}

bool sccContainsFilterPrintFunc(const LazyCallGraph::SCC &C) {}

bool shouldPrintIR(Any IR) {}

/// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
/// Any and does actual print job.
void unwrapAndPrint(raw_ostream &OS, Any IR) {}

// Return true when this is a pass for which changes should be ignored
bool isIgnored(StringRef PassID) {}

std::string makeHTMLReady(StringRef SR) {}

// Return the module when that is the appropriate level of comparison for \p IR.
const Module *getModuleForComparison(Any IR) {}

bool isInterestingFunction(const Function &F) {}

// Return true when this is a pass on IR for which printing
// of changes is desired.
bool isInteresting(Any IR, StringRef PassID, StringRef PassName) {}

} // namespace

template <typename T> ChangeReporter<T>::~ChangeReporter() {}

template <typename T>
void ChangeReporter<T>::saveIRBeforePass(Any IR, StringRef PassID,
                                         StringRef PassName) {}

template <typename T>
void ChangeReporter<T>::handleIRAfterPass(Any IR, StringRef PassID,
                                          StringRef PassName) {}

template <typename T>
void ChangeReporter<T>::handleInvalidatedPass(StringRef PassID) {}

template <typename T>
void ChangeReporter<T>::registerRequiredCallbacks(
    PassInstrumentationCallbacks &PIC) {}

template <typename T>
TextChangeReporter<T>::TextChangeReporter(bool Verbose)
    :{}

template <typename T> void TextChangeReporter<T>::handleInitialIR(Any IR) {}

template <typename T>
void TextChangeReporter<T>::omitAfter(StringRef PassID, std::string &Name) {}

template <typename T>
void TextChangeReporter<T>::handleInvalidated(StringRef PassID) {}

template <typename T>
void TextChangeReporter<T>::handleFiltered(StringRef PassID,
                                           std::string &Name) {}

template <typename T>
void TextChangeReporter<T>::handleIgnored(StringRef PassID, std::string &Name) {}

IRChangedPrinter::~IRChangedPrinter() = default;

void IRChangedPrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) {}

void IRChangedPrinter::generateIRRepresentation(Any IR, StringRef PassID,
                                                std::string &Output) {}

void IRChangedPrinter::handleAfter(StringRef PassID, std::string &Name,
                                   const std::string &Before,
                                   const std::string &After, Any) {}

IRChangedTester::~IRChangedTester() {}

void IRChangedTester::registerCallbacks(PassInstrumentationCallbacks &PIC) {}

void IRChangedTester::handleIR(const std::string &S, StringRef PassID) {}

void IRChangedTester::handleInitialIR(Any IR) {}

void IRChangedTester::omitAfter(StringRef PassID, std::string &Name) {}
void IRChangedTester::handleInvalidated(StringRef PassID) {}
void IRChangedTester::handleFiltered(StringRef PassID, std::string &Name) {}
void IRChangedTester::handleIgnored(StringRef PassID, std::string &Name) {}
void IRChangedTester::handleAfter(StringRef PassID, std::string &Name,
                                  const std::string &Before,
                                  const std::string &After, Any) {}

template <typename T>
void OrderedChangedData<T>::report(
    const OrderedChangedData &Before, const OrderedChangedData &After,
    function_ref<void(const T *, const T *)> HandlePair) {}

template <typename T>
void IRComparer<T>::compare(
    bool CompareModule,
    std::function<void(bool InModule, unsigned Minor,
                       const FuncDataT<T> &Before, const FuncDataT<T> &After)>
        CompareFunc) {}

template <typename T> void IRComparer<T>::analyzeIR(Any IR, IRDataT<T> &Data) {}

static bool shouldGenerateData(const Function &F) {}

static bool shouldGenerateData(const MachineFunction &MF) {}

template <typename T>
template <typename FunctionT>
bool IRComparer<T>::generateFunctionData(IRDataT<T> &Data, const FunctionT &F) {}

PrintIRInstrumentation::~PrintIRInstrumentation() {}

static SmallString<32> getIRFileDisplayName(Any IR) {}

std::string PrintIRInstrumentation::fetchDumpFilename(StringRef PassName,
                                                      Any IR) {}

enum class IRDumpFileSuffixType {};

static StringRef getFileSuffix(IRDumpFileSuffixType Type) {}

void PrintIRInstrumentation::pushPassRunDescriptor(
    StringRef PassID, Any IR, std::string &DumpIRFilename) {}

PrintIRInstrumentation::PassRunDescriptor
PrintIRInstrumentation::popPassRunDescriptor(StringRef PassID) {}

// Callers are responsible for closing the returned file descriptor
static int prepareDumpIRFileDescriptor(const StringRef DumpIRFilename) {}

void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {}

void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {}

void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {}

bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {}

bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) {}

bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {}

bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {}

bool PrintIRInstrumentation::shouldPrintPassNumbers() {}

bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {}

bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {}

void PrintIRInstrumentation::registerCallbacks(
    PassInstrumentationCallbacks &PIC) {}

void OptNoneInstrumentation::registerCallbacks(
    PassInstrumentationCallbacks &PIC) {}

bool OptNoneInstrumentation::shouldRun(StringRef PassID, Any IR) {}

bool OptPassGateInstrumentation::shouldRun(StringRef PassName, Any IR) {}

void OptPassGateInstrumentation::registerCallbacks(
    PassInstrumentationCallbacks &PIC) {}

raw_ostream &PrintPassInstrumentation::print() {}

void PrintPassInstrumentation::registerCallbacks(
    PassInstrumentationCallbacks &PIC) {}

PreservedCFGCheckerInstrumentation::CFG::CFG(const Function *F,
                                             bool TrackBBLifetime) {}

static void printBBName(raw_ostream &out, const BasicBlock *BB) {}

void PreservedCFGCheckerInstrumentation::CFG::printDiff(raw_ostream &out,
                                                        const CFG &Before,
                                                        const CFG &After) {}

// PreservedCFGCheckerInstrumentation uses PreservedCFGCheckerAnalysis to check
// passes, that reported they kept CFG analyses up-to-date, did not actually
// change CFG. This check is done as follows. Before every functional pass in
// BeforeNonSkippedPassCallback a CFG snapshot (an instance of
// PreservedCFGCheckerInstrumentation::CFG) is requested from
// FunctionAnalysisManager as a result of PreservedCFGCheckerAnalysis. When the
// functional pass finishes and reports that CFGAnalyses or AllAnalyses are
// up-to-date then the cached result of PreservedCFGCheckerAnalysis (if
// available) is checked to be equal to a freshly created CFG snapshot.
struct PreservedCFGCheckerAnalysis
    : public AnalysisInfoMixin<PreservedCFGCheckerAnalysis> {};

AnalysisKey PreservedCFGCheckerAnalysis::Key;

struct PreservedFunctionHashAnalysis
    : public AnalysisInfoMixin<PreservedFunctionHashAnalysis> {};

AnalysisKey PreservedFunctionHashAnalysis::Key;

struct PreservedModuleHashAnalysis
    : public AnalysisInfoMixin<PreservedModuleHashAnalysis> {};

AnalysisKey PreservedModuleHashAnalysis::Key;

bool PreservedCFGCheckerInstrumentation::CFG::invalidate(
    Function &F, const PreservedAnalyses &PA,
    FunctionAnalysisManager::Invalidator &) {}

static SmallVector<Function *, 1> GetFunctions(Any IR) {}

void PreservedCFGCheckerInstrumentation::registerCallbacks(
    PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM) {}

void VerifyInstrumentation::registerCallbacks(PassInstrumentationCallbacks &PIC,
                                              ModuleAnalysisManager *MAM) {}

InLineChangePrinter::~InLineChangePrinter() = default;

void InLineChangePrinter::generateIRRepresentation(Any IR,
                                                   StringRef PassID,
                                                   IRDataT<EmptyData> &D) {}

void InLineChangePrinter::handleAfter(StringRef PassID, std::string &Name,
                                      const IRDataT<EmptyData> &Before,
                                      const IRDataT<EmptyData> &After,
                                      Any IR) {}

void InLineChangePrinter::handleFunctionCompare(
    StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider,
    bool InModule, unsigned Minor, const FuncDataT<EmptyData> &Before,
    const FuncDataT<EmptyData> &After) {}

void InLineChangePrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) {}

TimeProfilingPassesHandler::TimeProfilingPassesHandler() {}

void TimeProfilingPassesHandler::registerCallbacks(
    PassInstrumentationCallbacks &PIC) {}

void TimeProfilingPassesHandler::runBeforePass(StringRef PassID, Any IR) {}

void TimeProfilingPassesHandler::runAfterPass() {}

namespace {

class DisplayNode;
class DotCfgDiffDisplayGraph;

// Base class for a node or edge in the dot-cfg-changes graph.
class DisplayElement {};

// An edge representing a transition between basic blocks in the
// dot-cfg-changes graph.
class DisplayEdge : public DisplayElement {};

// A node in the dot-cfg-changes graph which represents a basic block.
class DisplayNode : public DisplayElement {};

// Class representing a difference display (corresponds to a pdf file).
class DotCfgDiffDisplayGraph {};

void DisplayNode::createEdge(StringRef Value, DisplayNode &Node,
                             StringRef Colour) {}

void DisplayNode::createEdgeMap() {}

class DotCfgDiffNode;
class DotCfgDiff;

// A class representing a basic block in the Dot difference graph.
class DotCfgDiffNode {};

// Class representing the difference graph between two functions.
class DotCfgDiff {};

std::string DotCfgDiffNode::getBodyContent() const {}

std::string DotCfgDiff::colourize(std::string S, StringRef Colour) const {}

DotCfgDiff::DotCfgDiff(StringRef Title, const FuncDataT<DCData> &Before,
                       const FuncDataT<DCData> &After)
    :{}

DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(StringRef Title,
                                                      StringRef EntryNodeName) {}

void DotCfgDiffNode::createDisplayEdges(
    DotCfgDiffDisplayGraph &DisplayGraph, unsigned DisplayNodeIndex,
    std::map<const unsigned, unsigned> &NodeMap) const {}

void DotCfgDiffNode::finalize(DotCfgDiff &G) {}

} // namespace

namespace llvm {

template <> struct GraphTraits<DotCfgDiffDisplayGraph *> {};

template <>
struct DOTGraphTraits<DotCfgDiffDisplayGraph *> : public DefaultDOTGraphTraits {};

} // namespace llvm

namespace {

void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {}

} // namespace

namespace llvm {

DCData::DCData(const BasicBlock &B) {}

DCData::DCData(const MachineBasicBlock &B) {}

DotCfgChangeReporter::DotCfgChangeReporter(bool Verbose)
    :{}

void DotCfgChangeReporter::handleFunctionCompare(
    StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider,
    bool InModule, unsigned Minor, const FuncDataT<DCData> &Before,
    const FuncDataT<DCData> &After) {}

std::string DotCfgChangeReporter::genHTML(StringRef Text, StringRef DotFile,
                                          StringRef PDFFileName) {}

void DotCfgChangeReporter::handleInitialIR(Any IR) {}

void DotCfgChangeReporter::generateIRRepresentation(Any IR, StringRef PassID,
                                                    IRDataT<DCData> &Data) {}

void DotCfgChangeReporter::omitAfter(StringRef PassID, std::string &Name) {}

void DotCfgChangeReporter::handleAfter(StringRef PassID, std::string &Name,
                                       const IRDataT<DCData> &Before,
                                       const IRDataT<DCData> &After, Any IR) {}

void DotCfgChangeReporter::handleInvalidated(StringRef PassID) {}

void DotCfgChangeReporter::handleFiltered(StringRef PassID, std::string &Name) {}

void DotCfgChangeReporter::handleIgnored(StringRef PassID, std::string &Name) {}

bool DotCfgChangeReporter::initializeHTML() {}

DotCfgChangeReporter::~DotCfgChangeReporter() {}

void DotCfgChangeReporter::registerCallbacks(
    PassInstrumentationCallbacks &PIC) {}

StandardInstrumentations::StandardInstrumentations(
    LLVMContext &Context, bool DebugLogging, bool VerifyEach,
    PrintPassOptions PrintPassOpts)
    :{}

PrintCrashIRInstrumentation *PrintCrashIRInstrumentation::CrashReporter =;

void PrintCrashIRInstrumentation::reportCrashIR() {}

void PrintCrashIRInstrumentation::SignalHandler(void *) {}

PrintCrashIRInstrumentation::~PrintCrashIRInstrumentation() {}

void PrintCrashIRInstrumentation::registerCallbacks(
    PassInstrumentationCallbacks &PIC) {}

void StandardInstrumentations::registerCallbacks(
    PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM) {}

template class ChangeReporter<std::string>;
template class TextChangeReporter<std::string>;

template class BlockDataT<EmptyData>;
template class FuncDataT<EmptyData>;
template class IRDataT<EmptyData>;
template class ChangeReporter<IRDataT<EmptyData>>;
template class TextChangeReporter<IRDataT<EmptyData>>;
template class IRComparer<EmptyData>;

} // namespace llvm