xref: /llvm-project/clang/lib/Analysis/FlowSensitive/Logger.cpp (revision 59ff3adcc1310e22ab31163767e49b4edb20c6b4)
148f97e57SSam McCall //===-- Logger.cpp --------------------------------------------------------===//
248f97e57SSam McCall //
348f97e57SSam McCall // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
448f97e57SSam McCall // See https://llvm.org/LICENSE.txt for license information.
548f97e57SSam McCall // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
648f97e57SSam McCall //
748f97e57SSam McCall //===----------------------------------------------------------------------===//
848f97e57SSam McCall 
948f97e57SSam McCall #include "clang/Analysis/FlowSensitive/Logger.h"
10*59ff3adcSmartinboehme #include "clang/Analysis/FlowSensitive/AdornedCFG.h"
1148f97e57SSam McCall #include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
1248f97e57SSam McCall #include "llvm/Support/WithColor.h"
1348f97e57SSam McCall 
1448f97e57SSam McCall namespace clang::dataflow {
1548f97e57SSam McCall 
null()1648f97e57SSam McCall Logger &Logger::null() {
1748f97e57SSam McCall   struct NullLogger final : Logger {};
1848f97e57SSam McCall   static auto *Instance = new NullLogger();
1948f97e57SSam McCall   return *Instance;
2048f97e57SSam McCall }
2148f97e57SSam McCall 
2248f97e57SSam McCall namespace {
2348f97e57SSam McCall struct TextualLogger final : Logger {
2448f97e57SSam McCall   llvm::raw_ostream &OS;
2548f97e57SSam McCall   const CFG *CurrentCFG;
2648f97e57SSam McCall   const CFGBlock *CurrentBlock;
2748f97e57SSam McCall   const CFGElement *CurrentElement;
2848f97e57SSam McCall   unsigned CurrentElementIndex;
2948f97e57SSam McCall   bool ShowColors;
3048f97e57SSam McCall   llvm::DenseMap<const CFGBlock *, unsigned> VisitCount;
3148f97e57SSam McCall   TypeErasedDataflowAnalysis *CurrentAnalysis;
3248f97e57SSam McCall 
TextualLoggerclang::dataflow::__anon2dd689a10111::TextualLogger3348f97e57SSam McCall   TextualLogger(llvm::raw_ostream &OS)
3448f97e57SSam McCall       : OS(OS), ShowColors(llvm::WithColor::defaultAutoDetectFunction()(OS)) {}
3548f97e57SSam McCall 
beginAnalysisclang::dataflow::__anon2dd689a10111::TextualLogger36*59ff3adcSmartinboehme   virtual void beginAnalysis(const AdornedCFG &ACFG,
3748f97e57SSam McCall                              TypeErasedDataflowAnalysis &Analysis) override {
3848f97e57SSam McCall     {
3948f97e57SSam McCall       llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED, /*Bold=*/true);
4048f97e57SSam McCall       OS << "=== Beginning data flow analysis ===\n";
4148f97e57SSam McCall     }
42*59ff3adcSmartinboehme     auto &D = ACFG.getDecl();
43e6cd409fSMartin Braenne     D.print(OS);
4448f97e57SSam McCall     OS << "\n";
45e6cd409fSMartin Braenne     D.dump(OS);
46*59ff3adcSmartinboehme     CurrentCFG = &ACFG.getCFG();
4748f97e57SSam McCall     CurrentCFG->print(OS, Analysis.getASTContext().getLangOpts(), ShowColors);
4848f97e57SSam McCall     CurrentAnalysis = &Analysis;
4948f97e57SSam McCall   }
endAnalysisclang::dataflow::__anon2dd689a10111::TextualLogger5048f97e57SSam McCall   virtual void endAnalysis() override {
5148f97e57SSam McCall     llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED, /*Bold=*/true);
5248f97e57SSam McCall     unsigned Blocks = 0, Steps = 0;
5348f97e57SSam McCall     for (const auto &E : VisitCount) {
5448f97e57SSam McCall       ++Blocks;
5548f97e57SSam McCall       Steps += E.second;
5648f97e57SSam McCall     }
5748f97e57SSam McCall     llvm::errs() << "=== Finished analysis: " << Blocks << " blocks in "
5848f97e57SSam McCall                  << Steps << " total steps ===\n";
5948f97e57SSam McCall   }
enterBlockclang::dataflow::__anon2dd689a10111::TextualLogger60ed65ced2Smartinboehme   virtual void enterBlock(const CFGBlock &Block, bool PostVisit) override {
6148f97e57SSam McCall     unsigned Count = ++VisitCount[&Block];
6248f97e57SSam McCall     {
6348f97e57SSam McCall       llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED, /*Bold=*/true);
64ed65ced2Smartinboehme       OS << "=== Entering block B" << Block.getBlockID();
65ed65ced2Smartinboehme       if (PostVisit)
66ed65ced2Smartinboehme         OS << " (post-visit)";
67ed65ced2Smartinboehme       else
68ed65ced2Smartinboehme         OS << " (iteration " << Count << ")";
69ed65ced2Smartinboehme       OS << " ===\n";
7048f97e57SSam McCall     }
7148f97e57SSam McCall     Block.print(OS, CurrentCFG, CurrentAnalysis->getASTContext().getLangOpts(),
7248f97e57SSam McCall                 ShowColors);
7348f97e57SSam McCall     CurrentBlock = &Block;
7448f97e57SSam McCall     CurrentElement = nullptr;
7548f97e57SSam McCall     CurrentElementIndex = 0;
7648f97e57SSam McCall   }
enterElementclang::dataflow::__anon2dd689a10111::TextualLogger7748f97e57SSam McCall   virtual void enterElement(const CFGElement &Element) override {
7848f97e57SSam McCall     ++CurrentElementIndex;
7948f97e57SSam McCall     CurrentElement = &Element;
8048f97e57SSam McCall     {
8148f97e57SSam McCall       llvm::WithColor Subheader(OS, llvm::raw_ostream::Colors::CYAN,
8248f97e57SSam McCall                                 /*Bold=*/true);
8348f97e57SSam McCall       OS << "Processing element B" << CurrentBlock->getBlockID() << "."
8448f97e57SSam McCall          << CurrentElementIndex << ": ";
8548f97e57SSam McCall       Element.dumpToStream(OS);
8648f97e57SSam McCall     }
8748f97e57SSam McCall   }
recordStateclang::dataflow::__anon2dd689a10111::TextualLogger8848f97e57SSam McCall   void recordState(TypeErasedDataflowAnalysisState &State) override {
8948f97e57SSam McCall     {
9048f97e57SSam McCall       llvm::WithColor Subheader(OS, llvm::raw_ostream::Colors::CYAN,
9148f97e57SSam McCall                                 /*Bold=*/true);
9248f97e57SSam McCall       OS << "Computed state for B" << CurrentBlock->getBlockID() << "."
9348f97e57SSam McCall          << CurrentElementIndex << ":\n";
9448f97e57SSam McCall     }
9548f97e57SSam McCall     // FIXME: currently the environment dump is verbose and unenlightening.
9648f97e57SSam McCall     // FIXME: dump the user-defined lattice, too.
9748f97e57SSam McCall     State.Env.dump(OS);
9848f97e57SSam McCall     OS << "\n";
9948f97e57SSam McCall   }
blockConvergedclang::dataflow::__anon2dd689a10111::TextualLogger10048f97e57SSam McCall   void blockConverged() override {
10148f97e57SSam McCall     OS << "B" << CurrentBlock->getBlockID() << " has converged!\n";
10248f97e57SSam McCall   }
logTextclang::dataflow::__anon2dd689a10111::TextualLogger10348f97e57SSam McCall   virtual void logText(llvm::StringRef S) override { OS << S << "\n"; }
10448f97e57SSam McCall };
10548f97e57SSam McCall } // namespace
10648f97e57SSam McCall 
textual(llvm::raw_ostream & OS)10748f97e57SSam McCall std::unique_ptr<Logger> Logger::textual(llvm::raw_ostream &OS) {
10848f97e57SSam McCall   return std::make_unique<TextualLogger>(OS);
10948f97e57SSam McCall }
11048f97e57SSam McCall 
11148f97e57SSam McCall } // namespace clang::dataflow
112