20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/PostOrderIterator.h"
22 #include "llvm/Support/raw_ostream.h"
26 using namespace clang;
30 class DataflowWorklist {
32 llvm::BitVector enqueuedBlocks;
36 : enqueuedBlocks(cfg.getNumBlockIDs()),
39 void enqueueBlock(
const CFGBlock *block);
40 void enqueuePredecessors(
const CFGBlock *block);
50 if (block && !enqueuedBlocks[block->
getBlockID()]) {
52 worklist.push_back(block);
56 void DataflowWorklist::enqueuePredecessors(
const clang::CFGBlock *block) {
57 const unsigned OldWorklistSize = worklist.size();
59 E = block->
pred_end(); I != E; ++I) {
63 if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
69 void DataflowWorklist::sortWorklist() {
70 std::sort(worklist.begin(), worklist.end(), POV->getComparator());
73 const CFGBlock *DataflowWorklist::dequeue() {
76 const CFGBlock *b = worklist.pop_back_val();
82 class LiveVariablesImpl {
87 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
88 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
89 llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
90 llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;
91 const bool killAtAssign;
104 : analysisContext(ac),
107 killAtAssign(KillAtAssign) {}
112 return *((LiveVariablesImpl *) x);
124 return liveDecls.contains(D);
128 template <
typename SET>
129 SET mergeSets(SET A, SET B) {
133 for (
typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {
140 void LiveVariables::Observer::anchor() { }
146 llvm::ImmutableSetRef<const Stmt *>
147 SSetRefA(valsA.
liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory()),
148 SSetRefB(valsB.
liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory());
151 llvm::ImmutableSetRef<const VarDecl *>
152 DSetRefA(valsA.
liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),
153 DSetRefB(valsB.
liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());
156 SSetRefA = mergeSets(SSetRefA, SSetRefB);
157 DSetRefA = mergeSets(DSetRefA, DSetRefB);
162 DSetRefA.asImmutableSet());
186 return getImpl(impl).stmtsToLiveness[Loc].isLive(S);
194 class TransferFunctions :
public StmtVisitor<TransferFunctions> {
195 LiveVariablesImpl &LV;
200 TransferFunctions(LiveVariablesImpl &im,
204 : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
219 while (
const ArrayType *VT = dyn_cast<ArrayType>(ty)) {
221 if (VAT->getSizeExpr())
224 ty = VT->getElementType().getTypePtr();
232 if (
const Expr *Ex = dyn_cast<Expr>(S))
233 S = Ex->IgnoreParens();
235 S = EWC->getSubExpr();
239 S = OVE->getSourceExpr();
253 void TransferFunctions::Visit(
Stmt *
S) {
255 observer->observeStmt(S, currentBlock, val);
260 val.liveStmts = LV.SSetFact.remove(val.liveStmts, S);
265 switch (S->getStmtClass()) {
268 case Stmt::StmtExprClass: {
270 S = cast<StmtExpr>(
S)->getSubStmt();
273 case Stmt::CXXMemberCallExprClass: {
277 AddLiveStmt(val.liveStmts, LV.SSetFact, ImplicitObj);
281 case Stmt::ObjCMessageExprClass: {
285 val.liveDecls = LV.DSetFact.add(val.liveDecls,
286 LV.analysisContext.getSelfDecl());
289 case Stmt::DeclStmtClass: {
293 VA !=
nullptr; VA =
FindVA(VA->getElementType())) {
294 AddLiveStmt(val.liveStmts, LV.SSetFact, VA->getSizeExpr());
299 case Stmt::PseudoObjectExprClass: {
302 Expr *child = cast<PseudoObjectExpr>(
S)->getResultExpr();
305 child = OV->getSourceExpr();
307 val.liveStmts = LV.SSetFact.add(val.liveStmts, child);
312 case Stmt::ExprWithCleanupsClass: {
313 S = cast<ExprWithCleanups>(
S)->getSubExpr();
316 case Stmt::CXXBindTemporaryExprClass: {
317 S = cast<CXXBindTemporaryExpr>(
S)->getSubExpr();
320 case Stmt::UnaryExprOrTypeTraitExprClass: {
326 for (
Stmt *Child : S->children()) {
334 if (!LV.killAtAssign)
341 if (
const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
343 if (VD->getType()->isReferenceType())
348 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
352 observer->observerKill(DR);
357 void TransferFunctions::VisitBlockExpr(
BlockExpr *BE) {
359 LV.analysisContext.getReferencedBlockVars(BE->
getBlockDecl())) {
362 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
366 void TransferFunctions::VisitDeclRefExpr(
DeclRefExpr *DR) {
368 if (!
isAlwaysAlive(D) && LV.inAssignment.find(DR) == LV.inAssignment.end())
369 val.liveDecls = LV.DSetFact.add(val.liveDecls, D);
372 void TransferFunctions::VisitDeclStmt(
DeclStmt *DS) {
373 for (
const auto *DI : DS->
decls())
374 if (
const auto *VD = dyn_cast<VarDecl>(DI)) {
376 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
386 if (
DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
389 else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
390 VD = cast<VarDecl>(DR->
getDecl());
394 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
396 observer->observerKill(DR);
400 void TransferFunctions::
412 val.liveStmts = LV.SSetFact.add(val.liveStmts, subEx->
IgnoreParens());
416 void TransferFunctions::VisitUnaryOperator(
UnaryOperator *UO) {
434 if (isa<VarDecl>(DR->
getDecl())) {
436 observer->observerKill(DR);
445 TransferFunctions TF(*
this, val, obs, block);
449 TF.Visit(const_cast<Stmt*>(term));
453 ei = block->
rend(); it != ei; ++it) {
466 TF.Visit(const_cast<Stmt*>(S));
467 stmtsToLiveness[
S] = val;
473 const CFG *cfg =
getImpl(impl).analysisContext.getCFG();
475 getImpl(impl).runOnBlock(*it,
getImpl(impl).blocksEndToLiveness[*it], &obs);
478 LiveVariables::LiveVariables(
void *im) : impl(im) {}
481 delete (LiveVariablesImpl*) impl;
498 LiveVariablesImpl *LV =
new LiveVariablesImpl(AC, killAtAssign);
502 DataflowWorklist worklist(*cfg, AC);
508 worklist.enqueueBlock(block);
519 dyn_cast<BinaryOperator>(cs->getStmt())) {
522 dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens())) {
523 LV->inAssignment[DR] = 1;
531 worklist.sortWorklist();
533 while (
const CFGBlock *block = worklist.dequeue()) {
541 ei = block->
succ_end(); it != ei; ++it) {
543 val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
548 everAnalyzedBlock[block->
getBlockID()] =
true;
549 else if (prevVal.
equals(val))
555 LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
558 worklist.enqueuePredecessors(block);
565 getImpl(impl).dumpBlockLiveness(M);
568 void LiveVariablesImpl::dumpBlockLiveness(
const SourceManager &M) {
569 std::vector<const CFGBlock *> vec;
570 for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator
571 it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();
573 vec.push_back(it->first);
575 std::sort(vec.begin(), vec.end(), [](
const CFGBlock *A,
const CFGBlock *B) {
579 std::vector<const VarDecl*> declVec;
581 for (std::vector<const CFGBlock *>::iterator
582 it = vec.begin(), ei = vec.end(); it != ei; ++it) {
583 llvm::errs() <<
"\n[ B" << (*it)->getBlockID()
584 <<
" (live variables at block exit) ]\n";
591 se = vals.
liveDecls.end(); si != se; ++si) {
592 declVec.push_back(*si);
595 std::sort(declVec.begin(), declVec.end(), [](
const Decl *A,
const Decl *B) {
599 for (std::vector<const VarDecl*>::iterator di = declVec.begin(),
600 de = declVec.end(); di != de; ++di) {
601 llvm::errs() <<
" " << (*di)->getDeclName().getAsString()
603 (*di)->getLocation().dump(M);
604 llvm::errs() <<
">\n";
607 llvm::errs() <<
"\n";
The receiver is the instance of the superclass object.
static const VariableArrayType * FindVA(QualType Ty)
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()
bool isArgumentType() const
static const void * getTag()
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
UnaryExprOrTypeTrait getKind() const
static bool isAssignmentOp(Opcode Opc)
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)
ElementList::const_iterator const_iterator
A builtin binary operation expression such as "x + y" or "x <= y".
~LiveVariables() override
static const void * getTag()
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.
static LiveVariablesImpl & getImpl(void *x)
reverse_iterator rbegin()
SourceLocation getLocStart() const LLVM_READONLY
CFGTerminator getTerminator()
void dumpBlockLiveness(const SourceManager &M)
const Type * getTypePtr() const
SourceLocation getLocStart() const LLVM_READONLY
llvm::ImmutableSet< const VarDecl * > liveDecls
const BlockDecl * getBlockDecl() const
AdjacentBlocks::const_iterator const_succ_iterator
const Decl * getSingleDecl() const
pred_iterator pred_begin()
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. [C99 6.5.1p2].
bool equals(const LivenessValues &V) const
unsigned getNumBlockIDs() const
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