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 = ∈
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