1*06c3fb27SDimitry Andric //===-- Logger.h ------------------------------------------------*- C++ -*-===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric 9*06c3fb27SDimitry Andric #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H 10*06c3fb27SDimitry Andric #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H 11*06c3fb27SDimitry Andric 12*06c3fb27SDimitry Andric #include "clang/Analysis/CFG.h" 13*06c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h" 14*06c3fb27SDimitry Andric #include <memory> 15*06c3fb27SDimitry Andric 16*06c3fb27SDimitry Andric namespace clang::dataflow { 17*06c3fb27SDimitry Andric // Forward declarations so we can use Logger anywhere in the framework. 18*06c3fb27SDimitry Andric class ControlFlowContext; 19*06c3fb27SDimitry Andric class TypeErasedDataflowAnalysis; 20*06c3fb27SDimitry Andric struct TypeErasedDataflowAnalysisState; 21*06c3fb27SDimitry Andric 22*06c3fb27SDimitry Andric /// A logger is notified as the analysis progresses. 23*06c3fb27SDimitry Andric /// It can produce a report of the analysis's findings and how it came to them. 24*06c3fb27SDimitry Andric /// 25*06c3fb27SDimitry Andric /// The framework reports key structural events (e.g. traversal of blocks). 26*06c3fb27SDimitry Andric /// The specific analysis can add extra details to be presented in context. 27*06c3fb27SDimitry Andric class Logger { 28*06c3fb27SDimitry Andric public: 29*06c3fb27SDimitry Andric /// Returns a dummy logger that does nothing. 30*06c3fb27SDimitry Andric static Logger &null(); 31*06c3fb27SDimitry Andric /// A logger that simply writes messages to the specified ostream in real 32*06c3fb27SDimitry Andric /// time. 33*06c3fb27SDimitry Andric static std::unique_ptr<Logger> textual(llvm::raw_ostream &); 34*06c3fb27SDimitry Andric /// A logger that builds an HTML UI to inspect the analysis results. 35*06c3fb27SDimitry Andric /// Each function's analysis is written to a stream obtained from the factory. 36*06c3fb27SDimitry Andric static std::unique_ptr<Logger> 37*06c3fb27SDimitry Andric html(std::function<std::unique_ptr<llvm::raw_ostream>()>); 38*06c3fb27SDimitry Andric 39*06c3fb27SDimitry Andric virtual ~Logger() = default; 40*06c3fb27SDimitry Andric 41*06c3fb27SDimitry Andric /// Called by the framework as we start analyzing a new function or statement. 42*06c3fb27SDimitry Andric /// Forms a pair with endAnalysis(). 43*06c3fb27SDimitry Andric virtual void beginAnalysis(const ControlFlowContext &, 44*06c3fb27SDimitry Andric TypeErasedDataflowAnalysis &) {} 45*06c3fb27SDimitry Andric virtual void endAnalysis() {} 46*06c3fb27SDimitry Andric 47*06c3fb27SDimitry Andric // At any time during the analysis, we're computing the state for some target 48*06c3fb27SDimitry Andric // program point. 49*06c3fb27SDimitry Andric 50*06c3fb27SDimitry Andric /// Called when we start (re-)processing a block in the CFG. 51*06c3fb27SDimitry Andric /// The target program point is the entry to the specified block. 52*06c3fb27SDimitry Andric /// Calls to log() describe transferBranch(), join() etc. 53*06c3fb27SDimitry Andric virtual void enterBlock(const CFGBlock &) {} 54*06c3fb27SDimitry Andric /// Called when we start processing an element in the current CFG block. 55*06c3fb27SDimitry Andric /// The target program point is after the specified element. 56*06c3fb27SDimitry Andric /// Calls to log() describe the transfer() function. 57*06c3fb27SDimitry Andric virtual void enterElement(const CFGElement &) {} 58*06c3fb27SDimitry Andric 59*06c3fb27SDimitry Andric /// Records the analysis state computed for the current program point. 60*06c3fb27SDimitry Andric virtual void recordState(TypeErasedDataflowAnalysisState &) {} 61*06c3fb27SDimitry Andric /// Records that the analysis state for the current block is now final. 62*06c3fb27SDimitry Andric virtual void blockConverged() {} 63*06c3fb27SDimitry Andric 64*06c3fb27SDimitry Andric /// Called by the framework or user code to report some event. 65*06c3fb27SDimitry Andric /// The event is associated with the current context (program point). 66*06c3fb27SDimitry Andric /// The Emit function produces the log message. It may or may not be called, 67*06c3fb27SDimitry Andric /// depending on if the logger is interested; it should have no side effects. 68*06c3fb27SDimitry Andric void log(llvm::function_ref<void(llvm::raw_ostream &)> Emit) { 69*06c3fb27SDimitry Andric if (!ShouldLogText) 70*06c3fb27SDimitry Andric return; 71*06c3fb27SDimitry Andric std::string S; 72*06c3fb27SDimitry Andric llvm::raw_string_ostream OS(S); 73*06c3fb27SDimitry Andric Emit(OS); 74*06c3fb27SDimitry Andric logText(S); 75*06c3fb27SDimitry Andric } 76*06c3fb27SDimitry Andric 77*06c3fb27SDimitry Andric protected: 78*06c3fb27SDimitry Andric /// ShouldLogText should be false for trivial loggers that ignore logText(). 79*06c3fb27SDimitry Andric /// This allows log() to skip evaluating its Emit function. 80*06c3fb27SDimitry Andric Logger(bool ShouldLogText = true) : ShouldLogText(ShouldLogText) {} 81*06c3fb27SDimitry Andric 82*06c3fb27SDimitry Andric private: 83*06c3fb27SDimitry Andric bool ShouldLogText; 84*06c3fb27SDimitry Andric virtual void logText(llvm::StringRef) {} 85*06c3fb27SDimitry Andric }; 86*06c3fb27SDimitry Andric 87*06c3fb27SDimitry Andric } // namespace clang::dataflow 88*06c3fb27SDimitry Andric 89*06c3fb27SDimitry Andric #endif 90