/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Analysis/FlowSensitive/Logger.cpp
Line | Count | Source (jump to first uncovered line) |
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/ControlFlowContext.h" |
11 | | #include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h" |
12 | | #include "llvm/Support/WithColor.h" |
13 | | |
14 | | namespace clang::dataflow { |
15 | | |
16 | 670 | Logger &Logger::null() { |
17 | 670 | struct NullLogger final : Logger {}; |
18 | 670 | static auto *Instance = new NullLogger(); |
19 | 670 | return *Instance; |
20 | 670 | } |
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 | | |
33 | | TextualLogger(llvm::raw_ostream &OS) |
34 | 0 | : OS(OS), ShowColors(llvm::WithColor::defaultAutoDetectFunction()(OS)) {} |
35 | | |
36 | | virtual void beginAnalysis(const ControlFlowContext &CFG, |
37 | 0 | TypeErasedDataflowAnalysis &Analysis) override { |
38 | 0 | { |
39 | 0 | llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED, /*Bold=*/true); |
40 | 0 | OS << "=== Beginning data flow analysis ===\n"; |
41 | 0 | } |
42 | 0 | auto &D = CFG.getDecl(); |
43 | 0 | D.print(OS); |
44 | 0 | OS << "\n"; |
45 | 0 | D.dump(OS); |
46 | 0 | CurrentCFG = &CFG.getCFG(); |
47 | 0 | CurrentCFG->print(OS, Analysis.getASTContext().getLangOpts(), ShowColors); |
48 | 0 | CurrentAnalysis = &Analysis; |
49 | 0 | } |
50 | 0 | virtual void endAnalysis() override { |
51 | 0 | llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED, /*Bold=*/true); |
52 | 0 | unsigned Blocks = 0, Steps = 0; |
53 | 0 | for (const auto &E : VisitCount) { |
54 | 0 | ++Blocks; |
55 | 0 | Steps += E.second; |
56 | 0 | } |
57 | 0 | llvm::errs() << "=== Finished analysis: " << Blocks << " blocks in " |
58 | 0 | << Steps << " total steps ===\n"; |
59 | 0 | } |
60 | 0 | virtual void enterBlock(const CFGBlock &Block, bool PostVisit) override { |
61 | 0 | unsigned Count = ++VisitCount[&Block]; |
62 | 0 | { |
63 | 0 | llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED, /*Bold=*/true); |
64 | 0 | OS << "=== Entering block B" << Block.getBlockID(); |
65 | 0 | if (PostVisit) |
66 | 0 | OS << " (post-visit)"; |
67 | 0 | else |
68 | 0 | OS << " (iteration " << Count << ")"; |
69 | 0 | OS << " ===\n"; |
70 | 0 | } |
71 | 0 | Block.print(OS, CurrentCFG, CurrentAnalysis->getASTContext().getLangOpts(), |
72 | 0 | ShowColors); |
73 | 0 | CurrentBlock = &Block; |
74 | 0 | CurrentElement = nullptr; |
75 | 0 | CurrentElementIndex = 0; |
76 | 0 | } |
77 | 0 | virtual void enterElement(const CFGElement &Element) override { |
78 | 0 | ++CurrentElementIndex; |
79 | 0 | CurrentElement = ∈ |
80 | 0 | { |
81 | 0 | llvm::WithColor Subheader(OS, llvm::raw_ostream::Colors::CYAN, |
82 | 0 | /*Bold=*/true); |
83 | 0 | OS << "Processing element B" << CurrentBlock->getBlockID() << "." |
84 | 0 | << CurrentElementIndex << ": "; |
85 | 0 | Element.dumpToStream(OS); |
86 | 0 | } |
87 | 0 | } |
88 | 0 | void recordState(TypeErasedDataflowAnalysisState &State) override { |
89 | 0 | { |
90 | 0 | llvm::WithColor Subheader(OS, llvm::raw_ostream::Colors::CYAN, |
91 | 0 | /*Bold=*/true); |
92 | 0 | OS << "Computed state for B" << CurrentBlock->getBlockID() << "." |
93 | 0 | << CurrentElementIndex << ":\n"; |
94 | 0 | } |
95 | | // FIXME: currently the environment dump is verbose and unenlightening. |
96 | | // FIXME: dump the user-defined lattice, too. |
97 | 0 | State.Env.dump(OS); |
98 | 0 | OS << "\n"; |
99 | 0 | } |
100 | 0 | void blockConverged() override { |
101 | 0 | OS << "B" << CurrentBlock->getBlockID() << " has converged!\n"; |
102 | 0 | } |
103 | 0 | virtual void logText(llvm::StringRef S) override { OS << S << "\n"; } |
104 | | }; |
105 | | } // namespace |
106 | | |
107 | 0 | std::unique_ptr<Logger> Logger::textual(llvm::raw_ostream &OS) { |
108 | 0 | return std::make_unique<TextualLogger>(OS); |
109 | 0 | } |
110 | | |
111 | | } // namespace clang::dataflow |