1 //===- ThreadSafetyCommon.cpp ---------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Implementation of the interfaces declared in ThreadSafetyCommon.h
11 //===----------------------------------------------------------------------===//
13 #include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
14 #include "clang/AST/Attr.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/DeclGroup.h"
18 #include "clang/AST/DeclObjC.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprCXX.h"
21 #include "clang/AST/OperationKinds.h"
22 #include "clang/AST/Stmt.h"
23 #include "clang/AST/Type.h"
24 #include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
25 #include "clang/Analysis/CFG.h"
26 #include "clang/Basic/LLVM.h"
27 #include "clang/Basic/OperatorKinds.h"
28 #include "clang/Basic/Specifiers.h"
29 #include "llvm/ADT/StringExtras.h"
30 #include "llvm/ADT/StringRef.h"
31 #include "llvm/Support/Casting.h"
37 using namespace clang
;
38 using namespace threadSafety
;
40 // From ThreadSafetyUtil.h
41 std::string
threadSafety::getSourceLiteralString(const Expr
*CE
) {
42 switch (CE
->getStmtClass()) {
43 case Stmt::IntegerLiteralClass
:
44 return toString(cast
<IntegerLiteral
>(CE
)->getValue(), 10, true);
45 case Stmt::StringLiteralClass
: {
46 std::string
ret("\"");
47 ret
+= cast
<StringLiteral
>(CE
)->getString();
51 case Stmt::CharacterLiteralClass
:
52 case Stmt::CXXNullPtrLiteralExprClass
:
53 case Stmt::GNUNullExprClass
:
54 case Stmt::CXXBoolLiteralExprClass
:
55 case Stmt::FloatingLiteralClass
:
56 case Stmt::ImaginaryLiteralClass
:
57 case Stmt::ObjCStringLiteralClass
:
63 // Return true if E is a variable that points to an incomplete Phi node.
64 static bool isIncompletePhi(const til::SExpr
*E
) {
65 if (const auto *Ph
= dyn_cast
<til::Phi
>(E
))
66 return Ph
->status() == til::Phi::PH_Incomplete
;
70 using CallingContext
= SExprBuilder::CallingContext
;
72 til::SExpr
*SExprBuilder::lookupStmt(const Stmt
*S
) { return SMap
.lookup(S
); }
74 til::SCFG
*SExprBuilder::buildCFG(CFGWalker
&Walker
) {
79 static bool isCalleeArrow(const Expr
*E
) {
80 const auto *ME
= dyn_cast
<MemberExpr
>(E
->IgnoreParenCasts());
81 return ME
? ME
->isArrow() : false;
84 static StringRef
ClassifyDiagnostic(const CapabilityAttr
*A
) {
88 static StringRef
ClassifyDiagnostic(QualType VDT
) {
89 // We need to look at the declaration of the type of the value to determine
90 // which it is. The type should either be a record or a typedef, or a pointer
91 // or reference thereof.
92 if (const auto *RT
= VDT
->getAs
<RecordType
>()) {
93 if (const auto *RD
= RT
->getDecl())
94 if (const auto *CA
= RD
->getAttr
<CapabilityAttr
>())
95 return ClassifyDiagnostic(CA
);
96 } else if (const auto *TT
= VDT
->getAs
<TypedefType
>()) {
97 if (const auto *TD
= TT
->getDecl())
98 if (const auto *CA
= TD
->getAttr
<CapabilityAttr
>())
99 return ClassifyDiagnostic(CA
);
100 } else if (VDT
->isPointerType() || VDT
->isReferenceType())
101 return ClassifyDiagnostic(VDT
->getPointeeType());
106 /// Translate a clang expression in an attribute to a til::SExpr.
107 /// Constructs the context from D, DeclExp, and SelfDecl.
109 /// \param AttrExp The expression to translate.
110 /// \param D The declaration to which the attribute is attached.
111 /// \param DeclExp An expression involving the Decl to which the attribute
112 /// is attached. E.g. the call to a function.
113 /// \param Self S-expression to substitute for a \ref CXXThisExpr.
114 CapabilityExpr
SExprBuilder::translateAttrExpr(const Expr
*AttrExp
,
118 // If we are processing a raw attribute expression, with no substitutions.
119 if (!DeclExp
&& !Self
)
120 return translateAttrExpr(AttrExp
, nullptr);
122 CallingContext
Ctx(nullptr, D
);
124 // Examine DeclExp to find SelfArg and FunArgs, which are used to substitute
125 // for formal parameters when we call buildMutexID later.
127 /* We'll use Self. */;
128 else if (const auto *ME
= dyn_cast
<MemberExpr
>(DeclExp
)) {
129 Ctx
.SelfArg
= ME
->getBase();
130 Ctx
.SelfArrow
= ME
->isArrow();
131 } else if (const auto *CE
= dyn_cast
<CXXMemberCallExpr
>(DeclExp
)) {
132 Ctx
.SelfArg
= CE
->getImplicitObjectArgument();
133 Ctx
.SelfArrow
= isCalleeArrow(CE
->getCallee());
134 Ctx
.NumArgs
= CE
->getNumArgs();
135 Ctx
.FunArgs
= CE
->getArgs();
136 } else if (const auto *CE
= dyn_cast
<CallExpr
>(DeclExp
)) {
137 Ctx
.NumArgs
= CE
->getNumArgs();
138 Ctx
.FunArgs
= CE
->getArgs();
139 } else if (const auto *CE
= dyn_cast
<CXXConstructExpr
>(DeclExp
)) {
140 Ctx
.SelfArg
= nullptr; // Will be set below
141 Ctx
.NumArgs
= CE
->getNumArgs();
142 Ctx
.FunArgs
= CE
->getArgs();
146 assert(!Ctx
.SelfArg
&& "Ambiguous self argument");
149 // If the attribute has no arguments, then assume the argument is "this".
151 return CapabilityExpr(
152 Self
, ClassifyDiagnostic(cast
<CXXMethodDecl
>(D
)->getThisObjectType()),
154 else // For most attributes.
155 return translateAttrExpr(AttrExp
, &Ctx
);
158 // If the attribute has no arguments, then assume the argument is "this".
160 return translateAttrExpr(cast
<const Expr
*>(Ctx
.SelfArg
), nullptr);
161 else // For most attributes.
162 return translateAttrExpr(AttrExp
, &Ctx
);
165 /// Translate a clang expression in an attribute to a til::SExpr.
166 // This assumes a CallingContext has already been created.
167 CapabilityExpr
SExprBuilder::translateAttrExpr(const Expr
*AttrExp
,
168 CallingContext
*Ctx
) {
170 return CapabilityExpr();
172 if (const auto* SLit
= dyn_cast
<StringLiteral
>(AttrExp
)) {
173 if (SLit
->getString() == StringRef("*"))
174 // The "*" expr is a universal lock, which essentially turns off
175 // checks until it is removed from the lockset.
176 return CapabilityExpr(new (Arena
) til::Wildcard(), StringRef("wildcard"),
179 // Ignore other string literals for now.
180 return CapabilityExpr();
184 if (const auto *OE
= dyn_cast
<CXXOperatorCallExpr
>(AttrExp
)) {
185 if (OE
->getOperator() == OO_Exclaim
) {
187 AttrExp
= OE
->getArg(0);
190 else if (const auto *UO
= dyn_cast
<UnaryOperator
>(AttrExp
)) {
191 if (UO
->getOpcode() == UO_LNot
) {
193 AttrExp
= UO
->getSubExpr();
197 til::SExpr
*E
= translate(AttrExp
, Ctx
);
199 // Trap mutex expressions like nullptr, or 0.
200 // Any literal value is nonsense.
201 if (!E
|| isa
<til::Literal
>(E
))
202 return CapabilityExpr();
204 StringRef Kind
= ClassifyDiagnostic(AttrExp
->getType());
206 // Hack to deal with smart pointers -- strip off top-level pointer casts.
207 if (const auto *CE
= dyn_cast
<til::Cast
>(E
)) {
208 if (CE
->castOpcode() == til::CAST_objToPtr
)
209 return CapabilityExpr(CE
->expr(), Kind
, Neg
);
211 return CapabilityExpr(E
, Kind
, Neg
);
214 til::LiteralPtr
*SExprBuilder::createVariable(const VarDecl
*VD
) {
215 return new (Arena
) til::LiteralPtr(VD
);
218 std::pair
<til::LiteralPtr
*, StringRef
>
219 SExprBuilder::createThisPlaceholder(const Expr
*Exp
) {
220 return {new (Arena
) til::LiteralPtr(nullptr),
221 ClassifyDiagnostic(Exp
->getType())};
224 // Translate a clang statement or expression to a TIL expression.
225 // Also performs substitution of variables; Ctx provides the context.
226 // Dispatches on the type of S.
227 til::SExpr
*SExprBuilder::translate(const Stmt
*S
, CallingContext
*Ctx
) {
231 // Check if S has already been translated and cached.
232 // This handles the lookup of SSA names for DeclRefExprs here.
233 if (til::SExpr
*E
= lookupStmt(S
))
236 switch (S
->getStmtClass()) {
237 case Stmt::DeclRefExprClass
:
238 return translateDeclRefExpr(cast
<DeclRefExpr
>(S
), Ctx
);
239 case Stmt::CXXThisExprClass
:
240 return translateCXXThisExpr(cast
<CXXThisExpr
>(S
), Ctx
);
241 case Stmt::MemberExprClass
:
242 return translateMemberExpr(cast
<MemberExpr
>(S
), Ctx
);
243 case Stmt::ObjCIvarRefExprClass
:
244 return translateObjCIVarRefExpr(cast
<ObjCIvarRefExpr
>(S
), Ctx
);
245 case Stmt::CallExprClass
:
246 return translateCallExpr(cast
<CallExpr
>(S
), Ctx
);
247 case Stmt::CXXMemberCallExprClass
:
248 return translateCXXMemberCallExpr(cast
<CXXMemberCallExpr
>(S
), Ctx
);
249 case Stmt::CXXOperatorCallExprClass
:
250 return translateCXXOperatorCallExpr(cast
<CXXOperatorCallExpr
>(S
), Ctx
);
251 case Stmt::UnaryOperatorClass
:
252 return translateUnaryOperator(cast
<UnaryOperator
>(S
), Ctx
);
253 case Stmt::BinaryOperatorClass
:
254 case Stmt::CompoundAssignOperatorClass
:
255 return translateBinaryOperator(cast
<BinaryOperator
>(S
), Ctx
);
257 case Stmt::ArraySubscriptExprClass
:
258 return translateArraySubscriptExpr(cast
<ArraySubscriptExpr
>(S
), Ctx
);
259 case Stmt::ConditionalOperatorClass
:
260 return translateAbstractConditionalOperator(
261 cast
<ConditionalOperator
>(S
), Ctx
);
262 case Stmt::BinaryConditionalOperatorClass
:
263 return translateAbstractConditionalOperator(
264 cast
<BinaryConditionalOperator
>(S
), Ctx
);
266 // We treat these as no-ops
267 case Stmt::ConstantExprClass
:
268 return translate(cast
<ConstantExpr
>(S
)->getSubExpr(), Ctx
);
269 case Stmt::ParenExprClass
:
270 return translate(cast
<ParenExpr
>(S
)->getSubExpr(), Ctx
);
271 case Stmt::ExprWithCleanupsClass
:
272 return translate(cast
<ExprWithCleanups
>(S
)->getSubExpr(), Ctx
);
273 case Stmt::CXXBindTemporaryExprClass
:
274 return translate(cast
<CXXBindTemporaryExpr
>(S
)->getSubExpr(), Ctx
);
275 case Stmt::MaterializeTemporaryExprClass
:
276 return translate(cast
<MaterializeTemporaryExpr
>(S
)->getSubExpr(), Ctx
);
278 // Collect all literals
279 case Stmt::CharacterLiteralClass
:
280 case Stmt::CXXNullPtrLiteralExprClass
:
281 case Stmt::GNUNullExprClass
:
282 case Stmt::CXXBoolLiteralExprClass
:
283 case Stmt::FloatingLiteralClass
:
284 case Stmt::ImaginaryLiteralClass
:
285 case Stmt::IntegerLiteralClass
:
286 case Stmt::StringLiteralClass
:
287 case Stmt::ObjCStringLiteralClass
:
288 return new (Arena
) til::Literal(cast
<Expr
>(S
));
290 case Stmt::DeclStmtClass
:
291 return translateDeclStmt(cast
<DeclStmt
>(S
), Ctx
);
295 if (const auto *CE
= dyn_cast
<CastExpr
>(S
))
296 return translateCastExpr(CE
, Ctx
);
298 return new (Arena
) til::Undefined(S
);
301 til::SExpr
*SExprBuilder::translateDeclRefExpr(const DeclRefExpr
*DRE
,
302 CallingContext
*Ctx
) {
303 const auto *VD
= cast
<ValueDecl
>(DRE
->getDecl()->getCanonicalDecl());
305 // Function parameters require substitution and/or renaming.
306 if (const auto *PV
= dyn_cast
<ParmVarDecl
>(VD
)) {
307 unsigned I
= PV
->getFunctionScopeIndex();
308 const DeclContext
*D
= PV
->getDeclContext();
309 if (Ctx
&& Ctx
->FunArgs
) {
310 const Decl
*Canonical
= Ctx
->AttrDecl
->getCanonicalDecl();
311 if (isa
<FunctionDecl
>(D
)
312 ? (cast
<FunctionDecl
>(D
)->getCanonicalDecl() == Canonical
)
313 : (cast
<ObjCMethodDecl
>(D
)->getCanonicalDecl() == Canonical
)) {
314 // Substitute call arguments for references to function parameters
315 assert(I
< Ctx
->NumArgs
);
316 return translate(Ctx
->FunArgs
[I
], Ctx
->Prev
);
319 // Map the param back to the param of the original function declaration
320 // for consistent comparisons.
321 VD
= isa
<FunctionDecl
>(D
)
322 ? cast
<FunctionDecl
>(D
)->getCanonicalDecl()->getParamDecl(I
)
323 : cast
<ObjCMethodDecl
>(D
)->getCanonicalDecl()->getParamDecl(I
);
326 // For non-local variables, treat it as a reference to a named object.
327 return new (Arena
) til::LiteralPtr(VD
);
330 til::SExpr
*SExprBuilder::translateCXXThisExpr(const CXXThisExpr
*TE
,
331 CallingContext
*Ctx
) {
332 // Substitute for 'this'
333 if (Ctx
&& Ctx
->SelfArg
) {
334 if (const auto *SelfArg
= dyn_cast
<const Expr
*>(Ctx
->SelfArg
))
335 return translate(SelfArg
, Ctx
->Prev
);
337 return cast
<til::SExpr
*>(Ctx
->SelfArg
);
339 assert(SelfVar
&& "We have no variable for 'this'!");
343 static const ValueDecl
*getValueDeclFromSExpr(const til::SExpr
*E
) {
344 if (const auto *V
= dyn_cast
<til::Variable
>(E
))
345 return V
->clangDecl();
346 if (const auto *Ph
= dyn_cast
<til::Phi
>(E
))
347 return Ph
->clangDecl();
348 if (const auto *P
= dyn_cast
<til::Project
>(E
))
349 return P
->clangDecl();
350 if (const auto *L
= dyn_cast
<til::LiteralPtr
>(E
))
351 return L
->clangDecl();
355 static bool hasAnyPointerType(const til::SExpr
*E
) {
356 auto *VD
= getValueDeclFromSExpr(E
);
357 if (VD
&& VD
->getType()->isAnyPointerType())
359 if (const auto *C
= dyn_cast
<til::Cast
>(E
))
360 return C
->castOpcode() == til::CAST_objToPtr
;
365 // Grab the very first declaration of virtual method D
366 static const CXXMethodDecl
*getFirstVirtualDecl(const CXXMethodDecl
*D
) {
368 D
= D
->getCanonicalDecl();
369 auto OverriddenMethods
= D
->overridden_methods();
370 if (OverriddenMethods
.begin() == OverriddenMethods
.end())
371 return D
; // Method does not override anything
372 // FIXME: this does not work with multiple inheritance.
373 D
= *OverriddenMethods
.begin();
378 til::SExpr
*SExprBuilder::translateMemberExpr(const MemberExpr
*ME
,
379 CallingContext
*Ctx
) {
380 til::SExpr
*BE
= translate(ME
->getBase(), Ctx
);
381 til::SExpr
*E
= new (Arena
) til::SApply(BE
);
383 const auto *D
= cast
<ValueDecl
>(ME
->getMemberDecl()->getCanonicalDecl());
384 if (const auto *VD
= dyn_cast
<CXXMethodDecl
>(D
))
385 D
= getFirstVirtualDecl(VD
);
387 til::Project
*P
= new (Arena
) til::Project(E
, D
);
388 if (hasAnyPointerType(BE
))
393 til::SExpr
*SExprBuilder::translateObjCIVarRefExpr(const ObjCIvarRefExpr
*IVRE
,
394 CallingContext
*Ctx
) {
395 til::SExpr
*BE
= translate(IVRE
->getBase(), Ctx
);
396 til::SExpr
*E
= new (Arena
) til::SApply(BE
);
398 const auto *D
= cast
<ObjCIvarDecl
>(IVRE
->getDecl()->getCanonicalDecl());
400 til::Project
*P
= new (Arena
) til::Project(E
, D
);
401 if (hasAnyPointerType(BE
))
406 til::SExpr
*SExprBuilder::translateCallExpr(const CallExpr
*CE
,
409 if (CapabilityExprMode
) {
410 // Handle LOCK_RETURNED
411 if (const FunctionDecl
*FD
= CE
->getDirectCallee()) {
412 FD
= FD
->getMostRecentDecl();
413 if (LockReturnedAttr
*At
= FD
->getAttr
<LockReturnedAttr
>()) {
414 CallingContext
LRCallCtx(Ctx
);
415 LRCallCtx
.AttrDecl
= CE
->getDirectCallee();
416 LRCallCtx
.SelfArg
= SelfE
;
417 LRCallCtx
.NumArgs
= CE
->getNumArgs();
418 LRCallCtx
.FunArgs
= CE
->getArgs();
419 return const_cast<til::SExpr
*>(
420 translateAttrExpr(At
->getArg(), &LRCallCtx
).sexpr());
425 til::SExpr
*E
= translate(CE
->getCallee(), Ctx
);
426 for (const auto *Arg
: CE
->arguments()) {
427 til::SExpr
*A
= translate(Arg
, Ctx
);
428 E
= new (Arena
) til::Apply(E
, A
);
430 return new (Arena
) til::Call(E
, CE
);
433 til::SExpr
*SExprBuilder::translateCXXMemberCallExpr(
434 const CXXMemberCallExpr
*ME
, CallingContext
*Ctx
) {
435 if (CapabilityExprMode
) {
436 // Ignore calls to get() on smart pointers.
437 if (ME
->getMethodDecl()->getNameAsString() == "get" &&
438 ME
->getNumArgs() == 0) {
439 auto *E
= translate(ME
->getImplicitObjectArgument(), Ctx
);
440 return new (Arena
) til::Cast(til::CAST_objToPtr
, E
);
444 return translateCallExpr(cast
<CallExpr
>(ME
), Ctx
,
445 ME
->getImplicitObjectArgument());
448 til::SExpr
*SExprBuilder::translateCXXOperatorCallExpr(
449 const CXXOperatorCallExpr
*OCE
, CallingContext
*Ctx
) {
450 if (CapabilityExprMode
) {
451 // Ignore operator * and operator -> on smart pointers.
452 OverloadedOperatorKind k
= OCE
->getOperator();
453 if (k
== OO_Star
|| k
== OO_Arrow
) {
454 auto *E
= translate(OCE
->getArg(0), Ctx
);
455 return new (Arena
) til::Cast(til::CAST_objToPtr
, E
);
459 return translateCallExpr(cast
<CallExpr
>(OCE
), Ctx
);
462 til::SExpr
*SExprBuilder::translateUnaryOperator(const UnaryOperator
*UO
,
463 CallingContext
*Ctx
) {
464 switch (UO
->getOpcode()) {
469 return new (Arena
) til::Undefined(UO
);
472 if (CapabilityExprMode
) {
473 // interpret &Graph::mu_ as an existential.
474 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(UO
->getSubExpr())) {
475 if (DRE
->getDecl()->isCXXInstanceMember()) {
476 // This is a pointer-to-member expression, e.g. &MyClass::mu_.
477 // We interpret this syntax specially, as a wildcard.
478 auto *W
= new (Arena
) til::Wildcard();
479 return new (Arena
) til::Project(W
, DRE
->getDecl());
483 // otherwise, & is a no-op
484 return translate(UO
->getSubExpr(), Ctx
);
486 // We treat these as no-ops
489 return translate(UO
->getSubExpr(), Ctx
);
493 til::UnaryOp(til::UOP_Minus
, translate(UO
->getSubExpr(), Ctx
));
496 til::UnaryOp(til::UOP_BitNot
, translate(UO
->getSubExpr(), Ctx
));
499 til::UnaryOp(til::UOP_LogicNot
, translate(UO
->getSubExpr(), Ctx
));
501 // Currently unsupported
506 return new (Arena
) til::Undefined(UO
);
508 return new (Arena
) til::Undefined(UO
);
511 til::SExpr
*SExprBuilder::translateBinOp(til::TIL_BinaryOpcode Op
,
512 const BinaryOperator
*BO
,
513 CallingContext
*Ctx
, bool Reverse
) {
514 til::SExpr
*E0
= translate(BO
->getLHS(), Ctx
);
515 til::SExpr
*E1
= translate(BO
->getRHS(), Ctx
);
517 return new (Arena
) til::BinaryOp(Op
, E1
, E0
);
519 return new (Arena
) til::BinaryOp(Op
, E0
, E1
);
522 til::SExpr
*SExprBuilder::translateBinAssign(til::TIL_BinaryOpcode Op
,
523 const BinaryOperator
*BO
,
526 const Expr
*LHS
= BO
->getLHS();
527 const Expr
*RHS
= BO
->getRHS();
528 til::SExpr
*E0
= translate(LHS
, Ctx
);
529 til::SExpr
*E1
= translate(RHS
, Ctx
);
531 const ValueDecl
*VD
= nullptr;
532 til::SExpr
*CV
= nullptr;
533 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(LHS
)) {
535 CV
= lookupVarDecl(VD
);
539 til::SExpr
*Arg
= CV
? CV
: new (Arena
) til::Load(E0
);
540 E1
= new (Arena
) til::BinaryOp(Op
, Arg
, E1
);
541 E1
= addStatement(E1
, nullptr, VD
);
544 return updateVarDecl(VD
, E1
);
545 return new (Arena
) til::Store(E0
, E1
);
548 til::SExpr
*SExprBuilder::translateBinaryOperator(const BinaryOperator
*BO
,
549 CallingContext
*Ctx
) {
550 switch (BO
->getOpcode()) {
553 return new (Arena
) til::Undefined(BO
);
555 case BO_Mul
: return translateBinOp(til::BOP_Mul
, BO
, Ctx
);
556 case BO_Div
: return translateBinOp(til::BOP_Div
, BO
, Ctx
);
557 case BO_Rem
: return translateBinOp(til::BOP_Rem
, BO
, Ctx
);
558 case BO_Add
: return translateBinOp(til::BOP_Add
, BO
, Ctx
);
559 case BO_Sub
: return translateBinOp(til::BOP_Sub
, BO
, Ctx
);
560 case BO_Shl
: return translateBinOp(til::BOP_Shl
, BO
, Ctx
);
561 case BO_Shr
: return translateBinOp(til::BOP_Shr
, BO
, Ctx
);
562 case BO_LT
: return translateBinOp(til::BOP_Lt
, BO
, Ctx
);
563 case BO_GT
: return translateBinOp(til::BOP_Lt
, BO
, Ctx
, true);
564 case BO_LE
: return translateBinOp(til::BOP_Leq
, BO
, Ctx
);
565 case BO_GE
: return translateBinOp(til::BOP_Leq
, BO
, Ctx
, true);
566 case BO_EQ
: return translateBinOp(til::BOP_Eq
, BO
, Ctx
);
567 case BO_NE
: return translateBinOp(til::BOP_Neq
, BO
, Ctx
);
568 case BO_Cmp
: return translateBinOp(til::BOP_Cmp
, BO
, Ctx
);
569 case BO_And
: return translateBinOp(til::BOP_BitAnd
, BO
, Ctx
);
570 case BO_Xor
: return translateBinOp(til::BOP_BitXor
, BO
, Ctx
);
571 case BO_Or
: return translateBinOp(til::BOP_BitOr
, BO
, Ctx
);
572 case BO_LAnd
: return translateBinOp(til::BOP_LogicAnd
, BO
, Ctx
);
573 case BO_LOr
: return translateBinOp(til::BOP_LogicOr
, BO
, Ctx
);
575 case BO_Assign
: return translateBinAssign(til::BOP_Eq
, BO
, Ctx
, true);
576 case BO_MulAssign
: return translateBinAssign(til::BOP_Mul
, BO
, Ctx
);
577 case BO_DivAssign
: return translateBinAssign(til::BOP_Div
, BO
, Ctx
);
578 case BO_RemAssign
: return translateBinAssign(til::BOP_Rem
, BO
, Ctx
);
579 case BO_AddAssign
: return translateBinAssign(til::BOP_Add
, BO
, Ctx
);
580 case BO_SubAssign
: return translateBinAssign(til::BOP_Sub
, BO
, Ctx
);
581 case BO_ShlAssign
: return translateBinAssign(til::BOP_Shl
, BO
, Ctx
);
582 case BO_ShrAssign
: return translateBinAssign(til::BOP_Shr
, BO
, Ctx
);
583 case BO_AndAssign
: return translateBinAssign(til::BOP_BitAnd
, BO
, Ctx
);
584 case BO_XorAssign
: return translateBinAssign(til::BOP_BitXor
, BO
, Ctx
);
585 case BO_OrAssign
: return translateBinAssign(til::BOP_BitOr
, BO
, Ctx
);
588 // The clang CFG should have already processed both sides.
589 return translate(BO
->getRHS(), Ctx
);
591 return new (Arena
) til::Undefined(BO
);
594 til::SExpr
*SExprBuilder::translateCastExpr(const CastExpr
*CE
,
595 CallingContext
*Ctx
) {
596 CastKind K
= CE
->getCastKind();
598 case CK_LValueToRValue
: {
599 if (const auto *DRE
= dyn_cast
<DeclRefExpr
>(CE
->getSubExpr())) {
600 til::SExpr
*E0
= lookupVarDecl(DRE
->getDecl());
604 til::SExpr
*E0
= translate(CE
->getSubExpr(), Ctx
);
606 // FIXME!! -- get Load working properly
607 // return new (Arena) til::Load(E0);
610 case CK_DerivedToBase
:
611 case CK_UncheckedDerivedToBase
:
612 case CK_ArrayToPointerDecay
:
613 case CK_FunctionToPointerDecay
: {
614 til::SExpr
*E0
= translate(CE
->getSubExpr(), Ctx
);
618 // FIXME: handle different kinds of casts.
619 til::SExpr
*E0
= translate(CE
->getSubExpr(), Ctx
);
620 if (CapabilityExprMode
)
622 return new (Arena
) til::Cast(til::CAST_none
, E0
);
628 SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr
*E
,
629 CallingContext
*Ctx
) {
630 til::SExpr
*E0
= translate(E
->getBase(), Ctx
);
631 til::SExpr
*E1
= translate(E
->getIdx(), Ctx
);
632 return new (Arena
) til::ArrayIndex(E0
, E1
);
636 SExprBuilder::translateAbstractConditionalOperator(
637 const AbstractConditionalOperator
*CO
, CallingContext
*Ctx
) {
638 auto *C
= translate(CO
->getCond(), Ctx
);
639 auto *T
= translate(CO
->getTrueExpr(), Ctx
);
640 auto *E
= translate(CO
->getFalseExpr(), Ctx
);
641 return new (Arena
) til::IfThenElse(C
, T
, E
);
645 SExprBuilder::translateDeclStmt(const DeclStmt
*S
, CallingContext
*Ctx
) {
646 DeclGroupRef DGrp
= S
->getDeclGroup();
647 for (auto *I
: DGrp
) {
648 if (auto *VD
= dyn_cast_or_null
<VarDecl
>(I
)) {
649 Expr
*E
= VD
->getInit();
650 til::SExpr
* SE
= translate(E
, Ctx
);
652 // Add local variables with trivial type to the variable map
653 QualType T
= VD
->getType();
654 if (T
.isTrivialType(VD
->getASTContext()))
655 return addVarDecl(VD
, SE
);
664 // If (E) is non-trivial, then add it to the current basic block, and
665 // update the statement map so that S refers to E. Returns a new variable
667 // If E is trivial returns E.
668 til::SExpr
*SExprBuilder::addStatement(til::SExpr
* E
, const Stmt
*S
,
669 const ValueDecl
*VD
) {
670 if (!E
|| !CurrentBB
|| E
->block() || til::ThreadSafetyTIL::isTrivial(E
))
673 E
= new (Arena
) til::Variable(E
, VD
);
674 CurrentInstructions
.push_back(E
);
680 // Returns the current value of VD, if known, and nullptr otherwise.
681 til::SExpr
*SExprBuilder::lookupVarDecl(const ValueDecl
*VD
) {
682 auto It
= LVarIdxMap
.find(VD
);
683 if (It
!= LVarIdxMap
.end()) {
684 assert(CurrentLVarMap
[It
->second
].first
== VD
);
685 return CurrentLVarMap
[It
->second
].second
;
690 // if E is a til::Variable, update its clangDecl.
691 static void maybeUpdateVD(til::SExpr
*E
, const ValueDecl
*VD
) {
694 if (auto *V
= dyn_cast
<til::Variable
>(E
)) {
700 // Adds a new variable declaration.
701 til::SExpr
*SExprBuilder::addVarDecl(const ValueDecl
*VD
, til::SExpr
*E
) {
702 maybeUpdateVD(E
, VD
);
703 LVarIdxMap
.insert(std::make_pair(VD
, CurrentLVarMap
.size()));
704 CurrentLVarMap
.makeWritable();
705 CurrentLVarMap
.push_back(std::make_pair(VD
, E
));
709 // Updates a current variable declaration. (E.g. by assignment)
710 til::SExpr
*SExprBuilder::updateVarDecl(const ValueDecl
*VD
, til::SExpr
*E
) {
711 maybeUpdateVD(E
, VD
);
712 auto It
= LVarIdxMap
.find(VD
);
713 if (It
== LVarIdxMap
.end()) {
714 til::SExpr
*Ptr
= new (Arena
) til::LiteralPtr(VD
);
715 til::SExpr
*St
= new (Arena
) til::Store(Ptr
, E
);
718 CurrentLVarMap
.makeWritable();
719 CurrentLVarMap
.elem(It
->second
).second
= E
;
723 // Make a Phi node in the current block for the i^th variable in CurrentVarMap.
724 // If E != null, sets Phi[CurrentBlockInfo->ArgIndex] = E.
725 // If E == null, this is a backedge and will be set later.
726 void SExprBuilder::makePhiNodeVar(unsigned i
, unsigned NPreds
, til::SExpr
*E
) {
727 unsigned ArgIndex
= CurrentBlockInfo
->ProcessedPredecessors
;
728 assert(ArgIndex
> 0 && ArgIndex
< NPreds
);
730 til::SExpr
*CurrE
= CurrentLVarMap
[i
].second
;
731 if (CurrE
->block() == CurrentBB
) {
732 // We already have a Phi node in the current block,
733 // so just add the new variable to the Phi node.
734 auto *Ph
= dyn_cast
<til::Phi
>(CurrE
);
735 assert(Ph
&& "Expecting Phi node.");
737 Ph
->values()[ArgIndex
] = E
;
741 // Make a new phi node: phi(..., E)
742 // All phi args up to the current index are set to the current value.
743 til::Phi
*Ph
= new (Arena
) til::Phi(Arena
, NPreds
);
744 Ph
->values().setValues(NPreds
, nullptr);
745 for (unsigned PIdx
= 0; PIdx
< ArgIndex
; ++PIdx
)
746 Ph
->values()[PIdx
] = CurrE
;
748 Ph
->values()[ArgIndex
] = E
;
749 Ph
->setClangDecl(CurrentLVarMap
[i
].first
);
750 // If E is from a back-edge, or either E or CurrE are incomplete, then
751 // mark this node as incomplete; we may need to remove it later.
752 if (!E
|| isIncompletePhi(E
) || isIncompletePhi(CurrE
))
753 Ph
->setStatus(til::Phi::PH_Incomplete
);
755 // Add Phi node to current block, and update CurrentLVarMap[i]
756 CurrentArguments
.push_back(Ph
);
757 if (Ph
->status() == til::Phi::PH_Incomplete
)
758 IncompleteArgs
.push_back(Ph
);
760 CurrentLVarMap
.makeWritable();
761 CurrentLVarMap
.elem(i
).second
= Ph
;
764 // Merge values from Map into the current variable map.
765 // This will construct Phi nodes in the current basic block as necessary.
766 void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map
) {
767 assert(CurrentBlockInfo
&& "Not processing a block!");
769 if (!CurrentLVarMap
.valid()) {
770 // Steal Map, using copy-on-write.
771 CurrentLVarMap
= std::move(Map
);
774 if (CurrentLVarMap
.sameAs(Map
))
775 return; // Easy merge: maps from different predecessors are unchanged.
777 unsigned NPreds
= CurrentBB
->numPredecessors();
778 unsigned ESz
= CurrentLVarMap
.size();
779 unsigned MSz
= Map
.size();
780 unsigned Sz
= std::min(ESz
, MSz
);
782 for (unsigned i
= 0; i
< Sz
; ++i
) {
783 if (CurrentLVarMap
[i
].first
!= Map
[i
].first
) {
784 // We've reached the end of variables in common.
785 CurrentLVarMap
.makeWritable();
786 CurrentLVarMap
.downsize(i
);
789 if (CurrentLVarMap
[i
].second
!= Map
[i
].second
)
790 makePhiNodeVar(i
, NPreds
, Map
[i
].second
);
793 CurrentLVarMap
.makeWritable();
794 CurrentLVarMap
.downsize(Map
.size());
798 // Merge a back edge into the current variable map.
799 // This will create phi nodes for all variables in the variable map.
800 void SExprBuilder::mergeEntryMapBackEdge() {
801 // We don't have definitions for variables on the backedge, because we
802 // haven't gotten that far in the CFG. Thus, when encountering a back edge,
803 // we conservatively create Phi nodes for all variables. Unnecessary Phi
804 // nodes will be marked as incomplete, and stripped out at the end.
806 // An Phi node is unnecessary if it only refers to itself and one other
807 // variable, e.g. x = Phi(y, y, x) can be reduced to x = y.
809 assert(CurrentBlockInfo
&& "Not processing a block!");
811 if (CurrentBlockInfo
->HasBackEdges
)
813 CurrentBlockInfo
->HasBackEdges
= true;
815 CurrentLVarMap
.makeWritable();
816 unsigned Sz
= CurrentLVarMap
.size();
817 unsigned NPreds
= CurrentBB
->numPredecessors();
819 for (unsigned i
= 0; i
< Sz
; ++i
)
820 makePhiNodeVar(i
, NPreds
, nullptr);
823 // Update the phi nodes that were initially created for a back edge
824 // once the variable definitions have been computed.
825 // I.e., merge the current variable map into the phi nodes for Blk.
826 void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock
*Blk
) {
827 til::BasicBlock
*BB
= lookupBlock(Blk
);
828 unsigned ArgIndex
= BBInfo
[Blk
->getBlockID()].ProcessedPredecessors
;
829 assert(ArgIndex
> 0 && ArgIndex
< BB
->numPredecessors());
831 for (til::SExpr
*PE
: BB
->arguments()) {
832 auto *Ph
= dyn_cast_or_null
<til::Phi
>(PE
);
833 assert(Ph
&& "Expecting Phi Node.");
834 assert(Ph
->values()[ArgIndex
] == nullptr && "Wrong index for back edge.");
836 til::SExpr
*E
= lookupVarDecl(Ph
->clangDecl());
837 assert(E
&& "Couldn't find local variable for Phi node.");
838 Ph
->values()[ArgIndex
] = E
;
842 void SExprBuilder::enterCFG(CFG
*Cfg
, const NamedDecl
*D
,
843 const CFGBlock
*First
) {
844 // Perform initial setup operations.
845 unsigned NBlocks
= Cfg
->getNumBlockIDs();
846 Scfg
= new (Arena
) til::SCFG(Arena
, NBlocks
);
848 // allocate all basic blocks immediately, to handle forward references.
849 BBInfo
.resize(NBlocks
);
850 BlockMap
.resize(NBlocks
, nullptr);
851 // create map from clang blockID to til::BasicBlocks
852 for (auto *B
: *Cfg
) {
853 auto *BB
= new (Arena
) til::BasicBlock(Arena
);
854 BB
->reserveInstructions(B
->size());
855 BlockMap
[B
->getBlockID()] = BB
;
858 CurrentBB
= lookupBlock(&Cfg
->getEntry());
859 auto Parms
= isa
<ObjCMethodDecl
>(D
) ? cast
<ObjCMethodDecl
>(D
)->parameters()
860 : cast
<FunctionDecl
>(D
)->parameters();
861 for (auto *Pm
: Parms
) {
862 QualType T
= Pm
->getType();
863 if (!T
.isTrivialType(Pm
->getASTContext()))
866 // Add parameters to local variable map.
867 // FIXME: right now we emulate params with loads; that should be fixed.
868 til::SExpr
*Lp
= new (Arena
) til::LiteralPtr(Pm
);
869 til::SExpr
*Ld
= new (Arena
) til::Load(Lp
);
870 til::SExpr
*V
= addStatement(Ld
, nullptr, Pm
);
875 void SExprBuilder::enterCFGBlock(const CFGBlock
*B
) {
876 // Initialize TIL basic block and add it to the CFG.
877 CurrentBB
= lookupBlock(B
);
878 CurrentBB
->reservePredecessors(B
->pred_size());
879 Scfg
->add(CurrentBB
);
881 CurrentBlockInfo
= &BBInfo
[B
->getBlockID()];
883 // CurrentLVarMap is moved to ExitMap on block exit.
884 // FIXME: the entry block will hold function parameters.
885 // assert(!CurrentLVarMap.valid() && "CurrentLVarMap already initialized.");
888 void SExprBuilder::handlePredecessor(const CFGBlock
*Pred
) {
889 // Compute CurrentLVarMap on entry from ExitMaps of predecessors
891 CurrentBB
->addPredecessor(BlockMap
[Pred
->getBlockID()]);
892 BlockInfo
*PredInfo
= &BBInfo
[Pred
->getBlockID()];
893 assert(PredInfo
->UnprocessedSuccessors
> 0);
895 if (--PredInfo
->UnprocessedSuccessors
== 0)
896 mergeEntryMap(std::move(PredInfo
->ExitMap
));
898 mergeEntryMap(PredInfo
->ExitMap
.clone());
900 ++CurrentBlockInfo
->ProcessedPredecessors
;
903 void SExprBuilder::handlePredecessorBackEdge(const CFGBlock
*Pred
) {
904 mergeEntryMapBackEdge();
907 void SExprBuilder::enterCFGBlockBody(const CFGBlock
*B
) {
908 // The merge*() methods have created arguments.
909 // Push those arguments onto the basic block.
910 CurrentBB
->arguments().reserve(
911 static_cast<unsigned>(CurrentArguments
.size()), Arena
);
912 for (auto *A
: CurrentArguments
)
913 CurrentBB
->addArgument(A
);
916 void SExprBuilder::handleStatement(const Stmt
*S
) {
917 til::SExpr
*E
= translate(S
, nullptr);
921 void SExprBuilder::handleDestructorCall(const VarDecl
*VD
,
922 const CXXDestructorDecl
*DD
) {
923 til::SExpr
*Sf
= new (Arena
) til::LiteralPtr(VD
);
924 til::SExpr
*Dr
= new (Arena
) til::LiteralPtr(DD
);
925 til::SExpr
*Ap
= new (Arena
) til::Apply(Dr
, Sf
);
926 til::SExpr
*E
= new (Arena
) til::Call(Ap
);
927 addStatement(E
, nullptr);
930 void SExprBuilder::exitCFGBlockBody(const CFGBlock
*B
) {
931 CurrentBB
->instructions().reserve(
932 static_cast<unsigned>(CurrentInstructions
.size()), Arena
);
933 for (auto *V
: CurrentInstructions
)
934 CurrentBB
->addInstruction(V
);
936 // Create an appropriate terminator
937 unsigned N
= B
->succ_size();
938 auto It
= B
->succ_begin();
940 til::BasicBlock
*BB
= *It
? lookupBlock(*It
) : nullptr;
942 unsigned Idx
= BB
? BB
->findPredecessorIndex(CurrentBB
) : 0;
943 auto *Tm
= new (Arena
) til::Goto(BB
, Idx
);
944 CurrentBB
->setTerminator(Tm
);
947 til::SExpr
*C
= translate(B
->getTerminatorCondition(true), nullptr);
948 til::BasicBlock
*BB1
= *It
? lookupBlock(*It
) : nullptr;
950 til::BasicBlock
*BB2
= *It
? lookupBlock(*It
) : nullptr;
951 // FIXME: make sure these aren't critical edges.
952 auto *Tm
= new (Arena
) til::Branch(C
, BB1
, BB2
);
953 CurrentBB
->setTerminator(Tm
);
957 void SExprBuilder::handleSuccessor(const CFGBlock
*Succ
) {
958 ++CurrentBlockInfo
->UnprocessedSuccessors
;
961 void SExprBuilder::handleSuccessorBackEdge(const CFGBlock
*Succ
) {
962 mergePhiNodesBackEdge(Succ
);
963 ++BBInfo
[Succ
->getBlockID()].ProcessedPredecessors
;
966 void SExprBuilder::exitCFGBlock(const CFGBlock
*B
) {
967 CurrentArguments
.clear();
968 CurrentInstructions
.clear();
969 CurrentBlockInfo
->ExitMap
= std::move(CurrentLVarMap
);
971 CurrentBlockInfo
= nullptr;
974 void SExprBuilder::exitCFG(const CFGBlock
*Last
) {
975 for (auto *Ph
: IncompleteArgs
) {
976 if (Ph
->status() == til::Phi::PH_Incomplete
)
977 simplifyIncompleteArg(Ph
);
980 CurrentArguments
.clear();
981 CurrentInstructions
.clear();
982 IncompleteArgs
.clear();
989 public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {};
994 namespace threadSafety {
996 void printSCFG(CFGWalker &Walker) {
997 llvm::BumpPtrAllocator Bpa;
998 til::MemRegionRef Arena(&Bpa);
999 SExprBuilder SxBuilder(Arena);
1000 til::SCFG *Scfg = SxBuilder.buildCFG(Walker);
1001 TILPrinter::print(Scfg, llvm::errs());
1004 } // namespace threadSafety
1005 } // namespace clang