clang 24.0.0git
Facts.cpp
Go to the documentation of this file.
1//===- Facts.cpp - Lifetime Analysis Facts Implementation -------*- C++ -*-===//
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
10#include "clang/AST/Decl.h"
13#include "llvm/Support/TimeProfiler.h"
14
16
17void FactManager::computePersistentOrigins(const CFG &Cfg) {
18 llvm::TimeTraceScope TimeProfile("ComputePersistentOrigins");
19
20 unsigned NumOrigins = OriginMgr.getNumOrigins();
21 PersistentOrigins.resize(NumOrigins);
22 llvm::SmallVector<const CFGBlock *> OriginToFirstSeenBlock(NumOrigins,
23 nullptr);
24 for (const CFGBlock *B : Cfg) {
25 for (const Fact *F : getFacts(B)) {
26 auto CheckOrigin = [&](OriginID OID) {
27 if (PersistentOrigins.test(OID.Value))
28 return;
29 auto &FirstSeenBlock = OriginToFirstSeenBlock[OID.Value];
30 if (FirstSeenBlock == nullptr)
31 FirstSeenBlock = B;
32 if (FirstSeenBlock != B) {
33 // We saw this origin in more than one block.
34 PersistentOrigins.set(OID.Value);
35 }
36 };
37
38 switch (F->getKind()) {
40 CheckOrigin(F->getAs<IssueFact>()->getOriginID());
41 break;
43 const auto *OF = F->getAs<OriginFlowFact>();
44 CheckOrigin(OF->getDestOriginID());
45 CheckOrigin(OF->getSrcOriginID());
46 break;
47 }
48 case Fact::Kind::Use:
49 for (const OriginList *Cur = F->getAs<UseFact>()->getUsedOrigins(); Cur;
50 Cur = Cur->peelOuterOrigin())
51 CheckOrigin(Cur->getOuterOriginID());
52 break;
54 CheckOrigin(F->getAs<KillOriginFact>()->getKilledOrigin());
55 break;
57 // An escaping origin is read at the exit block but defined earlier, so
58 // it spans blocks and must participate in joins.
59 CheckOrigin(F->getAs<OriginEscapesFact>()->getEscapedOriginID());
60 break;
61 // `Expire` and `InvalidateOrigin` only ever clear an origin, so
62 // misclassifying one is harmless: the clear becomes a no-op.
67 break;
68 }
69 }
70 }
71}
72
73void Fact::dump(llvm::raw_ostream &OS, const LoanManager &,
74 const OriginManager &, const LoanPropagationAnalysis *) const {
75 OS << "Fact (Kind: " << static_cast<int>(K) << ")\n";
76}
77
78void IssueFact::dump(llvm::raw_ostream &OS, const LoanManager &LM,
79 const OriginManager &OM,
80 const LoanPropagationAnalysis *) const {
81 OS << "Issue (";
82 LM.getLoan(getLoanID())->dump(OS);
83 OS << ", ToOrigin: ";
84 OM.dump(getOriginID(), OS);
85 OS << ")\n";
86}
87
88void ExpireFact::dump(llvm::raw_ostream &OS, const LoanManager &LM,
89 const OriginManager &OM,
90 const LoanPropagationAnalysis *LPA) const {
91 OS << "Expire (";
92 getAccessPath().dump(OS);
93 if (auto OID = getOriginID()) {
94 OS << ", Origin: ";
95 OM.dump(*OID, OS);
96 }
97 OS << ")\n";
98}
99
100void OriginFlowFact::dump(llvm::raw_ostream &OS, const LoanManager &LM,
101 const OriginManager &OM,
102 const LoanPropagationAnalysis *LPA) const {
103 OS << "OriginFlow: \n";
104 OS << "\tDest: ";
105 OM.dump(getDestOriginID(), OS);
106 if (LPA) {
107 LoanSet DestinationLoans = LPA->getLoans(getDestOriginID(), this);
108 if (DestinationLoans.isEmpty())
109 OS << " has no loans";
110 else {
111 OS << " has loans to { ";
112 for (LoanID LID : DestinationLoans) {
113 LM.getLoan(LID)->getAccessPath().dump(OS);
114 OS << " ";
115 }
116 OS << "}";
117 }
118 }
119 OS << "\n";
120 OS << "\tSrc: ";
121 OM.dump(getSrcOriginID(), OS);
122 OS << (getKillDest() ? "" : ", Merge");
123 OS << "\n";
124}
125
126void MovedOriginFact::dump(llvm::raw_ostream &OS, const LoanManager &,
127 const OriginManager &OM,
128 const LoanPropagationAnalysis *) const {
129 OS << "MovedOrigins (";
130 OM.dump(getMovedOrigin(), OS);
131 OS << ")\n";
132}
133
134void ReturnEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &,
135 const OriginManager &OM,
136 const LoanPropagationAnalysis *) const {
137 OS << "OriginEscapes (";
138 OM.dump(getEscapedOriginID(), OS);
139 OS << ", via Return)\n";
140}
141
142void FieldEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &,
143 const OriginManager &OM,
144 const LoanPropagationAnalysis *) const {
145 OS << "OriginEscapes (";
146 OM.dump(getEscapedOriginID(), OS);
147 OS << ", via Field)\n";
148}
149
150void GlobalEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &,
151 const OriginManager &OM,
152 const LoanPropagationAnalysis *) const {
153 OS << "OriginEscapes (";
154 OM.dump(getEscapedOriginID(), OS);
155 OS << ", via Global)\n";
156}
157
158void ThisEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &,
159 const OriginManager &OM,
160 const LoanPropagationAnalysis *) const {
161 OS << "OriginEscapes (";
162 OM.dump(getEscapedOriginID(), OS);
163 OS << ", via This)\n";
164}
165
166void UseFact::dump(llvm::raw_ostream &OS, const LoanManager &,
167 const OriginManager &OM,
168 const LoanPropagationAnalysis *) const {
169 OS << "Use (";
170 size_t NumUsedOrigins = getUsedOrigins()->getLength();
171 size_t I = 0;
172 for (const OriginList *Cur = getUsedOrigins(); Cur;
173 Cur = Cur->peelOuterOrigin(), ++I) {
174 OM.dump(Cur->getOuterOriginID(), OS);
175 if (I < NumUsedOrigins - 1)
176 OS << ", ";
177 }
178 OS << ")\n";
179}
180
181void InvalidateOriginFact::dump(llvm::raw_ostream &OS, const LoanManager &,
182 const OriginManager &OM,
183 const LoanPropagationAnalysis *) const {
184 OS << "InvalidateOrigin (";
185 OM.dump(getInvalidatedOrigin(), OS);
186 OS << ")\n";
187}
188
189void TestPointFact::dump(llvm::raw_ostream &OS, const LoanManager &,
190 const OriginManager &,
191 const LoanPropagationAnalysis *) const {
192 OS << "TestPoint (Annotation: \"" << getAnnotation() << "\")\n";
193}
194
195void KillOriginFact::dump(llvm::raw_ostream &OS, const LoanManager &,
196 const OriginManager &OM,
197 const LoanPropagationAnalysis *) const {
198 OS << "KillOrigin (";
199 OM.dump(getKilledOrigin(), OS);
200 OS << ")\n";
201}
202
203llvm::StringMap<ProgramPoint> FactManager::getTestPoints() const {
204 llvm::StringMap<ProgramPoint> AnnotationToPointMap;
205 for (const auto &BlockFacts : BlockToFacts) {
206 for (const Fact *F : BlockFacts) {
207 if (const auto *TPF = F->getAs<TestPointFact>()) {
208 StringRef PointName = TPF->getAnnotation();
209 assert(!AnnotationToPointMap.contains(PointName) &&
210 "more than one test points with the same name");
211 AnnotationToPointMap[PointName] = F;
212 }
213 }
214 }
215 return AnnotationToPointMap;
216}
217
219 const LoanPropagationAnalysis *LPA) const {
220 llvm::dbgs() << "==========================================\n";
221 llvm::dbgs() << " Lifetime Analysis Facts:\n";
222 llvm::dbgs() << "==========================================\n";
223 if (const Decl *D = AC.getDecl())
224 if (const auto *ND = dyn_cast<NamedDecl>(D))
225 llvm::dbgs() << "Function: " << ND->getQualifiedNameAsString() << "\n";
226 // Print blocks in the order as they appear in code for a stable ordering.
227 for (const CFGBlock *B : *AC.getAnalysis<PostOrderCFGView>()) {
228 llvm::dbgs() << " Block B" << B->getBlockID() << ":\n";
229 for (const Fact *F : getFacts(B)) {
230 llvm::dbgs() << " ";
231 F->dump(llvm::dbgs(), LoanMgr, OriginMgr, LPA);
232 }
233 llvm::dbgs() << " End of Block\n";
234 }
235}
236
239 return BlockToFacts[getBlockID(P)];
240}
241
243 for (size_t i = 0; i < BlockToFacts.size(); ++i)
244 for (const Fact *F : BlockToFacts[i])
245 if (F == P)
246 return i;
247 llvm_unreachable("Failed to find BlockID for given ProgramPoint");
248}
249} // namespace clang::lifetimes::internal
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents a single basic block in a source-level CFG.
Definition CFG.h:651
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition CFG.h:1294
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
void dump(llvm::raw_ostream &OS) const
Definition Loans.cpp:13
const AccessPath & getAccessPath() const
Definition Facts.h:192
std::optional< OriginID > getOriginID() const
Definition Facts.h:193
void dump(llvm::raw_ostream &OS, const LoanManager &LM, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:88
llvm::ArrayRef< const Fact * > getFacts(const CFGBlock *B) const
Definition Facts.h:437
llvm::StringMap< ProgramPoint > getTestPoints() const
Retrieves program points that were specially marked in the source code for testing.
Definition Facts.cpp:203
void dump(const CFG &Cfg, AnalysisDeclContext &AC, const LoanPropagationAnalysis *LPA=nullptr) const
Definition Facts.cpp:218
size_t getBlockID(ProgramPoint P) const
Definition Facts.cpp:242
llvm::ArrayRef< const Fact * > getBlockContaining(ProgramPoint P) const
Retrieves all the facts in the block containing Program Point P.
Definition Facts.cpp:238
An abstract base class for a single, atomic lifetime-relevant event.
Definition Facts.h:99
virtual void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &, const LoanPropagationAnalysis *LPA=nullptr) const
Definition Facts.cpp:73
@ InvalidateOrigin
An origin is invalidated (e.g. vector resized, delete called).
Definition Facts.h:122
@ TestPoint
A marker for a specific point in the code, for testing.
Definition Facts.h:118
@ Expire
A loan expires as its underlying storage is freed (e.g., variable goes out of scope).
Definition Facts.h:107
@ Issue
A new loan is issued from a borrow expression (e.g., &x).
Definition Facts.h:104
@ OriginFlow
An origin is propagated from a source to a destination (e.g., p = q).
Definition Facts.h:112
@ MovedOrigin
An origin that is moved (e.g., passed to an rvalue reference parameter).
Definition Facts.h:116
@ Use
An origin is used (eg. appears as l-value expression like DeclRefExpr).
Definition Facts.h:114
@ OriginEscapes
An origin that escapes the function scope (e.g., via return).
Definition Facts.h:120
@ KillOrigin
All loans of an origin are cleared.
Definition Facts.h:124
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:142
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:150
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:181
void dump(llvm::raw_ostream &OS, const LoanManager &LM, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:78
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:195
Manages the creation, storage and retrieval of loans.
Definition Loans.h:233
const Loan * getLoan(LoanID ID) const
Definition Loans.h:255
LoanSet getLoans(OriginID OID, ProgramPoint P) const
const AccessPath & getAccessPath() const
Definition Loans.h:226
void dump(llvm::raw_ostream &OS) const
Definition Loans.cpp:39
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:126
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:100
A list of origins representing levels of indirection for pointer-like types.
Definition Origins.h:105
OriginList * peelOuterOrigin() const
Definition Origins.h:109
Manages the creation, storage, and retrieval of origins for pointer-like variables and expressions.
Definition Origins.h:135
void dump(OriginID OID, llvm::raw_ostream &OS) const
Definition Origins.cpp:368
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:134
A dummy-fact used to mark a specific point in the code for testing.
Definition Facts.h:398
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:189
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:158
void dump(llvm::raw_ostream &OS, const LoanManager &, const OriginManager &OM, const LoanPropagationAnalysis *LPA=nullptr) const override
Definition Facts.cpp:166
const OriginList * getUsedOrigins() const
Definition Facts.h:343
const Fact * ProgramPoint
A ProgramPoint identifies a location in the CFG by pointing to a specific Fact.
Definition Facts.h:157
utils::ID< struct LoanTag > LoanID
Definition Loans.h:27
utils::ID< struct OriginTag > OriginID
Definition Origins.h:28
utils::SetTy< LoanID > LoanSet