clang: lib/Analysis/LiveVariables.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
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"
24#include
25#include
26
27using namespace clang;
28
29namespace {
30class LiveVariablesImpl {
31public:
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;
41
42 LiveVariables::LivenessValues
43 merge(LiveVariables::LivenessValues valsA,
44 LiveVariables::LivenessValues valsB);
45
46 LiveVariables::LivenessValues
47 runOnBlock(const CFGBlock *block, LiveVariables::LivenessValues val,
48 LiveVariables::Observer *obs = nullptr);
49
50 void dumpBlockLiveness(const SourceManager& M);
51 void dumpExprLiveness(const SourceManager& M);
52
53 LiveVariablesImpl(AnalysisDeclContext &ac, bool KillAtAssign)
54 : analysisContext(ac),
55 ESetFact(false),
56 DSetFact(false),
57 BSetFact(false), killAtAssign(KillAtAssign) {}
58};
59}
60
61static LiveVariablesImpl &getImpl(void *x) {
62 return *((LiveVariablesImpl *) x);
63}
64
65
66
67
68
72
74 if (const auto *DD = dyn_cast(D)) {
75
76
77
79 return true;
80
81 for (const BindingDecl *BD : DD->bindings()) {
83 return true;
84 }
85 return false;
86 }
88}
89
90namespace {
91 template
92 SET mergeSets(SET A, SET B) {
93 if (A.isEmpty())
94 return B;
95
96 for (const auto *Elem : B) {
97 A = A.add(Elem);
98 }
99 return A;
100 }
101}
102
103void LiveVariables::Observer::anchor() { }
104
105LiveVariables::LivenessValues
106LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,
107 LiveVariables::LivenessValues valsB) {
108
109 llvm::ImmutableSetRef<const Expr *> SSetRefA(
110 valsA.liveExprs.getRootWithoutRetain(), ESetFact.getTreeFactory()),
111 SSetRefB(valsB.liveExprs.getRootWithoutRetain(),
112 ESetFact.getTreeFactory());
113
114 llvm::ImmutableSetRef<const VarDecl *>
115 DSetRefA(valsA.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),
116 DSetRefB(valsB.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());
117
118 llvm::ImmutableSetRef<const BindingDecl *>
119 BSetRefA(valsA.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory()),
120 BSetRefB(valsB.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory());
121
122 SSetRefA = mergeSets(SSetRefA, SSetRefB);
123 DSetRefA = mergeSets(DSetRefA, DSetRefB);
124 BSetRefA = mergeSets(BSetRefA, BSetRefB);
125
126
127
128 return LiveVariables::LivenessValues(SSetRefA.asImmutableSet(),
129 DSetRefA.asImmutableSet(),
130 BSetRefA.asImmutableSet());
131}
132
137
138
139
140
141
145
149
153
155 return getImpl(impl).stmtsToLiveness[Loc].isLive(Val);
156}
157
158
159
160
161
162namespace {
163class TransferFunctions : public StmtVisitor {
164 LiveVariablesImpl &LV;
167 const CFGBlock *currentBlock;
168public:
169 TransferFunctions(LiveVariablesImpl &im,
172 const CFGBlock *CurrentBlock)
173 : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
174
176 void VisitBlockExpr(BlockExpr *BE);
178 void VisitDeclStmt(DeclStmt *DS);
181 void Visit(Stmt *S);
182};
183}
184
187 while (const ArrayType *VT = dyn_cast(ty)) {
188 if (const VariableArrayType *VAT = dyn_cast(VT))
189 if (VAT->getSizeExpr())
190 return VAT;
191
192 ty = VT->getElementType().getTypePtr();
193 }
194
195 return nullptr;
196}
197
199 while (E) {
200 if (const Expr *Ex = dyn_cast(E))
202 if (const FullExpr *FE = dyn_cast(E)) {
203 E = FE->getSubExpr();
204 continue;
205 }
206 if (const OpaqueValueExpr *OVE = dyn_cast(E)) {
207 E = OVE->getSourceExpr();
208 continue;
209 }
210 break;
211 }
212 return E;
213}
214
216 llvm::ImmutableSet<const Expr *>::Factory &F,
217 const Expr *E) {
219}
220
221
222
223
224
225
227 llvm::ImmutableSet<const Expr *>::Factory &F,
230 if (auto const *BO = dyn_cast(Cond->IgnoreParens());
231 BO && BO->isLogicalOp()) {
234 }
235}
236
237void TransferFunctions::Visit(Stmt *S) {
238 if (observer)
239 observer->observeStmt(S, currentBlock, val);
240
242
243 if (const auto *E = dyn_cast(S)) {
244 val.liveExprs = LV.ESetFact.remove(val.liveExprs, E);
245 }
246
247
248
250 default:
251 break;
252 case Stmt::StmtExprClass: {
253
255 break;
256 }
257 case Stmt::CXXMemberCallExprClass: {
258
261 AddLiveExpr(val.liveExprs, LV.ESetFact, ImplicitObj);
262 }
263 break;
264 }
265 case Stmt::ObjCMessageExprClass: {
266
269 val.liveDecls = LV.DSetFact.add(val.liveDecls,
270 LV.analysisContext.getSelfDecl());
271 break;
272 }
273 case Stmt::DeclStmtClass: {
275 if (const VarDecl *VD = dyn_cast(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());
279 }
280 }
281 break;
282 }
283 case Stmt::PseudoObjectExprClass: {
284
285
287 if (!child) return;
288 if (OpaqueValueExpr *OV = dyn_cast(child))
289 child = OV->getSourceExpr();
291 val.liveExprs = LV.ESetFact.add(val.liveExprs, child);
292 return;
293 }
294
295
296 case Stmt::ExprWithCleanupsClass: {
298 break;
299 }
300 case Stmt::CXXBindTemporaryExprClass: {
302 break;
303 }
304 case Stmt::UnaryExprOrTypeTraitExprClass: {
305
306 return;
307 }
308 case Stmt::IfStmtClass: {
309
310
311
313 return;
314 }
315 case Stmt::WhileStmtClass: {
316
317
318
320 return;
321 }
322 case Stmt::DoStmtClass: {
323
324
325
327 return;
328 }
329 case Stmt::ForStmtClass: {
330
331
332
334 return;
335 }
336 case Stmt::ConditionalOperatorClass: {
337
338
339
340
341
342
343
344
345
346
347
348
349
350
353 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getTrueExpr());
354 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getFalseExpr());
355 return;
356 }
357 }
358
359
360
361
362 for (Stmt *Child : S->children()) {
363 if (const auto *E = dyn_cast_or_null(Child))
364 AddLiveExpr(val.liveExprs, LV.ESetFact, E);
365 }
366}
367
372
373void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
374 if (LV.killAtAssign && B->getOpcode() == BO_Assign) {
375 if (const auto *DR = dyn_cast(B->getLHS()->IgnoreParens())) {
376 LV.inAssignment.insert(DR);
377 }
378 }
380 if (!LV.killAtAssign)
381 return;
382
383
385
386 if (DeclRefExpr *DR = dyn_cast(LHS)) {
387 const Decl* D = DR->getDecl();
388 bool Killed = false;
389
390 if (const BindingDecl* BD = dyn_cast(D)) {
391 Killed = !BD->getType()->isReferenceType();
392 if (Killed) {
393 if (const auto *HV = BD->getHoldingVar())
394 val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
395
396 val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
397 }
398 } else if (const auto *VD = dyn_cast(D)) {
400 if (Killed)
401 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
402 }
403 }
404 }
405}
406
407void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
408 for (const VarDecl *VD :
409 LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl())) {
411 continue;
412 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
413 }
414}
415
416void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
418 bool InAssignment = LV.inAssignment.contains(DR);
419 if (const auto *BD = dyn_cast(D)) {
420 if (!InAssignment) {
421 if (const auto *HV = BD->getHoldingVar())
422 val.liveDecls = LV.DSetFact.add(val.liveDecls, HV);
423
424 val.liveBindings = LV.BSetFact.add(val.liveBindings, BD);
425 }
426 } else if (const auto *VD = dyn_cast(D)) {
428 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
429 }
430}
431
432void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
433 for (const auto *DI : DS->decls()) {
434 if (const auto *DD = dyn_cast(DI)) {
435 for (const auto *BD : DD->bindings()) {
436 if (const auto *HV = BD->getHoldingVar())
437 val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
438
439 val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
440 }
441
442
443
444 val.liveDecls = LV.DSetFact.remove(val.liveDecls, DD);
445 } else if (const auto *VD = dyn_cast(DI)) {
447 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
448 }
449 }
450}
451
452void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
453
454 DeclRefExpr *DR = nullptr;
455 const VarDecl *VD = nullptr;
456
457 Stmt *element = OS->getElement();
458 if (DeclStmt *DS = dyn_cast(element)) {
460 }
461 else if ((DR = dyn_cast(cast(element)->IgnoreParens()))) {
463 }
464
465 if (VD) {
466 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
467 }
468}
469
470void TransferFunctions::
471VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)
472{
473
474
475
477 return;
478
482 val.liveExprs = LV.ESetFact.add(val.liveExprs, subEx->IgnoreParens());
483 }
484}
485
486LiveVariables::LivenessValues
487LiveVariablesImpl::runOnBlock(const CFGBlock *block,
488 LiveVariables::LivenessValues val,
489 LiveVariables::Observer *obs) {
490
491 TransferFunctions TF(*this, val, obs, block);
492
493
495 TF.Visit(const_cast<Stmt*>(term));
496
497
499 ei = block->rend(); it != ei; ++it) {
500 const CFGElement &elem = *it;
501
502 if (std::optional Dtor =
503 elem.getAs()) {
505 continue;
506 }
507
508 if (!elem.getAs())
509 continue;
510
511 const Stmt *S = elem.castAs().getStmt();
512 TF.Visit(const_cast<Stmt*>(S));
513 stmtsToLiveness[S] = val;
514 }
515 return val;
516}
517
521 getImpl(impl).runOnBlock(B, getImpl(impl).blocksEndToLiveness[B], &obs);
522}
523
524LiveVariables::LiveVariables(void *im) : impl(im) {}
525
527 delete (LiveVariablesImpl*) impl;
528}
529
530std::unique_ptr
532
533
535 if (!cfg)
536 return nullptr;
537
538
539
541 return nullptr;
542
543 LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign);
544
545
546
548 llvm::BitVector everAnalyzedBlock(cfg->getNumBlockIDs());
549
550
553 }
554
556
557
558 LivenessValues &prevVal = LV->blocksEndToLiveness[block];
559
560
563 if (succ) {
564 val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
565 }
566 }
567
568 if (!everAnalyzedBlock[block->getBlockID()])
569 everAnalyzedBlock[block->getBlockID()] = true;
570 else if (prevVal == val)
571 continue;
572
573 prevVal = val;
574
575
576 LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
577
578
580 }
581
582 return std::unique_ptr(new LiveVariables(LV));
583}
584
586 getImpl(impl).dumpBlockLiveness(M);
587}
588
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));
595 });
596
597 std::vector<const VarDecl*> declVec;
598
599 for (const CFGBlock *block : vec) {
600 llvm::errs() << "\n[ B" << block->getBlockID()
601 << " (live variables at block exit) ]\n";
602 declVec.clear();
603 llvm::append_range(declVec, blocksEndToLiveness[block].liveDecls);
604 llvm::sort(declVec, [](const Decl *A, const Decl *B) {
606 });
607
608 for (const VarDecl *VD : declVec) {
611 llvm::errs() << ">\n";
612 }
613 }
614 llvm::errs() << "\n";
615}
616
618 getImpl(impl).dumpExprLiveness(M);
619}
620
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);
625 };
626
627
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";
636 E->dump();
637 }
638 llvm::errs() << "\n";
639 }
640}
641
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)
Definition LiveVariables.cpp:368
static void AddLiveExpr(llvm::ImmutableSet< const Expr * > &Set, llvm::ImmutableSet< const Expr * >::Factory &F, const Expr *E)
Definition LiveVariables.cpp:215
static LiveVariablesImpl & getImpl(void *x)
Definition LiveVariables.cpp:61
static const Expr * LookThroughExpr(const Expr *E)
Definition LiveVariables.cpp:198
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.
Definition LiveVariables.cpp:226
static bool isAlwaysAlive(const VarDecl *D)
Definition LiveVariables.cpp:142
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
Definition LiveVariables.cpp:133
llvm::ImmutableSet< const VarDecl * > liveDecls
bool isLive(const Expr *E) const
Definition LiveVariables.cpp:69
void dumpExprLiveness(const SourceManager &M)
Print to stderr the expression liveness information associated with each basic block.
Definition LiveVariables.cpp:617
void dumpBlockLiveness(const SourceManager &M)
Print to stderr the variable liveness information associated with each basic block.
Definition LiveVariables.cpp:585
void runOnAllBlocks(Observer &obs)
Definition LiveVariables.cpp:518
~LiveVariables() override
Definition LiveVariables.cpp:526
static const void * getTag()
Definition LiveVariables.cpp:642
bool isLive(const CFGBlock *B, const VarDecl *D)
Return true if a variable is live at the end of a specified block.
Definition LiveVariables.cpp:146
static std::unique_ptr< LiveVariables > computeLiveness(AnalysisDeclContext &analysisContext, bool killAtAssign)
Compute the liveness information for a given CFG.
Definition LiveVariables.cpp:531
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()
Definition LiveVariables.cpp:643
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.
RangeSelector merge(RangeSelector First, RangeSelector Second)
Selects the merge of the two ranges, i.e.
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)