clang 23.0.0git
LiveVariables.cpp
Go to the documentation of this file.
1//=- LiveVariables.cpp - Live Variable Analysis for Source CFGs ----------*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements Live Variables analysis for source-level CFGs.
10//
11//===----------------------------------------------------------------------===//
12
14#include "clang/AST/Stmt.h"
17#include "clang/Analysis/CFG.h"
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 <optional>
25#include <vector>
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), // Do not canonicalize ImmutableSets by default.
56 DSetFact(false), // This is a *major* performance win.
57 BSetFact(false), killAtAssign(KillAtAssign) {}
58};
59} // namespace
60
61static LiveVariablesImpl &getImpl(void *x) {
62 return *((LiveVariablesImpl *) x);
63}
64
65//===----------------------------------------------------------------------===//
66// Operations and queries on LivenessValues.
67//===----------------------------------------------------------------------===//
68
70 return liveExprs.contains(E);
71}
72
74 if (const auto *DD = dyn_cast<DecompositionDecl>(D)) {
75 // Note: the only known case this condition is necessary, is when a bindig
76 // to a tuple-like structure is created. The HoldingVar initializers have a
77 // DeclRefExpr to the DecompositionDecl.
78 if (liveDecls.contains(DD))
79 return true;
80
81 for (const BindingDecl *BD : DD->bindings()) {
82 if (liveBindings.contains(BD))
83 return true;
84 }
85 return false;
86 }
87 return liveDecls.contains(D);
88}
89
90namespace {
91 template <typename SET>
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} // namespace
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 // asImmutableSet() canonicalizes the tree, allowing us to do an easy
127 // comparison afterwards.
128 return LiveVariables::LivenessValues(SSetRefA.asImmutableSet(),
129 DSetRefA.asImmutableSet(),
130 BSetRefA.asImmutableSet());
131}
132
134 return liveExprs == V.liveExprs && liveDecls == V.liveDecls &&
135 liveBindings == V.liveBindings;
136}
137
138//===----------------------------------------------------------------------===//
139// Query methods.
140//===----------------------------------------------------------------------===//
141
142static bool isAlwaysAlive(const VarDecl *D) {
143 return D->hasGlobalStorage();
144}
145
146bool LiveVariables::isLive(const CFGBlock *B, const VarDecl *D) {
147 return isAlwaysAlive(D) || getImpl(impl).blocksEndToLiveness[B].isLive(D);
148}
149
150bool LiveVariables::isLive(const Stmt *S, const VarDecl *D) {
151 return isAlwaysAlive(D) || getImpl(impl).stmtsToLiveness[S].isLive(D);
152}
153
154bool LiveVariables::isLive(const Stmt *Loc, const Expr *Val) {
155 return getImpl(impl).stmtsToLiveness[Loc].isLive(Val);
156}
157
158//===----------------------------------------------------------------------===//
159// Dataflow computation.
160//===----------------------------------------------------------------------===//
161
162namespace {
163class TransferFunctions : public StmtVisitor<TransferFunctions> {
164 LiveVariablesImpl &LV;
166 LiveVariables::Observer *observer;
167 const CFGBlock *currentBlock;
168public:
169 TransferFunctions(LiveVariablesImpl &im,
171 LiveVariables::Observer *Observer,
172 const CFGBlock *CurrentBlock)
173 : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
174
175 void VisitBinaryOperator(BinaryOperator *BO);
176 void VisitBlockExpr(BlockExpr *BE);
177 void VisitDeclRefExpr(DeclRefExpr *DR);
178 void VisitDeclStmt(DeclStmt *DS);
179 void VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS);
180 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE);
181 void Visit(Stmt *S);
182};
183} // namespace
184
186 const Type *ty = Ty.getTypePtr();
187 while (const ArrayType *VT = dyn_cast<ArrayType>(ty)) {
188 if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(VT))
189 if (VAT->getSizeExpr())
190 return VAT;
191
192 ty = VT->getElementType().getTypePtr();
193 }
194
195 return nullptr;
196}
197
198static const Expr *LookThroughExpr(const Expr *E) {
199 while (E) {
200 E = E->IgnoreParens();
201 if (const FullExpr *FE = dyn_cast<FullExpr>(E)) {
202 E = FE->getSubExpr();
203 continue;
204 }
205 if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
206 E = OVE->getSourceExpr();
207 continue;
208 }
209 break;
210 }
211 return E;
212}
213
214static void AddLiveExpr(llvm::ImmutableSet<const Expr *> &Set,
215 llvm::ImmutableSet<const Expr *>::Factory &F,
216 const Expr *E) {
217 Set = F.add(Set, LookThroughExpr(E));
218}
219
220/// Add as a live expression all individual conditions in a logical expression.
221/// For example, for the expression:
222/// "(a < b) || (c && d && ((e || f) != (g && h)))"
223/// the following expressions will be added as live:
224/// "a < b", "c", "d", "((e || f) != (g && h))"
225static void AddAllConditionalTerms(llvm::ImmutableSet<const Expr *> &Set,
226 llvm::ImmutableSet<const Expr *>::Factory &F,
227 const Expr *Cond) {
228 AddLiveExpr(Set, F, Cond);
229 if (auto const *BO = dyn_cast<BinaryOperator>(Cond->IgnoreParens());
230 BO && BO->isLogicalOp()) {
231 AddAllConditionalTerms(Set, F, BO->getLHS());
232 AddAllConditionalTerms(Set, F, BO->getRHS());
233 }
234}
235
236void TransferFunctions::Visit(Stmt *S) {
237 if (observer)
238 observer->observeStmt(S, currentBlock, val);
239
241
242 if (const auto *E = dyn_cast<Expr>(S)) {
243 val.liveExprs = LV.ESetFact.remove(val.liveExprs, E);
244 }
245
246 // Mark all children expressions live.
247 // The "normal" case will be handled by iterating over 'S->children()' but
248 // before that we need this big 'switch' to handle the statement kinds where
249 // 'S->children()' isn't the exactly equal to the set of child expressions
250 // that we want to keep alive. (In some cases we need to skip some of the
251 // children, in other cases there are unusual child expressions that do not
252 // appear in 'S->children()'.)
253
254 switch (S->getStmtClass()) {
255 default:
256 break;
257 case Stmt::StmtExprClass: {
258 // For statement expressions, look through the compound statement.
259 S = cast<StmtExpr>(S)->getSubStmt();
260 break;
261 }
262 case Stmt::CXXMemberCallExprClass: {
263 // Include the implicit "this" pointer as being live.
264 CXXMemberCallExpr *CE = cast<CXXMemberCallExpr>(S);
265 if (Expr *ImplicitObj = CE->getImplicitObjectArgument()) {
266 AddLiveExpr(val.liveExprs, LV.ESetFact, ImplicitObj);
267 }
268 break;
269 }
270 case Stmt::ObjCMessageExprClass: {
271 // In calls to super, include the implicit "self" pointer as being live.
272 ObjCMessageExpr *CE = cast<ObjCMessageExpr>(S);
274 val.liveDecls = LV.DSetFact.add(val.liveDecls,
275 LV.analysisContext.getSelfDecl());
276 break;
277 }
278 case Stmt::DeclStmtClass: {
279 const DeclStmt *DS = cast<DeclStmt>(S);
280 if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) {
281 for (const VariableArrayType* VA = FindVA(VD->getType());
282 VA != nullptr; VA = FindVA(VA->getElementType())) {
283 AddLiveExpr(val.liveExprs, LV.ESetFact, VA->getSizeExpr());
284 }
285 }
286 break;
287 }
288 case Stmt::PseudoObjectExprClass: {
289 // A pseudo-object operation only directly consumes its result
290 // expression.
291 Expr *child = cast<PseudoObjectExpr>(S)->getResultExpr();
292 if (!child) return;
293 if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child))
294 child = OV->getSourceExpr();
295 child = child->IgnoreParens();
296 val.liveExprs = LV.ESetFact.add(val.liveExprs, child);
297 return;
298 }
299
300 // FIXME: These cases eventually shouldn't be needed.
301 case Stmt::ExprWithCleanupsClass: {
302 S = cast<ExprWithCleanups>(S)->getSubExpr();
303 break;
304 }
305 case Stmt::CXXBindTemporaryExprClass: {
306 S = cast<CXXBindTemporaryExpr>(S)->getSubExpr();
307 break;
308 }
309 case Stmt::UnaryExprOrTypeTraitExprClass: {
310 // No need to unconditionally visit subexpressions.
311 return;
312 }
313 case Stmt::IfStmtClass: {
314 // If one of the branches is an expression rather than a compound
315 // statement, it will be bad if we mark it as live at the terminator
316 // of the if-statement (i.e., immediately after the condition expression).
317 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<IfStmt>(S)->getCond());
318 return;
319 }
320 case Stmt::WhileStmtClass: {
321 // If the loop body is an expression rather than a compound statement,
322 // it will be bad if we mark it as live at the terminator of the loop
323 // (i.e., immediately after the condition expression).
324 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<WhileStmt>(S)->getCond());
325 return;
326 }
327 case Stmt::DoStmtClass: {
328 // If the loop body is an expression rather than a compound statement,
329 // it will be bad if we mark it as live at the terminator of the loop
330 // (i.e., immediately after the condition expression).
331 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<DoStmt>(S)->getCond());
332 return;
333 }
334 case Stmt::ForStmtClass: {
335 // If the loop body is an expression rather than a compound statement,
336 // it will be bad if we mark it as live at the terminator of the loop
337 // (i.e., immediately after the condition expression).
338 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<ForStmt>(S)->getCond());
339 return;
340 }
341 case Stmt::ConditionalOperatorClass: {
342 // Keep not only direct children alive, but also all the short-circuited
343 // parts of the condition. Short-circuiting evaluation may cause the
344 // conditional operator evaluation to skip the evaluation of the entire
345 // condtion expression, so the value of the entire condition expression is
346 // never computed.
347 //
348 // This makes a difference when we compare exploded nodes coming from true
349 // and false expressions with no side effects: the only difference in the
350 // state is the value of (part of) the condition.
351 //
352 // BinaryConditionalOperatorClass ('x ?: y') is not affected because it
353 // explicitly calculates the value of the entire condition expression (to
354 // possibly use as a value for the "true expr") even if it is
355 // short-circuited.
356 auto const *CO = cast<ConditionalOperator>(S);
357 AddAllConditionalTerms(val.liveExprs, LV.ESetFact, CO->getCond());
358 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getTrueExpr());
359 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getFalseExpr());
360 return;
361 }
362 }
363
364 // Mark all child expressions live -- "normal" case.
365 for (Stmt *Child : S->children()) {
366 if (const auto *E = dyn_cast_or_null<Expr>(Child))
367 AddLiveExpr(val.liveExprs, LV.ESetFact, E);
368 }
369}
370
371static bool writeShouldKill(const VarDecl *VD) {
372 return VD && !VD->getType()->isReferenceType() &&
373 !isAlwaysAlive(VD);
374}
375
376void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
377 if (LV.killAtAssign && B->getOpcode() == BO_Assign) {
378 if (const auto *DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParens())) {
379 LV.inAssignment.insert(DR);
380 }
381 }
382 if (B->isAssignmentOp()) {
383 if (!LV.killAtAssign)
384 return;
385
386 // Assigning to a variable?
387 Expr *LHS = B->getLHS()->IgnoreParens();
388
389 if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
390 const Decl* D = DR->getDecl();
391 bool Killed = false;
392
393 if (const BindingDecl* BD = dyn_cast<BindingDecl>(D)) {
394 Killed = !BD->getType()->isReferenceType();
395 if (Killed) {
396 if (const auto *HV = BD->getHoldingVar())
397 val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
398
399 val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
400 }
401 } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
402 Killed = writeShouldKill(VD);
403 if (Killed)
404 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
405 }
406 }
407 }
408}
409
410void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
411 for (const VarDecl *VD :
412 LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl())) {
413 if (isAlwaysAlive(VD))
414 continue;
415 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
416 }
417}
418
419void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
420 const Decl* D = DR->getDecl();
421 bool InAssignment = LV.inAssignment.contains(DR);
422 if (const auto *BD = dyn_cast<BindingDecl>(D)) {
423 if (!InAssignment) {
424 if (const auto *HV = BD->getHoldingVar())
425 val.liveDecls = LV.DSetFact.add(val.liveDecls, HV);
426
427 val.liveBindings = LV.BSetFact.add(val.liveBindings, BD);
428 }
429 } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
430 if (!InAssignment && !isAlwaysAlive(VD))
431 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
432 }
433}
434
435void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
436 for (const auto *DI : DS->decls()) {
437 if (const auto *DD = dyn_cast<DecompositionDecl>(DI)) {
438 for (const auto *BD : DD->bindings()) {
439 if (const auto *HV = BD->getHoldingVar())
440 val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
441
442 val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
443 }
444
445 // When a bindig to a tuple-like structure is created, the HoldingVar
446 // initializers have a DeclRefExpr to the DecompositionDecl.
447 val.liveDecls = LV.DSetFact.remove(val.liveDecls, DD);
448 } else if (const auto *VD = dyn_cast<VarDecl>(DI)) {
449 if (!isAlwaysAlive(VD))
450 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
451 }
452 }
453}
454
455void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
456 // Kill the iteration variable.
457 DeclRefExpr *DR = nullptr;
458 const VarDecl *VD = nullptr;
459
460 Stmt *element = OS->getElement();
461 if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
462 VD = cast<VarDecl>(DS->getSingleDecl());
463 }
464 else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
465 VD = cast<VarDecl>(DR->getDecl());
466 }
467
468 if (VD) {
469 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
470 }
471}
472
473void TransferFunctions::
474VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)
475{
476 // While sizeof(var) doesn't technically extend the liveness of 'var', it
477 // does extent the liveness of metadata if 'var' is a VariableArrayType.
478 // We handle that special case here.
479 if (UE->getKind() != UETT_SizeOf || UE->isArgumentType())
480 return;
481
482 const Expr *subEx = UE->getArgumentExpr();
483 if (subEx->getType()->isVariableArrayType()) {
484 assert(subEx->isLValue());
485 val.liveExprs = LV.ESetFact.add(val.liveExprs, subEx->IgnoreParens());
486 }
487}
488
489LiveVariables::LivenessValues
490LiveVariablesImpl::runOnBlock(const CFGBlock *block,
491 LiveVariables::LivenessValues val,
492 LiveVariables::Observer *obs) {
493
494 TransferFunctions TF(*this, val, obs, block);
495
496 // Visit the terminator (if any).
497 if (const Stmt *term = block->getTerminatorStmt())
498 TF.Visit(const_cast<Stmt*>(term));
499
500 // Apply the transfer function for all Stmts in the block.
501 for (CFGBlock::const_reverse_iterator it = block->rbegin(),
502 ei = block->rend(); it != ei; ++it) {
503 const CFGElement &elem = *it;
504
505 if (std::optional<CFGAutomaticObjDtor> Dtor =
506 elem.getAs<CFGAutomaticObjDtor>()) {
507 val.liveDecls = DSetFact.add(val.liveDecls, Dtor->getVarDecl());
508 continue;
509 }
510
511 if (!elem.getAs<CFGStmt>())
512 continue;
513
514 const Stmt *S = elem.castAs<CFGStmt>().getStmt();
515 TF.Visit(const_cast<Stmt*>(S));
516 stmtsToLiveness[S] = val;
517 }
518 return val;
519}
520
522 const CFG *cfg = getImpl(impl).analysisContext.getCFG();
523 for (CFGBlock *B : *cfg)
524 getImpl(impl).runOnBlock(B, getImpl(impl).blocksEndToLiveness[B], &obs);
525}
526
527LiveVariables::LiveVariables(void *im) : impl(im) {}
528
530 delete (LiveVariablesImpl*) impl;
531}
532
533std::unique_ptr<LiveVariables>
535
536 // No CFG? Bail out.
537 CFG *cfg = AC.getCFG();
538 if (!cfg)
539 return nullptr;
540
541 // The analysis currently has scalability issues for very large CFGs.
542 // Bail out if it looks too large.
543 if (cfg->getNumBlockIDs() > 300000)
544 return nullptr;
545
546 LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign);
547
548 // Construct the dataflow worklist. Enqueue the exit block as the
549 // start of the analysis.
550 BackwardDataflowWorklist worklist(*cfg, AC);
551 llvm::BitVector everAnalyzedBlock(cfg->getNumBlockIDs());
552
553 // FIXME: we should enqueue using post order.
554 for (const CFGBlock *B : cfg->nodes()) {
555 worklist.enqueueBlock(B);
556 }
557
558 while (const CFGBlock *block = worklist.dequeue()) {
559 // Determine if the block's end value has changed. If not, we
560 // have nothing left to do for this block.
561 LivenessValues &prevVal = LV->blocksEndToLiveness[block];
562
563 // Merge the values of all successor blocks.
564 LivenessValues val;
565 for (const CFGBlock *succ : block->succs()) {
566 if (succ) {
567 val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
568 }
569 }
570
571 if (!everAnalyzedBlock[block->getBlockID()])
572 everAnalyzedBlock[block->getBlockID()] = true;
573 else if (prevVal == val)
574 continue;
575
576 prevVal = val;
577
578 // Update the dataflow value for the start of this block.
579 LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
580
581 // Enqueue the value to the predecessors.
582 worklist.enqueuePredecessors(block);
583 }
584
585 return std::unique_ptr<LiveVariables>(new LiveVariables(LV));
586}
587
589 getImpl(impl).dumpBlockLiveness(M);
590}
591
592void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
593 std::vector<const CFGBlock *> vec;
594 vec.reserve(blocksEndToLiveness.size());
595 llvm::append_range(vec, llvm::make_first_range(blocksEndToLiveness));
596 llvm::sort(vec, [](const CFGBlock *A, const CFGBlock *B) {
597 return A->getBlockID() < B->getBlockID();
598 });
599
600 std::vector<const VarDecl*> declVec;
601
602 for (const CFGBlock *block : vec) {
603 llvm::errs() << "\n[ B" << block->getBlockID()
604 << " (live variables at block exit) ]\n";
605 declVec.clear();
606 llvm::append_range(declVec, blocksEndToLiveness[block].liveDecls);
607 llvm::sort(declVec, [](const Decl *A, const Decl *B) {
608 return A->getBeginLoc() < B->getBeginLoc();
609 });
610
611 for (const VarDecl *VD : declVec) {
612 llvm::errs() << " " << VD->getDeclName().getAsString() << " <";
613 VD->getLocation().print(llvm::errs(), M);
614 llvm::errs() << ">\n";
615 }
616 }
617 llvm::errs() << "\n";
618}
619
621 getImpl(impl).dumpExprLiveness(M);
622}
623
624void LiveVariablesImpl::dumpExprLiveness(const SourceManager &M) {
625 const ASTContext &Ctx = analysisContext.getASTContext();
626 auto ByIDs = [&Ctx](const Expr *L, const Expr *R) {
627 return L->getID(Ctx) < R->getID(Ctx);
628 };
629
630 // Don't iterate over blockEndsToLiveness directly because it's not sorted.
631 for (const CFGBlock *B : *analysisContext.getCFG()) {
632 llvm::errs() << "\n[ B" << B->getBlockID()
633 << " (live expressions at block exit) ]\n";
634 std::vector<const Expr *> LiveExprs;
635 llvm::append_range(LiveExprs, blocksEndToLiveness[B].liveExprs);
636 llvm::sort(LiveExprs, ByIDs);
637 for (const Expr *E : LiveExprs) {
638 llvm::errs() << "\n";
639 E->dump();
640 }
641 llvm::errs() << "\n";
642 }
643}
644
645const void *LiveVariables::getTag() { static int x; return &x; }
646const void *RelaxedLiveVariables::getTag() { static int x; return &x; }
#define V(N, I)
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static const VariableArrayType * FindVA(const Type *t)
Definition CFG.cpp:1513
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 ...
Definition ASTContext.h:229
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.
Definition TypeBase.h:3784
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4041
Expr * getLHS() const
Definition Expr.h:4091
static bool isAssignmentOp(Opcode Opc)
Definition Expr.h:4177
Opcode getOpcode() const
Definition Expr.h:4086
A binding in a decomposition declaration.
Definition DeclCXX.h:4190
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition Expr.h:6672
const BlockDecl * getBlockDecl() const
Definition Expr.h:6684
Represents a single basic block in a source-level CFG.
Definition CFG.h:632
reverse_iterator rbegin()
Definition CFG.h:942
reverse_iterator rend()
Definition CFG.h:943
ElementList::const_reverse_iterator const_reverse_iterator
Definition CFG.h:930
succ_range succs()
Definition CFG.h:1027
Stmt * getTerminatorStmt()
Definition CFG.h:1114
unsigned getBlockID() const
Definition CFG.h:1134
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
Definition CFG.h:100
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
Definition CFG.h:110
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition CFG.h:1250
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Definition CFG.h:1443
llvm::iterator_range< iterator > nodes()
Definition CFG.h:1344
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition ExprCXX.cpp:729
void enqueueBlock(const CFGBlock *Block)
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1273
ValueDecl * getDecl()
Definition Expr.h:1341
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1641
decl_range decls()
Definition Stmt.h:1689
const Decl * getSingleDecl() const
Definition Stmt.h:1656
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
SourceLocation getLocation() const
Definition DeclBase.h:447
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:439
std::string getAsString() const
Retrieve the human-readable string for this name.
This represents one expression.
Definition Expr.h:112
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3093
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:284
QualType getType() const
Definition Expr.h:144
FullExpr - Represents a "full-expression" node.
Definition Expr.h:1052
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)
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.
Definition Decl.h:340
Represents Objective-C's collection statement.
Definition StmtObjC.h:23
@ SuperInstance
The receiver is the instance of the superclass object.
Definition ExprObjC.h:985
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
Definition ExprObjC.h:1260
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1181
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8445
static const void * getTag()
void print(raw_ostream &OS, const SourceManager &SM) const
This class handles loading and caching of source files into memory.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
Definition Stmt.h:86
child_range children()
Definition Stmt.cpp:304
StmtClass getStmtClass() const
Definition Stmt.h:1503
int64_t getID(const ASTContext &Context) const
Definition Stmt.cpp:379
The base class of the type hierarchy.
Definition TypeBase.h:1875
bool isReferenceType() const
Definition TypeBase.h:8706
bool isVariableArrayType() const
Definition TypeBase.h:8793
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition Expr.h:2628
UnaryExprOrTypeTrait getKind() const
Definition Expr.h:2660
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:924
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1239
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4028
@ 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.
Expr * Cond
};
U cast(CodeGen::Address addr)
Definition Address.h:327
#define false
Definition stdbool.h:26
A worklist implementation for backward dataflow analysis.
void enqueuePredecessors(const CFGBlock *Block)