20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/PostOrderIterator.h"
22 #include "llvm/ADT/PriorityQueue.h"
23 #include "llvm/Support/raw_ostream.h"
27 using namespace clang;
31 class DataflowWorklist {
32 llvm::BitVector enqueuedBlocks;
34 llvm::PriorityQueue<const CFGBlock *, SmallVector<const CFGBlock *, 20>,
39 : enqueuedBlocks(cfg.getNumBlockIDs()),
41 worklist(POV->getComparator()) {}
43 void enqueueBlock(
const CFGBlock *block);
44 void enqueuePredecessors(
const CFGBlock *block);
52 if (block && !enqueuedBlocks[block->
getBlockID()]) {
58 void DataflowWorklist::enqueuePredecessors(
const clang::CFGBlock *block) {
65 const CFGBlock *DataflowWorklist::dequeue() {
75 class LiveVariablesImpl {
80 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
81 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
82 llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
83 llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;
84 const bool killAtAssign;
97 : analysisContext(ac),
100 killAtAssign(KillAtAssign) {}
105 return *((LiveVariablesImpl *) x);
117 return liveDecls.contains(D);
121 template <
typename SET>
122 SET mergeSets(SET A, SET B) {
126 for (
typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {
133 void LiveVariables::Observer::anchor() { }
139 llvm::ImmutableSetRef<const Stmt *>
140 SSetRefA(valsA.
liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory()),
141 SSetRefB(valsB.
liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory());
144 llvm::ImmutableSetRef<const VarDecl *>
145 DSetRefA(valsA.
liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),
146 DSetRefB(valsB.
liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());
149 SSetRefA = mergeSets(SSetRefA, SSetRefB);
150 DSetRefA = mergeSets(DSetRefA, DSetRefB);
155 DSetRefA.asImmutableSet());
179 return getImpl(impl).stmtsToLiveness[Loc].isLive(S);
187 class TransferFunctions :
public StmtVisitor<TransferFunctions> {
188 LiveVariablesImpl &LV;
193 TransferFunctions(LiveVariablesImpl &im,
197 : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
212 while (
const ArrayType *VT = dyn_cast<ArrayType>(ty)) {
214 if (VAT->getSizeExpr())
217 ty = VT->getElementType().getTypePtr();
225 if (
const Expr *Ex = dyn_cast<Expr>(S))
226 S = Ex->IgnoreParens();
228 S = EWC->getSubExpr();
232 S = OVE->getSourceExpr();
246 void TransferFunctions::Visit(
Stmt *
S) {
248 observer->observeStmt(S, currentBlock, val);
253 val.liveStmts = LV.SSetFact.remove(val.liveStmts, S);
261 case Stmt::StmtExprClass: {
263 S = cast<StmtExpr>(
S)->getSubStmt();
266 case Stmt::CXXMemberCallExprClass: {
270 AddLiveStmt(val.liveStmts, LV.SSetFact, ImplicitObj);
274 case Stmt::ObjCMessageExprClass: {
278 val.liveDecls = LV.DSetFact.add(val.liveDecls,
279 LV.analysisContext.getSelfDecl());
282 case Stmt::DeclStmtClass: {
286 VA !=
nullptr; VA =
FindVA(VA->getElementType())) {
287 AddLiveStmt(val.liveStmts, LV.SSetFact, VA->getSizeExpr());
292 case Stmt::PseudoObjectExprClass: {
295 Expr *child = cast<PseudoObjectExpr>(
S)->getResultExpr();
298 child = OV->getSourceExpr();
300 val.liveStmts = LV.SSetFact.add(val.liveStmts, child);
305 case Stmt::ExprWithCleanupsClass: {
306 S = cast<ExprWithCleanups>(
S)->getSubExpr();
309 case Stmt::CXXBindTemporaryExprClass: {
310 S = cast<CXXBindTemporaryExpr>(
S)->getSubExpr();
313 case Stmt::UnaryExprOrTypeTraitExprClass: {
327 if (!LV.killAtAssign)
334 if (
const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
336 if (VD->getType()->isReferenceType())
341 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
345 observer->observerKill(DR);
350 void TransferFunctions::VisitBlockExpr(
BlockExpr *BE) {
352 LV.analysisContext.getReferencedBlockVars(BE->
getBlockDecl())) {
355 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
359 void TransferFunctions::VisitDeclRefExpr(
DeclRefExpr *DR) {
361 if (!
isAlwaysAlive(D) && LV.inAssignment.find(DR) == LV.inAssignment.end())
362 val.liveDecls = LV.DSetFact.add(val.liveDecls, D);
365 void TransferFunctions::VisitDeclStmt(
DeclStmt *DS) {
366 for (
const auto *DI : DS->
decls())
367 if (
const auto *VD = dyn_cast<VarDecl>(DI)) {
369 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
379 if (
DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
382 else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
383 VD = cast<VarDecl>(DR->
getDecl());
387 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
389 observer->observerKill(DR);
393 void TransferFunctions::
405 val.liveStmts = LV.SSetFact.add(val.liveStmts, subEx->
IgnoreParens());
409 void TransferFunctions::VisitUnaryOperator(
UnaryOperator *UO) {
427 if (isa<VarDecl>(DR->
getDecl())) {
429 observer->observerKill(DR);
438 TransferFunctions TF(*
this, val, obs, block);
442 TF.Visit(const_cast<Stmt*>(term));
446 ei = block->
rend(); it != ei; ++it) {
459 TF.Visit(const_cast<Stmt*>(S));
460 stmtsToLiveness[
S] = val;
466 const CFG *cfg =
getImpl(impl).analysisContext.getCFG();
468 getImpl(impl).runOnBlock(*it,
getImpl(impl).blocksEndToLiveness[*it], &obs);
471 LiveVariables::LiveVariables(
void *im) : impl(im) {}
474 delete (LiveVariablesImpl*) impl;
491 LiveVariablesImpl *LV =
new LiveVariablesImpl(AC, killAtAssign);
495 DataflowWorklist worklist(*cfg, AC);
501 worklist.enqueueBlock(block);
512 dyn_cast<BinaryOperator>(cs->getStmt())) {
513 if (BO->getOpcode() == BO_Assign) {
515 dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens())) {
516 LV->inAssignment[DR] = 1;
524 while (
const CFGBlock *block = worklist.dequeue()) {
532 ei = block->
succ_end(); it != ei; ++it) {
534 val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
539 everAnalyzedBlock[block->
getBlockID()] =
true;
540 else if (prevVal.
equals(val))
546 LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
549 worklist.enqueuePredecessors(block);
556 getImpl(impl).dumpBlockLiveness(M);
559 void LiveVariablesImpl::dumpBlockLiveness(
const SourceManager &M) {
560 std::vector<const CFGBlock *> vec;
561 for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator
562 it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();
564 vec.push_back(it->first);
566 std::sort(vec.begin(), vec.end(), [](
const CFGBlock *A,
const CFGBlock *B) {
570 std::vector<const VarDecl*> declVec;
572 for (std::vector<const CFGBlock *>::iterator
573 it = vec.begin(), ei = vec.end(); it != ei; ++it) {
574 llvm::errs() <<
"\n[ B" << (*it)->getBlockID()
575 <<
" (live variables at block exit) ]\n";
582 se = vals.
liveDecls.end(); si != se; ++si) {
583 declVec.push_back(*si);
586 std::sort(declVec.begin(), declVec.end(), [](
const Decl *A,
const Decl *B) {
590 for (std::vector<const VarDecl*>::iterator di = declVec.begin(),
591 de = declVec.end(); di != de; ++di) {
592 llvm::errs() <<
" " << (*di)->getDeclName().getAsString()
594 (*di)->getLocation().dump(M);
595 llvm::errs() <<
">\n";
598 llvm::errs() <<
"\n";
The receiver is the instance of the superclass object.
StmtClass getStmtClass() const
static const VariableArrayType * FindVA(QualType Ty)
A (possibly-)qualified type.
static bool isAlwaysAlive(const VarDecl *D)
static const Stmt * LookThroughStmt(const Stmt *S)
static LiveVariables * computeLiveness(AnalysisDeclContext &analysisContext, bool killAtAssign)
Compute the liveness information for a given CFG.
succ_iterator succ_begin()
Stmt - This represents one statement.
bool isArgumentType() const
Decl - This represents one declaration (or definition), e.g.
The base class of the type hierarchy.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
static const void * getTag()
VarDecl - An instance of this class is created to represent a variable declaration or definition...
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
UnaryExprOrTypeTrait getKind() const
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
static bool isAssignmentOp(Opcode Opc)
AnalysisDeclContext contains the context data for the function or method under analysis.
CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated for automatic object or t...
Expr * getImplicitObjectArgument() const
Retrieves the implicit object argument for the member call.
void runOnAllBlocks(Observer &obs)
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type...
static bool runOnBlock(const CFGBlock *block, const CFG &cfg, AnalysisDeclContext &ac, CFGBlockValues &vals, const ClassifyRefs &classification, llvm::BitVector &wasAnalyzed, UninitVariablesHandler &handler)
bool isLive(const CFGBlock *B, const VarDecl *D)
Return true if a variable is live at the end of a specified block.
ElementList::const_iterator const_iterator
A builtin binary operation expression such as "x + y" or "x <= y".
detail::InMemoryDirectory::const_iterator I
~LiveVariables() override
static const void * getTag()
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand...
CFGBlock - Represents a single basic block in a source-level CFG.
Expr - This represents one expression.
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
bool isVariableArrayType() const
AdjacentBlocks::const_iterator const_pred_iterator
Expr * getSubExpr() const
unsigned getBlockID() const
An expression that sends a message to the given Objective-C object or class.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
static LiveVariablesImpl & getImpl(void *x)
reverse_iterator rbegin()
SourceLocation getLocStart() const LLVM_READONLY
CFGTerminator getTerminator()
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
void dumpBlockLiveness(const SourceManager &M)
Print to stderr the liveness information associated with each basic block.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
SourceLocation getLocStart() const LLVM_READONLY
Represents a call to a member function that may be written either with member call syntax (e...
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
llvm::ImmutableSet< const VarDecl * > liveDecls
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
const BlockDecl * getBlockDecl() const
AdjacentBlocks::const_iterator const_succ_iterator
const Decl * getSingleDecl() const
pred_iterator pred_begin()
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language...
detail::InMemoryDirectory::const_iterator E
llvm::ImmutableSet< const Stmt * > liveStmts
Represents Objective-C's collection statement.
bool isLive(const Stmt *S) const
static void AddLiveStmt(llvm::ImmutableSet< const Stmt * > &Set, llvm::ImmutableSet< const Stmt * >::Factory &F, const Stmt *S)
CFGElement - Represents a top-level expression in a basic block.
A reference to a declared variable, function, enum, etc.
bool equals(const LivenessValues &V) const
Represents a C array with a specified size that is not an integer-constant-expression.
unsigned getNumBlockIDs() const
getNumBlockIDs - Returns the total number of BlockIDs allocated (which start at 0).
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
This class handles loading and caching of source files into memory.
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
Expr * IgnoreParens() LLVM_READONLY
IgnoreParens - Ignore parentheses.