blob: 2c90b2a4be7411b2261e19afcebd3b51e5596432 [file] [log] [blame]
DeLesley Hutchinsb2213912014-04-07 18:09:54 +00001//===- ThreadSafetyCommon.cpp ----------------------------------*- C++ --*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Implementation of the interfaces declared in ThreadSafetyCommon.h
11//
12//===----------------------------------------------------------------------===//
13
Aaron Ballman28347a72014-04-09 21:12:04 +000014#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000015#include "clang/AST/Attr.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/ExprCXX.h"
18#include "clang/AST/StmtCXX.h"
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000019#include "clang/Analysis/Analyses/PostOrderCFGView.h"
DeLesley Hutchinsf7813c52014-04-08 22:21:22 +000020#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
DeLesley Hutchins7e615c22014-04-09 22:39:43 +000021#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000022#include "clang/Analysis/AnalysisContext.h"
23#include "clang/Analysis/CFG.h"
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000024#include "clang/Basic/OperatorKinds.h"
25#include "clang/Basic/SourceLocation.h"
26#include "clang/Basic/SourceManager.h"
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000027#include "llvm/ADT/DenseMap.h"
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000028#include "llvm/ADT/SmallVector.h"
29#include "llvm/ADT/StringRef.h"
DeLesley Hutchins7e615c22014-04-09 22:39:43 +000030
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +000031#include <algorithm>
32#include <climits>
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000033#include <vector>
34
35
36namespace clang {
37namespace threadSafety {
38
39typedef SExprBuilder::CallingContext CallingContext;
40
41
42til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) {
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +000043 auto It = SMap.find(S);
44 if (It != SMap.end())
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000045 return It->second;
Aaron Ballman3f993c12014-04-09 17:45:44 +000046 return nullptr;
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000047}
48
49void SExprBuilder::insertStmt(const Stmt *S, til::Variable *V) {
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +000050 SMap.insert(std::make_pair(S, V));
51}
52
53
54til::SCFG *SExprBuilder::buildCFG(CFGWalker &Walker) {
55 Walker.walk(*this);
56 return Scfg;
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000057}
58
59
60// Translate a clang statement or expression to a TIL expression.
61// Also performs substitution of variables; Ctx provides the context.
62// Dispatches on the type of S.
63til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +000064 if (!S)
65 return nullptr;
66
DeLesley Hutchinsb2213912014-04-07 18:09:54 +000067 // Check if S has already been translated and cached.
68 // This handles the lookup of SSA names for DeclRefExprs here.
69 if (til::SExpr *E = lookupStmt(S))
70 return E;
71
72 switch (S->getStmtClass()) {
73 case Stmt::DeclRefExprClass:
74 return translateDeclRefExpr(cast<DeclRefExpr>(S), Ctx);
75 case Stmt::CXXThisExprClass:
76 return translateCXXThisExpr(cast<CXXThisExpr>(S), Ctx);
77 case Stmt::MemberExprClass:
78 return translateMemberExpr(cast<MemberExpr>(S), Ctx);
79 case Stmt::CallExprClass:
80 return translateCallExpr(cast<CallExpr>(S), Ctx);
81 case Stmt::CXXMemberCallExprClass:
82 return translateCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), Ctx);
83 case Stmt::CXXOperatorCallExprClass:
84 return translateCXXOperatorCallExpr(cast<CXXOperatorCallExpr>(S), Ctx);
85 case Stmt::UnaryOperatorClass:
86 return translateUnaryOperator(cast<UnaryOperator>(S), Ctx);
87 case Stmt::BinaryOperatorClass:
88 return translateBinaryOperator(cast<BinaryOperator>(S), Ctx);
89
90 case Stmt::ArraySubscriptExprClass:
91 return translateArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Ctx);
92 case Stmt::ConditionalOperatorClass:
93 return translateConditionalOperator(cast<ConditionalOperator>(S), Ctx);
94 case Stmt::BinaryConditionalOperatorClass:
95 return translateBinaryConditionalOperator(
96 cast<BinaryConditionalOperator>(S), Ctx);
97
98 // We treat these as no-ops
99 case Stmt::ParenExprClass:
100 return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx);
101 case Stmt::ExprWithCleanupsClass:
102 return translate(cast<ExprWithCleanups>(S)->getSubExpr(), Ctx);
103 case Stmt::CXXBindTemporaryExprClass:
104 return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx);
105
106 // Collect all literals
107 case Stmt::CharacterLiteralClass:
108 case Stmt::CXXNullPtrLiteralExprClass:
109 case Stmt::GNUNullExprClass:
110 case Stmt::CXXBoolLiteralExprClass:
111 case Stmt::FloatingLiteralClass:
112 case Stmt::ImaginaryLiteralClass:
113 case Stmt::IntegerLiteralClass:
114 case Stmt::StringLiteralClass:
115 case Stmt::ObjCStringLiteralClass:
116 return new (Arena) til::Literal(cast<Expr>(S));
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000117
118 case Stmt::DeclStmtClass:
119 return translateDeclStmt(cast<DeclStmt>(S), Ctx);
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000120 default:
121 break;
122 }
123 if (const CastExpr *CE = dyn_cast<CastExpr>(S))
124 return translateCastExpr(CE, Ctx);
125
126 return new (Arena) til::Undefined(S);
127}
128
129
130til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE,
131 CallingContext *Ctx) {
132 const ValueDecl *VD = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
133
134 // Function parameters require substitution and/or renaming.
135 if (const ParmVarDecl *PV = dyn_cast_or_null<ParmVarDecl>(VD)) {
136 const FunctionDecl *FD =
137 cast<FunctionDecl>(PV->getDeclContext())->getCanonicalDecl();
138 unsigned I = PV->getFunctionScopeIndex();
139
140 if (Ctx && Ctx->FunArgs && FD == Ctx->AttrDecl->getCanonicalDecl()) {
141 // Substitute call arguments for references to function parameters
142 assert(I < Ctx->NumArgs);
143 return translate(Ctx->FunArgs[I], Ctx->Prev);
144 }
145 // Map the param back to the param of the original function declaration
146 // for consistent comparisons.
147 VD = FD->getParamDecl(I);
148 }
149
150 // For non-local variables, treat it as a referenced to a named object.
151 return new (Arena) til::LiteralPtr(VD);
152}
153
154
155til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE,
156 CallingContext *Ctx) {
157 // Substitute for 'this'
158 if (Ctx && Ctx->SelfArg)
159 return translate(Ctx->SelfArg, Ctx->Prev);
160 assert(SelfVar && "We have no variable for 'this'!");
161 return SelfVar;
162}
163
164
165til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME,
166 CallingContext *Ctx) {
167 til::SExpr *E = translate(ME->getBase(), Ctx);
168 E = new (Arena) til::SApply(E);
169 return new (Arena) til::Project(E, ME->getMemberDecl());
170}
171
172
173til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE,
174 CallingContext *Ctx) {
175 // TODO -- Lock returned
176 til::SExpr *E = translate(CE->getCallee(), Ctx);
Aaron Ballman3f993c12014-04-09 17:45:44 +0000177 for (const auto *Arg : CE->arguments()) {
178 til::SExpr *A = translate(Arg, Ctx);
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000179 E = new (Arena) til::Apply(E, A);
180 }
181 return new (Arena) til::Call(E, CE);
182}
183
184
185til::SExpr *SExprBuilder::translateCXXMemberCallExpr(
186 const CXXMemberCallExpr *ME, CallingContext *Ctx) {
187 return translateCallExpr(cast<CallExpr>(ME), Ctx);
188}
189
190
191til::SExpr *SExprBuilder::translateCXXOperatorCallExpr(
192 const CXXOperatorCallExpr *OCE, CallingContext *Ctx) {
193 return translateCallExpr(cast<CallExpr>(OCE), Ctx);
194}
195
196
197til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO,
198 CallingContext *Ctx) {
199 switch (UO->getOpcode()) {
200 case UO_PostInc:
201 case UO_PostDec:
202 case UO_PreInc:
203 case UO_PreDec:
204 return new (Arena) til::Undefined(UO);
205
206 // We treat these as no-ops
207 case UO_AddrOf:
208 case UO_Deref:
209 case UO_Plus:
210 return translate(UO->getSubExpr(), Ctx);
211
212 case UO_Minus:
213 case UO_Not:
214 case UO_LNot:
215 case UO_Real:
216 case UO_Imag:
Aaron Ballman3f993c12014-04-09 17:45:44 +0000217 case UO_Extension:
218 return new (Arena)
219 til::UnaryOp(UO->getOpcode(), translate(UO->getSubExpr(), Ctx));
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000220 }
221 return new (Arena) til::Undefined(UO);
222}
223
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000224
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000225til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO,
226 CallingContext *Ctx) {
227 switch (BO->getOpcode()) {
228 case BO_PtrMemD:
229 case BO_PtrMemI:
230 return new (Arena) til::Undefined(BO);
231
232 case BO_Mul:
233 case BO_Div:
234 case BO_Rem:
235 case BO_Add:
236 case BO_Sub:
237 case BO_Shl:
238 case BO_Shr:
239 case BO_LT:
240 case BO_GT:
241 case BO_LE:
242 case BO_GE:
243 case BO_EQ:
244 case BO_NE:
245 case BO_And:
246 case BO_Xor:
247 case BO_Or:
248 case BO_LAnd:
Aaron Ballman3f993c12014-04-09 17:45:44 +0000249 case BO_LOr:
250 return new (Arena)
251 til::BinaryOp(BO->getOpcode(), translate(BO->getLHS(), Ctx),
252 translate(BO->getRHS(), Ctx));
253
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000254 case BO_Assign: {
255 const Expr *LHS = BO->getLHS();
256 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHS)) {
257 const Expr *RHS = BO->getRHS();
258 til::SExpr *E1 = translate(RHS, Ctx);
259 return updateVarDecl(DRE->getDecl(), E1);
260 }
261 til::SExpr *E0 = translate(LHS, Ctx);
262 til::SExpr *E1 = translate(BO->getRHS(), Ctx);
263 return new (Arena) til::Store(E0, E1);
264 }
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000265 case BO_MulAssign:
266 case BO_DivAssign:
267 case BO_RemAssign:
268 case BO_AddAssign:
269 case BO_SubAssign:
270 case BO_ShlAssign:
271 case BO_ShrAssign:
272 case BO_AndAssign:
273 case BO_XorAssign:
274 case BO_OrAssign:
275 return new (Arena) til::Undefined(BO);
276
277 case BO_Comma:
278 // TODO: handle LHS
279 return translate(BO->getRHS(), Ctx);
280 }
281
282 return new (Arena) til::Undefined(BO);
283}
284
285
286til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE,
287 CallingContext *Ctx) {
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000288 clang::CastKind K = CE->getCastKind();
289 switch (K) {
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000290 case CK_LValueToRValue: {
291 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
292 til::SExpr *E0 = lookupVarDecl(DRE->getDecl());
293 if (E0)
294 return E0;
295 }
296 til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000297 return new (Arena) til::Load(E0);
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000298 }
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000299 case CK_NoOp:
300 case CK_DerivedToBase:
301 case CK_UncheckedDerivedToBase:
302 case CK_ArrayToPointerDecay:
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000303 case CK_FunctionToPointerDecay: {
304 til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000305 return E0;
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000306 }
307 default: {
308 til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000309 return new (Arena) til::Cast(K, E0);
310 }
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000311 }
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000312}
313
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000314
Aaron Ballman3f993c12014-04-09 17:45:44 +0000315til::SExpr *
316SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E,
317 CallingContext *Ctx) {
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000318 return new (Arena) til::Undefined(E);
319}
320
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000321
Aaron Ballman3f993c12014-04-09 17:45:44 +0000322til::SExpr *
323SExprBuilder::translateConditionalOperator(const ConditionalOperator *C,
324 CallingContext *Ctx) {
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000325 return new (Arena) til::Undefined(C);
326}
327
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000328
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000329til::SExpr *SExprBuilder::translateBinaryConditionalOperator(
330 const BinaryConditionalOperator *C, CallingContext *Ctx) {
331 return new (Arena) til::Undefined(C);
332}
333
DeLesley Hutchins7e615c22014-04-09 22:39:43 +0000334
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000335til::SExpr *
336SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) {
337 DeclGroupRef DGrp = S->getDeclGroup();
338 for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
339 if (VarDecl *VD = dyn_cast_or_null<VarDecl>(*I)) {
340 Expr *E = VD->getInit();
341 til::SExpr* SE = translate(E, Ctx);
DeLesley Hutchins7e615c22014-04-09 22:39:43 +0000342
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000343 // Add local variables with trivial type to the variable map
344 QualType T = VD->getType();
345 if (T.isTrivialType(VD->getASTContext())) {
346 return addVarDecl(VD, SE);
347 }
348 else {
349 // TODO: add alloca
350 }
351 }
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000352 }
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000353 return nullptr;
354}
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000355
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000356
357// If (E) is non-trivial, then add it to the current basic block, and
358// update the statement map so that S refers to E. Returns a new variable
359// that refers to E.
360// If E is trivial returns E.
361til::SExpr *SExprBuilder::addStatement(til::SExpr* E, const Stmt *S,
362 const ValueDecl *VD) {
363 if (!E)
364 return nullptr;
365 if (til::ThreadSafetyTIL::isTrivial(E))
366 return E;
367
368 til::Variable *V = new (Arena) til::Variable(E, VD);
369 V->setID(CurrentBlockID, CurrentVarID++);
370 CurrentBB->addInstr(V);
371 if (S)
372 insertStmt(S, V);
373 return V;
374}
375
376
377// Returns the current value of VD, if known, and nullptr otherwise.
378til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) {
379 auto It = IdxMap.find(VD);
380 if (It != IdxMap.end())
381 return CurrentNameMap[It->second].second;
382 return nullptr;
383}
384
385
386// if E is a til::Variable, update its clangDecl.
387inline void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) {
388 if (!E)
389 return;
390 if (til::Variable *V = dyn_cast<til::Variable>(E)) {
391 if (!V->clangDecl())
392 V->setClangDecl(VD);
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000393 }
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000394}
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000395
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000396// Adds a new variable declaration.
397til::SExpr *SExprBuilder::addVarDecl(const ValueDecl *VD, til::SExpr *E) {
398 maybeUpdateVD(E, VD);
399 IdxMap.insert(std::make_pair(VD, CurrentNameMap.size()));
400 CurrentNameMap.makeWritable();
401 CurrentNameMap.push_back(std::make_pair(VD, E));
402 return E;
403}
404
405
406// Updates a current variable declaration. (E.g. by assignment)
407til::SExpr *SExprBuilder::updateVarDecl(const ValueDecl *VD, til::SExpr *E) {
408 maybeUpdateVD(E, VD);
409 auto It = IdxMap.find(VD);
410 if (It == IdxMap.end()) {
411 til::SExpr *Ptr = new (Arena) til::LiteralPtr(VD);
412 til::SExpr *St = new (Arena) til::Store(Ptr, E);
413 return St;
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000414 }
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000415 CurrentNameMap.makeWritable();
416 CurrentNameMap.elem(It->second).second = E;
417 return E;
418}
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000419
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000420
421// Merge values from Map into the current entry map.
422void SExprBuilder::mergeEntryMap(NameVarMap Map) {
423 assert(CurrentBlockInfo && "Not processing a block!");
424
425 if (!CurrentNameMap.valid()) {
426 // Steal Map, using copy-on-write.
427 CurrentNameMap = std::move(Map);
428 return;
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000429 }
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000430 if (CurrentNameMap.sameAs(Map))
431 return; // Easy merge: maps from different predecessors are unchanged.
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000432
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000433 unsigned ESz = CurrentNameMap.size();
434 unsigned MSz = Map.size();
435 unsigned Sz = std::max(ESz, MSz);
436 bool W = CurrentNameMap.writable();
437 for (unsigned i=0; i<Sz; ++i) {
438 if (CurrentNameMap[i].first != Map[i].first) {
439 if (!W)
440 CurrentNameMap.makeWritable();
441 CurrentNameMap.downsize(i);
442 break;
443 }
444 if (CurrentNameMap[i].second != Map[i].second) {
445 til::Variable *V =
446 dyn_cast<til::Variable>(CurrentNameMap[i].second);
447 if (V && V->getBlockID() == CurrentBB->blockID()) {
448 // We already have a Phi node, so add the new variable.
449 til::Phi *Ph = dyn_cast<til::Phi>(V->definition());
450 assert(Ph && "Expecting Phi node.");
451 Ph->values()[CurrentArgIndex] = Map[i].second;
452 }
453 else {
454 if (!W)
455 CurrentNameMap.makeWritable();
456 unsigned NPreds = CurrentBB->numPredecessors();
457 assert(CurrentArgIndex > 0 && CurrentArgIndex < NPreds);
458
459 // Make a new phi node. All phi args up to the current index must
460 // be the same, and equal to the current NameMap value.
461 auto *Ph = new (Arena) til::Phi(Arena, NPreds);
462 Ph->values().setValues(NPreds, nullptr);
463 for (unsigned PIdx = 0; PIdx < CurrentArgIndex; ++PIdx)
464 Ph->values()[PIdx] = CurrentNameMap[i].second;
465 Ph->values()[CurrentArgIndex] = Map[i].second;
466
467 // Add phi node to current basic block.
468 auto *Var = new (Arena) til::Variable(Ph, CurrentNameMap[i].first);
469 Var->setID(CurrentBlockID, CurrentVarID++);
470 CurrentBB->addArgument(Var);
471 CurrentNameMap.elem(i).second = Var;
472 }
473 }
DeLesley Hutchins11bb30872014-04-07 22:56:24 +0000474 }
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000475 if (ESz > MSz) {
476 if (!W)
477 CurrentNameMap.makeWritable();
478 CurrentNameMap.downsize(Map.size());
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000479 }
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000480}
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000481
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000482
483
484void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D,
485 const CFGBlock *First) {
486 // Perform initial setup operations.
487 unsigned NBlocks = Cfg->getNumBlockIDs();
488 Scfg = new (Arena) til::SCFG(Arena, NBlocks);
489
490 // allocate all basic blocks immediately, to handle forward references.
491 BlockMap.reserve(NBlocks);
492 BBInfo.resize(NBlocks);
493 for (auto *B : *Cfg) {
494 auto *BB = new (Arena) til::BasicBlock(Arena, 0, B->size());
495 BlockMap.push_back(BB);
DeLesley Hutchins11bb30872014-04-07 22:56:24 +0000496 }
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000497 CallCtx = new SExprBuilder::CallingContext(D);
498}
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000499
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000500
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000501
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000502void SExprBuilder::enterCFGBlock(const CFGBlock *B) {
503 // Intialize TIL basic block and add it to the CFG.
504 CurrentBB = BlockMap[B->getBlockID()];
505 CurrentBB->setBlockID(CurrentBlockID);
506 CurrentBB->setNumPredecessors(B->pred_size());
507 Scfg->add(CurrentBB);
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000508
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000509 CurrentBlockInfo = &BBInfo[B->getBlockID()];
510 CurrentVarID = 0;
511 CurrentArgIndex = 0;
512
513 assert(!CurrentNameMap.valid() && "CurrentNameMap already initialized.");
514}
515
516
517void SExprBuilder::handlePredecessor(const CFGBlock *Pred) {
518 // Compute CurrentNameMap on entry from ExitMaps of predecessors
519
520 BlockInfo *PredInfo = &BBInfo[Pred->getBlockID()];
521 assert(PredInfo->SuccessorsToProcess > 0);
522
523 if (--PredInfo->SuccessorsToProcess == 0)
524 mergeEntryMap(std::move(PredInfo->ExitMap));
525 else
526 mergeEntryMap(PredInfo->ExitMap.clone());
527
528 ++CurrentArgIndex;
529}
530
531
532void SExprBuilder::handlePredecessorBackEdge(const CFGBlock *Pred) {
533 CurrentBlockInfo->HasBackEdges = true;
534}
535
536
537void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) { }
538
539
540void SExprBuilder::handleStatement(const Stmt *S) {
541 til::SExpr *E = translate(S, CallCtx);
542 addStatement(E, S);
543}
544
545
546void SExprBuilder::handleDestructorCall(const VarDecl *VD,
547 const CXXDestructorDecl *DD) {
548 til::SExpr *Sf = new (Arena) til::LiteralPtr(VD);
549 til::SExpr *Dr = new (Arena) til::LiteralPtr(DD);
550 til::SExpr *Ap = new (Arena) til::Apply(Dr, Sf);
551 til::SExpr *E = new (Arena) til::Call(Ap);
552 addStatement(E, nullptr);
553}
554
555
556
557void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {
558 unsigned N = B->succ_size();
559 auto It = B->succ_begin();
560 if (N == 1) {
561 til::BasicBlock *BB = *It ? BlockMap[(*It)->getBlockID()] : nullptr;
562 // TODO: set index
563 til::SExpr *Tm = new (Arena) til::Goto(BB, 0);
564 CurrentBB->setTerminator(Tm);
565 }
566 else if (N == 2) {
567 til::SExpr *C = translate(B->getTerminatorCondition(true), CallCtx);
568 til::BasicBlock *BB1 = *It ? BlockMap[(*It)->getBlockID()] : nullptr;
569 ++It;
570 til::BasicBlock *BB2 = *It ? BlockMap[(*It)->getBlockID()] : nullptr;
571 // TODO: set conditional, set index
572 til::SExpr *Tm = new (Arena) til::Branch(C, BB1, BB2);
573 CurrentBB->setTerminator(Tm);
574 }
575}
576
577
578void SExprBuilder::handleSuccessor(const CFGBlock *Succ) {
579 ++CurrentBlockInfo->SuccessorsToProcess;
580}
581
582
583void SExprBuilder::handleSuccessorBackEdge(const CFGBlock *Succ) {
584
585}
586
587
588void SExprBuilder::exitCFGBlock(const CFGBlock *B) {
589 CurrentBlockInfo->ExitMap = std::move(CurrentNameMap);
590 CurrentBlockID++;
591 CurrentBB = nullptr;
592 CurrentBlockInfo = nullptr;
593}
594
595
596void SExprBuilder::exitCFG(const CFGBlock *Last) {
597 CurrentBlockID = 0;
598 CurrentVarID = 0;
599 CurrentArgIndex = 0;
600}
601
602
603
604class LLVMPrinter : public til::PrettyPrinter<LLVMPrinter, llvm::raw_ostream> {
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000605};
606
607
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000608void printSCFG(CFGWalker &Walker) {
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000609 llvm::BumpPtrAllocator Bpa;
610 til::MemRegionRef Arena(&Bpa);
DeLesley Hutchinsaab9aff2014-04-15 23:23:19 +0000611 SExprBuilder builder(Arena);
612 til::SCFG *Cfg = builder.buildCFG(Walker);
613 LLVMPrinter::print(Cfg, llvm::errs());
DeLesley Hutchinsb2213912014-04-07 18:09:54 +0000614}
615
616
617
618} // end namespace threadSafety
619
620} // end namespace clang