106c3fb27SDimitry Andric //===-- Logger.h ------------------------------------------------*- C++ -*-===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H 1006c3fb27SDimitry Andric #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_LOGGER_H 1106c3fb27SDimitry Andric 1206c3fb27SDimitry Andric #include "clang/Analysis/CFG.h" 1306c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h" 1406c3fb27SDimitry Andric #include <memory> 1506c3fb27SDimitry Andric 1606c3fb27SDimitry Andric namespace clang::dataflow { 1706c3fb27SDimitry Andric // Forward declarations so we can use Logger anywhere in the framework. 18*0fca6ea1SDimitry Andric class AdornedCFG; 1906c3fb27SDimitry Andric class TypeErasedDataflowAnalysis; 2006c3fb27SDimitry Andric struct TypeErasedDataflowAnalysisState; 2106c3fb27SDimitry Andric 2206c3fb27SDimitry Andric /// A logger is notified as the analysis progresses. 2306c3fb27SDimitry Andric /// It can produce a report of the analysis's findings and how it came to them. 2406c3fb27SDimitry Andric /// 2506c3fb27SDimitry Andric /// The framework reports key structural events (e.g. traversal of blocks). 2606c3fb27SDimitry Andric /// The specific analysis can add extra details to be presented in context. 2706c3fb27SDimitry Andric class Logger { 2806c3fb27SDimitry Andric public: 2906c3fb27SDimitry Andric /// Returns a dummy logger that does nothing. 3006c3fb27SDimitry Andric static Logger &null(); 3106c3fb27SDimitry Andric /// A logger that simply writes messages to the specified ostream in real 3206c3fb27SDimitry Andric /// time. 3306c3fb27SDimitry Andric static std::unique_ptr<Logger> textual(llvm::raw_ostream &); 3406c3fb27SDimitry Andric /// A logger that builds an HTML UI to inspect the analysis results. 3506c3fb27SDimitry Andric /// Each function's analysis is written to a stream obtained from the factory. 3606c3fb27SDimitry Andric static std::unique_ptr<Logger> 3706c3fb27SDimitry Andric html(std::function<std::unique_ptr<llvm::raw_ostream>()>); 3806c3fb27SDimitry Andric 3906c3fb27SDimitry Andric virtual ~Logger() = default; 4006c3fb27SDimitry Andric 4106c3fb27SDimitry Andric /// Called by the framework as we start analyzing a new function or statement. 4206c3fb27SDimitry Andric /// Forms a pair with endAnalysis(). 43*0fca6ea1SDimitry Andric virtual void beginAnalysis(const AdornedCFG &, TypeErasedDataflowAnalysis &) { 44*0fca6ea1SDimitry Andric } 4506c3fb27SDimitry Andric virtual void endAnalysis() {} 4606c3fb27SDimitry Andric 4706c3fb27SDimitry Andric // At any time during the analysis, we're computing the state for some target 4806c3fb27SDimitry Andric // program point. 4906c3fb27SDimitry Andric 5006c3fb27SDimitry Andric /// Called when we start (re-)processing a block in the CFG. 5106c3fb27SDimitry Andric /// The target program point is the entry to the specified block. 5206c3fb27SDimitry Andric /// Calls to log() describe transferBranch(), join() etc. 535f757f3fSDimitry Andric /// `PostVisit` specifies whether we're processing the block for the 545f757f3fSDimitry Andric /// post-visit callback. 555f757f3fSDimitry Andric virtual void enterBlock(const CFGBlock &, bool PostVisit) {} 5606c3fb27SDimitry Andric /// Called when we start processing an element in the current CFG block. 5706c3fb27SDimitry Andric /// The target program point is after the specified element. 5806c3fb27SDimitry Andric /// Calls to log() describe the transfer() function. 5906c3fb27SDimitry Andric virtual void enterElement(const CFGElement &) {} 6006c3fb27SDimitry Andric 6106c3fb27SDimitry Andric /// Records the analysis state computed for the current program point. 6206c3fb27SDimitry Andric virtual void recordState(TypeErasedDataflowAnalysisState &) {} 6306c3fb27SDimitry Andric /// Records that the analysis state for the current block is now final. 6406c3fb27SDimitry Andric virtual void blockConverged() {} 6506c3fb27SDimitry Andric 6606c3fb27SDimitry Andric /// Called by the framework or user code to report some event. 6706c3fb27SDimitry Andric /// The event is associated with the current context (program point). 6806c3fb27SDimitry Andric /// The Emit function produces the log message. It may or may not be called, 6906c3fb27SDimitry Andric /// depending on if the logger is interested; it should have no side effects. 7006c3fb27SDimitry Andric void log(llvm::function_ref<void(llvm::raw_ostream &)> Emit) { 7106c3fb27SDimitry Andric if (!ShouldLogText) 7206c3fb27SDimitry Andric return; 7306c3fb27SDimitry Andric std::string S; 7406c3fb27SDimitry Andric llvm::raw_string_ostream OS(S); 7506c3fb27SDimitry Andric Emit(OS); 7606c3fb27SDimitry Andric logText(S); 7706c3fb27SDimitry Andric } 7806c3fb27SDimitry Andric 7906c3fb27SDimitry Andric protected: 8006c3fb27SDimitry Andric /// ShouldLogText should be false for trivial loggers that ignore logText(). 8106c3fb27SDimitry Andric /// This allows log() to skip evaluating its Emit function. 8206c3fb27SDimitry Andric Logger(bool ShouldLogText = true) : ShouldLogText(ShouldLogText) {} 8306c3fb27SDimitry Andric 8406c3fb27SDimitry Andric private: 8506c3fb27SDimitry Andric bool ShouldLogText; 8606c3fb27SDimitry Andric virtual void logText(llvm::StringRef) {} 8706c3fb27SDimitry Andric }; 8806c3fb27SDimitry Andric 8906c3fb27SDimitry Andric } // namespace clang::dataflow 9006c3fb27SDimitry Andric 9106c3fb27SDimitry Andric #endif 92