clang 24.0.0git
ThreadSafetyCommon.cpp
Go to the documentation of this file.
1//===- ThreadSafetyCommon.cpp ---------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// Implementation of the interfaces declared in ThreadSafetyCommon.h
10//
11//===----------------------------------------------------------------------===//
12
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"
22#include "clang/AST/Stmt.h"
23#include "clang/AST/Type.h"
25#include "clang/Analysis/CFG.h"
26#include "clang/Basic/LLVM.h"
29#include "llvm/ADT/ScopeExit.h"
30#include "llvm/ADT/StringExtras.h"
31#include "llvm/ADT/StringRef.h"
32#include <algorithm>
33#include <cassert>
34#include <string>
35#include <utility>
36
37using namespace clang;
38using namespace threadSafety;
39
40// From ThreadSafetyUtil.h
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();
48 ret += "\"";
49 return ret;
50 }
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:
58 default:
59 return "#lit";
60 }
61}
62
63// Return true if E is a variable that points to an incomplete Phi node.
64static bool isIncompletePhi(const til::SExpr *E) {
65 if (const auto *Ph = dyn_cast<til::Phi>(E))
66 return Ph->status() == til::Phi::PH_Incomplete;
67 return false;
68}
69
70static constexpr std::pair<StringRef, bool> ClassifyCapabilityFallback{
71 /*Kind=*/StringRef("mutex"),
72 /*Reentrant=*/false};
73
74// Returns pair (Kind, Reentrant).
75static std::pair<StringRef, bool> classifyCapability(const TypeDecl &TD) {
76 if (const auto *CA = TD.getAttr<CapabilityAttr>())
77 return {CA->getName(), TD.hasAttr<ReentrantCapabilityAttr>()};
78
80}
81
82// Returns pair (Kind, Reentrant).
83static std::pair<StringRef, bool> classifyCapability(QualType QT) {
84 // We need to look at the declaration of the type of the value to determine
85 // which it is. The type should either be a record or a typedef, or a pointer
86 // or reference thereof.
87 if (const auto *RD = QT->getAsRecordDecl())
88 return classifyCapability(*RD);
89 if (const auto *TT = QT->getAs<TypedefType>())
90 return classifyCapability(*TT->getDecl());
93
95}
96
98 const auto &[Kind, Reentrant] = classifyCapability(QT);
99 *this = CapabilityExpr(E, Kind, Neg, Reentrant);
100}
101
103
104til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) { return SMap.lookup(S); }
105
107 Walker.walk(*this);
108 return Scfg;
109}
110
111/// If CE calls through a function pointer field D, return the member access
112/// through which the field was reached; its base is the implicit object
113/// ('this') for the attributes on the field.
115 const NamedDecl *D) {
116 if (!isa<FieldDecl>(D))
117 return nullptr;
118 // Look through the operators that CallExpr::getCalleeDecl looks through
119 // when it finds D, e.g. in `(*dev->lock)()`.
120 const Expr *Callee = CE->getCallee()->IgnoreParenCasts();
121 while (const auto *UO = dyn_cast<UnaryOperator>(Callee)) {
122 if (UO->getOpcode() != UO_Deref && UO->getOpcode() != UO_AddrOf &&
123 UO->getOpcode() != UO_Plus)
124 break;
125 Callee = UO->getSubExpr()->IgnoreParenCasts();
126 }
127 return dyn_cast<MemberExpr>(Callee);
128}
129
130/// Translate a clang expression in an attribute to a til::SExpr.
131/// Constructs the context from D, DeclExp, and SelfDecl.
132///
133/// \param AttrExp The expression to translate.
134/// \param D The declaration to which the attribute is attached.
135/// \param DeclExp An expression involving the Decl to which the attribute
136/// is attached. E.g. the call to a function.
137/// \param Self S-expression to substitute for a \ref CXXThisExpr in a call,
138/// or argument to a cleanup function.
140 const NamedDecl *D,
141 const Expr *DeclExp,
142 til::SExpr *Self) {
143 // If we are processing a raw attribute expression, with no substitutions.
144 if (!DeclExp && !Self)
145 return translateAttrExpr(AttrExp, nullptr);
146
147 CallingContext Ctx(nullptr, D);
148
149 // Examine DeclExp to find SelfArg and FunArgs, which are used to substitute
150 // for formal parameters when we call buildMutexID later.
151 if (!DeclExp)
152 /* We'll use Self. */;
153 else if (const auto *ME = dyn_cast<MemberExpr>(DeclExp)) {
154 Ctx.SelfArg = ME->getBase();
155 } else if (const auto *CE = dyn_cast<CXXMemberCallExpr>(DeclExp)) {
156 Ctx.SelfArg = CE->getImplicitObjectArgument();
157 Ctx.NumArgs = CE->getNumArgs();
158 Ctx.FunArgs = CE->getArgs();
159 } else if (const auto *CE = dyn_cast<CallExpr>(DeclExp)) {
160 // Calls to operators that are members need to be treated like member calls.
162 Ctx.SelfArg = CE->getArg(0);
163 Ctx.NumArgs = CE->getNumArgs() - 1;
164 Ctx.FunArgs = CE->getArgs() + 1;
165 } else {
166 if (const MemberExpr *ME = getFunPtrFieldCallee(CE, D))
167 Ctx.SelfArg = ME->getBase();
168 Ctx.NumArgs = CE->getNumArgs();
169 Ctx.FunArgs = CE->getArgs();
170 }
171 } else if (const auto *CE = dyn_cast<CXXConstructExpr>(DeclExp)) {
172 Ctx.SelfArg = nullptr; // Will be set below
173 Ctx.NumArgs = CE->getNumArgs();
174 Ctx.FunArgs = CE->getArgs();
175 }
176
177 // Usually we want to substitute the self-argument for "this", but lambdas
178 // are an exception: "this" on or in a lambda call operator doesn't refer
179 // to the lambda, but to captured "this" in the context it was created in.
180 // This can happen for operator calls and member calls, so fix it up here.
181 if (const auto *CMD = dyn_cast<CXXMethodDecl>(D))
182 if (CMD->getParent()->isLambda())
183 Ctx.SelfArg = nullptr;
184
185 if (Self) {
186 assert(!Ctx.SelfArg && "Ambiguous self argument");
187 assert(isa<FunctionDecl>(D) && "Self argument requires function");
188 if (isa<CXXMethodDecl>(D))
189 Ctx.SelfArg = Self;
190 else
191 Ctx.FunArgs = Self;
192
193 // If the attribute has no arguments, then assume the argument is "this".
194 if (!AttrExp)
195 return CapabilityExpr(
196 Self, cast<CXXMethodDecl>(D)->getFunctionObjectParameterType(),
197 false);
198 else // For most attributes.
199 return translateAttrExpr(AttrExp, &Ctx);
200 }
201
202 // If the attribute has no arguments, then assume the argument is "this".
203 // SelfArg may be null for non-method callees (e.g. function pointers).
204 if (!AttrExp) {
205 if (!Ctx.SelfArg)
206 return CapabilityExpr();
207 return translateAttrExpr(cast<const Expr *>(Ctx.SelfArg), nullptr);
208 }
209
210 // For most attributes.
211 return translateAttrExpr(AttrExp, &Ctx);
212}
213
214/// Translate a clang expression in an attribute to a til::SExpr.
215// This assumes a CallingContext has already been created.
217 CallingContext *Ctx) {
218 if (!AttrExp)
219 return CapabilityExpr();
220
221 if (const auto* SLit = dyn_cast<StringLiteral>(AttrExp)) {
222 if (SLit->getString() == "*")
223 // The "*" expr is a universal lock, which essentially turns off
224 // checks until it is removed from the lockset.
225 return CapabilityExpr(new (Arena) til::Wildcard(), StringRef("wildcard"),
226 /*Neg=*/false, /*Reentrant=*/false);
227 else
228 // Ignore other string literals for now.
229 return CapabilityExpr();
230 }
231
232 bool Neg = false;
233 if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(AttrExp)) {
234 if (OE->getOperator() == OO_Exclaim) {
235 Neg = true;
236 AttrExp = OE->getArg(0);
237 }
238 }
239 else if (const auto *UO = dyn_cast<UnaryOperator>(AttrExp)) {
240 if (UO->getOpcode() == UO_LNot) {
241 Neg = true;
242 AttrExp = UO->getSubExpr()->IgnoreImplicit();
243 }
244 }
245
246 const til::SExpr *E = translate(AttrExp, Ctx);
247
248 // Trap mutex expressions like nullptr, or 0.
249 // Any literal value is nonsense.
250 if (!E || isa<til::Literal>(E))
251 return CapabilityExpr();
252
253 // Hack to deal with smart pointers -- strip off top-level pointer casts.
254 if (const auto *CE = dyn_cast<til::Cast>(E)) {
255 if (CE->castOpcode() == til::CAST_objToPtr)
256 E = CE->expr();
257 }
258 return CapabilityExpr(E, AttrExp->getType(), Neg);
259}
260
262 CallingContext *Ctx) {
263 assert(VD);
264
265 // General recursion guard for x = f(x). If we are already in the process of
266 // defining VD, use its pre-assignment value to break the cycle.
267 if (VarsBeingTranslated.contains(VD->getCanonicalDecl()))
268 return new (Arena) til::LiteralPtr(VD);
269
270 // The closure captures state that is updated to correctly translate chains of
271 // aliases. Restore it when we are done with recursive translation.
272 llvm::scope_exit Cleanup([&, RestoreClosure = VarsBeingTranslated.empty()
273 ? LookupLocalVarExpr
274 : nullptr] {
275 VarsBeingTranslated.erase(VD->getCanonicalDecl());
276 if (VarsBeingTranslated.empty())
277 LookupLocalVarExpr = RestoreClosure;
278 });
279 VarsBeingTranslated.insert(VD->getCanonicalDecl());
280
281 QualType Ty = VD->getType();
282 if (!VD->isStaticLocal() && Ty->isPointerType()) {
283 // Substitute local variable aliases with a canonical definition.
284 if (LookupLocalVarExpr) {
285 // Attempt to resolve an alias through the more complex local variable map
286 // lookup. This will fail with complex control-flow graphs (where we
287 // revert to no alias resolution to retain stable variable names).
288 if (const Expr *E = LookupLocalVarExpr(VD)) {
289 til::SExpr *Result = translate(E, Ctx);
290 // Unsupported expression (such as heap allocations) will be undefined;
291 // rather than failing here, we simply revert to the pointer being the
292 // canonical variable.
294 return Result;
295 }
296 }
297 }
298
299 return new (Arena) til::LiteralPtr(VD);
300}
301
302// Translate a clang statement or expression to a TIL expression.
303// Also performs substitution of variables; Ctx provides the context.
304// Dispatches on the type of S.
306 if (!S)
307 return nullptr;
308
309 // Check if S has already been translated and cached.
310 // This handles the lookup of SSA names for DeclRefExprs here.
311 if (til::SExpr *E = lookupStmt(S))
312 return E;
313
314 switch (S->getStmtClass()) {
315 case Stmt::DeclRefExprClass:
316 return translateDeclRefExpr(cast<DeclRefExpr>(S), Ctx);
317 case Stmt::CXXThisExprClass:
318 return translateCXXThisExpr(cast<CXXThisExpr>(S), Ctx);
319 case Stmt::MemberExprClass:
320 return translateMemberExpr(cast<MemberExpr>(S), Ctx);
321 case Stmt::ObjCIvarRefExprClass:
322 return translateObjCIVarRefExpr(cast<ObjCIvarRefExpr>(S), Ctx);
323 case Stmt::CallExprClass:
324 return translateCallExpr(cast<CallExpr>(S), Ctx);
325 case Stmt::CXXMemberCallExprClass:
326 return translateCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), Ctx);
327 case Stmt::CXXOperatorCallExprClass:
328 return translateCXXOperatorCallExpr(cast<CXXOperatorCallExpr>(S), Ctx);
329 case Stmt::UnaryOperatorClass:
330 return translateUnaryOperator(cast<UnaryOperator>(S), Ctx);
331 case Stmt::BinaryOperatorClass:
332 case Stmt::CompoundAssignOperatorClass:
333 return translateBinaryOperator(cast<BinaryOperator>(S), Ctx);
334
335 case Stmt::ArraySubscriptExprClass:
336 return translateArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Ctx);
337 case Stmt::ConditionalOperatorClass:
338 return translateAbstractConditionalOperator(
340 case Stmt::BinaryConditionalOperatorClass:
341 return translateAbstractConditionalOperator(
343
344 // We treat these as no-ops
345 case Stmt::ConstantExprClass:
346 return translate(cast<ConstantExpr>(S)->getSubExpr(), Ctx);
347 case Stmt::ParenExprClass:
348 return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx);
349 case Stmt::ExprWithCleanupsClass:
350 return translate(cast<ExprWithCleanups>(S)->getSubExpr(), Ctx);
351 case Stmt::CXXBindTemporaryExprClass:
352 return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx);
353 case Stmt::MaterializeTemporaryExprClass:
354 return translate(cast<MaterializeTemporaryExpr>(S)->getSubExpr(), Ctx);
355
356 // Collect all literals
357 case Stmt::CharacterLiteralClass:
358 return new (Arena)
360 case Stmt::CXXNullPtrLiteralExprClass:
361 case Stmt::GNUNullExprClass:
362 return new (Arena) til::LiteralT(nullptr);
363 case Stmt::CXXBoolLiteralExprClass:
364 return new (Arena) til::LiteralT(cast<CXXBoolLiteralExpr>(S)->getValue());
365 case Stmt::IntegerLiteralClass: {
366 const auto *IL = cast<IntegerLiteral>(S);
367 const auto *BT = cast<BuiltinType>(IL->getType());
368 const llvm::APInt &Value = IL->getValue();
369 if (BT->isSignedInteger())
370 return new (Arena) til::LiteralT(Value.getSExtValue());
371 else if (BT->isUnsignedInteger())
372 return new (Arena) til::LiteralT(Value.getZExtValue());
373 else
374 llvm_unreachable("Invalid integer type");
375 }
376 case Stmt::StringLiteralClass:
377 return new (Arena) til::LiteralT(cast<StringLiteral>(S)->getBytes());
378 case Stmt::ObjCStringLiteralClass:
379 return new (Arena)
380 til::LiteralT(cast<ObjCStringLiteral>(S)->getString()->getBytes());
381
382 case Stmt::DeclStmtClass:
383 return translateDeclStmt(cast<DeclStmt>(S), Ctx);
384 case Stmt::StmtExprClass:
385 return translateStmtExpr(cast<StmtExpr>(S), Ctx);
386 default:
387 break;
388 }
389 if (const auto *CE = dyn_cast<CastExpr>(S))
390 return translateCastExpr(CE, Ctx);
391
392 return new (Arena) til::Undefined(S);
393}
394
395/// Helper to extract the canonical parameter declaration from a function or
396/// function pointer. This unwraps pointer and reference types to reach the
397/// underlying function prototype.
398static const ParmVarDecl *getCanonicalParamDecl(const Decl *D, unsigned I) {
399 if (const auto *FD = dyn_cast<FunctionDecl>(D))
400 return FD->getCanonicalDecl()->getParamDecl(I);
401 if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
402 return MD->getCanonicalDecl()->getParamDecl(I);
403 if (const auto *DD = dyn_cast<DeclaratorDecl>(D)) {
404 if (auto *TSI = DD->getTypeSourceInfo()) {
405 TypeLoc TL = TSI->getTypeLoc();
406 if (auto RTL = TL.getAsAdjusted<ReferenceTypeLoc>())
407 TL = RTL.getPointeeLoc();
408 // A function pointer can be multiple levels deep.
409 while (auto PTL = TL.getAsAdjusted<PointerTypeLoc>())
410 TL = PTL.getPointeeLoc();
411 if (auto FPTL = TL.getAsAdjusted<FunctionProtoTypeLoc>())
412 if (I < FPTL.getNumParams())
413 return FPTL.getParam(I);
414 }
415 }
416 return nullptr;
417}
418
420 if (const auto *V = dyn_cast<til::Variable>(E))
421 return V->clangDecl();
422 if (const auto *Ph = dyn_cast<til::Phi>(E))
423 return Ph->clangDecl();
424 if (const auto *P = dyn_cast<til::Project>(E))
425 return P->clangDecl();
426 if (const auto *L = dyn_cast<til::LiteralPtr>(E))
427 return L->clangDecl();
428 return nullptr;
429}
430
431static bool hasAnyPointerType(const til::SExpr *E) {
432 auto *VD = getValueDeclFromSExpr(E);
433 if (VD && VD->getType()->isAnyPointerType())
434 return true;
435 if (const auto *C = dyn_cast<til::Cast>(E))
436 return C->castOpcode() == til::CAST_objToPtr;
437
438 return false;
439}
440
441til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE,
442 CallingContext *Ctx) {
443 const auto *VD = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
444
445 // Function parameters require substitution and/or renaming.
446 if (const auto *PV = dyn_cast<ParmVarDecl>(VD)) {
447 unsigned I = PV->getFunctionScopeIndex();
448 const DeclContext *D = PV->getDeclContext();
449 if (Ctx && Ctx->FunArgs) {
450 const Decl *Canonical = Ctx->AttrDecl->getCanonicalDecl();
451 bool Match = false;
452 if (const auto *FD = dyn_cast<FunctionDecl>(D))
453 Match = (FD->getCanonicalDecl() == Canonical);
454 else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
455 Match = (MD->getCanonicalDecl() == Canonical);
456 else if (getCanonicalParamDecl(Canonical, I) == PV->getCanonicalDecl())
457 Match = true;
458 else
459 llvm_unreachable("ParmVarDecl does not belong to current declaration");
460
461 if (Match) {
462 // Substitute call arguments for references to function parameters
463 if (const Expr *const *FunArgs =
464 dyn_cast<const Expr *const *>(Ctx->FunArgs)) {
465 assert(I < Ctx->NumArgs);
466 return translate(FunArgs[I], Ctx->Prev);
467 }
468
469 assert(I == 0);
470 return cast<til::SExpr *>(Ctx->FunArgs);
471 }
472 }
473 // Map the param back to the param of the original function declaration
474 // for consistent comparisons.
475 if (const auto *PVD = getCanonicalParamDecl(cast<Decl>(D), I))
476 VD = PVD;
477 }
478
479 if (const auto *VarD = dyn_cast<VarDecl>(VD))
480 return translateVariable(VarD, Ctx);
481
482 // FIXME: A FieldDecl reached via a DeclRefExpr should ideally be modelled as
483 // a MemberExpr with an artificial self in the AST (e.g. ImplicitThisExpr as a
484 // C equivalent of CXXThisExpr). Until such AST support is available, project
485 // the field on the current SelfArg, so implicit member references in C and in
486 // parameter attributes are not lost.
487 if (const auto *FD = dyn_cast<FieldDecl>(VD); FD && Ctx && Ctx->SelfArg) {
488 til::SExpr *BE = translateCXXThisExpr(nullptr, Ctx);
489 til::SExpr *E = new (Arena) til::SApply(BE);
490 til::Project *P = new (Arena) til::Project(E, FD);
491 if (hasAnyPointerType(BE))
492 P->setArrow(true);
493 return P;
494 }
495
496 // For non-local variables, treat it as a reference to a named object.
497 return new (Arena) til::LiteralPtr(VD);
498}
499
500til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE,
501 CallingContext *Ctx) {
502 // Substitute for 'this'
503 if (Ctx && Ctx->SelfArg) {
504 if (const auto *SelfArg = dyn_cast<const Expr *>(Ctx->SelfArg))
505 return translate(SelfArg, Ctx->Prev);
506 else
507 return cast<til::SExpr *>(Ctx->SelfArg);
508 }
509 assert(SelfVar && "We have no variable for 'this'!");
510 return SelfVar;
511}
512
513// Grab the very first declaration of virtual method D
515 while (true) {
516 D = D->getCanonicalDecl();
517 auto OverriddenMethods = D->overridden_methods();
518 if (OverriddenMethods.begin() == OverriddenMethods.end())
519 return D; // Method does not override anything
520 // FIXME: this does not work with multiple inheritance.
521 D = *OverriddenMethods.begin();
522 }
523 return nullptr;
524}
525
526til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME,
527 CallingContext *Ctx) {
528 til::SExpr *BE = translate(ME->getBase(), Ctx);
529 til::SExpr *E = new (Arena) til::SApply(BE);
530
531 const auto *D = cast<ValueDecl>(ME->getMemberDecl()->getCanonicalDecl());
532 if (const auto *VD = dyn_cast<CXXMethodDecl>(D))
533 D = getFirstVirtualDecl(VD);
534
535 til::Project *P = new (Arena) til::Project(E, D);
536 if (hasAnyPointerType(BE))
537 P->setArrow(true);
538 return P;
539}
540
541til::SExpr *SExprBuilder::translateObjCIVarRefExpr(const ObjCIvarRefExpr *IVRE,
542 CallingContext *Ctx) {
543 til::SExpr *BE = translate(IVRE->getBase(), Ctx);
544 til::SExpr *E = new (Arena) til::SApply(BE);
545
546 const auto *D = cast<ObjCIvarDecl>(IVRE->getDecl()->getCanonicalDecl());
547
548 til::Project *P = new (Arena) til::Project(E, D);
549 if (hasAnyPointerType(BE))
550 P->setArrow(true);
551 return P;
552}
553
554til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE,
555 CallingContext *Ctx,
556 const Expr *SelfE) {
557 if (CapabilityExprMode) {
558 // Handle LOCK_RETURNED, on a function or a function pointer.
559 if (const auto *D = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
560 const NamedDecl *AttrD = D;
561 if (const auto *FD = dyn_cast<FunctionDecl>(D))
562 AttrD = FD->getMostRecentDecl();
563 if (const auto *At = AttrD->getAttr<LockReturnedAttr>()) {
564 CallingContext LRCallCtx(Ctx);
565 LRCallCtx.AttrDecl = D;
566 LRCallCtx.SelfArg = SelfE;
567 if (!SelfE)
568 if (const MemberExpr *ME = getFunPtrFieldCallee(CE, D))
569 LRCallCtx.SelfArg = ME->getBase();
570 LRCallCtx.NumArgs = CE->getNumArgs();
571 LRCallCtx.FunArgs = CE->getArgs();
572 return const_cast<til::SExpr *>(
573 translateAttrExpr(At->getArg(), &LRCallCtx).sexpr());
574 }
575 }
576 }
577
578 til::SExpr *E = translate(CE->getCallee(), Ctx);
579 // Explicitly propagate Undefined, when the callee couldn't be analyzed.
580 if (isa<til::Undefined>(E))
581 return E;
582 for (const auto *Arg : CE->arguments()) {
583 til::SExpr *A = translate(Arg, Ctx);
584 E = new (Arena) til::Apply(E, A);
585 }
586 return new (Arena) til::Call(E, CE);
587}
588
589til::SExpr *SExprBuilder::translateCXXMemberCallExpr(
590 const CXXMemberCallExpr *ME, CallingContext *Ctx) {
591 if (CapabilityExprMode) {
592 // Ignore calls to get() on smart pointers. A call through a pointer to
593 // member function has no method declaration.
594 const CXXMethodDecl *MD = ME->getMethodDecl();
595 if (ME->getNumArgs() == 0 && MD && MD->getIdentifier() &&
596 MD->getIdentifier()->isStr("get")) {
597 auto *E = translate(ME->getImplicitObjectArgument(), Ctx);
598 return new (Arena) til::Cast(til::CAST_objToPtr, E);
599 // return E;
600 }
601 }
602 return translateCallExpr(cast<CallExpr>(ME), Ctx,
604}
605
606til::SExpr *SExprBuilder::translateCXXOperatorCallExpr(
607 const CXXOperatorCallExpr *OCE, CallingContext *Ctx) {
608 if (CapabilityExprMode) {
609 // Ignore operator * and operator -> on smart pointers.
611 if (k == OO_Star || k == OO_Arrow) {
612 auto *E = translate(OCE->getArg(0), Ctx);
613 return new (Arena) til::Cast(til::CAST_objToPtr, E);
614 // return E;
615 }
616 }
617 return translateCallExpr(cast<CallExpr>(OCE), Ctx);
618}
619
620til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO,
621 CallingContext *Ctx) {
622 switch (UO->getOpcode()) {
623 case UO_PostInc:
624 case UO_PostDec:
625 case UO_PreInc:
626 case UO_PreDec:
627 return new (Arena) til::Undefined(UO);
628
629 case UO_AddrOf:
630 if (CapabilityExprMode) {
631 // interpret &Graph::mu_ as an existential.
632 if (const auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr())) {
633 if (DRE->getDecl()->isCXXInstanceMember()) {
634 // This is a pointer-to-member expression, e.g. &MyClass::mu_.
635 // We interpret this syntax specially, as a wildcard.
636 auto *W = new (Arena) til::Wildcard();
637 return new (Arena) til::Project(W, DRE->getDecl());
638 }
639 }
640 }
641 // otherwise, & is a no-op
642 return translate(UO->getSubExpr(), Ctx);
643
644 // We treat these as no-ops
645 case UO_Deref:
646 case UO_Plus:
647 return translate(UO->getSubExpr(), Ctx);
648
649 case UO_Minus:
650 return new (Arena)
651 til::UnaryOp(til::UOP_Minus, translate(UO->getSubExpr(), Ctx));
652 case UO_Not:
653 return new (Arena)
654 til::UnaryOp(til::UOP_BitNot, translate(UO->getSubExpr(), Ctx));
655 case UO_LNot:
656 return new (Arena)
657 til::UnaryOp(til::UOP_LogicNot, translate(UO->getSubExpr(), Ctx));
658
659 // Currently unsupported
660 case UO_Real:
661 case UO_Imag:
662 case UO_Extension:
663 case UO_Coawait:
664 return new (Arena) til::Undefined(UO);
665 }
666 return new (Arena) til::Undefined(UO);
667}
668
669til::SExpr *SExprBuilder::translateBinOp(til::TIL_BinaryOpcode Op,
670 const BinaryOperator *BO,
671 CallingContext *Ctx, bool Reverse) {
672 til::SExpr *E0 = translate(BO->getLHS(), Ctx);
673 til::SExpr *E1 = translate(BO->getRHS(), Ctx);
674 if (Reverse)
675 return new (Arena) til::BinaryOp(Op, E1, E0);
676 else
677 return new (Arena) til::BinaryOp(Op, E0, E1);
678}
679
680til::SExpr *SExprBuilder::translateBinAssign(til::TIL_BinaryOpcode Op,
681 const BinaryOperator *BO,
682 CallingContext *Ctx,
683 bool Assign) {
684 const Expr *LHS = BO->getLHS();
685 const Expr *RHS = BO->getRHS();
686 til::SExpr *E0 = translate(LHS, Ctx);
687 til::SExpr *E1 = translate(RHS, Ctx);
688
689 const ValueDecl *VD = nullptr;
690 til::SExpr *CV = nullptr;
691 if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
692 VD = DRE->getDecl();
693 CV = lookupVarDecl(VD);
694 }
695
696 if (!Assign) {
697 til::SExpr *Arg = CV ? CV : new (Arena) til::Load(E0);
698 E1 = new (Arena) til::BinaryOp(Op, Arg, E1);
699 E1 = addStatement(E1, nullptr, VD);
700 }
701 if (VD && CV)
702 return updateVarDecl(VD, E1);
703 return new (Arena) til::Store(E0, E1);
704}
705
706til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO,
707 CallingContext *Ctx) {
708 switch (BO->getOpcode()) {
709 case BO_PtrMemD:
710 case BO_PtrMemI:
711 return new (Arena) til::Undefined(BO);
712
713 case BO_Mul: return translateBinOp(til::BOP_Mul, BO, Ctx);
714 case BO_Div: return translateBinOp(til::BOP_Div, BO, Ctx);
715 case BO_Rem: return translateBinOp(til::BOP_Rem, BO, Ctx);
716 case BO_Add: return translateBinOp(til::BOP_Add, BO, Ctx);
717 case BO_Sub: return translateBinOp(til::BOP_Sub, BO, Ctx);
718 case BO_Shl: return translateBinOp(til::BOP_Shl, BO, Ctx);
719 case BO_Shr: return translateBinOp(til::BOP_Shr, BO, Ctx);
720 case BO_LT: return translateBinOp(til::BOP_Lt, BO, Ctx);
721 case BO_GT: return translateBinOp(til::BOP_Lt, BO, Ctx, true);
722 case BO_LE: return translateBinOp(til::BOP_Leq, BO, Ctx);
723 case BO_GE: return translateBinOp(til::BOP_Leq, BO, Ctx, true);
724 case BO_EQ: return translateBinOp(til::BOP_Eq, BO, Ctx);
725 case BO_NE: return translateBinOp(til::BOP_Neq, BO, Ctx);
726 case BO_Cmp: return translateBinOp(til::BOP_Cmp, BO, Ctx);
727 case BO_And: return translateBinOp(til::BOP_BitAnd, BO, Ctx);
728 case BO_Xor: return translateBinOp(til::BOP_BitXor, BO, Ctx);
729 case BO_Or: return translateBinOp(til::BOP_BitOr, BO, Ctx);
730 case BO_LAnd: return translateBinOp(til::BOP_LogicAnd, BO, Ctx);
731 case BO_LOr: return translateBinOp(til::BOP_LogicOr, BO, Ctx);
732
733 case BO_Assign: return translateBinAssign(til::BOP_Eq, BO, Ctx, true);
734 case BO_MulAssign: return translateBinAssign(til::BOP_Mul, BO, Ctx);
735 case BO_DivAssign: return translateBinAssign(til::BOP_Div, BO, Ctx);
736 case BO_RemAssign: return translateBinAssign(til::BOP_Rem, BO, Ctx);
737 case BO_AddAssign: return translateBinAssign(til::BOP_Add, BO, Ctx);
738 case BO_SubAssign: return translateBinAssign(til::BOP_Sub, BO, Ctx);
739 case BO_ShlAssign: return translateBinAssign(til::BOP_Shl, BO, Ctx);
740 case BO_ShrAssign: return translateBinAssign(til::BOP_Shr, BO, Ctx);
741 case BO_AndAssign: return translateBinAssign(til::BOP_BitAnd, BO, Ctx);
742 case BO_XorAssign: return translateBinAssign(til::BOP_BitXor, BO, Ctx);
743 case BO_OrAssign: return translateBinAssign(til::BOP_BitOr, BO, Ctx);
744
745 case BO_Comma:
746 // The clang CFG should have already processed both sides.
747 return translate(BO->getRHS(), Ctx);
748 }
749 return new (Arena) til::Undefined(BO);
750}
751
752til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE,
753 CallingContext *Ctx) {
754 CastKind K = CE->getCastKind();
755 switch (K) {
756 case CK_LValueToRValue: {
757 if (const auto *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
758 til::SExpr *E0 = lookupVarDecl(DRE->getDecl());
759 if (E0)
760 return E0;
761 }
762 til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
763 return E0;
764 // FIXME!! -- get Load working properly
765 // return new (Arena) til::Load(E0);
766 }
767 case CK_NoOp:
768 case CK_DerivedToBase:
769 case CK_UncheckedDerivedToBase:
770 case CK_ArrayToPointerDecay:
771 case CK_FunctionToPointerDecay: {
772 til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
773 return E0;
774 }
775 default: {
776 // FIXME: handle different kinds of casts.
777 til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
778 if (CapabilityExprMode)
779 return E0;
780 return new (Arena) til::Cast(til::CAST_none, E0);
781 }
782 }
783}
784
786SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E,
787 CallingContext *Ctx) {
788 til::SExpr *E0 = translate(E->getBase(), Ctx);
789 til::SExpr *E1 = translate(E->getIdx(), Ctx);
790 return new (Arena) til::ArrayIndex(E0, E1);
791}
792
794SExprBuilder::translateAbstractConditionalOperator(
795 const AbstractConditionalOperator *CO, CallingContext *Ctx) {
796 auto *C = translate(CO->getCond(), Ctx);
797 auto *T = translate(CO->getTrueExpr(), Ctx);
798 auto *E = translate(CO->getFalseExpr(), Ctx);
799 return new (Arena) til::IfThenElse(C, T, E);
800}
801
803SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) {
804 DeclGroupRef DGrp = S->getDeclGroup();
805 for (auto *I : DGrp) {
806 if (auto *VD = dyn_cast_or_null<VarDecl>(I)) {
807 Expr *E = VD->getInit();
808 til::SExpr* SE = translate(E, Ctx);
809
810 // Add local variables with trivial type to the variable map
811 QualType T = VD->getType();
812 if (T.isTrivialType(VD->getASTContext()))
813 return addVarDecl(VD, SE);
814 else {
815 // TODO: add alloca
816 }
817 }
818 }
819 return nullptr;
820}
821
822til::SExpr *SExprBuilder::translateStmtExpr(const StmtExpr *SE,
823 CallingContext *Ctx) {
824 // The value of a statement expression is the value of the last statement,
825 // which must be an expression.
826 const CompoundStmt *CS = SE->getSubStmt();
827 return CS->body_empty() ? new (Arena) til::Undefined(SE)
828 : translate(CS->body_back(), Ctx);
829}
830
831// If (E) is non-trivial, then add it to the current basic block, and
832// update the statement map so that S refers to E. Returns a new variable
833// that refers to E.
834// If E is trivial returns E.
835til::SExpr *SExprBuilder::addStatement(til::SExpr* E, const Stmt *S,
836 const ValueDecl *VD) {
837 if (!E || !CurrentBB || E->block() || til::ThreadSafetyTIL::isTrivial(E))
838 return E;
839 if (VD)
840 E = new (Arena) til::Variable(E, VD);
841 CurrentInstructions.push_back(E);
842 if (S)
843 insertStmt(S, E);
844 return E;
845}
846
847// Returns the current value of VD, if known, and nullptr otherwise.
848til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) {
849 auto It = LVarIdxMap.find(VD);
850 if (It != LVarIdxMap.end()) {
851 assert(CurrentLVarMap[It->second].first == VD);
852 return CurrentLVarMap[It->second].second;
853 }
854 return nullptr;
855}
856
857// if E is a til::Variable, update its clangDecl.
858static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) {
859 if (!E)
860 return;
861 if (auto *V = dyn_cast<til::Variable>(E)) {
862 if (!V->clangDecl())
863 V->setClangDecl(VD);
864 }
865}
866
867// Adds a new variable declaration.
868til::SExpr *SExprBuilder::addVarDecl(const ValueDecl *VD, til::SExpr *E) {
869 maybeUpdateVD(E, VD);
870 LVarIdxMap.insert(std::make_pair(VD, CurrentLVarMap.size()));
871 CurrentLVarMap.makeWritable();
872 CurrentLVarMap.push_back(std::make_pair(VD, E));
873 return E;
874}
875
876// Updates a current variable declaration. (E.g. by assignment)
877til::SExpr *SExprBuilder::updateVarDecl(const ValueDecl *VD, til::SExpr *E) {
878 maybeUpdateVD(E, VD);
879 auto It = LVarIdxMap.find(VD);
880 if (It == LVarIdxMap.end()) {
881 til::SExpr *Ptr = new (Arena) til::LiteralPtr(VD);
882 til::SExpr *St = new (Arena) til::Store(Ptr, E);
883 return St;
884 }
885 CurrentLVarMap.makeWritable();
886 CurrentLVarMap.elem(It->second).second = E;
887 return E;
888}
889
890// Make a Phi node in the current block for the i^th variable in CurrentVarMap.
891// If E != null, sets Phi[CurrentBlockInfo->ArgIndex] = E.
892// If E == null, this is a backedge and will be set later.
893void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) {
894 unsigned ArgIndex = CurrentBlockInfo->ProcessedPredecessors;
895 assert(ArgIndex > 0 && ArgIndex < NPreds);
896
897 til::SExpr *CurrE = CurrentLVarMap[i].second;
898 if (CurrE->block() == CurrentBB) {
899 // We already have a Phi node in the current block,
900 // so just add the new variable to the Phi node.
901 auto *Ph = dyn_cast<til::Phi>(CurrE);
902 assert(Ph && "Expecting Phi node.");
903 if (E)
904 Ph->values()[ArgIndex] = E;
905 return;
906 }
907
908 // Make a new phi node: phi(..., E)
909 // All phi args up to the current index are set to the current value.
910 til::Phi *Ph = new (Arena) til::Phi(Arena, NPreds);
911 Ph->values().setValues(NPreds, nullptr);
912 for (unsigned PIdx = 0; PIdx < ArgIndex; ++PIdx)
913 Ph->values()[PIdx] = CurrE;
914 if (E)
915 Ph->values()[ArgIndex] = E;
916 Ph->setClangDecl(CurrentLVarMap[i].first);
917 // If E is from a back-edge, or either E or CurrE are incomplete, then
918 // mark this node as incomplete; we may need to remove it later.
919 if (!E || isIncompletePhi(E) || isIncompletePhi(CurrE))
921
922 // Add Phi node to current block, and update CurrentLVarMap[i]
923 CurrentArguments.push_back(Ph);
924 if (Ph->status() == til::Phi::PH_Incomplete)
925 IncompleteArgs.push_back(Ph);
926
927 CurrentLVarMap.makeWritable();
928 CurrentLVarMap.elem(i).second = Ph;
929}
930
931// Merge values from Map into the current variable map.
932// This will construct Phi nodes in the current basic block as necessary.
933void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map) {
934 assert(CurrentBlockInfo && "Not processing a block!");
935
936 if (!CurrentLVarMap.valid()) {
937 // Steal Map, using copy-on-write.
938 CurrentLVarMap = std::move(Map);
939 return;
940 }
941 if (CurrentLVarMap.sameAs(Map))
942 return; // Easy merge: maps from different predecessors are unchanged.
943
944 unsigned NPreds = CurrentBB->numPredecessors();
945 unsigned ESz = CurrentLVarMap.size();
946 unsigned MSz = Map.size();
947 unsigned Sz = std::min(ESz, MSz);
948
949 for (unsigned i = 0; i < Sz; ++i) {
950 if (CurrentLVarMap[i].first != Map[i].first) {
951 // We've reached the end of variables in common.
952 CurrentLVarMap.makeWritable();
953 CurrentLVarMap.downsize(i);
954 break;
955 }
956 if (CurrentLVarMap[i].second != Map[i].second)
957 makePhiNodeVar(i, NPreds, Map[i].second);
958 }
959 if (ESz > MSz) {
960 CurrentLVarMap.makeWritable();
961 CurrentLVarMap.downsize(Map.size());
962 }
963}
964
965// Merge a back edge into the current variable map.
966// This will create phi nodes for all variables in the variable map.
967void SExprBuilder::mergeEntryMapBackEdge() {
968 // We don't have definitions for variables on the backedge, because we
969 // haven't gotten that far in the CFG. Thus, when encountering a back edge,
970 // we conservatively create Phi nodes for all variables. Unnecessary Phi
971 // nodes will be marked as incomplete, and stripped out at the end.
972 //
973 // An Phi node is unnecessary if it only refers to itself and one other
974 // variable, e.g. x = Phi(y, y, x) can be reduced to x = y.
975
976 assert(CurrentBlockInfo && "Not processing a block!");
977
978 if (CurrentBlockInfo->HasBackEdges)
979 return;
980 CurrentBlockInfo->HasBackEdges = true;
981
982 CurrentLVarMap.makeWritable();
983 unsigned Sz = CurrentLVarMap.size();
984 unsigned NPreds = CurrentBB->numPredecessors();
985
986 for (unsigned i = 0; i < Sz; ++i)
987 makePhiNodeVar(i, NPreds, nullptr);
988}
989
990// Update the phi nodes that were initially created for a back edge
991// once the variable definitions have been computed.
992// I.e., merge the current variable map into the phi nodes for Blk.
993void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *Blk) {
994 til::BasicBlock *BB = lookupBlock(Blk);
995 unsigned ArgIndex = BBInfo[Blk->getBlockID()].ProcessedPredecessors;
996 assert(ArgIndex > 0 && ArgIndex < BB->numPredecessors());
997
998 for (til::SExpr *PE : BB->arguments()) {
999 auto *Ph = dyn_cast_or_null<til::Phi>(PE);
1000 assert(Ph && "Expecting Phi Node.");
1001 assert(Ph->values()[ArgIndex] == nullptr && "Wrong index for back edge.");
1002
1003 til::SExpr *E = lookupVarDecl(Ph->clangDecl());
1004 assert(E && "Couldn't find local variable for Phi node.");
1005 Ph->values()[ArgIndex] = E;
1006 }
1007}
1008
1009void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D,
1010 const CFGBlock *First) {
1011 // Perform initial setup operations.
1012 unsigned NBlocks = Cfg->getNumBlockIDs();
1013 Scfg = new (Arena) til::SCFG(Arena, NBlocks);
1014
1015 // allocate all basic blocks immediately, to handle forward references.
1016 BBInfo.resize(NBlocks);
1017 BlockMap.resize(NBlocks, nullptr);
1018 // create map from clang blockID to til::BasicBlocks
1019 for (auto *B : *Cfg) {
1020 auto *BB = new (Arena) til::BasicBlock(Arena);
1021 BB->reserveInstructions(B->size());
1022 BlockMap[B->getBlockID()] = BB;
1023 }
1024
1025 CurrentBB = lookupBlock(&Cfg->getEntry());
1026 auto Parms = isa<ObjCMethodDecl>(D) ? cast<ObjCMethodDecl>(D)->parameters()
1027 : cast<FunctionDecl>(D)->parameters();
1028 for (auto *Pm : Parms) {
1029 QualType T = Pm->getType();
1030 if (!T.isTrivialType(Pm->getASTContext()))
1031 continue;
1032
1033 // Add parameters to local variable map.
1034 // FIXME: right now we emulate params with loads; that should be fixed.
1035 til::SExpr *Lp = new (Arena) til::LiteralPtr(Pm);
1036 til::SExpr *Ld = new (Arena) til::Load(Lp);
1037 til::SExpr *V = addStatement(Ld, nullptr, Pm);
1038 addVarDecl(Pm, V);
1039 }
1040}
1041
1042void SExprBuilder::enterCFGBlock(const CFGBlock *B) {
1043 // Initialize TIL basic block and add it to the CFG.
1044 CurrentBB = lookupBlock(B);
1045 CurrentBB->reservePredecessors(B->pred_size());
1046 Scfg->add(CurrentBB);
1047
1048 CurrentBlockInfo = &BBInfo[B->getBlockID()];
1049
1050 // CurrentLVarMap is moved to ExitMap on block exit.
1051 // FIXME: the entry block will hold function parameters.
1052 // assert(!CurrentLVarMap.valid() && "CurrentLVarMap already initialized.");
1053}
1054
1055void SExprBuilder::handlePredecessor(const CFGBlock *Pred) {
1056 // Compute CurrentLVarMap on entry from ExitMaps of predecessors
1057
1058 CurrentBB->addPredecessor(BlockMap[Pred->getBlockID()]);
1059 BlockInfo *PredInfo = &BBInfo[Pred->getBlockID()];
1060 assert(PredInfo->UnprocessedSuccessors > 0);
1061
1062 if (--PredInfo->UnprocessedSuccessors == 0)
1063 mergeEntryMap(std::move(PredInfo->ExitMap));
1064 else
1065 mergeEntryMap(PredInfo->ExitMap.clone());
1066
1067 ++CurrentBlockInfo->ProcessedPredecessors;
1068}
1069
1070void SExprBuilder::handlePredecessorBackEdge(const CFGBlock *Pred) {
1071 mergeEntryMapBackEdge();
1072}
1073
1074void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) {
1075 // The merge*() methods have created arguments.
1076 // Push those arguments onto the basic block.
1077 CurrentBB->arguments().reserve(
1078 static_cast<unsigned>(CurrentArguments.size()), Arena);
1079 for (auto *A : CurrentArguments)
1080 CurrentBB->addArgument(A);
1081}
1082
1083void SExprBuilder::handleStatement(const Stmt *S) {
1084 til::SExpr *E = translate(S, nullptr);
1085 addStatement(E, S);
1086}
1087
1088void SExprBuilder::handleDestructorCall(const VarDecl *VD,
1089 const CXXDestructorDecl *DD) {
1090 til::SExpr *Sf = new (Arena) til::LiteralPtr(VD);
1091 til::SExpr *Dr = new (Arena) til::LiteralPtr(DD);
1092 til::SExpr *Ap = new (Arena) til::Apply(Dr, Sf);
1093 til::SExpr *E = new (Arena) til::Call(Ap);
1094 addStatement(E, nullptr);
1095}
1096
1097void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {
1098 CurrentBB->instructions().reserve(
1099 static_cast<unsigned>(CurrentInstructions.size()), Arena);
1100 for (auto *V : CurrentInstructions)
1101 CurrentBB->addInstruction(V);
1102
1103 // Create an appropriate terminator
1104 unsigned N = B->succ_size();
1105 auto It = B->succ_begin();
1106 if (N == 1) {
1107 til::BasicBlock *BB = *It ? lookupBlock(*It) : nullptr;
1108 // TODO: set index
1109 unsigned Idx = BB ? BB->findPredecessorIndex(CurrentBB) : 0;
1110 auto *Tm = new (Arena) til::Goto(BB, Idx);
1111 CurrentBB->setTerminator(Tm);
1112 }
1113 else if (N == 2) {
1114 til::SExpr *C = translate(B->getTerminatorCondition(true), nullptr);
1115 til::BasicBlock *BB1 = *It ? lookupBlock(*It) : nullptr;
1116 ++It;
1117 til::BasicBlock *BB2 = *It ? lookupBlock(*It) : nullptr;
1118 // FIXME: make sure these aren't critical edges.
1119 auto *Tm = new (Arena) til::Branch(C, BB1, BB2);
1120 CurrentBB->setTerminator(Tm);
1121 }
1122}
1123
1124void SExprBuilder::handleSuccessor(const CFGBlock *Succ) {
1125 ++CurrentBlockInfo->UnprocessedSuccessors;
1126}
1127
1128void SExprBuilder::handleSuccessorBackEdge(const CFGBlock *Succ) {
1129 mergePhiNodesBackEdge(Succ);
1130 ++BBInfo[Succ->getBlockID()].ProcessedPredecessors;
1131}
1132
1133void SExprBuilder::exitCFGBlock(const CFGBlock *B) {
1134 CurrentArguments.clear();
1135 CurrentInstructions.clear();
1136 CurrentBlockInfo->ExitMap = std::move(CurrentLVarMap);
1137 CurrentBB = nullptr;
1138 CurrentBlockInfo = nullptr;
1139}
1140
1141void SExprBuilder::exitCFG(const CFGBlock *Last) {
1142 for (auto *Ph : IncompleteArgs) {
1143 if (Ph->status() == til::Phi::PH_Incomplete)
1145 }
1146
1147 CurrentArguments.clear();
1148 CurrentInstructions.clear();
1149 IncompleteArgs.clear();
1150}
1151
1152#ifndef NDEBUG
1153namespace {
1154
1155class TILPrinter :
1156 public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {};
1157
1158} // namespace
1159
1160namespace clang {
1161namespace threadSafety {
1162
1163void printSCFG(CFGWalker &Walker) {
1164 llvm::BumpPtrAllocator Bpa;
1165 til::MemRegionRef Arena(&Bpa);
1166 SExprBuilder SxBuilder(Arena);
1167 til::SCFG *Scfg = SxBuilder.buildCFG(Walker);
1168 TILPrinter::print(Scfg, llvm::errs());
1169}
1170
1171} // namespace threadSafety
1172} // namespace clang
1173#endif // NDEBUG
#define V(N, I)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines an enumeration for C++ overloaded operators.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Defines various enumerations that describe declaration and type specifiers.
static bool isIncompletePhi(const til::SExpr *E)
static const MemberExpr * getFunPtrFieldCallee(const CallExpr *CE, const NamedDecl *D)
If CE calls through a function pointer field D, return the member access through which the field was ...
SExprBuilder::CallingContext CallingContext
static const ParmVarDecl * getCanonicalParamDecl(const Decl *D, unsigned I)
Helper to extract the canonical parameter declaration from a function or function pointer.
static const ValueDecl * getValueDeclFromSExpr(const til::SExpr *E)
static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD)
static bool hasAnyPointerType(const til::SExpr *E)
static const CXXMethodDecl * getFirstVirtualDecl(const CXXMethodDecl *D)
static std::pair< StringRef, bool > classifyCapability(const TypeDecl &TD)
static constexpr std::pair< StringRef, bool > ClassifyCapabilityFallback
C Language Family Type Representation.
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Definition Expr.h:4600
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4606
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4612
Expr * getLHS() const
Definition Expr.h:4157
Expr * getRHS() const
Definition Expr.h:4159
Opcode getOpcode() const
Definition Expr.h:4152
succ_iterator succ_begin()
Definition CFG.h:1046
unsigned pred_size() const
Definition CFG.h:1067
const Stmt * getTerminatorCondition(bool StripParens=true) const
Definition CFG.cpp:6534
unsigned getBlockID() const
Definition CFG.h:1178
unsigned succ_size() const
Definition CFG.h:1064
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Definition CFG.h:1488
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Definition ExprCXX.cpp:773
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition ExprCXX.cpp:754
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2150
overridden_method_range overridden_methods() const
Definition DeclCXX.cpp:2828
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition DeclCXX.h:2263
OverloadedOperatorKind getOperator() const
Returns the kind of overloaded operator that this expression refers to.
Definition ExprCXX.h:116
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:3012
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3216
Expr * getCallee()
Definition Expr.h:3159
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3203
Expr ** getArgs()
Retrieve the call arguments.
Definition Expr.h:3206
arg_range arguments()
Definition Expr.h:3264
Decl * getCalleeDecl()
Definition Expr.h:3189
CastKind getCastKind() const
Definition Expr.h:3789
Expr * getSubExpr()
Definition Expr.h:3795
bool body_empty() const
Definition Stmt.h:1796
Stmt * body_back()
Definition Stmt.h:1820
ValueDecl * getDecl()
Definition Expr.h:1383
const DeclGroupRef getDeclGroup() const
Definition Stmt.h:1661
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:583
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:550
bool hasAttr() const
Definition DeclBase.h:587
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:997
This represents one expression.
Definition Expr.h:114
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3134
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3117
QualType getType() const
Definition Expr.h:146
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3433
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3516
Expr * getBase() const
Definition Expr.h:3510
This represents a decl that may have a name.
Definition Decl.h:276
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:297
NamedDecl * getMostRecentDecl()
Definition Decl.h:503
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
Definition Decl.cpp:1977
ObjCIvarDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition DeclObjC.h:1997
ObjCIvarDecl * getDecl()
Definition ExprObjC.h:611
const Expr * getBase() const
Definition ExprObjC.h:615
Represents a parameter to a function.
Definition Decl.h:1832
Wrapper for source info for pointers.
Definition TypeLoc.h:1544
A (possibly-)qualified type.
Definition TypeBase.h:938
CompoundStmt * getSubStmt()
Definition Expr.h:4681
Stmt - This represents one statement.
Definition Stmt.h:85
StmtClass getStmtClass() const
Definition Stmt.h:1505
Represents a declaration of a type.
Definition Decl.h:3664
Base wrapper for a particular "section" of type source info.
Definition TypeLoc.h:59
T getAsAdjusted() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
Definition TypeLoc.h:2766
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isPointerType() const
Definition TypeBase.h:8683
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool isPointerOrReferenceType() const
Definition TypeBase.h:8687
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
Expr * getSubExpr() const
Definition Expr.h:2354
Opcode getOpcode() const
Definition Expr.h:2349
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:714
QualType getType() const
Definition Decl.h:725
Represents a variable declaration or definition.
Definition Decl.h:934
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:2238
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1216
CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D, const Expr *DeclExp, til::SExpr *Self=nullptr)
Translate a clang expression in an attribute to a til::SExpr.
til::SExpr * translate(const Stmt *S, CallingContext *Ctx)
til::SExpr * lookupStmt(const Stmt *S)
til::SCFG * buildCFG(CFGWalker &Walker)
til::SExpr * translateVariable(const VarDecl *VD, CallingContext *Ctx)
til::BasicBlock * lookupBlock(const CFGBlock *B)
const InstrArray & arguments() const
unsigned findPredecessorIndex(const BasicBlock *BB) const
Return the index of BB, or Predecessors.size if BB is not a predecessor.
A Literal pointer to an object allocated in memory.
const ValueDecl * clangDecl() const
Return the clang declaration of the variable for this Phi node, if any.
void setClangDecl(const ValueDecl *Cvd)
Set the clang variable associated with this Phi node.
const ValArray & values() const
An SCFG is a control-flow graph.
Base class for AST nodes in the typed intermediate language.
BasicBlock * block() const
Returns the block, if this is an instruction in a basic block, otherwise returns null.
void setValues(unsigned Sz, const T &C)
Placeholder for expressions that cannot be represented in the TIL.
Placeholder for a wildcard that matches any other expression.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
void simplifyIncompleteArg(til::Phi *Ph)
TIL_BinaryOpcode
Opcode for binary arithmetic operations.
void printSCFG(CFGWalker &Walker)
std::string getSourceLiteralString(const Expr *CE)
Top level wrappers for InstallAPI frontend operations.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
Definition Sema.h:824
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Result
The result type of a method or function.
Definition TypeBase.h:906
const FunctionProtoType * T
CastKind
CastKind - The kind of operation required for a conversion.
U cast(CodeGen::Address addr)
Definition Address.h:327
Encapsulates the lexical context of a function call.
llvm::PointerUnion< const Expr *const *, til::SExpr * > FunArgs
llvm::PointerUnion< const Expr *, til::SExpr * > SelfArg