diff --git a/clang/include/clang/Analysis/FlowSensitive/Logger.h b/clang/include/clang/Analysis/FlowSensitive/Logger.h --- a/clang/include/clang/Analysis/FlowSensitive/Logger.h +++ b/clang/include/clang/Analysis/FlowSensitive/Logger.h @@ -31,6 +31,13 @@ /// A logger that simply writes messages to the specified ostream in real /// time. static std::unique_ptr textual(llvm::raw_ostream &); + // A logger that builds an HTML UI to inspect the analysis results. + // One file is written under the specified dir per analyzed function. + static std::unique_ptr html(llvm::StringRef Dir); + // A logger that builds an HTML UI to inspect the analysis results. + // Each function's analysis is written to a stream obtained from the factory. + static std::unique_ptr + html(std::function()>); virtual ~Logger() = default; diff --git a/clang/lib/Analysis/FlowSensitive/CMakeLists.txt b/clang/lib/Analysis/FlowSensitive/CMakeLists.txt --- a/clang/lib/Analysis/FlowSensitive/CMakeLists.txt +++ b/clang/lib/Analysis/FlowSensitive/CMakeLists.txt @@ -2,6 +2,7 @@ ControlFlowContext.cpp DataflowAnalysisContext.cpp DataflowEnvironment.cpp + HTMLLogger.cpp Logger.cpp Transfer.cpp TypeErasedDataflowAnalysis.cpp @@ -16,3 +17,14 @@ ) add_subdirectory(Models) + +add_custom_command(OUTPUT HTMLLogger.inc + COMMAND "${Python3_EXECUTABLE}" bundle_resources.py + ${CMAKE_CURRENT_BINARY_DIR}/HTMLLogger.inc + HTMLLogger.css HTMLLogger.js + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Bundling HTMLLogger resources" + DEPENDS bundle_resources.py HTMLLogger.css HTMLLogger.js + VERBATIM) +add_custom_target(clangAnalysisFlowSensitiveResources DEPENDS HTMLLogger.inc) +add_dependencies(clangAnalysisFlowSensitive clangAnalysisFlowSensitiveResources) \ No newline at end of file diff --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp --- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp @@ -24,10 +24,11 @@ #include #include -static llvm::cl::opt - DataflowLog("dataflow-log", llvm::cl::Hidden, llvm::cl::ValueOptional, - llvm::cl::desc("Emit log of dataflow analysis. With no arg, " - "writes textual log to stderr.")); +static llvm::cl::opt DataflowLog( + "dataflow-log", llvm::cl::Hidden, llvm::cl::ValueOptional, + llvm::cl::desc("Emit log of dataflow analysis. With no arg, writes textual " + "log to stderr. With an arg, writes HTML logs under the " + "specified directory (one per analyzed function).")); namespace clang { namespace dataflow { @@ -390,9 +391,9 @@ // This is ugly but provides a uniform method for ad-hoc debugging dataflow- // based tools. if (Opts.Log == nullptr && DataflowLog.getNumOccurrences()) { - LogOwner = Logger::textual(llvm::errs()); + LogOwner = DataflowLog.empty() ? Logger::textual(llvm::errs()) + : Logger::html(DataflowLog); this->Opts.Log = LogOwner.get(); - // FIXME: if the flag is given a value, write an HTML log to a file. } } diff --git a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp @@ -0,0 +1,506 @@ +//===-- HTMLLogger.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the HTML logger. Given a directory dir/, we write +// dir/0.html for the first analysis, etc. +// These files contain a visualization that allows inspecting the CFG and the +// state of the analysis at each point. +// Static assets (HTMLLogger.js, HTMLLogger.css) and SVG graphs etc are embedded +// so this file is self-contained. +// +// VIEWS +// +// The timeline and function view are always shown. These allow selecting basic +// blocks, statements within them, and processing iterations (BBs are visited +// multiple times when e.g. loops are involved). +// These are written directly into the HTML body. +// +// There are also listings of particular basic blocks, and dumps of the state +// at particular analysis points (i.e. BB2 iteration 3 statement 2). +// These are only shown when the relevant BB/analysis point is *selected*. +// These are defined inside