xref: /aosp_15_r20/external/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===- ThreadSafetyCommon.h ------------------------------------*- C++ --*-===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // Parts of thread safety analysis that are not specific to thread safety
11*67e74705SXin Li // itself have been factored into classes here, where they can be potentially
12*67e74705SXin Li // used by other analyses.  Currently these include:
13*67e74705SXin Li //
14*67e74705SXin Li // * Generalize clang CFG visitors.
15*67e74705SXin Li // * Conversion of the clang CFG to SSA form.
16*67e74705SXin Li // * Translation of clang Exprs to TIL SExprs
17*67e74705SXin Li //
18*67e74705SXin Li // UNDER CONSTRUCTION.  USE AT YOUR OWN RISK.
19*67e74705SXin Li //
20*67e74705SXin Li //===----------------------------------------------------------------------===//
21*67e74705SXin Li 
22*67e74705SXin Li #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
23*67e74705SXin Li #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
24*67e74705SXin Li 
25*67e74705SXin Li #include "clang/Analysis/Analyses/PostOrderCFGView.h"
26*67e74705SXin Li #include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
27*67e74705SXin Li #include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
28*67e74705SXin Li #include "clang/Analysis/AnalysisContext.h"
29*67e74705SXin Li #include "clang/Basic/OperatorKinds.h"
30*67e74705SXin Li #include <memory>
31*67e74705SXin Li #include <ostream>
32*67e74705SXin Li #include <sstream>
33*67e74705SXin Li #include <vector>
34*67e74705SXin Li 
35*67e74705SXin Li 
36*67e74705SXin Li namespace clang {
37*67e74705SXin Li namespace threadSafety {
38*67e74705SXin Li 
39*67e74705SXin Li 
40*67e74705SXin Li // Various helper functions on til::SExpr
41*67e74705SXin Li namespace sx {
42*67e74705SXin Li 
equals(const til::SExpr * E1,const til::SExpr * E2)43*67e74705SXin Li inline bool equals(const til::SExpr *E1, const til::SExpr *E2) {
44*67e74705SXin Li   return til::EqualsComparator::compareExprs(E1, E2);
45*67e74705SXin Li }
46*67e74705SXin Li 
matches(const til::SExpr * E1,const til::SExpr * E2)47*67e74705SXin Li inline bool matches(const til::SExpr *E1, const til::SExpr *E2) {
48*67e74705SXin Li   // We treat a top-level wildcard as the "univsersal" lock.
49*67e74705SXin Li   // It matches everything for the purpose of checking locks, but not
50*67e74705SXin Li   // for unlocking them.
51*67e74705SXin Li   if (isa<til::Wildcard>(E1))
52*67e74705SXin Li     return isa<til::Wildcard>(E2);
53*67e74705SXin Li   if (isa<til::Wildcard>(E2))
54*67e74705SXin Li     return isa<til::Wildcard>(E1);
55*67e74705SXin Li 
56*67e74705SXin Li   return til::MatchComparator::compareExprs(E1, E2);
57*67e74705SXin Li }
58*67e74705SXin Li 
partiallyMatches(const til::SExpr * E1,const til::SExpr * E2)59*67e74705SXin Li inline bool partiallyMatches(const til::SExpr *E1, const til::SExpr *E2) {
60*67e74705SXin Li   const auto *PE1 = dyn_cast_or_null<til::Project>(E1);
61*67e74705SXin Li   if (!PE1)
62*67e74705SXin Li     return false;
63*67e74705SXin Li   const auto *PE2 = dyn_cast_or_null<til::Project>(E2);
64*67e74705SXin Li   if (!PE2)
65*67e74705SXin Li     return false;
66*67e74705SXin Li   return PE1->clangDecl() == PE2->clangDecl();
67*67e74705SXin Li }
68*67e74705SXin Li 
toString(const til::SExpr * E)69*67e74705SXin Li inline std::string toString(const til::SExpr *E) {
70*67e74705SXin Li   std::stringstream ss;
71*67e74705SXin Li   til::StdPrinter::print(E, ss);
72*67e74705SXin Li   return ss.str();
73*67e74705SXin Li }
74*67e74705SXin Li 
75*67e74705SXin Li }  // end namespace sx
76*67e74705SXin Li 
77*67e74705SXin Li 
78*67e74705SXin Li 
79*67e74705SXin Li // This class defines the interface of a clang CFG Visitor.
80*67e74705SXin Li // CFGWalker will invoke the following methods.
81*67e74705SXin Li // Note that methods are not virtual; the visitor is templatized.
82*67e74705SXin Li class CFGVisitor {
83*67e74705SXin Li   // Enter the CFG for Decl D, and perform any initial setup operations.
enterCFG(CFG * Cfg,const NamedDecl * D,const CFGBlock * First)84*67e74705SXin Li   void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First) {}
85*67e74705SXin Li 
86*67e74705SXin Li   // Enter a CFGBlock.
enterCFGBlock(const CFGBlock * B)87*67e74705SXin Li   void enterCFGBlock(const CFGBlock *B) {}
88*67e74705SXin Li 
89*67e74705SXin Li   // Returns true if this visitor implements handlePredecessor
visitPredecessors()90*67e74705SXin Li   bool visitPredecessors() { return true; }
91*67e74705SXin Li 
92*67e74705SXin Li   // Process a predecessor edge.
handlePredecessor(const CFGBlock * Pred)93*67e74705SXin Li   void handlePredecessor(const CFGBlock *Pred) {}
94*67e74705SXin Li 
95*67e74705SXin Li   // Process a successor back edge to a previously visited block.
handlePredecessorBackEdge(const CFGBlock * Pred)96*67e74705SXin Li   void handlePredecessorBackEdge(const CFGBlock *Pred) {}
97*67e74705SXin Li 
98*67e74705SXin Li   // Called just before processing statements.
enterCFGBlockBody(const CFGBlock * B)99*67e74705SXin Li   void enterCFGBlockBody(const CFGBlock *B) {}
100*67e74705SXin Li 
101*67e74705SXin Li   // Process an ordinary statement.
handleStatement(const Stmt * S)102*67e74705SXin Li   void handleStatement(const Stmt *S) {}
103*67e74705SXin Li 
104*67e74705SXin Li   // Process a destructor call
handleDestructorCall(const VarDecl * VD,const CXXDestructorDecl * DD)105*67e74705SXin Li   void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {}
106*67e74705SXin Li 
107*67e74705SXin Li   // Called after all statements have been handled.
exitCFGBlockBody(const CFGBlock * B)108*67e74705SXin Li   void exitCFGBlockBody(const CFGBlock *B) {}
109*67e74705SXin Li 
110*67e74705SXin Li   // Return true
visitSuccessors()111*67e74705SXin Li   bool visitSuccessors() { return true; }
112*67e74705SXin Li 
113*67e74705SXin Li   // Process a successor edge.
handleSuccessor(const CFGBlock * Succ)114*67e74705SXin Li   void handleSuccessor(const CFGBlock *Succ) {}
115*67e74705SXin Li 
116*67e74705SXin Li   // Process a successor back edge to a previously visited block.
handleSuccessorBackEdge(const CFGBlock * Succ)117*67e74705SXin Li   void handleSuccessorBackEdge(const CFGBlock *Succ) {}
118*67e74705SXin Li 
119*67e74705SXin Li   // Leave a CFGBlock.
exitCFGBlock(const CFGBlock * B)120*67e74705SXin Li   void exitCFGBlock(const CFGBlock *B) {}
121*67e74705SXin Li 
122*67e74705SXin Li   // Leave the CFG, and perform any final cleanup operations.
exitCFG(const CFGBlock * Last)123*67e74705SXin Li   void exitCFG(const CFGBlock *Last) {}
124*67e74705SXin Li };
125*67e74705SXin Li 
126*67e74705SXin Li 
127*67e74705SXin Li // Walks the clang CFG, and invokes methods on a given CFGVisitor.
128*67e74705SXin Li class CFGWalker {
129*67e74705SXin Li public:
CFGWalker()130*67e74705SXin Li   CFGWalker() : CFGraph(nullptr), ACtx(nullptr), SortedGraph(nullptr) {}
131*67e74705SXin Li 
132*67e74705SXin Li   // Initialize the CFGWalker.  This setup only needs to be done once, even
133*67e74705SXin Li   // if there are multiple passes over the CFG.
init(AnalysisDeclContext & AC)134*67e74705SXin Li   bool init(AnalysisDeclContext &AC) {
135*67e74705SXin Li     ACtx = &AC;
136*67e74705SXin Li     CFGraph = AC.getCFG();
137*67e74705SXin Li     if (!CFGraph)
138*67e74705SXin Li       return false;
139*67e74705SXin Li 
140*67e74705SXin Li     // Ignore anonymous functions.
141*67e74705SXin Li     if (!dyn_cast_or_null<NamedDecl>(AC.getDecl()))
142*67e74705SXin Li       return false;
143*67e74705SXin Li 
144*67e74705SXin Li     SortedGraph = AC.getAnalysis<PostOrderCFGView>();
145*67e74705SXin Li     if (!SortedGraph)
146*67e74705SXin Li       return false;
147*67e74705SXin Li 
148*67e74705SXin Li     return true;
149*67e74705SXin Li   }
150*67e74705SXin Li 
151*67e74705SXin Li   // Traverse the CFG, calling methods on V as appropriate.
152*67e74705SXin Li   template <class Visitor>
walk(Visitor & V)153*67e74705SXin Li   void walk(Visitor &V) {
154*67e74705SXin Li     PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
155*67e74705SXin Li 
156*67e74705SXin Li     V.enterCFG(CFGraph, getDecl(), &CFGraph->getEntry());
157*67e74705SXin Li 
158*67e74705SXin Li     for (const auto *CurrBlock : *SortedGraph) {
159*67e74705SXin Li       VisitedBlocks.insert(CurrBlock);
160*67e74705SXin Li 
161*67e74705SXin Li       V.enterCFGBlock(CurrBlock);
162*67e74705SXin Li 
163*67e74705SXin Li       // Process predecessors, handling back edges last
164*67e74705SXin Li       if (V.visitPredecessors()) {
165*67e74705SXin Li         SmallVector<CFGBlock*, 4> BackEdges;
166*67e74705SXin Li         // Process successors
167*67e74705SXin Li         for (CFGBlock::const_pred_iterator SI = CurrBlock->pred_begin(),
168*67e74705SXin Li                                            SE = CurrBlock->pred_end();
169*67e74705SXin Li              SI != SE; ++SI) {
170*67e74705SXin Li           if (*SI == nullptr)
171*67e74705SXin Li             continue;
172*67e74705SXin Li 
173*67e74705SXin Li           if (!VisitedBlocks.alreadySet(*SI)) {
174*67e74705SXin Li             BackEdges.push_back(*SI);
175*67e74705SXin Li             continue;
176*67e74705SXin Li           }
177*67e74705SXin Li           V.handlePredecessor(*SI);
178*67e74705SXin Li         }
179*67e74705SXin Li 
180*67e74705SXin Li         for (auto *Blk : BackEdges)
181*67e74705SXin Li           V.handlePredecessorBackEdge(Blk);
182*67e74705SXin Li       }
183*67e74705SXin Li 
184*67e74705SXin Li       V.enterCFGBlockBody(CurrBlock);
185*67e74705SXin Li 
186*67e74705SXin Li       // Process statements
187*67e74705SXin Li       for (const auto &BI : *CurrBlock) {
188*67e74705SXin Li         switch (BI.getKind()) {
189*67e74705SXin Li         case CFGElement::Statement: {
190*67e74705SXin Li           V.handleStatement(BI.castAs<CFGStmt>().getStmt());
191*67e74705SXin Li           break;
192*67e74705SXin Li         }
193*67e74705SXin Li         case CFGElement::AutomaticObjectDtor: {
194*67e74705SXin Li           CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>();
195*67e74705SXin Li           CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>(
196*67e74705SXin Li               AD.getDestructorDecl(ACtx->getASTContext()));
197*67e74705SXin Li           VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl());
198*67e74705SXin Li           V.handleDestructorCall(VD, DD);
199*67e74705SXin Li           break;
200*67e74705SXin Li         }
201*67e74705SXin Li         default:
202*67e74705SXin Li           break;
203*67e74705SXin Li         }
204*67e74705SXin Li       }
205*67e74705SXin Li 
206*67e74705SXin Li       V.exitCFGBlockBody(CurrBlock);
207*67e74705SXin Li 
208*67e74705SXin Li       // Process successors, handling back edges first.
209*67e74705SXin Li       if (V.visitSuccessors()) {
210*67e74705SXin Li         SmallVector<CFGBlock*, 8> ForwardEdges;
211*67e74705SXin Li 
212*67e74705SXin Li         // Process successors
213*67e74705SXin Li         for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
214*67e74705SXin Li                                            SE = CurrBlock->succ_end();
215*67e74705SXin Li              SI != SE; ++SI) {
216*67e74705SXin Li           if (*SI == nullptr)
217*67e74705SXin Li             continue;
218*67e74705SXin Li 
219*67e74705SXin Li           if (!VisitedBlocks.alreadySet(*SI)) {
220*67e74705SXin Li             ForwardEdges.push_back(*SI);
221*67e74705SXin Li             continue;
222*67e74705SXin Li           }
223*67e74705SXin Li           V.handleSuccessorBackEdge(*SI);
224*67e74705SXin Li         }
225*67e74705SXin Li 
226*67e74705SXin Li         for (auto *Blk : ForwardEdges)
227*67e74705SXin Li           V.handleSuccessor(Blk);
228*67e74705SXin Li       }
229*67e74705SXin Li 
230*67e74705SXin Li       V.exitCFGBlock(CurrBlock);
231*67e74705SXin Li     }
232*67e74705SXin Li     V.exitCFG(&CFGraph->getExit());
233*67e74705SXin Li   }
234*67e74705SXin Li 
getGraph()235*67e74705SXin Li   const CFG *getGraph() const { return CFGraph; }
getGraph()236*67e74705SXin Li   CFG *getGraph() { return CFGraph; }
237*67e74705SXin Li 
getDecl()238*67e74705SXin Li   const NamedDecl *getDecl() const {
239*67e74705SXin Li     return dyn_cast<NamedDecl>(ACtx->getDecl());
240*67e74705SXin Li   }
241*67e74705SXin Li 
getSortedGraph()242*67e74705SXin Li   const PostOrderCFGView *getSortedGraph() const { return SortedGraph; }
243*67e74705SXin Li 
244*67e74705SXin Li private:
245*67e74705SXin Li   CFG *CFGraph;
246*67e74705SXin Li   AnalysisDeclContext *ACtx;
247*67e74705SXin Li   PostOrderCFGView *SortedGraph;
248*67e74705SXin Li };
249*67e74705SXin Li 
250*67e74705SXin Li 
251*67e74705SXin Li 
252*67e74705SXin Li 
253*67e74705SXin Li class CapabilityExpr {
254*67e74705SXin Li   // TODO: move this back into ThreadSafety.cpp
255*67e74705SXin Li   // This is specific to thread safety.  It is here because
256*67e74705SXin Li   // translateAttrExpr needs it, but that should be moved too.
257*67e74705SXin Li 
258*67e74705SXin Li private:
259*67e74705SXin Li   const til::SExpr* CapExpr;   ///< The capability expression.
260*67e74705SXin Li   bool Negated;                ///< True if this is a negative capability
261*67e74705SXin Li 
262*67e74705SXin Li public:
CapabilityExpr(const til::SExpr * E,bool Neg)263*67e74705SXin Li   CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {}
264*67e74705SXin Li 
sexpr()265*67e74705SXin Li   const til::SExpr* sexpr()    const { return CapExpr; }
negative()266*67e74705SXin Li   bool              negative() const { return Negated; }
267*67e74705SXin Li 
268*67e74705SXin Li   CapabilityExpr operator!() const {
269*67e74705SXin Li     return CapabilityExpr(CapExpr, !Negated);
270*67e74705SXin Li   }
271*67e74705SXin Li 
equals(const CapabilityExpr & other)272*67e74705SXin Li   bool equals(const CapabilityExpr &other) const {
273*67e74705SXin Li     return (Negated == other.Negated) && sx::equals(CapExpr, other.CapExpr);
274*67e74705SXin Li   }
275*67e74705SXin Li 
matches(const CapabilityExpr & other)276*67e74705SXin Li   bool matches(const CapabilityExpr &other) const {
277*67e74705SXin Li     return (Negated == other.Negated) && sx::matches(CapExpr, other.CapExpr);
278*67e74705SXin Li   }
279*67e74705SXin Li 
matchesUniv(const CapabilityExpr & CapE)280*67e74705SXin Li   bool matchesUniv(const CapabilityExpr &CapE) const {
281*67e74705SXin Li     return isUniversal() || matches(CapE);
282*67e74705SXin Li   }
283*67e74705SXin Li 
partiallyMatches(const CapabilityExpr & other)284*67e74705SXin Li   bool partiallyMatches(const CapabilityExpr &other) const {
285*67e74705SXin Li     return (Negated == other.Negated) &&
286*67e74705SXin Li             sx::partiallyMatches(CapExpr, other.CapExpr);
287*67e74705SXin Li   }
288*67e74705SXin Li 
valueDecl()289*67e74705SXin Li   const ValueDecl* valueDecl() const {
290*67e74705SXin Li     if (Negated || CapExpr == nullptr)
291*67e74705SXin Li       return nullptr;
292*67e74705SXin Li     if (auto *P = dyn_cast<til::Project>(CapExpr))
293*67e74705SXin Li       return P->clangDecl();
294*67e74705SXin Li     if (auto *P = dyn_cast<til::LiteralPtr>(CapExpr))
295*67e74705SXin Li       return P->clangDecl();
296*67e74705SXin Li     return nullptr;
297*67e74705SXin Li   }
298*67e74705SXin Li 
toString()299*67e74705SXin Li   std::string toString() const {
300*67e74705SXin Li     if (Negated)
301*67e74705SXin Li       return "!" + sx::toString(CapExpr);
302*67e74705SXin Li     return sx::toString(CapExpr);
303*67e74705SXin Li   }
304*67e74705SXin Li 
shouldIgnore()305*67e74705SXin Li   bool shouldIgnore() const { return CapExpr == nullptr; }
306*67e74705SXin Li 
isInvalid()307*67e74705SXin Li   bool isInvalid() const { return sexpr() && isa<til::Undefined>(sexpr()); }
308*67e74705SXin Li 
isUniversal()309*67e74705SXin Li   bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); }
310*67e74705SXin Li };
311*67e74705SXin Li 
312*67e74705SXin Li 
313*67e74705SXin Li 
314*67e74705SXin Li // Translate clang::Expr to til::SExpr.
315*67e74705SXin Li class SExprBuilder {
316*67e74705SXin Li public:
317*67e74705SXin Li   /// \brief Encapsulates the lexical context of a function call.  The lexical
318*67e74705SXin Li   /// context includes the arguments to the call, including the implicit object
319*67e74705SXin Li   /// argument.  When an attribute containing a mutex expression is attached to
320*67e74705SXin Li   /// a method, the expression may refer to formal parameters of the method.
321*67e74705SXin Li   /// Actual arguments must be substituted for formal parameters to derive
322*67e74705SXin Li   /// the appropriate mutex expression in the lexical context where the function
323*67e74705SXin Li   /// is called.  PrevCtx holds the context in which the arguments themselves
324*67e74705SXin Li   /// should be evaluated; multiple calling contexts can be chained together
325*67e74705SXin Li   /// by the lock_returned attribute.
326*67e74705SXin Li   struct CallingContext {
327*67e74705SXin Li     CallingContext  *Prev;      // The previous context; or 0 if none.
328*67e74705SXin Li     const NamedDecl *AttrDecl;  // The decl to which the attr is attached.
329*67e74705SXin Li     const Expr *SelfArg;        // Implicit object argument -- e.g. 'this'
330*67e74705SXin Li     unsigned NumArgs;           // Number of funArgs
331*67e74705SXin Li     const Expr *const *FunArgs; // Function arguments
332*67e74705SXin Li     bool SelfArrow;             // is Self referred to with -> or .?
333*67e74705SXin Li 
334*67e74705SXin Li     CallingContext(CallingContext *P, const NamedDecl *D = nullptr)
PrevCallingContext335*67e74705SXin Li         : Prev(P), AttrDecl(D), SelfArg(nullptr),
336*67e74705SXin Li           NumArgs(0), FunArgs(nullptr), SelfArrow(false)
337*67e74705SXin Li     {}
338*67e74705SXin Li   };
339*67e74705SXin Li 
SExprBuilder(til::MemRegionRef A)340*67e74705SXin Li   SExprBuilder(til::MemRegionRef A)
341*67e74705SXin Li       : Arena(A), SelfVar(nullptr), Scfg(nullptr), CurrentBB(nullptr),
342*67e74705SXin Li         CurrentBlockInfo(nullptr) {
343*67e74705SXin Li     // FIXME: we don't always have a self-variable.
344*67e74705SXin Li     SelfVar = new (Arena) til::Variable(nullptr);
345*67e74705SXin Li     SelfVar->setKind(til::Variable::VK_SFun);
346*67e74705SXin Li   }
347*67e74705SXin Li 
348*67e74705SXin Li   // Translate a clang expression in an attribute to a til::SExpr.
349*67e74705SXin Li   // Constructs the context from D, DeclExp, and SelfDecl.
350*67e74705SXin Li   CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D,
351*67e74705SXin Li                                    const Expr *DeclExp, VarDecl *SelfD=nullptr);
352*67e74705SXin Li 
353*67e74705SXin Li   CapabilityExpr translateAttrExpr(const Expr *AttrExp, CallingContext *Ctx);
354*67e74705SXin Li 
355*67e74705SXin Li   // Translate a clang statement or expression to a TIL expression.
356*67e74705SXin Li   // Also performs substitution of variables; Ctx provides the context.
357*67e74705SXin Li   // Dispatches on the type of S.
358*67e74705SXin Li   til::SExpr *translate(const Stmt *S, CallingContext *Ctx);
359*67e74705SXin Li   til::SCFG  *buildCFG(CFGWalker &Walker);
360*67e74705SXin Li 
361*67e74705SXin Li   til::SExpr *lookupStmt(const Stmt *S);
362*67e74705SXin Li 
lookupBlock(const CFGBlock * B)363*67e74705SXin Li   til::BasicBlock *lookupBlock(const CFGBlock *B) {
364*67e74705SXin Li     return BlockMap[B->getBlockID()];
365*67e74705SXin Li   }
366*67e74705SXin Li 
getCFG()367*67e74705SXin Li   const til::SCFG *getCFG() const { return Scfg; }
getCFG()368*67e74705SXin Li   til::SCFG *getCFG() { return Scfg; }
369*67e74705SXin Li 
370*67e74705SXin Li private:
371*67e74705SXin Li   til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE,
372*67e74705SXin Li                                    CallingContext *Ctx) ;
373*67e74705SXin Li   til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx);
374*67e74705SXin Li   til::SExpr *translateMemberExpr(const MemberExpr *ME, CallingContext *Ctx);
375*67e74705SXin Li   til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx,
376*67e74705SXin Li                                 const Expr *SelfE = nullptr);
377*67e74705SXin Li   til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME,
378*67e74705SXin Li                                          CallingContext *Ctx);
379*67e74705SXin Li   til::SExpr *translateCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE,
380*67e74705SXin Li                                            CallingContext *Ctx);
381*67e74705SXin Li   til::SExpr *translateUnaryOperator(const UnaryOperator *UO,
382*67e74705SXin Li                                      CallingContext *Ctx);
383*67e74705SXin Li   til::SExpr *translateBinOp(til::TIL_BinaryOpcode Op,
384*67e74705SXin Li                              const BinaryOperator *BO,
385*67e74705SXin Li                              CallingContext *Ctx, bool Reverse = false);
386*67e74705SXin Li   til::SExpr *translateBinAssign(til::TIL_BinaryOpcode Op,
387*67e74705SXin Li                                  const BinaryOperator *BO,
388*67e74705SXin Li                                  CallingContext *Ctx, bool Assign = false);
389*67e74705SXin Li   til::SExpr *translateBinaryOperator(const BinaryOperator *BO,
390*67e74705SXin Li                                       CallingContext *Ctx);
391*67e74705SXin Li   til::SExpr *translateCastExpr(const CastExpr *CE, CallingContext *Ctx);
392*67e74705SXin Li   til::SExpr *translateArraySubscriptExpr(const ArraySubscriptExpr *E,
393*67e74705SXin Li                                           CallingContext *Ctx);
394*67e74705SXin Li   til::SExpr *translateAbstractConditionalOperator(
395*67e74705SXin Li       const AbstractConditionalOperator *C, CallingContext *Ctx);
396*67e74705SXin Li 
397*67e74705SXin Li   til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx);
398*67e74705SXin Li 
399*67e74705SXin Li   // Map from statements in the clang CFG to SExprs in the til::SCFG.
400*67e74705SXin Li   typedef llvm::DenseMap<const Stmt*, til::SExpr*> StatementMap;
401*67e74705SXin Li 
402*67e74705SXin Li   // Map from clang local variables to indices in a LVarDefinitionMap.
403*67e74705SXin Li   typedef llvm::DenseMap<const ValueDecl *, unsigned> LVarIndexMap;
404*67e74705SXin Li 
405*67e74705SXin Li   // Map from local variable indices to SSA variables (or constants).
406*67e74705SXin Li   typedef std::pair<const ValueDecl *, til::SExpr *> NameVarPair;
407*67e74705SXin Li   typedef CopyOnWriteVector<NameVarPair> LVarDefinitionMap;
408*67e74705SXin Li 
409*67e74705SXin Li   struct BlockInfo {
410*67e74705SXin Li     LVarDefinitionMap ExitMap;
411*67e74705SXin Li     bool HasBackEdges;
412*67e74705SXin Li     unsigned UnprocessedSuccessors;   // Successors yet to be processed
413*67e74705SXin Li     unsigned ProcessedPredecessors;   // Predecessors already processed
414*67e74705SXin Li 
BlockInfoBlockInfo415*67e74705SXin Li     BlockInfo()
416*67e74705SXin Li         : HasBackEdges(false), UnprocessedSuccessors(0),
417*67e74705SXin Li           ProcessedPredecessors(0) {}
BlockInfoBlockInfo418*67e74705SXin Li     BlockInfo(BlockInfo &&RHS)
419*67e74705SXin Li         : ExitMap(std::move(RHS.ExitMap)),
420*67e74705SXin Li           HasBackEdges(RHS.HasBackEdges),
421*67e74705SXin Li           UnprocessedSuccessors(RHS.UnprocessedSuccessors),
422*67e74705SXin Li           ProcessedPredecessors(RHS.ProcessedPredecessors) {}
423*67e74705SXin Li 
424*67e74705SXin Li     BlockInfo &operator=(BlockInfo &&RHS) {
425*67e74705SXin Li       if (this != &RHS) {
426*67e74705SXin Li         ExitMap = std::move(RHS.ExitMap);
427*67e74705SXin Li         HasBackEdges = RHS.HasBackEdges;
428*67e74705SXin Li         UnprocessedSuccessors = RHS.UnprocessedSuccessors;
429*67e74705SXin Li         ProcessedPredecessors = RHS.ProcessedPredecessors;
430*67e74705SXin Li       }
431*67e74705SXin Li       return *this;
432*67e74705SXin Li     }
433*67e74705SXin Li 
434*67e74705SXin Li   private:
435*67e74705SXin Li     BlockInfo(const BlockInfo &) = delete;
436*67e74705SXin Li     void operator=(const BlockInfo &) = delete;
437*67e74705SXin Li   };
438*67e74705SXin Li 
439*67e74705SXin Li   // We implement the CFGVisitor API
440*67e74705SXin Li   friend class CFGWalker;
441*67e74705SXin Li 
442*67e74705SXin Li   void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First);
443*67e74705SXin Li   void enterCFGBlock(const CFGBlock *B);
visitPredecessors()444*67e74705SXin Li   bool visitPredecessors() { return true; }
445*67e74705SXin Li   void handlePredecessor(const CFGBlock *Pred);
446*67e74705SXin Li   void handlePredecessorBackEdge(const CFGBlock *Pred);
447*67e74705SXin Li   void enterCFGBlockBody(const CFGBlock *B);
448*67e74705SXin Li   void handleStatement(const Stmt *S);
449*67e74705SXin Li   void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD);
450*67e74705SXin Li   void exitCFGBlockBody(const CFGBlock *B);
visitSuccessors()451*67e74705SXin Li   bool visitSuccessors() { return true; }
452*67e74705SXin Li   void handleSuccessor(const CFGBlock *Succ);
453*67e74705SXin Li   void handleSuccessorBackEdge(const CFGBlock *Succ);
454*67e74705SXin Li   void exitCFGBlock(const CFGBlock *B);
455*67e74705SXin Li   void exitCFG(const CFGBlock *Last);
456*67e74705SXin Li 
insertStmt(const Stmt * S,til::SExpr * E)457*67e74705SXin Li   void insertStmt(const Stmt *S, til::SExpr *E) {
458*67e74705SXin Li     SMap.insert(std::make_pair(S, E));
459*67e74705SXin Li   }
460*67e74705SXin Li   til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD);
461*67e74705SXin Li 
462*67e74705SXin Li   til::SExpr *addStatement(til::SExpr *E, const Stmt *S,
463*67e74705SXin Li                            const ValueDecl *VD = nullptr);
464*67e74705SXin Li   til::SExpr *lookupVarDecl(const ValueDecl *VD);
465*67e74705SXin Li   til::SExpr *addVarDecl(const ValueDecl *VD, til::SExpr *E);
466*67e74705SXin Li   til::SExpr *updateVarDecl(const ValueDecl *VD, til::SExpr *E);
467*67e74705SXin Li 
468*67e74705SXin Li   void makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E);
469*67e74705SXin Li   void mergeEntryMap(LVarDefinitionMap Map);
470*67e74705SXin Li   void mergeEntryMapBackEdge();
471*67e74705SXin Li   void mergePhiNodesBackEdge(const CFGBlock *Blk);
472*67e74705SXin Li 
473*67e74705SXin Li private:
474*67e74705SXin Li   // Set to true when parsing capability expressions, which get translated
475*67e74705SXin Li   // inaccurately in order to hack around smart pointers etc.
476*67e74705SXin Li   static const bool CapabilityExprMode = true;
477*67e74705SXin Li 
478*67e74705SXin Li   til::MemRegionRef Arena;
479*67e74705SXin Li   til::Variable *SelfVar;       // Variable to use for 'this'.  May be null.
480*67e74705SXin Li 
481*67e74705SXin Li   til::SCFG *Scfg;
482*67e74705SXin Li   StatementMap SMap;                       // Map from Stmt to TIL Variables
483*67e74705SXin Li   LVarIndexMap LVarIdxMap;                 // Indices of clang local vars.
484*67e74705SXin Li   std::vector<til::BasicBlock *> BlockMap; // Map from clang to til BBs.
485*67e74705SXin Li   std::vector<BlockInfo> BBInfo;           // Extra information per BB.
486*67e74705SXin Li                                            // Indexed by clang BlockID.
487*67e74705SXin Li 
488*67e74705SXin Li   LVarDefinitionMap CurrentLVarMap;
489*67e74705SXin Li   std::vector<til::Phi*>   CurrentArguments;
490*67e74705SXin Li   std::vector<til::SExpr*> CurrentInstructions;
491*67e74705SXin Li   std::vector<til::Phi*>   IncompleteArgs;
492*67e74705SXin Li   til::BasicBlock *CurrentBB;
493*67e74705SXin Li   BlockInfo *CurrentBlockInfo;
494*67e74705SXin Li };
495*67e74705SXin Li 
496*67e74705SXin Li 
497*67e74705SXin Li // Dump an SCFG to llvm::errs().
498*67e74705SXin Li void printSCFG(CFGWalker &Walker);
499*67e74705SXin Li 
500*67e74705SXin Li 
501*67e74705SXin Li } // end namespace threadSafety
502*67e74705SXin Li 
503*67e74705SXin Li } // end namespace clang
504*67e74705SXin Li 
505*67e74705SXin Li #endif  // LLVM_CLANG_THREAD_SAFETY_COMMON_H
506