xref: /freebsd/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/Logger.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1  //===-- Logger.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 "clang/Analysis/FlowSensitive/Logger.h"
10  #include "clang/Analysis/FlowSensitive/AdornedCFG.h"
11  #include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
12  #include "llvm/Support/WithColor.h"
13  
14  namespace clang::dataflow {
15  
null()16  Logger &Logger::null() {
17    struct NullLogger final : Logger {};
18    static auto *Instance = new NullLogger();
19    return *Instance;
20  }
21  
22  namespace {
23  struct TextualLogger final : Logger {
24    llvm::raw_ostream &OS;
25    const CFG *CurrentCFG;
26    const CFGBlock *CurrentBlock;
27    const CFGElement *CurrentElement;
28    unsigned CurrentElementIndex;
29    bool ShowColors;
30    llvm::DenseMap<const CFGBlock *, unsigned> VisitCount;
31    TypeErasedDataflowAnalysis *CurrentAnalysis;
32  
TextualLoggerclang::dataflow::__anon8c8eae2e0111::TextualLogger33    TextualLogger(llvm::raw_ostream &OS)
34        : OS(OS), ShowColors(llvm::WithColor::defaultAutoDetectFunction()(OS)) {}
35  
beginAnalysisclang::dataflow::__anon8c8eae2e0111::TextualLogger36    virtual void beginAnalysis(const AdornedCFG &ACFG,
37                               TypeErasedDataflowAnalysis &Analysis) override {
38      {
39        llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED, /*Bold=*/true);
40        OS << "=== Beginning data flow analysis ===\n";
41      }
42      auto &D = ACFG.getDecl();
43      D.print(OS);
44      OS << "\n";
45      D.dump(OS);
46      CurrentCFG = &ACFG.getCFG();
47      CurrentCFG->print(OS, Analysis.getASTContext().getLangOpts(), ShowColors);
48      CurrentAnalysis = &Analysis;
49    }
endAnalysisclang::dataflow::__anon8c8eae2e0111::TextualLogger50    virtual void endAnalysis() override {
51      llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED, /*Bold=*/true);
52      unsigned Blocks = 0, Steps = 0;
53      for (const auto &E : VisitCount) {
54        ++Blocks;
55        Steps += E.second;
56      }
57      llvm::errs() << "=== Finished analysis: " << Blocks << " blocks in "
58                   << Steps << " total steps ===\n";
59    }
enterBlockclang::dataflow::__anon8c8eae2e0111::TextualLogger60    virtual void enterBlock(const CFGBlock &Block, bool PostVisit) override {
61      unsigned Count = ++VisitCount[&Block];
62      {
63        llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED, /*Bold=*/true);
64        OS << "=== Entering block B" << Block.getBlockID();
65        if (PostVisit)
66          OS << " (post-visit)";
67        else
68          OS << " (iteration " << Count << ")";
69        OS << " ===\n";
70      }
71      Block.print(OS, CurrentCFG, CurrentAnalysis->getASTContext().getLangOpts(),
72                  ShowColors);
73      CurrentBlock = &Block;
74      CurrentElement = nullptr;
75      CurrentElementIndex = 0;
76    }
enterElementclang::dataflow::__anon8c8eae2e0111::TextualLogger77    virtual void enterElement(const CFGElement &Element) override {
78      ++CurrentElementIndex;
79      CurrentElement = &Element;
80      {
81        llvm::WithColor Subheader(OS, llvm::raw_ostream::Colors::CYAN,
82                                  /*Bold=*/true);
83        OS << "Processing element B" << CurrentBlock->getBlockID() << "."
84           << CurrentElementIndex << ": ";
85        Element.dumpToStream(OS);
86      }
87    }
recordStateclang::dataflow::__anon8c8eae2e0111::TextualLogger88    void recordState(TypeErasedDataflowAnalysisState &State) override {
89      {
90        llvm::WithColor Subheader(OS, llvm::raw_ostream::Colors::CYAN,
91                                  /*Bold=*/true);
92        OS << "Computed state for B" << CurrentBlock->getBlockID() << "."
93           << CurrentElementIndex << ":\n";
94      }
95      // FIXME: currently the environment dump is verbose and unenlightening.
96      // FIXME: dump the user-defined lattice, too.
97      State.Env.dump(OS);
98      OS << "\n";
99    }
blockConvergedclang::dataflow::__anon8c8eae2e0111::TextualLogger100    void blockConverged() override {
101      OS << "B" << CurrentBlock->getBlockID() << " has converged!\n";
102    }
logTextclang::dataflow::__anon8c8eae2e0111::TextualLogger103    virtual void logText(llvm::StringRef S) override { OS << S << "\n"; }
104  };
105  } // namespace
106  
textual(llvm::raw_ostream & OS)107  std::unique_ptr<Logger> Logger::textual(llvm::raw_ostream &OS) {
108    return std::make_unique<TextualLogger>(OS);
109  }
110  
111  } // namespace clang::dataflow
112