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 {
 
   32  AnalysisDeclContext &analysisContext;
 
   33  llvm::ImmutableSet<const Expr *>::Factory ESetFact;
 
   34  llvm::ImmutableSet<const VarDecl *>::Factory DSetFact;
 
   35  llvm::ImmutableSet<const BindingDecl *>::Factory BSetFact;
 
   36  llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
 
   37  llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
 
   38  llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
 
   39  llvm::DenseSet<const DeclRefExpr *> inAssignment;
 
   40  const bool killAtAssign;
 
   42  LiveVariables::LivenessValues
 
   43  merge(LiveVariables::LivenessValues valsA,
 
   44        LiveVariables::LivenessValues valsB);
 
   46  LiveVariables::LivenessValues
 
   47  runOnBlock(
const CFGBlock *block, LiveVariables::LivenessValues val,
 
   48             LiveVariables::Observer *obs = 
nullptr);
 
   50  void dumpBlockLiveness(
const SourceManager& M);
 
   51  void dumpExprLiveness(
const SourceManager& M);
 
   53  LiveVariablesImpl(AnalysisDeclContext &ac, 
bool KillAtAssign)
 
   54      : analysisContext(ac),
 
   57        BSetFact(
false), killAtAssign(KillAtAssign) {}
 
   61static LiveVariablesImpl &
getImpl(
void *x) {
 
   62  return *((LiveVariablesImpl *) x);
 
 
   74  if (
const auto *DD = dyn_cast<DecompositionDecl>(D)) {
 
 
   91  template <
typename SET>
 
   92  SET mergeSets(SET A, SET B) {
 
   96    for (
const auto *Elem : B) {
 
  103void LiveVariables::Observer::anchor() { }
 
  105LiveVariables::LivenessValues
 
  106LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,
 
  107                         LiveVariables::LivenessValues valsB) {
 
  109  llvm::ImmutableSetRef<const Expr *> SSetRefA(
 
  110      valsA.
liveExprs.getRootWithoutRetain(), ESetFact.getTreeFactory()),
 
  111      SSetRefB(valsB.
liveExprs.getRootWithoutRetain(),
 
  112               ESetFact.getTreeFactory());
 
  114  llvm::ImmutableSetRef<const VarDecl *>
 
  115    DSetRefA(valsA.
liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),
 
  116    DSetRefB(valsB.
liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());
 
  118  llvm::ImmutableSetRef<const BindingDecl *>
 
  119    BSetRefA(valsA.
liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory()),
 
  120    BSetRefB(valsB.
liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory());
 
  122  SSetRefA = mergeSets(SSetRefA, SSetRefB);
 
  123  DSetRefA = mergeSets(DSetRefA, DSetRefB);
 
  124  BSetRefA = mergeSets(BSetRefA, BSetRefB);
 
  128  return LiveVariables::LivenessValues(SSetRefA.asImmutableSet(),
 
  129                                       DSetRefA.asImmutableSet(),
 
  130                                       BSetRefA.asImmutableSet());
 
  155  return getImpl(impl).stmtsToLiveness[Loc].isLive(Val);
 
 
  163class TransferFunctions : 
public StmtVisitor<TransferFunctions> {
 
  164  LiveVariablesImpl &LV;
 
  169  TransferFunctions(LiveVariablesImpl &im,
 
  173  : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
 
  187  while (
const ArrayType *VT = dyn_cast<ArrayType>(ty)) {
 
  189      if (VAT->getSizeExpr())
 
  192    ty = VT->getElementType().getTypePtr();
 
 
  200    if (
const Expr *Ex = dyn_cast<Expr>(E))
 
  202    if (
const FullExpr *FE = dyn_cast<FullExpr>(E)) {
 
  203      E = FE->getSubExpr();
 
  207      E = OVE->getSourceExpr();
 
 
  216                        llvm::ImmutableSet<const Expr *>::Factory &F,
 
 
  227                                   llvm::ImmutableSet<const Expr *>::Factory &F,
 
  230  if (
auto const *BO = dyn_cast<BinaryOperator>(
Cond->IgnoreParens());
 
  231      BO && BO->isLogicalOp()) {
 
 
  237void TransferFunctions::Visit(Stmt *S) {
 
  239    observer->observeStmt(S, currentBlock, val);
 
  243  if (
const auto *E = dyn_cast<Expr>(S)) {
 
  244    val.liveExprs = LV.ESetFact.remove(val.liveExprs, E);
 
  252    case Stmt::StmtExprClass: {
 
  257    case Stmt::CXXMemberCallExprClass: {
 
  261        AddLiveExpr(val.liveExprs, LV.ESetFact, ImplicitObj);
 
  265    case Stmt::ObjCMessageExprClass: {
 
  269        val.liveDecls = LV.DSetFact.add(val.liveDecls,
 
  270                                        LV.analysisContext.getSelfDecl());
 
  273    case Stmt::DeclStmtClass: {
 
  275      if (
const VarDecl *VD = dyn_cast<VarDecl>(DS->
getSingleDecl())) {
 
  276        for (
const VariableArrayType* VA = 
FindVA(VD->getType());
 
  277             VA != 
nullptr; VA = 
FindVA(VA->getElementType())) {
 
  278          AddLiveExpr(val.liveExprs, LV.ESetFact, VA->getSizeExpr());
 
  283    case Stmt::PseudoObjectExprClass: {
 
  288      if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child))
 
  289        child = OV->getSourceExpr();
 
  291      val.liveExprs = LV.ESetFact.add(val.liveExprs, child);
 
  296    case Stmt::ExprWithCleanupsClass: {
 
  300    case Stmt::CXXBindTemporaryExprClass: {
 
  304    case Stmt::UnaryExprOrTypeTraitExprClass: {
 
  308    case Stmt::IfStmtClass: {
 
  315    case Stmt::WhileStmtClass: {
 
  322    case Stmt::DoStmtClass: {
 
  329    case Stmt::ForStmtClass: {
 
  336    case Stmt::ConditionalOperatorClass: {
 
  353      AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getTrueExpr());
 
  354      AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getFalseExpr());
 
  363    if (
const auto *E = dyn_cast_or_null<Expr>(Child))
 
  373void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
 
  374  if (LV.killAtAssign && B->
getOpcode() == BO_Assign) {
 
  376      LV.inAssignment.insert(DR);
 
  380    if (!LV.killAtAssign)
 
  386    if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
 
  387      const Decl* D = DR->getDecl();
 
  390      if (
const BindingDecl* BD = dyn_cast<BindingDecl>(D)) {
 
  391        Killed = !BD->getType()->isReferenceType();
 
  393          if (
const auto *HV = BD->getHoldingVar())
 
  394            val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
 
  396          val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
 
  398      } 
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
 
  401          val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
 
  407void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
 
  408  for (
const VarDecl *VD :
 
  409       LV.analysisContext.getReferencedBlockVars(BE->
getBlockDecl())) {
 
  412    val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
 
  416void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
 
  418  bool InAssignment = LV.inAssignment.contains(DR);
 
  419  if (
const auto *BD = dyn_cast<BindingDecl>(D)) {
 
  421      if (
const auto *HV = BD->getHoldingVar())
 
  422        val.liveDecls = LV.DSetFact.add(val.liveDecls, HV);
 
  424      val.liveBindings = LV.BSetFact.add(val.liveBindings, BD);
 
  426  } 
else if (
const auto *VD = dyn_cast<VarDecl>(D)) {
 
  428      val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
 
  432void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
 
  433  for (
const auto *DI : DS->
decls()) {
 
  434    if (
const auto *DD = dyn_cast<DecompositionDecl>(DI)) {
 
  435      for (
const auto *BD : DD->bindings()) {
 
  436        if (
const auto *HV = BD->getHoldingVar())
 
  437          val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
 
  439        val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
 
  444      val.liveDecls = LV.DSetFact.remove(val.liveDecls, DD);
 
  445    } 
else if (
const auto *VD = dyn_cast<VarDecl>(DI)) {
 
  447        val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
 
  452void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
 
  454  DeclRefExpr *DR = 
nullptr;
 
  455  const VarDecl *VD = 
nullptr;
 
  457  Stmt *element = 
OS->getElement();
 
  458  if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
 
  461  else if ((DR = dyn_cast<DeclRefExpr>(
cast<Expr>(element)->IgnoreParens()))) {
 
  466    val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
 
  470void TransferFunctions::
 
  471VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)
 
  482    val.liveExprs = LV.ESetFact.add(val.liveExprs, subEx->
IgnoreParens());
 
  486LiveVariables::LivenessValues
 
  487LiveVariablesImpl::runOnBlock(
const CFGBlock *block,
 
  488                              LiveVariables::LivenessValues val,
 
  489                              LiveVariables::Observer *obs) {
 
  491  TransferFunctions TF(*
this, val, obs, block);
 
  495    TF.Visit(
const_cast<Stmt*
>(term));
 
  499       ei = block->
rend(); it != ei; ++it) {
 
  500    const CFGElement &elem = *it;
 
  502    if (std::optional<CFGAutomaticObjDtor> Dtor =
 
  503            elem.
getAs<CFGAutomaticObjDtor>()) {
 
  508    if (!elem.
getAs<CFGStmt>())
 
  511    const Stmt *S = elem.
castAs<CFGStmt>().getStmt();
 
  512    TF.Visit(
const_cast<Stmt*
>(S));
 
  513    stmtsToLiveness[S] = val;
 
  521    getImpl(impl).runOnBlock(B, 
getImpl(impl).blocksEndToLiveness[B], &obs);
 
 
  524LiveVariables::LiveVariables(
void *im) : impl(im) {}
 
  527  delete (LiveVariablesImpl*) impl;
 
 
  530std::unique_ptr<LiveVariables>
 
  543  LiveVariablesImpl *LV = 
new LiveVariablesImpl(AC, killAtAssign);
 
  564        val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
 
  569      everAnalyzedBlock[block->
getBlockID()] = 
true;
 
  570    else if (prevVal == val)
 
  576    LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
 
  582  return std::unique_ptr<LiveVariables>(
new LiveVariables(LV));
 
 
  586  getImpl(impl).dumpBlockLiveness(M);
 
 
  589void LiveVariablesImpl::dumpBlockLiveness(
const SourceManager &M) {
 
  590  std::vector<const CFGBlock *> vec;
 
  591  vec.reserve(blocksEndToLiveness.size());
 
  592  llvm::append_range(vec, llvm::make_first_range(blocksEndToLiveness));
 
  597  std::vector<const VarDecl*> declVec;
 
  600    llvm::errs() << 
"\n[ B" << block->
getBlockID()
 
  601                 << 
" (live variables at block exit) ]\n";
 
  603    llvm::append_range(declVec, blocksEndToLiveness[block].liveDecls);
 
  604    llvm::sort(declVec, [](
const Decl *A, 
const Decl *B) {
 
  608    for (
const VarDecl *VD : declVec) {
 
  611      llvm::errs() << 
">\n";
 
  614  llvm::errs() << 
"\n";
 
  618  getImpl(impl).dumpExprLiveness(M);
 
 
  621void LiveVariablesImpl::dumpExprLiveness(
const SourceManager &M) {
 
  622  const ASTContext &Ctx = analysisContext.getASTContext();
 
  623  auto ByIDs = [&Ctx](
const Expr *L, 
const Expr *R) {
 
  624    return L->
getID(Ctx) < R->getID(Ctx);
 
  628  for (
const CFGBlock *B : *analysisContext.getCFG()) {
 
  629    llvm::errs() << 
"\n[ B" << B->getBlockID()
 
  630                 << 
" (live expressions at block exit) ]\n";
 
  631    std::vector<const Expr *> LiveExprs;
 
  632    llvm::append_range(LiveExprs, blocksEndToLiveness[B].liveExprs);
 
  633    llvm::sort(LiveExprs, ByIDs);
 
  634    for (
const Expr *E : LiveExprs) {
 
  635      llvm::errs() << 
"\n";
 
  638    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(llvm::ImmutableSet< const Expr * > &Set, llvm::ImmutableSet< const Expr * >::Factory &F, const Expr *E)
static LiveVariablesImpl & getImpl(void *x)
static const Expr * LookThroughExpr(const Expr *E)
static void AddAllConditionalTerms(llvm::ImmutableSet< const Expr * > &Set, llvm::ImmutableSet< 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.
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.
llvm::ImmutableSet< const BindingDecl * > liveBindings
llvm::ImmutableSet< const Expr * > liveExprs
bool operator==(const LivenessValues &V) const
llvm::ImmutableSet< const VarDecl * > liveDecls
bool isLive(const Expr *E) const
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.
The JSON file list parser is used to communicate input to InstallAPI.
U cast(CodeGen::Address addr)
A worklist implementation for backward dataflow analysis.
void enqueuePredecessors(const CFGBlock *Block)