;
28classLiveVariablesImpl {
31llvm::ImmutableSet<const Expr *>::Factory ESetFact;
32llvm::ImmutableSet<const VarDecl *>::Factory DSetFact;
33llvm::ImmutableSet<const BindingDecl *>::Factory BSetFact;
34llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
35llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
36llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
37llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;
38 const boolkillAtAssign;
52: analysisContext(ac),
55BSetFact(
false), killAtAssign(KillAtAssign) {}
59staticLiveVariablesImpl &
getImpl(
void*x) {
60 return*((LiveVariablesImpl *) x);
72 if(
const auto*DD = dyn_cast<DecompositionDecl>(
D)) {
75alive |= liveBindings.contains(BD);
80alive |= liveDecls.contains(DD);
83 returnliveDecls.contains(
D);
87 template<
typenameSET>
88SET mergeSets(SET A, SET B) {
92 for(
typenameSET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {
99voidLiveVariables::Observer::anchor() { }
105llvm::ImmutableSetRef<const Expr *> SSetRefA(
106valsA.
liveExprs.getRootWithoutRetain(), ESetFact.getTreeFactory()),
107SSetRefB(valsB.
liveExprs.getRootWithoutRetain(),
108ESetFact.getTreeFactory());
110llvm::ImmutableSetRef<const VarDecl *>
111DSetRefA(valsA.
liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),
112DSetRefB(valsB.
liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());
114llvm::ImmutableSetRef<const BindingDecl *>
115BSetRefA(valsA.
liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory()),
116BSetRefB(valsB.
liveBindings.getRootWithoutRetain(), BSetFact.getTreeFactory());
118SSetRefA = mergeSets(SSetRefA, SSetRefB);
119DSetRefA = mergeSets(DSetRefA, DSetRefB);
120BSetRefA = mergeSets(BSetRefA, BSetRefB);
125DSetRefA.asImmutableSet(),
126BSetRefA.asImmutableSet());
130 returnliveExprs ==
V.liveExprs && liveDecls ==
V.liveDecls;
138 return D->hasGlobalStorage();
150 return getImpl(impl).stmtsToLiveness[
Loc].isLive(Val);
158classTransferFunctions :
public StmtVisitor<TransferFunctions> {
159LiveVariablesImpl &LV;
164TransferFunctions(LiveVariablesImpl &im,
168: LV(im), val(Val), observer(Observer), currentBlock(
CurrentBlock) {}
177 voidVisit(
Stmt*S);
183 while(
const ArrayType*VT = dyn_cast<ArrayType>(ty)) {
185 if(VAT->getSizeExpr())
188ty = VT->getElementType().getTypePtr();
196 if(
const Expr*Ex = dyn_cast<Expr>(
E))
198 if(
const FullExpr*FE = dyn_cast<FullExpr>(
E)) {
199 E= FE->getSubExpr();
203 E= OVE->getSourceExpr();
212llvm::ImmutableSet<const Expr *>::Factory &F,
223llvm::ImmutableSet<const Expr *>::Factory &F,
226 if(
auto const*BO = dyn_cast<BinaryOperator>(Cond->
IgnoreParens());
227BO && BO->isLogicalOp()) {
233voidTransferFunctions::Visit(
Stmt*S) {
235observer->observeStmt(S, currentBlock, val);
239 if(
const auto*
E= dyn_cast<Expr>(S)) {
240val.liveExprs = LV.ESetFact.remove(val.liveExprs,
E);
245 switch(S->getStmtClass()) {
248 caseStmt::StmtExprClass: {
250S = cast<StmtExpr>(S)->getSubStmt();
253 caseStmt::CXXMemberCallExprClass: {
257 AddLiveExpr(val.liveExprs, LV.ESetFact, ImplicitObj);
261 caseStmt::ObjCMessageExprClass: {
265val.liveDecls = LV.DSetFact.add(val.liveDecls,
266LV.analysisContext.getSelfDecl());
269 caseStmt::DeclStmtClass: {
270 const DeclStmt*DS = cast<DeclStmt>(S);
273VA !=
nullptr; VA =
FindVA(VA->getElementType())) {
274 AddLiveExpr(val.liveExprs, LV.ESetFact, VA->getSizeExpr());
279 caseStmt::PseudoObjectExprClass: {
282 Expr*child = cast<PseudoObjectExpr>(S)->getResultExpr();
285child = OV->getSourceExpr();
287val.liveExprs = LV.ESetFact.add(val.liveExprs, child);
292 caseStmt::ExprWithCleanupsClass: {
293S = cast<ExprWithCleanups>(S)->getSubExpr();
296 caseStmt::CXXBindTemporaryExprClass: {
297S = cast<CXXBindTemporaryExpr>(S)->getSubExpr();
300 caseStmt::UnaryExprOrTypeTraitExprClass: {
304 caseStmt::IfStmtClass: {
308 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<IfStmt>(S)->getCond());
311 caseStmt::WhileStmtClass: {
315 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<WhileStmt>(S)->getCond());
318 caseStmt::DoStmtClass: {
322 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<DoStmt>(S)->getCond());
325 caseStmt::ForStmtClass: {
329 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<ForStmt>(S)->getCond());
332 caseStmt::ConditionalOperatorClass: {
347 auto const*CO = cast<ConditionalOperator>(S);
349 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getTrueExpr());
350 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getFalseExpr());
358 for(
Stmt*Child : S->children()) {
359 if(
const auto*
E= dyn_cast_or_null<Expr>(Child))
370 if(LV.killAtAssign && B->
getOpcode() == BO_Assign) {
372LV.inAssignment[DR] = 1;
376 if(!LV.killAtAssign)
382 if(
DeclRefExpr*DR = dyn_cast<DeclRefExpr>(LHS)) {
383 const Decl*
D= DR->getDecl();
384 boolKilled =
false;
386 if(
const BindingDecl* BD = dyn_cast<BindingDecl>(
D)) {
387Killed = !BD->getType()->isReferenceType();
389 if(
const auto*HV = BD->getHoldingVar())
390val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
392val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
394}
else if(
const auto*VD = dyn_cast<VarDecl>(
D)) {
397val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
401 if(Killed && observer)
402observer->observerKill(DR);
407voidTransferFunctions::VisitBlockExpr(
BlockExpr*BE) {
409LV.analysisContext.getReferencedBlockVars(BE->
getBlockDecl())) {
412val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
416voidTransferFunctions::VisitDeclRefExpr(
DeclRefExpr*DR) {
418 boolInAssignment = LV.inAssignment[DR];
419 if(
const auto*BD = dyn_cast<BindingDecl>(
D)) {
421 if(
const auto*HV = BD->getHoldingVar())
422val.liveDecls = LV.DSetFact.
add(val.liveDecls, HV);
424val.liveBindings = LV.BSetFact.add(val.liveBindings, BD);
426}
else if(
const auto*VD = dyn_cast<VarDecl>(
D)) {
428val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
432voidTransferFunctions::VisitDeclStmt(
DeclStmt*DS) {
433 for(
const auto*DI : DS->
decls()) {
434 if(
const auto*DD = dyn_cast<DecompositionDecl>(DI)) {
435 for(
const auto*BD : DD->bindings()) {
436 if(
const auto*HV = BD->getHoldingVar())
437val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
439val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
444val.liveDecls = LV.DSetFact.remove(val.liveDecls, DD);
445}
else if(
const auto*VD = dyn_cast<VarDecl>(DI)) {
447val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
457 Stmt*element = OS->getElement();
458 if(
DeclStmt*DS = dyn_cast<DeclStmt>(element)) {
461 else if((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
462VD = cast<VarDecl>(DR->
getDecl());
466val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
468observer->observerKill(DR);
472voidTransferFunctions::
484val.liveExprs = LV.ESetFact.add(val.liveExprs, subEx->
IgnoreParens());
488voidTransferFunctions::VisitUnaryOperator(
UnaryOperator*UO) {
507 if(isa<VarDecl>(
D) || isa<BindingDecl>(
D)) {
509observer->observerKill(DR);
515LiveVariablesImpl::runOnBlock(
const CFGBlock*block,
519TransferFunctions TF(*
this, val, obs, block);
523TF.Visit(
const_cast<Stmt*
>(term));
527ei = block->
rend(); it != ei; ++it) {
530 if(std::optional<CFGAutomaticObjDtor> Dtor =
540TF.Visit(
const_cast<Stmt*
>(S));
541stmtsToLiveness[S] = val;
547 const CFG*cfg =
getImpl(impl).analysisContext.getCFG();
549 getImpl(impl).runOnBlock(*it,
getImpl(impl).blocksEndToLiveness[*it], &obs);
552LiveVariables::LiveVariables(
void*im) : impl(im) {}
555 delete(LiveVariablesImpl*) impl;
558std::unique_ptr<LiveVariables>
562 CFG*cfg = AC.getCFG();
571LiveVariablesImpl *LV =
newLiveVariablesImpl(AC, killAtAssign);
591ei = block->
succ_end(); it != ei; ++it) {
593val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
597 if(!everAnalyzedBlock[block->
getBlockID()])
598everAnalyzedBlock[block->
getBlockID()] =
true;
599 else if(prevVal.
equals(val))
605LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
611 returnstd::unique_ptr<LiveVariables>(
new LiveVariables(LV));
615 getImpl(impl).dumpBlockLiveness(M);
618voidLiveVariablesImpl::dumpBlockLiveness(
const SourceManager&M) {
619std::vector<const CFGBlock *> vec;
620 for(llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator
621it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();
623vec.push_back(it->first);
629std::vector<const VarDecl*> declVec;
631 for(std::vector<const CFGBlock *>::iterator
632it = vec.begin(), ei = vec.end(); it != ei; ++it) {
633llvm::errs() <<
"\n[ B"<< (*it)->getBlockID()
634<<
" (live variables at block exit) ]\n";
639 for(llvm::ImmutableSet<const VarDecl *>::iterator si =
641se = vals.
liveDecls.end(); si != se; ++si) {
642declVec.push_back(*si);
645llvm::sort(declVec, [](
const Decl*A,
const Decl*B) {
649 for(std::vector<const VarDecl*>::iterator di = declVec.begin(),
650de = declVec.end(); di != de; ++di) {
651llvm::errs() <<
" "<< (*di)->getDeclName().getAsString()
653(*di)->getLocation().print(llvm::errs(), M);
654llvm::errs() <<
">\n";
657llvm::errs() <<
"\n";
661 getImpl(impl).dumpExprLiveness(M);
664voidLiveVariablesImpl::dumpExprLiveness(
const SourceManager&M) {
666 for(
const CFGBlock*B : *analysisContext.getCFG()) {
668llvm::errs() <<
"\n[ B"<< B->getBlockID()
669<<
" (live expressions at block exit) ]\n";
670 for(
const Expr*
E: blocksEndToLiveness[B].liveExprs) {
671llvm::errs() <<
"\n";
674llvm::errs() <<
"\n";
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)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4