Path: blob/main/contrib/llvm-project/clang/lib/Analysis/LiveVariables.cpp
35233 views
//=- LiveVariables.cpp - Live Variable Analysis for Source CFGs ----------*-==//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements Live Variables analysis for source-level CFGs.9//10//===----------------------------------------------------------------------===//1112#include "clang/Analysis/Analyses/LiveVariables.h"13#include "clang/AST/Stmt.h"14#include "clang/AST/StmtVisitor.h"15#include "clang/Analysis/AnalysisDeclContext.h"16#include "clang/Analysis/CFG.h"17#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"18#include "llvm/ADT/DenseMap.h"19#include "llvm/Support/raw_ostream.h"20#include <algorithm>21#include <optional>22#include <vector>2324using namespace clang;2526namespace {27class LiveVariablesImpl {28public:29AnalysisDeclContext &analysisContext;30llvm::ImmutableSet<const Expr *>::Factory ESetFact;31llvm::ImmutableSet<const VarDecl *>::Factory DSetFact;32llvm::ImmutableSet<const BindingDecl *>::Factory BSetFact;33llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;34llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;35llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;36llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;37const bool killAtAssign;3839LiveVariables::LivenessValues40merge(LiveVariables::LivenessValues valsA,41LiveVariables::LivenessValues valsB);4243LiveVariables::LivenessValues44runOnBlock(const CFGBlock *block, LiveVariables::LivenessValues val,45LiveVariables::Observer *obs = nullptr);4647void dumpBlockLiveness(const SourceManager& M);48void dumpExprLiveness(const SourceManager& M);4950LiveVariablesImpl(AnalysisDeclContext &ac, bool KillAtAssign)51: analysisContext(ac),52ESetFact(false), // Do not canonicalize ImmutableSets by default.53DSetFact(false), // This is a *major* performance win.54BSetFact(false), killAtAssign(KillAtAssign) {}55};56} // namespace5758static LiveVariablesImpl &getImpl(void *x) {59return *((LiveVariablesImpl *) x);60}6162//===----------------------------------------------------------------------===//63// Operations and queries on LivenessValues.64//===----------------------------------------------------------------------===//6566bool LiveVariables::LivenessValues::isLive(const Expr *E) const {67return liveExprs.contains(E);68}6970bool LiveVariables::LivenessValues::isLive(const VarDecl *D) const {71if (const auto *DD = dyn_cast<DecompositionDecl>(D)) {72bool alive = false;73for (const BindingDecl *BD : DD->bindings())74alive |= liveBindings.contains(BD);7576// Note: the only known case this condition is necessary, is when a bindig77// to a tuple-like structure is created. The HoldingVar initializers have a78// DeclRefExpr to the DecompositionDecl.79alive |= liveDecls.contains(DD);80return alive;81}82return liveDecls.contains(D);83}8485namespace {86template <typename SET>87SET mergeSets(SET A, SET B) {88if (A.isEmpty())89return B;9091for (typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {92A = A.add(*it);93}94return A;95}96} // namespace9798void LiveVariables::Observer::anchor() { }99100LiveVariables::LivenessValues101LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,102LiveVariables::LivenessValues valsB) {103104llvm::ImmutableSetRef<const Expr *> SSetRefA(105valsA.liveExprs.getRootWithoutRetain(), ESetFact.getTreeFactory()),106SSetRefB(valsB.liveExprs.getRootWithoutRetain(),107ESetFact.getTreeFactory());108109llvm::ImmutableSetRef<const VarDecl *>110DSetRefA(valsA.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),111DSetRefB(valsB.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());112113llvm::ImmutableSetRef<const BindingDecl *>114BSetRefA(valsA.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory()),115BSetRefB(valsB.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory());116117SSetRefA = mergeSets(SSetRefA, SSetRefB);118DSetRefA = mergeSets(DSetRefA, DSetRefB);119BSetRefA = mergeSets(BSetRefA, BSetRefB);120121// asImmutableSet() canonicalizes the tree, allowing us to do an easy122// comparison afterwards.123return LiveVariables::LivenessValues(SSetRefA.asImmutableSet(),124DSetRefA.asImmutableSet(),125BSetRefA.asImmutableSet());126}127128bool LiveVariables::LivenessValues::equals(const LivenessValues &V) const {129return liveExprs == V.liveExprs && liveDecls == V.liveDecls;130}131132//===----------------------------------------------------------------------===//133// Query methods.134//===----------------------------------------------------------------------===//135136static bool isAlwaysAlive(const VarDecl *D) {137return D->hasGlobalStorage();138}139140bool LiveVariables::isLive(const CFGBlock *B, const VarDecl *D) {141return isAlwaysAlive(D) || getImpl(impl).blocksEndToLiveness[B].isLive(D);142}143144bool LiveVariables::isLive(const Stmt *S, const VarDecl *D) {145return isAlwaysAlive(D) || getImpl(impl).stmtsToLiveness[S].isLive(D);146}147148bool LiveVariables::isLive(const Stmt *Loc, const Expr *Val) {149return getImpl(impl).stmtsToLiveness[Loc].isLive(Val);150}151152//===----------------------------------------------------------------------===//153// Dataflow computation.154//===----------------------------------------------------------------------===//155156namespace {157class TransferFunctions : public StmtVisitor<TransferFunctions> {158LiveVariablesImpl &LV;159LiveVariables::LivenessValues &val;160LiveVariables::Observer *observer;161const CFGBlock *currentBlock;162public:163TransferFunctions(LiveVariablesImpl &im,164LiveVariables::LivenessValues &Val,165LiveVariables::Observer *Observer,166const CFGBlock *CurrentBlock)167: LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}168169void VisitBinaryOperator(BinaryOperator *BO);170void VisitBlockExpr(BlockExpr *BE);171void VisitDeclRefExpr(DeclRefExpr *DR);172void VisitDeclStmt(DeclStmt *DS);173void VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS);174void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE);175void VisitUnaryOperator(UnaryOperator *UO);176void Visit(Stmt *S);177};178} // namespace179180static const VariableArrayType *FindVA(QualType Ty) {181const Type *ty = Ty.getTypePtr();182while (const ArrayType *VT = dyn_cast<ArrayType>(ty)) {183if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(VT))184if (VAT->getSizeExpr())185return VAT;186187ty = VT->getElementType().getTypePtr();188}189190return nullptr;191}192193static const Expr *LookThroughExpr(const Expr *E) {194while (E) {195if (const Expr *Ex = dyn_cast<Expr>(E))196E = Ex->IgnoreParens();197if (const FullExpr *FE = dyn_cast<FullExpr>(E)) {198E = FE->getSubExpr();199continue;200}201if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {202E = OVE->getSourceExpr();203continue;204}205break;206}207return E;208}209210static void AddLiveExpr(llvm::ImmutableSet<const Expr *> &Set,211llvm::ImmutableSet<const Expr *>::Factory &F,212const Expr *E) {213Set = F.add(Set, LookThroughExpr(E));214}215216void TransferFunctions::Visit(Stmt *S) {217if (observer)218observer->observeStmt(S, currentBlock, val);219220StmtVisitor<TransferFunctions>::Visit(S);221222if (const auto *E = dyn_cast<Expr>(S)) {223val.liveExprs = LV.ESetFact.remove(val.liveExprs, E);224}225226// Mark all children expressions live.227228switch (S->getStmtClass()) {229default:230break;231case Stmt::StmtExprClass: {232// For statement expressions, look through the compound statement.233S = cast<StmtExpr>(S)->getSubStmt();234break;235}236case Stmt::CXXMemberCallExprClass: {237// Include the implicit "this" pointer as being live.238CXXMemberCallExpr *CE = cast<CXXMemberCallExpr>(S);239if (Expr *ImplicitObj = CE->getImplicitObjectArgument()) {240AddLiveExpr(val.liveExprs, LV.ESetFact, ImplicitObj);241}242break;243}244case Stmt::ObjCMessageExprClass: {245// In calls to super, include the implicit "self" pointer as being live.246ObjCMessageExpr *CE = cast<ObjCMessageExpr>(S);247if (CE->getReceiverKind() == ObjCMessageExpr::SuperInstance)248val.liveDecls = LV.DSetFact.add(val.liveDecls,249LV.analysisContext.getSelfDecl());250break;251}252case Stmt::DeclStmtClass: {253const DeclStmt *DS = cast<DeclStmt>(S);254if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) {255for (const VariableArrayType* VA = FindVA(VD->getType());256VA != nullptr; VA = FindVA(VA->getElementType())) {257AddLiveExpr(val.liveExprs, LV.ESetFact, VA->getSizeExpr());258}259}260break;261}262case Stmt::PseudoObjectExprClass: {263// A pseudo-object operation only directly consumes its result264// expression.265Expr *child = cast<PseudoObjectExpr>(S)->getResultExpr();266if (!child) return;267if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child))268child = OV->getSourceExpr();269child = child->IgnoreParens();270val.liveExprs = LV.ESetFact.add(val.liveExprs, child);271return;272}273274// FIXME: These cases eventually shouldn't be needed.275case Stmt::ExprWithCleanupsClass: {276S = cast<ExprWithCleanups>(S)->getSubExpr();277break;278}279case Stmt::CXXBindTemporaryExprClass: {280S = cast<CXXBindTemporaryExpr>(S)->getSubExpr();281break;282}283case Stmt::UnaryExprOrTypeTraitExprClass: {284// No need to unconditionally visit subexpressions.285return;286}287case Stmt::IfStmtClass: {288// If one of the branches is an expression rather than a compound289// statement, it will be bad if we mark it as live at the terminator290// of the if-statement (i.e., immediately after the condition expression).291AddLiveExpr(val.liveExprs, LV.ESetFact, cast<IfStmt>(S)->getCond());292return;293}294case Stmt::WhileStmtClass: {295// If the loop body is an expression rather than a compound statement,296// it will be bad if we mark it as live at the terminator of the loop297// (i.e., immediately after the condition expression).298AddLiveExpr(val.liveExprs, LV.ESetFact, cast<WhileStmt>(S)->getCond());299return;300}301case Stmt::DoStmtClass: {302// If the loop body is an expression rather than a compound statement,303// it will be bad if we mark it as live at the terminator of the loop304// (i.e., immediately after the condition expression).305AddLiveExpr(val.liveExprs, LV.ESetFact, cast<DoStmt>(S)->getCond());306return;307}308case Stmt::ForStmtClass: {309// If the loop body is an expression rather than a compound statement,310// it will be bad if we mark it as live at the terminator of the loop311// (i.e., immediately after the condition expression).312AddLiveExpr(val.liveExprs, LV.ESetFact, cast<ForStmt>(S)->getCond());313return;314}315316}317318// HACK + FIXME: What is this? One could only guess that this is an attempt to319// fish for live values, for example, arguments from a call expression.320// Maybe we could take inspiration from UninitializedVariable analysis?321for (Stmt *Child : S->children()) {322if (const auto *E = dyn_cast_or_null<Expr>(Child))323AddLiveExpr(val.liveExprs, LV.ESetFact, E);324}325}326327static bool writeShouldKill(const VarDecl *VD) {328return VD && !VD->getType()->isReferenceType() &&329!isAlwaysAlive(VD);330}331332void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {333if (LV.killAtAssign && B->getOpcode() == BO_Assign) {334if (const auto *DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParens())) {335LV.inAssignment[DR] = 1;336}337}338if (B->isAssignmentOp()) {339if (!LV.killAtAssign)340return;341342// Assigning to a variable?343Expr *LHS = B->getLHS()->IgnoreParens();344345if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {346const Decl* D = DR->getDecl();347bool Killed = false;348349if (const BindingDecl* BD = dyn_cast<BindingDecl>(D)) {350Killed = !BD->getType()->isReferenceType();351if (Killed) {352if (const auto *HV = BD->getHoldingVar())353val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);354355val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);356}357} else if (const auto *VD = dyn_cast<VarDecl>(D)) {358Killed = writeShouldKill(VD);359if (Killed)360val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);361362}363364if (Killed && observer)365observer->observerKill(DR);366}367}368}369370void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {371for (const VarDecl *VD :372LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl())) {373if (isAlwaysAlive(VD))374continue;375val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);376}377}378379void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {380const Decl* D = DR->getDecl();381bool InAssignment = LV.inAssignment[DR];382if (const auto *BD = dyn_cast<BindingDecl>(D)) {383if (!InAssignment) {384if (const auto *HV = BD->getHoldingVar())385val.liveDecls = LV.DSetFact.add(val.liveDecls, HV);386387val.liveBindings = LV.BSetFact.add(val.liveBindings, BD);388}389} else if (const auto *VD = dyn_cast<VarDecl>(D)) {390if (!InAssignment && !isAlwaysAlive(VD))391val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);392}393}394395void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {396for (const auto *DI : DS->decls()) {397if (const auto *DD = dyn_cast<DecompositionDecl>(DI)) {398for (const auto *BD : DD->bindings()) {399if (const auto *HV = BD->getHoldingVar())400val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);401402val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);403}404405// When a bindig to a tuple-like structure is created, the HoldingVar406// initializers have a DeclRefExpr to the DecompositionDecl.407val.liveDecls = LV.DSetFact.remove(val.liveDecls, DD);408} else if (const auto *VD = dyn_cast<VarDecl>(DI)) {409if (!isAlwaysAlive(VD))410val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);411}412}413}414415void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {416// Kill the iteration variable.417DeclRefExpr *DR = nullptr;418const VarDecl *VD = nullptr;419420Stmt *element = OS->getElement();421if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) {422VD = cast<VarDecl>(DS->getSingleDecl());423}424else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {425VD = cast<VarDecl>(DR->getDecl());426}427428if (VD) {429val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);430if (observer && DR)431observer->observerKill(DR);432}433}434435void TransferFunctions::436VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)437{438// While sizeof(var) doesn't technically extend the liveness of 'var', it439// does extent the liveness of metadata if 'var' is a VariableArrayType.440// We handle that special case here.441if (UE->getKind() != UETT_SizeOf || UE->isArgumentType())442return;443444const Expr *subEx = UE->getArgumentExpr();445if (subEx->getType()->isVariableArrayType()) {446assert(subEx->isLValue());447val.liveExprs = LV.ESetFact.add(val.liveExprs, subEx->IgnoreParens());448}449}450451void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) {452// Treat ++/-- as a kill.453// Note we don't actually have to do anything if we don't have an observer,454// since a ++/-- acts as both a kill and a "use".455if (!observer)456return;457458switch (UO->getOpcode()) {459default:460return;461case UO_PostInc:462case UO_PostDec:463case UO_PreInc:464case UO_PreDec:465break;466}467468if (auto *DR = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens())) {469const Decl *D = DR->getDecl();470if (isa<VarDecl>(D) || isa<BindingDecl>(D)) {471// Treat ++/-- as a kill.472observer->observerKill(DR);473}474}475}476477LiveVariables::LivenessValues478LiveVariablesImpl::runOnBlock(const CFGBlock *block,479LiveVariables::LivenessValues val,480LiveVariables::Observer *obs) {481482TransferFunctions TF(*this, val, obs, block);483484// Visit the terminator (if any).485if (const Stmt *term = block->getTerminatorStmt())486TF.Visit(const_cast<Stmt*>(term));487488// Apply the transfer function for all Stmts in the block.489for (CFGBlock::const_reverse_iterator it = block->rbegin(),490ei = block->rend(); it != ei; ++it) {491const CFGElement &elem = *it;492493if (std::optional<CFGAutomaticObjDtor> Dtor =494elem.getAs<CFGAutomaticObjDtor>()) {495val.liveDecls = DSetFact.add(val.liveDecls, Dtor->getVarDecl());496continue;497}498499if (!elem.getAs<CFGStmt>())500continue;501502const Stmt *S = elem.castAs<CFGStmt>().getStmt();503TF.Visit(const_cast<Stmt*>(S));504stmtsToLiveness[S] = val;505}506return val;507}508509void LiveVariables::runOnAllBlocks(LiveVariables::Observer &obs) {510const CFG *cfg = getImpl(impl).analysisContext.getCFG();511for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it)512getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs);513}514515LiveVariables::LiveVariables(void *im) : impl(im) {}516517LiveVariables::~LiveVariables() {518delete (LiveVariablesImpl*) impl;519}520521std::unique_ptr<LiveVariables>522LiveVariables::computeLiveness(AnalysisDeclContext &AC, bool killAtAssign) {523524// No CFG? Bail out.525CFG *cfg = AC.getCFG();526if (!cfg)527return nullptr;528529// The analysis currently has scalability issues for very large CFGs.530// Bail out if it looks too large.531if (cfg->getNumBlockIDs() > 300000)532return nullptr;533534LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign);535536// Construct the dataflow worklist. Enqueue the exit block as the537// start of the analysis.538BackwardDataflowWorklist worklist(*cfg, AC);539llvm::BitVector everAnalyzedBlock(cfg->getNumBlockIDs());540541// FIXME: we should enqueue using post order.542for (const CFGBlock *B : cfg->nodes()) {543worklist.enqueueBlock(B);544}545546while (const CFGBlock *block = worklist.dequeue()) {547// Determine if the block's end value has changed. If not, we548// have nothing left to do for this block.549LivenessValues &prevVal = LV->blocksEndToLiveness[block];550551// Merge the values of all successor blocks.552LivenessValues val;553for (CFGBlock::const_succ_iterator it = block->succ_begin(),554ei = block->succ_end(); it != ei; ++it) {555if (const CFGBlock *succ = *it) {556val = LV->merge(val, LV->blocksBeginToLiveness[succ]);557}558}559560if (!everAnalyzedBlock[block->getBlockID()])561everAnalyzedBlock[block->getBlockID()] = true;562else if (prevVal.equals(val))563continue;564565prevVal = val;566567// Update the dataflow value for the start of this block.568LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);569570// Enqueue the value to the predecessors.571worklist.enqueuePredecessors(block);572}573574return std::unique_ptr<LiveVariables>(new LiveVariables(LV));575}576577void LiveVariables::dumpBlockLiveness(const SourceManager &M) {578getImpl(impl).dumpBlockLiveness(M);579}580581void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {582std::vector<const CFGBlock *> vec;583for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator584it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();585it != ei; ++it) {586vec.push_back(it->first);587}588llvm::sort(vec, [](const CFGBlock *A, const CFGBlock *B) {589return A->getBlockID() < B->getBlockID();590});591592std::vector<const VarDecl*> declVec;593594for (std::vector<const CFGBlock *>::iterator595it = vec.begin(), ei = vec.end(); it != ei; ++it) {596llvm::errs() << "\n[ B" << (*it)->getBlockID()597<< " (live variables at block exit) ]\n";598599LiveVariables::LivenessValues vals = blocksEndToLiveness[*it];600declVec.clear();601602for (llvm::ImmutableSet<const VarDecl *>::iterator si =603vals.liveDecls.begin(),604se = vals.liveDecls.end(); si != se; ++si) {605declVec.push_back(*si);606}607608llvm::sort(declVec, [](const Decl *A, const Decl *B) {609return A->getBeginLoc() < B->getBeginLoc();610});611612for (std::vector<const VarDecl*>::iterator di = declVec.begin(),613de = declVec.end(); di != de; ++di) {614llvm::errs() << " " << (*di)->getDeclName().getAsString()615<< " <";616(*di)->getLocation().print(llvm::errs(), M);617llvm::errs() << ">\n";618}619}620llvm::errs() << "\n";621}622623void LiveVariables::dumpExprLiveness(const SourceManager &M) {624getImpl(impl).dumpExprLiveness(M);625}626627void LiveVariablesImpl::dumpExprLiveness(const SourceManager &M) {628// Don't iterate over blockEndsToLiveness directly because it's not sorted.629for (const CFGBlock *B : *analysisContext.getCFG()) {630631llvm::errs() << "\n[ B" << B->getBlockID()632<< " (live expressions at block exit) ]\n";633for (const Expr *E : blocksEndToLiveness[B].liveExprs) {634llvm::errs() << "\n";635E->dump();636}637llvm::errs() << "\n";638}639}640641const void *LiveVariables::getTag() { static int x; return &x; }642const void *RelaxedLiveVariables::getTag() { static int x; return &x; }643644645