12#include "llvm/Support/WithColor.h"
17 struct NullLogger final :
Logger {};
18 static auto *Instance =
new NullLogger();
23struct TextualLogger final :
Logger {
24 llvm::raw_ostream &OS;
25 const CFG *CurrentCFG;
28 unsigned CurrentElementIndex;
30 llvm::DenseMap<const CFGBlock *, unsigned> VisitCount;
33 TextualLogger(llvm::raw_ostream &OS)
34 : OS(OS), ShowColors(
llvm::WithColor::defaultAutoDetectFunction()(OS)) {}
36 virtual void beginAnalysis(
const AdornedCFG &ACFG,
37 TypeErasedDataflowAnalysis &Analysis)
override {
39 llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED,
true);
40 OS <<
"=== Beginning data flow analysis ===\n";
42 auto &D = ACFG.getDecl();
46 CurrentCFG = &ACFG.getCFG();
47 CurrentCFG->
print(OS, Analysis.getASTContext().getLangOpts(), ShowColors);
48 CurrentAnalysis = &Analysis;
50 virtual void endAnalysis()
override {
51 llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED,
true);
52 unsigned Blocks = 0, Steps = 0;
53 for (
const auto &E : VisitCount) {
57 llvm::errs() <<
"=== Finished analysis: " << Blocks <<
" blocks in "
58 << Steps <<
" total steps ===\n";
60 virtual void enterBlock(
const CFGBlock &
Block,
bool PostVisit)
override {
61 unsigned Count = ++VisitCount[&
Block];
63 llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED,
true);
64 OS <<
"=== Entering block B" <<
Block.getBlockID();
66 OS <<
" (post-visit)";
68 OS <<
" (iteration " << Count <<
")";
71 Block.print(OS, CurrentCFG, CurrentAnalysis->getASTContext().getLangOpts(),
73 CurrentBlock = &
Block;
74 CurrentElement =
nullptr;
75 CurrentElementIndex = 0;
77 virtual void enterElement(
const CFGElement &Element)
override {
78 ++CurrentElementIndex;
79 CurrentElement = ∈
81 llvm::WithColor Subheader(OS, llvm::raw_ostream::Colors::CYAN,
83 OS <<
"Processing element B" << CurrentBlock->getBlockID() <<
"."
84 << CurrentElementIndex <<
": ";
85 Element.dumpToStream(OS);
88 void recordState(TypeErasedDataflowAnalysisState &State)
override {
90 llvm::WithColor Subheader(OS, llvm::raw_ostream::Colors::CYAN,
92 OS <<
"Computed state for B" << CurrentBlock->getBlockID() <<
"."
93 << CurrentElementIndex <<
":\n";
100 void blockConverged()
override {
101 OS <<
"B" << CurrentBlock->getBlockID() <<
" has converged!\n";
103 virtual void logText(llvm::StringRef S)
override { OS << S <<
"\n"; }
108 return std::make_unique<TextualLogger>(OS);
Represents a single basic block in a source-level CFG.
Represents a top-level expression in a basic block.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
void print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const
print - A simple pretty printer of a CFG that outputs to an ostream.
A logger is notified as the analysis progresses.
static std::unique_ptr< Logger > textual(llvm::raw_ostream &)
A logger that simply writes messages to the specified ostream in real time.
Logger(bool ShouldLogText=true)
ShouldLogText should be false for trivial loggers that ignore logText().
static Logger & null()
Returns a dummy logger that does nothing.
Type-erased base class for dataflow analyses built on a single lattice type.
Dataflow Directional Tag Classes.
Diagnostic wrappers for TextAPI types for error reporting.