1e5dd7070Spatrick //===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick // 7e5dd7070Spatrick //===----------------------------------------------------------------------===// 8e5dd7070Spatrick // 9e5dd7070Spatrick // This file implements Live Variables analysis for source-level CFGs. 10e5dd7070Spatrick // 11e5dd7070Spatrick //===----------------------------------------------------------------------===// 12e5dd7070Spatrick 13e5dd7070Spatrick #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H 14e5dd7070Spatrick #define LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H 15e5dd7070Spatrick 16e5dd7070Spatrick #include "clang/AST/Decl.h" 17e5dd7070Spatrick #include "clang/Analysis/AnalysisDeclContext.h" 18e5dd7070Spatrick #include "llvm/ADT/ImmutableSet.h" 19e5dd7070Spatrick 20e5dd7070Spatrick namespace clang { 21e5dd7070Spatrick 22e5dd7070Spatrick class CFG; 23e5dd7070Spatrick class CFGBlock; 24e5dd7070Spatrick class Stmt; 25e5dd7070Spatrick class DeclRefExpr; 26e5dd7070Spatrick class SourceManager; 27e5dd7070Spatrick 28e5dd7070Spatrick class LiveVariables : public ManagedAnalysis { 29e5dd7070Spatrick public: 30e5dd7070Spatrick class LivenessValues { 31e5dd7070Spatrick public: 32e5dd7070Spatrick 33*a9ac8606Spatrick llvm::ImmutableSet<const Expr *> liveExprs; 34e5dd7070Spatrick llvm::ImmutableSet<const VarDecl *> liveDecls; 35e5dd7070Spatrick llvm::ImmutableSet<const BindingDecl *> liveBindings; 36e5dd7070Spatrick 37e5dd7070Spatrick bool equals(const LivenessValues &V) const; 38e5dd7070Spatrick LivenessValues()39e5dd7070Spatrick LivenessValues() 40*a9ac8606Spatrick : liveExprs(nullptr), liveDecls(nullptr), liveBindings(nullptr) {} 41e5dd7070Spatrick LivenessValues(llvm::ImmutableSet<const Expr * > liveExprs,llvm::ImmutableSet<const VarDecl * > LiveDecls,llvm::ImmutableSet<const BindingDecl * > LiveBindings)42*a9ac8606Spatrick LivenessValues(llvm::ImmutableSet<const Expr *> liveExprs, 43e5dd7070Spatrick llvm::ImmutableSet<const VarDecl *> LiveDecls, 44e5dd7070Spatrick llvm::ImmutableSet<const BindingDecl *> LiveBindings) 45*a9ac8606Spatrick : liveExprs(liveExprs), liveDecls(LiveDecls), 46e5dd7070Spatrick liveBindings(LiveBindings) {} 47e5dd7070Spatrick 48*a9ac8606Spatrick bool isLive(const Expr *E) const; 49e5dd7070Spatrick bool isLive(const VarDecl *D) const; 50e5dd7070Spatrick 51e5dd7070Spatrick friend class LiveVariables; 52e5dd7070Spatrick }; 53e5dd7070Spatrick 54e5dd7070Spatrick class Observer { 55e5dd7070Spatrick virtual void anchor(); 56e5dd7070Spatrick public: ~Observer()57e5dd7070Spatrick virtual ~Observer() {} 58e5dd7070Spatrick 59e5dd7070Spatrick /// A callback invoked right before invoking the 60e5dd7070Spatrick /// liveness transfer function on the given statement. observeStmt(const Stmt * S,const CFGBlock * currentBlock,const LivenessValues & V)61e5dd7070Spatrick virtual void observeStmt(const Stmt *S, 62e5dd7070Spatrick const CFGBlock *currentBlock, 63e5dd7070Spatrick const LivenessValues& V) {} 64e5dd7070Spatrick 65e5dd7070Spatrick /// Called when the live variables analysis registers 66e5dd7070Spatrick /// that a variable is killed. observerKill(const DeclRefExpr * DR)67e5dd7070Spatrick virtual void observerKill(const DeclRefExpr *DR) {} 68e5dd7070Spatrick }; 69e5dd7070Spatrick 70e5dd7070Spatrick ~LiveVariables() override; 71e5dd7070Spatrick 72e5dd7070Spatrick /// Compute the liveness information for a given CFG. 73ec727ea7Spatrick static std::unique_ptr<LiveVariables> 74ec727ea7Spatrick computeLiveness(AnalysisDeclContext &analysisContext, bool killAtAssign); 75e5dd7070Spatrick 76e5dd7070Spatrick /// Return true if a variable is live at the end of a 77e5dd7070Spatrick /// specified block. 78e5dd7070Spatrick bool isLive(const CFGBlock *B, const VarDecl *D); 79e5dd7070Spatrick 80e5dd7070Spatrick /// Returns true if a variable is live at the beginning of the 81e5dd7070Spatrick /// the statement. This query only works if liveness information 82e5dd7070Spatrick /// has been recorded at the statement level (see runOnAllBlocks), and 83e5dd7070Spatrick /// only returns liveness information for block-level expressions. 84e5dd7070Spatrick bool isLive(const Stmt *S, const VarDecl *D); 85e5dd7070Spatrick 86*a9ac8606Spatrick /// Returns true the block-level expression value is live 87e5dd7070Spatrick /// before the given block-level expression (see runOnAllBlocks). 88*a9ac8606Spatrick bool isLive(const Stmt *Loc, const Expr *Val); 89e5dd7070Spatrick 90e5dd7070Spatrick /// Print to stderr the variable liveness information associated with 91e5dd7070Spatrick /// each basic block. 92e5dd7070Spatrick void dumpBlockLiveness(const SourceManager &M); 93e5dd7070Spatrick 94*a9ac8606Spatrick /// Print to stderr the expression liveness information associated with 95e5dd7070Spatrick /// each basic block. 96*a9ac8606Spatrick void dumpExprLiveness(const SourceManager &M); 97e5dd7070Spatrick 98e5dd7070Spatrick void runOnAllBlocks(Observer &obs); 99e5dd7070Spatrick 100ec727ea7Spatrick static std::unique_ptr<LiveVariables> create(AnalysisDeclContext & analysisContext)101ec727ea7Spatrick create(AnalysisDeclContext &analysisContext) { 102e5dd7070Spatrick return computeLiveness(analysisContext, true); 103e5dd7070Spatrick } 104e5dd7070Spatrick 105e5dd7070Spatrick static const void *getTag(); 106e5dd7070Spatrick 107e5dd7070Spatrick private: 108e5dd7070Spatrick LiveVariables(void *impl); 109e5dd7070Spatrick void *impl; 110e5dd7070Spatrick }; 111e5dd7070Spatrick 112e5dd7070Spatrick class RelaxedLiveVariables : public LiveVariables { 113e5dd7070Spatrick public: 114ec727ea7Spatrick static std::unique_ptr<LiveVariables> create(AnalysisDeclContext & analysisContext)115ec727ea7Spatrick create(AnalysisDeclContext &analysisContext) { 116e5dd7070Spatrick return computeLiveness(analysisContext, false); 117e5dd7070Spatrick } 118e5dd7070Spatrick 119e5dd7070Spatrick static const void *getTag(); 120e5dd7070Spatrick }; 121e5dd7070Spatrick 122e5dd7070Spatrick } // end namespace clang 123e5dd7070Spatrick 124e5dd7070Spatrick #endif 125