20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/DenseSet.h"
22#include "llvm/ADT/STLExtras.h"
23#include "llvm/Support/raw_ostream.h"
30class LiveVariablesImpl {
34 AnalysisDeclContext &analysisContext;
35 SetTy<const Expr *>::Factory ESetFact;
36 SetTy<const VarDecl *>::Factory DSetFact;
37 SetTy<const BindingDecl *>::Factory BSetFact;
38 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
39 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
40 llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
41 llvm::DenseSet<const DeclRefExpr *> inAssignment;
42 const bool killAtAssign;
44 LiveVariables::LivenessValues
45 merge(LiveVariables::LivenessValues valsA,
46 LiveVariables::LivenessValues valsB);
48 LiveVariables::LivenessValues
49 runOnBlock(
const CFGBlock *block, LiveVariables::LivenessValues val,
50 LiveVariables::Observer *obs =
nullptr);
52 void dumpBlockLiveness(
const SourceManager& M);
53 void dumpExprLiveness(
const SourceManager& M);
55 LiveVariablesImpl(AnalysisDeclContext &ac,
bool KillAtAssign)
56 : analysisContext(ac), killAtAssign(KillAtAssign) {}
60static LiveVariablesImpl &
getImpl(
void *x) {
61 return *((LiveVariablesImpl *) x);
73 if (
const auto *DD = dyn_cast<DecompositionDecl>(D)) {
89void LiveVariables::Observer::anchor() { }
125 return getImpl(impl).stmtsToLiveness[Loc].isLive(Val);
133class TransferFunctions :
public StmtVisitor<TransferFunctions> {
134 LiveVariablesImpl &LV;
139 TransferFunctions(LiveVariablesImpl &im,
143 : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
157 while (
const ArrayType *VT = dyn_cast<ArrayType>(ty)) {
159 if (VAT->getSizeExpr())
162 ty = VT->getElementType().getTypePtr();
171 if (
const FullExpr *FE = dyn_cast<FullExpr>(E)) {
172 E = FE->getSubExpr();
176 E = OVE->getSourceExpr();
200 if (
auto const *BO = dyn_cast<BinaryOperator>(Cond->
IgnoreParens());
201 BO && BO->isLogicalOp()) {
207void TransferFunctions::Visit(Stmt *S) {
209 observer->observeStmt(S, currentBlock, val);
213 if (
const auto *E = dyn_cast<Expr>(S)) {
214 val.liveExprs = LV.ESetFact.remove(val.liveExprs, E);
228 case Stmt::StmtExprClass: {
233 case Stmt::CXXMemberCallExprClass: {
237 AddLiveExpr(val.liveExprs, LV.ESetFact, ImplicitObj);
241 case Stmt::ObjCMessageExprClass: {
245 val.liveDecls = LV.DSetFact.add(val.liveDecls,
246 LV.analysisContext.getSelfDecl());
249 case Stmt::DeclStmtClass: {
251 if (
const VarDecl *VD = dyn_cast<VarDecl>(DS->
getSingleDecl())) {
252 for (
const VariableArrayType* VA =
FindVA(VD->getType());
253 VA !=
nullptr; VA =
FindVA(VA->getElementType())) {
254 AddLiveExpr(val.liveExprs, LV.ESetFact, VA->getSizeExpr());
259 case Stmt::AttributedStmtClass: {
264 AddLiveExpr(val.liveExprs, LV.ESetFact, Attr->getAssumption());
268 case Stmt::PseudoObjectExprClass: {
273 if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child))
274 child = OV->getSourceExpr();
276 val.liveExprs = LV.ESetFact.add(val.liveExprs, child);
281 case Stmt::ExprWithCleanupsClass: {
285 case Stmt::CXXBindTemporaryExprClass: {
289 case Stmt::UnaryExprOrTypeTraitExprClass: {
293 case Stmt::IfStmtClass: {
300 case Stmt::WhileStmtClass: {
307 case Stmt::DoStmtClass: {
314 case Stmt::ForStmtClass: {
321 case Stmt::ConditionalOperatorClass: {
338 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getTrueExpr());
339 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getFalseExpr());
342 case Stmt::BinaryOperatorClass: {
344 if (BO->isLogicalOp()) {
355 if (
const auto *E = dyn_cast_or_null<Expr>(Child))
365void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
366 if (LV.killAtAssign && B->
getOpcode() == BO_Assign) {
368 LV.inAssignment.insert(DR);
372 if (!LV.killAtAssign)
378 if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
379 const Decl* D = DR->getDecl();
382 if (
const BindingDecl* BD = dyn_cast<BindingDecl>(D)) {
383 Killed = !BD->getType()->isReferenceType();
385 if (
const auto *HV = BD->getHoldingVar())
386 val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
388 val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
390 }
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
393 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
399void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
400 for (
const VarDecl *VD :
401 LV.analysisContext.getReferencedBlockVars(BE->
getBlockDecl())) {
404 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
408void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
410 bool InAssignment = LV.inAssignment.contains(DR);
411 if (
const auto *BD = dyn_cast<BindingDecl>(D)) {
413 if (
const auto *HV = BD->getHoldingVar())
414 val.liveDecls = LV.DSetFact.add(val.liveDecls, HV);
416 val.liveBindings = LV.BSetFact.add(val.liveBindings, BD);
418 }
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
420 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
424void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
425 for (
const auto *DI : DS->
decls()) {
426 if (
const auto *DD = dyn_cast<DecompositionDecl>(DI)) {
427 for (
const auto *BD : DD->bindings()) {
428 if (
const auto *HV = BD->getHoldingVar())
429 val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
431 val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
436 val.liveDecls = LV.DSetFact.remove(val.liveDecls, DD);
437 }
else if (
const auto *VD = dyn_cast<VarDecl>(DI)) {
439 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
444void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
446 DeclRefExpr *DR =
nullptr;
447 const VarDecl *VD =
nullptr;
449 Stmt *element =
OS->getElement();
450 if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
453 else if ((DR = dyn_cast<DeclRefExpr>(
cast<Expr>(element)->IgnoreParens()))) {
458 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
462void TransferFunctions::
463VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)
474 val.liveExprs = LV.ESetFact.add(val.liveExprs, subEx->
IgnoreParens());
478LiveVariables::LivenessValues
479LiveVariablesImpl::runOnBlock(
const CFGBlock *block,
480 LiveVariables::LivenessValues val,
481 LiveVariables::Observer *obs) {
483 TransferFunctions TF(*
this, val, obs, block);
487 TF.Visit(
const_cast<Stmt*
>(term));
491 ei = block->
rend(); it != ei; ++it) {
492 const CFGElement &elem = *it;
494 if (std::optional<CFGAutomaticObjDtor> Dtor =
495 elem.
getAs<CFGAutomaticObjDtor>()) {
500 if (!elem.
getAs<CFGStmt>())
503 const Stmt *S = elem.
castAs<CFGStmt>().getStmt();
504 TF.Visit(
const_cast<Stmt*
>(S));
505 stmtsToLiveness[S] = val;
513 getImpl(impl).runOnBlock(B,
getImpl(impl).blocksEndToLiveness[B], &obs);
516LiveVariables::LiveVariables(
void *im) : impl(im) {}
519 delete (LiveVariablesImpl*) impl;
522std::unique_ptr<LiveVariables>
535 LiveVariablesImpl *LV =
new LiveVariablesImpl(AC, killAtAssign);
556 val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
561 everAnalyzedBlock[block->
getBlockID()] =
true;
562 else if (prevVal == val)
568 LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
574 return std::unique_ptr<LiveVariables>(
new LiveVariables(LV));
578 getImpl(impl).dumpBlockLiveness(M);
581void LiveVariablesImpl::dumpBlockLiveness(
const SourceManager &M) {
582 std::vector<const CFGBlock *> vec;
583 vec.reserve(blocksEndToLiveness.size());
584 llvm::append_range(vec, llvm::make_first_range(blocksEndToLiveness));
589 std::vector<const VarDecl*> declVec;
592 llvm::errs() <<
"\n[ B" << block->
getBlockID()
593 <<
" (live variables at block exit) ]\n";
595 llvm::append_range(declVec, blocksEndToLiveness[block].liveDecls);
596 llvm::sort(declVec, [](
const Decl *A,
const Decl *B) {
600 for (
const VarDecl *VD : declVec) {
603 llvm::errs() <<
">\n";
606 llvm::errs() <<
"\n";
610 getImpl(impl).dumpExprLiveness(M);
613void LiveVariablesImpl::dumpExprLiveness(
const SourceManager &M) {
614 const ASTContext &Ctx = analysisContext.getASTContext();
615 auto ByIDs = [&Ctx](
const Expr *L,
const Expr *R) {
616 return L->
getID(Ctx) < R->getID(Ctx);
620 for (
const CFGBlock *B : *analysisContext.getCFG()) {
621 llvm::errs() <<
"\n[ B" << B->getBlockID()
622 <<
" (live expressions at block exit) ]\n";
623 std::vector<const Expr *> LiveExprs;
624 llvm::append_range(LiveExprs, blocksEndToLiveness[B].liveExprs);
625 llvm::sort(LiveExprs, ByIDs);
626 for (
const Expr *E : LiveExprs) {
627 llvm::errs() <<
"\n";
630 llvm::errs() <<
"\n";
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static const VariableArrayType * FindVA(const Type *t)
static bool writeShouldKill(const VarDecl *VD)
static void AddLiveExpr(LiveVariables::SetTy< const Expr * > &Set, LiveVariables::SetTy< const Expr * >::Factory &F, const Expr *E)
static LiveVariablesImpl & getImpl(void *x)
static const Expr * LookThroughExpr(const Expr *E)
static void AddAllConditionalTerms(LiveVariables::SetTy< const Expr * > &Set, LiveVariables::SetTy< const Expr * >::Factory &F, const Expr *Cond)
Add as a live expression all individual conditions in a logical expression.
static bool isAlwaysAlive(const VarDecl *D)
Defines the SourceManager interface.
static bool runOnBlock(const CFGBlock *block, const CFG &cfg, AnalysisDeclContext &ac, CFGBlockValues &vals, const ClassifyRefs &classification, llvm::BitVector &wasAnalyzed, UninitVariablesHandler &handler)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
ArrayRef< const Attr * > getAttrs() const
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isAssignmentOp(Opcode Opc)
A binding in a decomposition declaration.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
const BlockDecl * getBlockDecl() const
Represents a single basic block in a source-level CFG.
reverse_iterator rbegin()
ElementList::const_reverse_iterator const_reverse_iterator
Stmt * getTerminatorStmt()
unsigned getBlockID() const
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
llvm::iterator_range< iterator > nodes()
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
void enqueueBlock(const CFGBlock *Block)
const CFGBlock * dequeue()
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
const Decl * getSingleDecl() const
Decl - This represents one declaration (or definition), e.g.
SourceLocation getLocation() const
SourceLocation getBeginLoc() const LLVM_READONLY
std::string getAsString() const
Retrieve the human-readable string for this name.
This represents one expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
FullExpr - Represents a "full-expression" node.
bool operator==(const LivenessValues &V) const
SetTy< const BindingDecl * > liveBindings
SetTy< const Expr * > liveExprs
bool isLive(const Expr *E) const
SetTy< const VarDecl * > liveDecls
llvm::ImmutableSet< T, llvm::ImutContainerInfo< T >, false > SetTy
void dumpExprLiveness(const SourceManager &M)
Print to stderr the expression liveness information associated with each basic block.
void dumpBlockLiveness(const SourceManager &M)
Print to stderr the variable liveness information associated with each basic block.
void runOnAllBlocks(Observer &obs)
~LiveVariables() override
static const void * getTag()
bool isLive(const CFGBlock *B, const VarDecl *D)
Return true if a variable is live at the end of a specified block.
static std::unique_ptr< LiveVariables > computeLiveness(AnalysisDeclContext &analysisContext, bool killAtAssign)
Compute the liveness information for a given CFG.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents Objective-C's collection statement.
@ SuperInstance
The receiver is the instance of the superclass object.
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
static const void * getTag()
void print(raw_ostream &OS, const SourceManager &SM) const
This class handles loading and caching of source files into memory.
void Visit(PTR(Stmt) S, ParamTys... P)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
StmtClass getStmtClass() const
int64_t getID(const ASTContext &Context) const
The base class of the type hierarchy.
bool isReferenceType() const
bool isVariableArrayType() const
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
bool isArgumentType() const
UnaryExprOrTypeTrait getKind() const
Represents a variable declaration or definition.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Represents a C array with a specified size that is not an integer-constant-expression.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
Top level wrappers for InstallAPI frontend operations.
auto getSpecificAttrs(const Container &container)
U cast(CodeGen::Address addr)
A worklist implementation for backward dataflow analysis.
void enqueuePredecessors(const CFGBlock *Block)