20#include "llvm/ADT/BitVector.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/Support/TimeProfiler.h"
23#include "llvm/Support/raw_ostream.h"
31 llvm::TimeTraceScope(
"ComputePersistentOrigins");
33 llvm::BitVector PersistentOrigins(NumOrigins);
39 auto CheckOrigin = [&](
OriginID OID) {
40 if (PersistentOrigins.test(OID.Value))
42 auto &FirstSeenBlock = OriginToFirstSeenBlock[OID.Value];
43 if (FirstSeenBlock ==
nullptr)
45 if (FirstSeenBlock != B) {
47 PersistentOrigins.set(OID.Value);
51 switch (F->getKind()) {
57 CheckOrigin(OF->getDestOriginID());
58 CheckOrigin(OF->getSrcOriginID());
64 CheckOrigin(Cur->getOuterOriginID());
73 return PersistentOrigins;
92 : PersistentOrigins(Persistent), BlockLocalOrigins(BlockLocal) {}
96 return PersistentOrigins ==
Other.PersistentOrigins &&
97 BlockLocalOrigins ==
Other.BlockLocalOrigins;
101 void dump(llvm::raw_ostream &OS)
const {
102 OS <<
"LoanPropagationLattice State:\n";
103 OS <<
" Persistent Origins:\n";
104 if (PersistentOrigins.isEmpty())
106 for (
const auto &Entry : PersistentOrigins) {
107 if (Entry.second.isEmpty())
108 OS <<
" Origin " << Entry.first <<
" contains no loans\n";
109 for (
const LoanID &LID : Entry.second)
110 OS <<
" Origin " << Entry.first <<
" contains Loan " << LID <<
"\n";
112 OS <<
" Block-Local Origins:\n";
113 if (BlockLocalOrigins.isEmpty())
115 for (
const auto &Entry : BlockLocalOrigins) {
116 if (Entry.second.isEmpty())
117 OS <<
" Origin " << Entry.first <<
" contains no loans\n";
118 for (
const LoanID &LID : Entry.second)
119 OS <<
" Origin " << Entry.first <<
" contains Loan " << LID <<
"\n";
127 AnalysisImpl(
const CFG &
C, AnalysisDeclContext &AC, FactManager &F,
128 OriginLoanMap::Factory &OriginLoanMapFactory,
129 LoanSet::Factory &LoanSetFactory)
130 : DataflowAnalysis(
C, AC, F), OriginLoanMapFactory(OriginLoanMapFactory),
131 LoanSetFactory(LoanSetFactory),
134 using Base::transfer;
136 StringRef getAnalysisName()
const {
return "LoanPropagation"; }
138 Lattice getInitialState() {
return Lattice{}; }
142 Lattice join(Lattice A, Lattice B) {
144 A.PersistentOrigins, B.PersistentOrigins, OriginLoanMapFactory,
146 assert((S1 || S2) &&
"unexpectedly merging 2 empty sets");
151 return utils::join(*S1, *S2, LoanSetFactory);
156 return Lattice(JoinedOrigins, OriginLoanMapFactory.getEmptyMap());
160 Lattice
transfer(Lattice In,
const IssueFact &F) {
162 LoanID LID = F.getLoanID();
163 LoanSet NewLoans = LoanSetFactory.add(LoanSetFactory.getEmptySet(), LID);
164 return setLoans(In, OID, NewLoans);
170 Lattice
transfer(Lattice In,
const OriginFlowFact &F) {
171 OriginID DestOID = F.getDestOriginID();
172 OriginID SrcOID = F.getSrcOriginID();
175 F.getKillDest() ? LoanSetFactory.getEmptySet() : getLoans(In, DestOID);
176 LoanSet SrcLoans = getLoans(In, SrcOID);
179 return setLoans(In, DestOID, MergedLoans);
183 return getLoans(getState(P), OID);
188 bool isPersistent(
OriginID OID)
const {
189 return PersistentOrigins.test(OID.Value);
193 if (isPersistent(OID))
194 return Lattice(OriginLoanMapFactory.add(L.PersistentOrigins, OID, Loans),
195 L.BlockLocalOrigins);
196 return Lattice(L.PersistentOrigins,
197 OriginLoanMapFactory.add(L.BlockLocalOrigins, OID, Loans));
202 isPersistent(OID) ? &L.PersistentOrigins : &L.BlockLocalOrigins;
203 if (
auto *Loans = Map->lookup(OID))
205 return LoanSetFactory.getEmptySet();
208 OriginLoanMap::Factory &OriginLoanMapFactory;
209 LoanSet::Factory &LoanSetFactory;
213 llvm::BitVector PersistentOrigins;
218 using AnalysisImpl::AnalysisImpl;
223 OriginLoanMap::Factory &OriginLoanMapFactory,
224 LoanSet::Factory &LoanSetFactory)
225 : PImpl(
std::make_unique<
Impl>(
C, AC, F, OriginLoanMapFactory,
233 return PImpl->getLoans(OID, P);
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents a single basic block in a source-level CFG.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
A generic, policy-based driver for dataflow analyses.
llvm::ArrayRef< const Fact * > getFacts(const CFGBlock *B) const
OriginManager & getOriginMgr()
An abstract base class for a single, atomic lifetime-relevant event.
@ TestPoint
A marker for a specific point in the code, for testing.
@ Expire
A loan expires as its underlying storage is freed (e.g., variable goes out of scope).
@ Issue
A new loan is issued from a borrow expression (e.g., &x).
@ OriginFlow
An origin is propagated from a source to a destination (e.g., p = q).
@ Use
An origin is used (eg. appears as l-value expression like DeclRefExpr).
@ OriginEscapes
An origin that escapes the function scope (e.g., via return).
OriginID getOriginID() const
LoanSet getLoans(OriginID OID, ProgramPoint P) const
~LoanPropagationAnalysis()
LoanPropagationAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F, OriginLoanMap::Factory &OriginLoanMapFactory, LoanSet::Factory &LoanSetFactory)
A list of origins representing levels of indirection for pointer-like types.
OriginList * peelOuterOrigin() const
unsigned getNumOrigins() const
const OriginList * getUsedOrigins() const
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, Environment::ValueModel &Model)
Evaluates S and updates Env accordingly.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
@ Asymmetric
An asymmetric join preserves keys unique to the first map as-is, while applying the JoinValues operat...
static llvm::ImmutableSet< T > join(llvm::ImmutableSet< T > A, llvm::ImmutableSet< T > B, typename llvm::ImmutableSet< T >::Factory &F)
Computes the union of two ImmutableSets.
const Fact * ProgramPoint
A ProgramPoint identifies a location in the CFG by pointing to a specific Fact.
llvm::ImmutableSet< LoanID > LoanSet
utils::ID< struct LoanTag > LoanID
utils::ID< struct OriginTag > OriginID
llvm::ImmutableMap< OriginID, LoanSet > OriginLoanMap
static llvm::BitVector computePersistentOrigins(const FactManager &FactMgr, const CFG &C)
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
bool operator!=(CanQual< T > x, CanQual< U > y)
@ Other
Other implicit parameter.