112 lines · cpp
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-exception6//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 14namespace clang::dataflow {15 16Logger &Logger::null() {17 struct NullLogger final : Logger {};18 static auto *Instance = new NullLogger();19 return *Instance;20}21 22namespace {23struct 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 : OS(OS), ShowColors(llvm::WithColor::defaultAutoDetectFunction()(OS)) {}35 36 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 }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) {54 ++Blocks;55 Steps += E.second;56 }57 llvm::errs() << "=== Finished analysis: " << Blocks << " blocks in "58 << Steps << " total steps ===\n";59 }60 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 else68 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 }77 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 }88 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 }100 void blockConverged() override {101 OS << "B" << CurrentBlock->getBlockID() << " has converged!\n";102 }103 virtual void logText(llvm::StringRef S) override { OS << S << "\n"; }104};105} // namespace106 107std::unique_ptr<Logger> Logger::textual(llvm::raw_ostream &OS) {108 return std::make_unique<TextualLogger>(OS);109}110 111} // namespace clang::dataflow112