sgatev created this revision. sgatev added reviewers: ymandel, NoQ, xazax.hun, gribozavr. Herald added subscribers: rnkovacs, mgorny. sgatev requested review of this revision. Herald added a project: clang.
This is part of the implementation of the dataflow analysis framework. See "[RFC] A dataflow analysis framework for Clang AST" on cfe-dev. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D114234 Files: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h clang/include/clang/Analysis/FlowSensitive/Environment.h clang/lib/Analysis/CMakeLists.txt clang/lib/Analysis/FlowSensitive/CMakeLists.txt clang/lib/Analysis/FlowSensitive/DataflowAnalysis.cpp
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysis.cpp =================================================================== --- /dev/null +++ clang/lib/Analysis/FlowSensitive/DataflowAnalysis.cpp @@ -0,0 +1,33 @@ +//===- DataflowAnalysis.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 defines base types for building dataflow analyses that run over +// Control-Flow Graphs (CFGs). +// +//===----------------------------------------------------------------------===// + +#include <vector> + +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h" +#include "clang/Analysis/FlowSensitive/Environment.h" +#include "llvm/ADT/Optional.h" + +namespace clang { +namespace dataflow { + +std::vector<llvm::Optional<DataflowAnalysisState>> +runDataflowAnalysis(const CFG &Cfg, DataflowAnalysisDynamic &Analysis, + const Environment &InitEnv) { + // FIXME: Implement work list-based algorithm to compute the fixed + // point of `Analysis::transform` for every basic block in `Cfg`. + return {}; +} + +} // namespace dataflow +} // namespace clang Index: clang/lib/Analysis/FlowSensitive/CMakeLists.txt =================================================================== --- /dev/null +++ clang/lib/Analysis/FlowSensitive/CMakeLists.txt @@ -0,0 +1,7 @@ +add_clang_library(clangAnalysisFlowSensitive + DataflowAnalysis.cpp + + LINK_LIBS + clangAnalysis + clangAST + ) Index: clang/lib/Analysis/CMakeLists.txt =================================================================== --- clang/lib/Analysis/CMakeLists.txt +++ clang/lib/Analysis/CMakeLists.txt @@ -44,3 +44,4 @@ ) add_subdirectory(plugins) +add_subdirectory(FlowSensitive) Index: clang/include/clang/Analysis/FlowSensitive/Environment.h =================================================================== --- /dev/null +++ clang/include/clang/Analysis/FlowSensitive/Environment.h @@ -0,0 +1,27 @@ +//===-- Environment.h -------------------------------------------*- C++ -*-===// +// +// 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 defines an Environment class that is used by dataflow analyses +// that run over Control-Flow Graphs (CFGs) to keep track of the state of the +// program at given program points. +// +//===----------------------------------------------------------------------===// + +#ifndef LOCAL_GOOGLE_HOME_SGATEV_LLVM_PROJECT_DATAFLOW_CLANG_INCLUDE_CLANG_ANALYSIS_FLOWSENSITIVE_ENVIRONMENT_H_ +#define LOCAL_GOOGLE_HOME_SGATEV_LLVM_PROJECT_DATAFLOW_CLANG_INCLUDE_CLANG_ANALYSIS_FLOWSENSITIVE_ENVIRONMENT_H_ + +namespace clang { +namespace dataflow { + +// Holds the state of the program (store and heap) at a given program point. +class Environment {}; + +} // namespace dataflow +} // namespace clang + +#endif // LOCAL_GOOGLE_HOME_SGATEV_LLVM_PROJECT_DATAFLOW_CLANG_INCLUDE_CLANG_ANALYSIS_FLOWSENSITIVE_ENVIRONMENT_H_ Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h =================================================================== --- /dev/null +++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h @@ -0,0 +1,162 @@ +//===- DataflowAnalysis.h ---------------------------------------*- C++ -*-===// +// +// 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 defines base types for building dataflow analyses that run over +// Control-Flow Graphs (CFGs). +// +//===----------------------------------------------------------------------===// + +#ifndef LOCAL_GOOGLE_HOME_SGATEV_LLVM_PROJECT_DATAFLOW_CLANG_INCLUDE_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H_ +#define LOCAL_GOOGLE_HOME_SGATEV_LLVM_PROJECT_DATAFLOW_CLANG_INCLUDE_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H_ + +#include <cassert> +#include <utility> +#include <vector> + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Stmt.h" +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/FlowSensitive/Environment.h" +#include "llvm/ADT/Any.h" +#include "llvm/ADT/Optional.h" + +namespace clang { +namespace dataflow { + +// Type-erased lattice element container. +// +// Requirements: +// +// The type of the object stored in the container must be a bounded +// join-semilattice. +struct AnyLatticeElement { + llvm::Any Value; +}; + +// Effect indicating whether a lattice join operation resulted in a new value. +enum class LatticeJoinEffect { + Unchanged, + Changed, +}; + +// Type-erased base class for dataflow analyses built on a single lattice type. +class DataflowAnalysisDynamic { +public: + // Returns the `ASTContext` that is used by the analysis. + virtual ASTContext &getASTContext() = 0; + + // Returns a lattice element that models the initial state of a basic block. + virtual AnyLatticeElement initialElementDynamic() = 0; + + // Joins two lattice elements by computing their least upper bound. Places the + // join result in the left element and returns an effect indicating whether + // any changes were made to it. + virtual LatticeJoinEffect joinDynamic(AnyLatticeElement &, + const AnyLatticeElement &) = 0; + + // Returns true if and only if the two given lattice elements are equal. + virtual bool isEqualDynamic(const AnyLatticeElement &, + const AnyLatticeElement &) = 0; + + // Applies the analysis transfer function for a given statement and lattice + // element. + virtual AnyLatticeElement + transferDynamic(const Stmt *, const AnyLatticeElement &, Environment &) = 0; +}; + +// Base class template for dataflow analyses built on a single lattice type. +// +// Requirements: +// +// `Derived` must be derived from a specialization of this class template and +// must provide the following public members: +// * `LatticeT InitialElement()` - returns a lattice element that models the +// initial state of a basic block; +// * `LatticeT Transfer(const Stmt*, const LatticeT&, Environment&)` - applies +// the analysis transfer function for a given statement and lattice element. +// +// `LatticeT` is a bounded join-semilattice that is used by `Derived` and must +// provide the following public members: +// * `LatticeJoinEffect Join(const LatticeT&)` - joins the object and the +// argument by computing their least upper bound, modifies the object if +// necessary, and returns an effect indicating whether any changes were made +// to it; +// * `bool operator==(const LatticeT&) const` - returns true if and only if +// the object is equal to the argument. +template <typename Derived, typename LatticeT> +class DataflowAnalysis : public DataflowAnalysisDynamic { +public: + // Bounded join-semilattice that is used in the analysis. + using Lattice = LatticeT; + + explicit DataflowAnalysis(ASTContext &Context) : Context(Context) {} + + ASTContext &getASTContext() final { return Context; } + + AnyLatticeElement initialElementDynamic() final { + return AnyLatticeElement{static_cast<Derived *>(this)->initialElement()}; + } + + LatticeJoinEffect joinDynamic(AnyLatticeElement &E1, + const AnyLatticeElement &E2) final { + Lattice *L1 = llvm::any_cast<Lattice>(&E1.Value); + assert(L1 != nullptr); + const Lattice *L2 = llvm::any_cast<Lattice>(&E2.Value); + assert(L2 != nullptr); + return L1->join(*L2); + } + + bool isEqualDynamic(const AnyLatticeElement &E1, + const AnyLatticeElement &E2) final { + const Lattice *L1 = llvm::any_cast<Lattice>(&E1.Value); + assert(L1 != nullptr); + const Lattice *L2 = llvm::any_cast<Lattice>(&E2.Value); + assert(L2 != nullptr); + return *L1 == *L2; + } + + AnyLatticeElement transferDynamic(const Stmt *Stmt, + const AnyLatticeElement &E, + Environment &Environment) final { + const Lattice *L = llvm::any_cast<Lattice>(&E.Value); + assert(L != nullptr); + return AnyLatticeElement{ + static_cast<Derived *>(this)->transfer(Stmt, *L, Environment)}; + } + +private: + ASTContext &Context; +}; + +// Model of the program at a given program point. +struct DataflowAnalysisState { + DataflowAnalysisState(AnyLatticeElement Lattice, Environment Env) + : Lattice(std::move(Lattice)), Env(std::move(Env)) {} + + // Model of a program property. + AnyLatticeElement Lattice; + + // Model of the state of the program (store and heap). + Environment Env; +}; + +// Performs dataflow analysis and returns a mapping from basic block IDs to +// dataflow analysis states that model the respective basic blocks. +// +// Requirements: +// +// `Cfg` must have been built with `CFG::BuildOptions::setAllAlwaysAdd()` to +// ensure that all sub-expressions in a basic block are evaluated. +std::vector<llvm::Optional<DataflowAnalysisState>> +runDataflowAnalysis(const CFG &Cfg, DataflowAnalysisDynamic &Analysis, + const Environment &InitEnv); + +} // namespace dataflow +} // namespace clang + +#endif // LOCAL_GOOGLE_HOME_SGATEV_LLVM_PROJECT_DATAFLOW_CLANG_INCLUDE_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSIS_H_
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits