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();
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())) {
520 if (BO->getOpcode() == BO_Assign) {
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;
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;
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) {
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)
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()
bool isArgumentType() const
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()
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.
const TemplateArgument * iterator
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.