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