1 //===-- Logger.cpp --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
14 namespace clang::dataflow
{
16 Logger
&Logger::null() {
17 struct NullLogger final
: Logger
{};
18 static auto *Instance
= new NullLogger();
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
;
30 llvm::DenseMap
<const CFGBlock
*, unsigned> VisitCount
;
31 TypeErasedDataflowAnalysis
*CurrentAnalysis
;
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
, /*Bold=*/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
, /*Bold=*/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
, /*Bold=*/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
= &Element
;
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";
95 // FIXME: currently the environment dump is verbose and unenlightening.
96 // FIXME: dump the user-defined lattice, too.
100 void blockConverged() override
{
101 OS
<< "B" << CurrentBlock
->getBlockID() << " has converged!\n";
103 virtual void logText(llvm::StringRef S
) override
{ OS
<< S
<< "\n"; }
107 std::unique_ptr
<Logger
> Logger::textual(llvm::raw_ostream
&OS
) {
108 return std::make_unique
<TextualLogger
>(OS
);
111 } // namespace clang::dataflow