clang: lib/Analysis/LiveVariables.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

19#include "llvm/ADT/DenseMap.h"

20#include "llvm/Support/raw_ostream.h"

21#include

22#include

23#include

24

25using namespace clang;

26

27namespace {

28class LiveVariablesImpl {

29public:

31 llvm::ImmutableSet<const Expr *>::Factory ESetFact;

32 llvm::ImmutableSet<const VarDecl *>::Factory DSetFact;

33 llvm::ImmutableSet<const BindingDecl *>::Factory BSetFact;

34 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;

35 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;

36 llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;

37 llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;

38 const bool killAtAssign;

39

43

47

50

52 : analysisContext(ac),

53 ESetFact(false),

54 DSetFact(false),

55 BSetFact(false), killAtAssign(KillAtAssign) {}

56};

57}

58

59static LiveVariablesImpl &getImpl(void *x) {

60 return *((LiveVariablesImpl *) x);

61}

62

63

64

65

66

69}

70

72 if (const auto *DD = dyn_cast(D)) {

73 bool alive = false;

74 for (const BindingDecl *BD : DD->bindings())

75 alive |= liveBindings.contains(BD);

76

77

78

79

80 alive |= liveDecls.contains(DD);

81 return alive;

82 }

83 return liveDecls.contains(D);

84}

85

86namespace {

87 template

88 SET mergeSets(SET A, SET B) {

89 if (A.isEmpty())

90 return B;

91

92 for (typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {

93 A = A.add(*it);

94 }

95 return A;

96 }

97}

98

99void LiveVariables::Observer::anchor() { }

100

104

105 llvm::ImmutableSetRef<const Expr *> SSetRefA(

106 valsA.liveExprs.getRootWithoutRetain(), ESetFact.getTreeFactory()),

107 SSetRefB(valsB.liveExprs.getRootWithoutRetain(),

108 ESetFact.getTreeFactory());

109

110 llvm::ImmutableSetRef<const VarDecl *>

111 DSetRefA(valsA.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),

112 DSetRefB(valsB.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());

113

114 llvm::ImmutableSetRef<const BindingDecl *>

115 BSetRefA(valsA.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory()),

116 BSetRefB(valsB.liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory());

117

118 SSetRefA = mergeSets(SSetRefA, SSetRefB);

119 DSetRefA = mergeSets(DSetRefA, DSetRefB);

120 BSetRefA = mergeSets(BSetRefA, BSetRefB);

121

122

123

125 DSetRefA.asImmutableSet(),

126 BSetRefA.asImmutableSet());

127}

128

130 return liveExprs == V.liveExprs && liveDecls == V.liveDecls;

131}

132

133

134

135

136

138 return D->hasGlobalStorage();

139}

140

143}

144

147}

148

150 return getImpl(impl).stmtsToLiveness[Loc].isLive(Val);

151}

152

153

154

155

156

157namespace {

158class TransferFunctions : public StmtVisitor {

159 LiveVariablesImpl &LV;

162 const CFGBlock *currentBlock;

163public:

164 TransferFunctions(LiveVariablesImpl &im,

168 : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}

169

171 void VisitBlockExpr(BlockExpr *BE);

173 void VisitDeclStmt(DeclStmt *DS);

177 void Visit(Stmt *S);

178};

179}

180

183 while (const ArrayType *VT = dyn_cast(ty)) {

184 if (const VariableArrayType *VAT = dyn_cast(VT))

185 if (VAT->getSizeExpr())

186 return VAT;

187

188 ty = VT->getElementType().getTypePtr();

189 }

190

191 return nullptr;

192}

193

195 while (E) {

196 if (const Expr *Ex = dyn_cast(E))

198 if (const FullExpr *FE = dyn_cast(E)) {

199 E = FE->getSubExpr();

200 continue;

201 }

202 if (const OpaqueValueExpr *OVE = dyn_cast(E)) {

203 E = OVE->getSourceExpr();

204 continue;

205 }

206 break;

207 }

208 return E;

209}

210

212 llvm::ImmutableSet<const Expr *>::Factory &F,

215}

216

217

218

219

220

221

223 llvm::ImmutableSet<const Expr *>::Factory &F,

224 const Expr *Cond) {

226 if (auto const *BO = dyn_cast(Cond->IgnoreParens());

227 BO && BO->isLogicalOp()) {

230 }

231}

232

233void TransferFunctions::Visit(Stmt *S) {

234 if (observer)

235 observer->observeStmt(S, currentBlock, val);

236

238

239 if (const auto *E = dyn_cast(S)) {

240 val.liveExprs = LV.ESetFact.remove(val.liveExprs, E);

241 }

242

243

244

245 switch (S->getStmtClass()) {

246 default:

247 break;

248 case Stmt::StmtExprClass: {

249

250 S = cast(S)->getSubStmt();

251 break;

252 }

253 case Stmt::CXXMemberCallExprClass: {

254

257 AddLiveExpr(val.liveExprs, LV.ESetFact, ImplicitObj);

258 }

259 break;

260 }

261 case Stmt::ObjCMessageExprClass: {

262

265 val.liveDecls = LV.DSetFact.add(val.liveDecls,

266 LV.analysisContext.getSelfDecl());

267 break;

268 }

269 case Stmt::DeclStmtClass: {

270 const DeclStmt *DS = cast(S);

273 VA != nullptr; VA = FindVA(VA->getElementType())) {

274 AddLiveExpr(val.liveExprs, LV.ESetFact, VA->getSizeExpr());

275 }

276 }

277 break;

278 }

279 case Stmt::PseudoObjectExprClass: {

280

281

282 Expr *child = cast(S)->getResultExpr();

283 if (!child) return;

284 if (OpaqueValueExpr *OV = dyn_cast(child))

285 child = OV->getSourceExpr();

287 val.liveExprs = LV.ESetFact.add(val.liveExprs, child);

288 return;

289 }

290

291

292 case Stmt::ExprWithCleanupsClass: {

293 S = cast(S)->getSubExpr();

294 break;

295 }

296 case Stmt::CXXBindTemporaryExprClass: {

297 S = cast(S)->getSubExpr();

298 break;

299 }

300 case Stmt::UnaryExprOrTypeTraitExprClass: {

301

302 return;

303 }

304 case Stmt::IfStmtClass: {

305

306

307

308 AddLiveExpr(val.liveExprs, LV.ESetFact, cast(S)->getCond());

309 return;

310 }

311 case Stmt::WhileStmtClass: {

312

313

314

315 AddLiveExpr(val.liveExprs, LV.ESetFact, cast(S)->getCond());

316 return;

317 }

318 case Stmt::DoStmtClass: {

319

320

321

322 AddLiveExpr(val.liveExprs, LV.ESetFact, cast(S)->getCond());

323 return;

324 }

325 case Stmt::ForStmtClass: {

326

327

328

329 AddLiveExpr(val.liveExprs, LV.ESetFact, cast(S)->getCond());

330 return;

331 }

332 case Stmt::ConditionalOperatorClass: {

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347 auto const *CO = cast(S);

349 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getTrueExpr());

350 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getFalseExpr());

351 return;

352 }

353 }

354

355

356

357

358 for (Stmt *Child : S->children()) {

359 if (const auto *E = dyn_cast_or_null(Child))

361 }

362}

363

367}

368

369void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {

370 if (LV.killAtAssign && B->getOpcode() == BO_Assign) {

371 if (const auto *DR = dyn_cast(B->getLHS()->IgnoreParens())) {

372 LV.inAssignment[DR] = 1;

373 }

374 }

376 if (!LV.killAtAssign)

377 return;

378

379

381

382 if (DeclRefExpr *DR = dyn_cast(LHS)) {

383 const Decl* D = DR->getDecl();

384 bool Killed = false;

385

386 if (const BindingDecl* BD = dyn_cast(D)) {

387 Killed = !BD->getType()->isReferenceType();

388 if (Killed) {

389 if (const auto *HV = BD->getHoldingVar())

390 val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);

391

392 val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);

393 }

394 } else if (const auto *VD = dyn_cast(D)) {

396 if (Killed)

397 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);

398

399 }

400

401 if (Killed && observer)

402 observer->observerKill(DR);

403 }

404 }

405}

406

407void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {

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[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

453

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()))) {

462 VD = cast(DR->getDecl());

463 }

464

465 if (VD) {

466 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);

467 if (observer && DR)

468 observer->observerKill(DR);

469 }

470}

471

472void TransferFunctions::

474{

475

476

477

479 return;

480

484 val.liveExprs = LV.ESetFact.add(val.liveExprs, subEx->IgnoreParens());

485 }

486}

487

488void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) {

489

490

491

492 if (!observer)

493 return;

494

496 default:

497 return;

498 case UO_PostInc:

499 case UO_PostDec:

500 case UO_PreInc:

501 case UO_PreDec:

502 break;

503 }

504

507 if (isa(D) || isa(D)) {

508

509 observer->observerKill(DR);

510 }

511 }

512}

513

515LiveVariablesImpl::runOnBlock(const CFGBlock *block,

518

519 TransferFunctions TF(*this, val, obs, block);

520

521

523 TF.Visit(const_cast<Stmt*>(term));

524

525

527 ei = block->rend(); it != ei; ++it) {

529

530 if (std::optional Dtor =

533 continue;

534 }

535

537 continue;

538

540 TF.Visit(const_cast<Stmt*>(S));

541 stmtsToLiveness[S] = val;

542 }

543 return val;

544}

545

547 const CFG *cfg = getImpl(impl).analysisContext.getCFG();

549 getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs);

550}

551

552LiveVariables::LiveVariables(void *im) : impl(im) {}

553

555 delete (LiveVariablesImpl*) impl;

556}

557

558std::unique_ptr

560

561

562 CFG *cfg = AC.getCFG();

563 if (!cfg)

564 return nullptr;

565

566

567

569 return nullptr;

570

571 LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign);

572

573

574

576 llvm::BitVector everAnalyzedBlock(cfg->getNumBlockIDs());

577

578

581 }

582

584

585

586 LivenessValues &prevVal = LV->blocksEndToLiveness[block];

587

588

591 ei = block->succ_end(); it != ei; ++it) {

592 if (const CFGBlock *succ = *it) {

593 val = LV->merge(val, LV->blocksBeginToLiveness[succ]);

594 }

595 }

596

597 if (!everAnalyzedBlock[block->getBlockID()])

598 everAnalyzedBlock[block->getBlockID()] = true;

599 else if (prevVal.equals(val))

600 continue;

601

602 prevVal = val;

603

604

605 LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);

606

607

609 }

610

611 return std::unique_ptr(new LiveVariables(LV));

612}

613

615 getImpl(impl).dumpBlockLiveness(M);

616}

617

618void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {

619 std::vector<const CFGBlock *> vec;

620 for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator

621 it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();

622 it != ei; ++it) {

623 vec.push_back(it->first);

624 }

627 });

628

629 std::vector<const VarDecl*> declVec;

630

631 for (std::vector<const CFGBlock *>::iterator

632 it = vec.begin(), ei = vec.end(); it != ei; ++it) {

633 llvm::errs() << "\n[ B" << (*it)->getBlockID()

634 << " (live variables at block exit) ]\n";

635

637 declVec.clear();

638

639 for (llvm::ImmutableSet<const VarDecl *>::iterator si =

641 se = vals.liveDecls.end(); si != se; ++si) {

642 declVec.push_back(*si);

643 }

644

645 llvm::sort(declVec, [](const Decl *A, const Decl *B) {

647 });

648

649 for (std::vector<const VarDecl*>::iterator di = declVec.begin(),

650 de = declVec.end(); di != de; ++di) {

651 llvm::errs() << " " << (*di)->getDeclName().getAsString()

652 << " <";

653 (*di)->getLocation().print(llvm::errs(), M);

654 llvm::errs() << ">\n";

655 }

656 }

657 llvm::errs() << "\n";

658}

659

661 getImpl(impl).dumpExprLiveness(M);

662}

663

664void LiveVariablesImpl::dumpExprLiveness(const SourceManager &M) {

665

666 for (const CFGBlock *B : *analysisContext.getCFG()) {

667

668 llvm::errs() << "\n[ B" << B->getBlockID()

669 << " (live expressions at block exit) ]\n";

670 for (const Expr *E : blocksEndToLiveness[B].liveExprs) {

671 llvm::errs() << "\n";

673 }

674 llvm::errs() << "\n";

675 }

676}

677

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)

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)

const CFGBlock * CurrentBlock

static bool runOnBlock(const CFGBlock *block, const CFG &cfg, AnalysisDeclContext &ac, CFGBlockValues &vals, const ClassifyRefs &classification, llvm::BitVector &wasAnalyzed, UninitVariablesHandler &handler)

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 C++ object destructor implicitly generated for automatic object or temporary bound to cons...

Represents a single basic block in a source-level CFG.

reverse_iterator rbegin()

succ_iterator succ_begin()

Stmt * getTerminatorStmt()

unsigned getBlockID() const

AdjacentBlocks::const_iterator const_succ_iterator

Represents a top-level expression in a basic block.

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()

Represents a call to a member function that may be written either with member call syntax (e....

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 getBeginLoc() const LLVM_READONLY

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

llvm::ImmutableSet< const VarDecl * > liveDecls

bool isLive(const Expr *E) const

bool equals(const LivenessValues &V) 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)

~LiveVariables() override

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.

Represents Objective-C's collection statement.

An expression that sends a message to the given Objective-C object or class.

@ 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()

This class handles loading and caching of source files into memory.

RetTy Visit(PTR(Stmt) S, ParamTys... P)

StmtVisitor - This class implements a simple visitor for Stmt subclasses.

Stmt - This represents one statement.

void dump() const

Dumps the specified AST fragment and all subtrees to llvm::errs().

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

UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...

Expr * getSubExpr() const

Represents a variable declaration or definition.

Represents a C array with a specified size that is not an integer-constant-expression.

The JSON file list parser is used to communicate input to InstallAPI.

A worklist implementation for backward dataflow analysis.

void enqueuePredecessors(const CFGBlock *Block)