@@ -76,6 +76,73 @@ std::map<Decl *, QualType> PulseVisitor::inferArrayTypes(FunctionDecl *FD) {
7676 return DeclToPulseSymbol;
7777}
7878
79+ bool checkIsSameStructInstance (Expr *A, Expr *B, ASTContext &Context) {
80+ A = A->IgnoreImpCasts ();
81+ B = B->IgnoreImpCasts ();
82+
83+ DeclRefExpr *DeclRefA = dyn_cast<DeclRefExpr>(A);
84+ if (!DeclRefA)
85+ return false ;
86+
87+ DeclRefExpr *DeclRefB = dyn_cast<DeclRefExpr>(B);
88+ if (!DeclRefB)
89+ return false ;
90+
91+ if (DeclRefA && DeclRefB) {
92+ return DeclRefA->getDecl () == DeclRefB->getDecl ();
93+ }
94+
95+ MemberExpr *MemA = dyn_cast<MemberExpr>(A);
96+ MemberExpr *MemB = dyn_cast<MemberExpr>(B);
97+
98+ if (MemA && MemB) {
99+ return checkIsSameStructInstance (MemA->getBase (), MemB->getBase (), Context);
100+ }
101+
102+ // Also check recursively pointer derefernces and array access.
103+ UnaryOperator *UOA = dyn_cast<UnaryOperator>(A);
104+ UnaryOperator *UOB = dyn_cast<UnaryOperator>(B);
105+
106+ if (UOA && UOB && UOA ->getOpcode () == UOB ->getOpcode ()) {
107+ return checkIsSameStructInstance (UOA ->getSubExpr (), UOB ->getSubExpr (),
108+ Context);
109+ }
110+
111+ return false ;
112+ }
113+
114+ bool checkIfLastStructAccess (MemberExpr *ToCheck, CompoundStmt *CS ,
115+ ASTContext &Context) {
116+ Expr *ToCheckBase = ToCheck->getBase ()->IgnoreImpCasts ();
117+ SourceManager &SM = Context.getSourceManager ();
118+ SourceLocation ToCheckLoc = ToCheck->getExprLoc ();
119+ SourceLocation LastLoc = ToCheckLoc;
120+
121+ for (const Stmt *S : CS ->body ()) {
122+ // Traverse the compound statement and visit it recursively.
123+ // We store the last accessed member in LastLoc.
124+ // When we encounter a member expr, we check if this is the same instance as
125+ // the ToBeChecked member expression.
126+ // We also check if the member expression comes after the to be checked
127+ // member,
128+ // if so we update Last loc.
129+ for (const Stmt *Child : S->children ()) {
130+ if (auto *ME = dyn_cast<MemberExpr>(Child)) {
131+ Expr *Base = ME ->getBase ()->IgnoreImpCasts ();
132+ if (Context.getParents (*Base).size () > 0 &&
133+ SM .isBeforeInTranslationUnit (ToCheckLoc, ME ->getExprLoc ()) &&
134+ checkIsSameStructInstance (Base, ToCheckBase, Context)) {
135+ LastLoc = ME ->getExprLoc ();
136+ }
137+ }
138+ }
139+ }
140+
141+ // If the location of the member to be checked is the same as the last loc
142+ // This is indeed the last access to the member.
143+ return ToCheckLoc == LastLoc;
144+ }
145+
79146bool PulseVisitor::checkIsRecursiveFunction (FunctionDecl *FD ) {
80147
81148 bool result = false ;
@@ -852,6 +919,8 @@ bool PulseVisitor::VisitFunctionDecl(FunctionDecl *FD) {
852919 auto *PulseBody = pulseFromCompoundStmt (CS , &Analyzer, Module);
853920
854921 // Release declarations that are function parameters.
922+ // TODO: Vidush Eventually we should get rid of these.
923+ // This is just in case there are release expressions left and we need to release them.
855924 PulseSequence *NewSeq = nullptr ;
856925 PulseSequence *Head = nullptr ;
857926 for (auto It = TrackStructExplodeAndRecover.begin (); It != TrackStructExplodeAndRecover.end ();) {
@@ -975,7 +1044,8 @@ PulseStmt *PulseVisitor::pulseFromCompoundStmt(Stmt *S,
9751044
9761045 for (auto *InnerStmt : CS ->body ()) {
9771046
978- auto *NextPulseStmt = pulseFromStmt (InnerStmt, Analyzer, nullptr , Modul);
1047+ auto *NextPulseStmt =
1048+ pulseFromStmt (InnerStmt, Analyzer, nullptr , Modul, CS );
9791049 if (NextPulseStmt == nullptr )
9801050 continue ;
9811051
@@ -998,7 +1068,8 @@ PulseStmt *PulseVisitor::pulseFromCompoundStmt(Stmt *S,
9981068}
9991069
10001070PulseStmt *PulseVisitor::pulseFromStmt (Stmt *S, ExprMutationAnalyzer *Analyzer,
1001- Stmt *Parent, PulseModul *Module) {
1071+ Stmt *Parent, PulseModul *Module,
1072+ CompoundStmt *CS ) {
10021073
10031074 if (!S)
10041075 return nullptr ;
@@ -1243,8 +1314,6 @@ PulseStmt *PulseVisitor::pulseFromStmt(Stmt *S, ExprMutationAnalyzer *Analyzer,
12431314 PulseCall->pushArg (ParenthesisDeref);
12441315 Assignment->Lhs = PulseCall;
12451316
1246- assert (ExprsBef.empty () && " Expected ExprsBefore to be empty!\n " );
1247-
12481317 auto It = TrackStructExplodeAndRecover.find (VD );
12491318 if (It == TrackStructExplodeAndRecover.end ()){
12501319 auto *NewSeq = new PulseSequence ();
@@ -1256,6 +1325,47 @@ PulseStmt *PulseVisitor::pulseFromStmt(Stmt *S, ExprMutationAnalyzer *Analyzer,
12561325 return NewSeq;
12571326 }
12581327
1328+ auto *RetSeq = releaseExprs (ExprsBef);
1329+
1330+ assert (ExprsBef.empty () && " Expected ExprsBefore to be empty!\n " );
1331+
1332+ if (checkIfLastStructAccess (ME , CS , Ctx)) {
1333+
1334+ It = TrackStructExplodeAndRecover.find (VD );
1335+ auto ItElem = *It;
1336+ auto &Decl = ItElem.first ;
1337+ auto &Info = ItElem.second ;
1338+ // recover not released.
1339+ // In fact assert that a recover should not be released before.
1340+ assert (!Info.second && " A recover was released for the struct when "
1341+ " there are accesses remaining!\n " );
1342+ if (auto *ParamD = dyn_cast<ParmVarDecl>(Decl)) {
1343+
1344+ auto StructName =
1345+ ParamD->getType ()->getPointeeType ().getAsString ();
1346+
1347+ auto *RecoverStatememt = new GenericStmt ();
1348+ RecoverStatememt->body =
1349+ StructName + " _recover " + ParamD->getNameAsString () + " ;" ;
1350+ TrackStructExplodeAndRecover.erase (It);
1351+
1352+ auto *NewSeq = new PulseSequence ();
1353+ NewSeq->assignS1 (Assignment);
1354+ NewSeq->assignS2 (RecoverStatememt);
1355+ if (RetSeq) {
1356+ RetSeq->assignS2 (NewSeq);
1357+ return RetSeq;
1358+ }
1359+
1360+ return NewSeq;
1361+ }
1362+ }
1363+
1364+ if (RetSeq) {
1365+ RetSeq->assignS2 (Assignment);
1366+ return RetSeq;
1367+ }
1368+
12591369 return Assignment;
12601370 }
12611371
@@ -1432,8 +1542,8 @@ PulseStmt *PulseVisitor::pulseFromStmt(Stmt *S, ExprMutationAnalyzer *Analyzer,
14321542
14331543 auto PulseCond =
14341544 getTermFromCExpr (Cond, Analyzer, ExprsBefore, Parent, Cond->getType (), Module);
1435- auto *PulseElse = pulseFromStmt (Else, Analyzer, Parent, Module);
1436- auto *PulseThen = pulseFromStmt (Then, Analyzer, Parent, Module);
1545+ auto *PulseElse = pulseFromStmt (Else, Analyzer, Parent, Module, CS );
1546+ auto *PulseThen = pulseFromStmt (Then, Analyzer, Parent, Module, CS );
14371547
14381548 auto PulseIfStmt = new PulseIf ();
14391549 PulseIfStmt->setTag (PulseStmtTag::If);
@@ -1551,7 +1661,8 @@ PulseStmt *PulseVisitor::pulseFromStmt(Stmt *S, ExprMutationAnalyzer *Analyzer,
15511661 }
15521662
15531663 PulseWhile->setTag (PulseStmtTag::WhileStmt);
1554- PulseWhile->Guard = pulseFromStmt (WhileCond, Analyzer, Parent, Module);
1664+ PulseWhile->Guard =
1665+ pulseFromStmt (WhileCond, Analyzer, Parent, Module, CS );
15551666 PulseWhile->Body = pulseFromCompoundStmt (CompundBody, Analyzer, Module);
15561667
15571668 return PulseWhile;
@@ -1560,7 +1671,8 @@ PulseStmt *PulseVisitor::pulseFromStmt(Stmt *S, ExprMutationAnalyzer *Analyzer,
15601671 auto *PulseWhile = new PulseWhileStmt ();
15611672 PulseWhile->setTag (PulseStmtTag::WhileStmt);
15621673
1563- PulseWhile->Guard = pulseFromStmt (WhileCond, Analyzer, Parent, Module);
1674+ PulseWhile->Guard =
1675+ pulseFromStmt (WhileCond, Analyzer, Parent, Module, CS );
15641676 PulseWhile->Body = pulseFromCompoundStmt (WhileBody, Analyzer, Module);
15651677
15661678 return PulseWhile;
@@ -1605,7 +1717,7 @@ PulseStmt *PulseVisitor::pulseFromStmt(Stmt *S, ExprMutationAnalyzer *Analyzer,
16051717 }
16061718 }
16071719 }
1608- NewSequence->assignS2 (pulseFromStmt (SubStmt, Analyzer, Parent, Module));
1720+ NewSequence->assignS2 (pulseFromStmt (SubStmt, Analyzer, Parent, Module, CS ));
16091721 return NewSequence;
16101722 } else {
16111723 llvm::outs () << " \n\n Print in pulseFromStmt\n " ;
@@ -1715,9 +1827,6 @@ PulseVisitor::getTermFromCExpr(Expr *E, ExprMutationAnalyzer *MutAnalyzer,
17151827 // Wrap Call Expr into a Paren to be safe.
17161828 auto *NewParen = new Paren ();
17171829 NewParen->setInnerExpr (NewAppENode);
1718-
1719- assert (ExprsBefore.empty () && " Unreleased expressions!\n " );
1720-
17211830 return NewParen;
17221831
17231832 llvm::outs () << " \n\n Print Expresion in PulseVisitor::getTermFromCExpr "
@@ -2049,8 +2158,7 @@ PulseVisitor::getTermFromCExpr(Expr *E, ExprMutationAnalyzer *MutAnalyzer,
20492158 assert (false && " Should not reach here!" );
20502159 return nullptr ;
20512160 } else if (auto *ME = dyn_cast<MemberExpr>(E)) {
2052-
2053-
2161+
20542162 auto *MemberExprDecl = ME ->getMemberDecl ();
20552163
20562164 auto *BaseExpr = ME ->getBase ()->IgnoreParens ()->IgnoreImpCasts ();
0 commit comments