10b57cec5SDimitry Andric //===- ThreadSafetyCommon.cpp ---------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Implementation of the interfaces declared in ThreadSafetyCommon.h 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/Analysis/Analyses/ThreadSafetyCommon.h" 140b57cec5SDimitry Andric #include "clang/AST/Attr.h" 150b57cec5SDimitry Andric #include "clang/AST/Decl.h" 160b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 170b57cec5SDimitry Andric #include "clang/AST/DeclGroup.h" 180b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 190b57cec5SDimitry Andric #include "clang/AST/Expr.h" 200b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h" 210b57cec5SDimitry Andric #include "clang/AST/OperationKinds.h" 220b57cec5SDimitry Andric #include "clang/AST/Stmt.h" 230b57cec5SDimitry Andric #include "clang/AST/Type.h" 240b57cec5SDimitry Andric #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" 250b57cec5SDimitry Andric #include "clang/Analysis/CFG.h" 260b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 270b57cec5SDimitry Andric #include "clang/Basic/OperatorKinds.h" 280b57cec5SDimitry Andric #include "clang/Basic/Specifiers.h" 29fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h" 300b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 310b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 320b57cec5SDimitry Andric #include <algorithm> 330b57cec5SDimitry Andric #include <cassert> 340b57cec5SDimitry Andric #include <string> 350b57cec5SDimitry Andric #include <utility> 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric using namespace clang; 380b57cec5SDimitry Andric using namespace threadSafety; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric // From ThreadSafetyUtil.h 410b57cec5SDimitry Andric std::string threadSafety::getSourceLiteralString(const Expr *CE) { 420b57cec5SDimitry Andric switch (CE->getStmtClass()) { 430b57cec5SDimitry Andric case Stmt::IntegerLiteralClass: 44fe6060f1SDimitry Andric return toString(cast<IntegerLiteral>(CE)->getValue(), 10, true); 450b57cec5SDimitry Andric case Stmt::StringLiteralClass: { 460b57cec5SDimitry Andric std::string ret("\""); 470b57cec5SDimitry Andric ret += cast<StringLiteral>(CE)->getString(); 480b57cec5SDimitry Andric ret += "\""; 490b57cec5SDimitry Andric return ret; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric case Stmt::CharacterLiteralClass: 520b57cec5SDimitry Andric case Stmt::CXXNullPtrLiteralExprClass: 530b57cec5SDimitry Andric case Stmt::GNUNullExprClass: 540b57cec5SDimitry Andric case Stmt::CXXBoolLiteralExprClass: 550b57cec5SDimitry Andric case Stmt::FloatingLiteralClass: 560b57cec5SDimitry Andric case Stmt::ImaginaryLiteralClass: 570b57cec5SDimitry Andric case Stmt::ObjCStringLiteralClass: 580b57cec5SDimitry Andric default: 590b57cec5SDimitry Andric return "#lit"; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric // Return true if E is a variable that points to an incomplete Phi node. 640b57cec5SDimitry Andric static bool isIncompletePhi(const til::SExpr *E) { 650b57cec5SDimitry Andric if (const auto *Ph = dyn_cast<til::Phi>(E)) 660b57cec5SDimitry Andric return Ph->status() == til::Phi::PH_Incomplete; 670b57cec5SDimitry Andric return false; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric using CallingContext = SExprBuilder::CallingContext; 710b57cec5SDimitry Andric 7206c3fb27SDimitry Andric til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) { return SMap.lookup(S); } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric til::SCFG *SExprBuilder::buildCFG(CFGWalker &Walker) { 750b57cec5SDimitry Andric Walker.walk(*this); 760b57cec5SDimitry Andric return Scfg; 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric static bool isCalleeArrow(const Expr *E) { 800b57cec5SDimitry Andric const auto *ME = dyn_cast<MemberExpr>(E->IgnoreParenCasts()); 810b57cec5SDimitry Andric return ME ? ME->isArrow() : false; 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 8481ad6265SDimitry Andric static StringRef ClassifyDiagnostic(const CapabilityAttr *A) { 8581ad6265SDimitry Andric return A->getName(); 8681ad6265SDimitry Andric } 8781ad6265SDimitry Andric 8881ad6265SDimitry Andric static StringRef ClassifyDiagnostic(QualType VDT) { 8981ad6265SDimitry Andric // We need to look at the declaration of the type of the value to determine 9081ad6265SDimitry Andric // which it is. The type should either be a record or a typedef, or a pointer 9181ad6265SDimitry Andric // or reference thereof. 9281ad6265SDimitry Andric if (const auto *RT = VDT->getAs<RecordType>()) { 9381ad6265SDimitry Andric if (const auto *RD = RT->getDecl()) 9481ad6265SDimitry Andric if (const auto *CA = RD->getAttr<CapabilityAttr>()) 9581ad6265SDimitry Andric return ClassifyDiagnostic(CA); 9681ad6265SDimitry Andric } else if (const auto *TT = VDT->getAs<TypedefType>()) { 9781ad6265SDimitry Andric if (const auto *TD = TT->getDecl()) 9881ad6265SDimitry Andric if (const auto *CA = TD->getAttr<CapabilityAttr>()) 9981ad6265SDimitry Andric return ClassifyDiagnostic(CA); 10081ad6265SDimitry Andric } else if (VDT->isPointerType() || VDT->isReferenceType()) 10181ad6265SDimitry Andric return ClassifyDiagnostic(VDT->getPointeeType()); 10281ad6265SDimitry Andric 10381ad6265SDimitry Andric return "mutex"; 10481ad6265SDimitry Andric } 10581ad6265SDimitry Andric 1060b57cec5SDimitry Andric /// Translate a clang expression in an attribute to a til::SExpr. 1070b57cec5SDimitry Andric /// Constructs the context from D, DeclExp, and SelfDecl. 1080b57cec5SDimitry Andric /// 1090b57cec5SDimitry Andric /// \param AttrExp The expression to translate. 1100b57cec5SDimitry Andric /// \param D The declaration to which the attribute is attached. 1110b57cec5SDimitry Andric /// \param DeclExp An expression involving the Decl to which the attribute 1120b57cec5SDimitry Andric /// is attached. E.g. the call to a function. 1135f757f3fSDimitry Andric /// \param Self S-expression to substitute for a \ref CXXThisExpr in a call, 1145f757f3fSDimitry Andric /// or argument to a cleanup function. 1150b57cec5SDimitry Andric CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, 1160b57cec5SDimitry Andric const NamedDecl *D, 1170b57cec5SDimitry Andric const Expr *DeclExp, 118bdd1243dSDimitry Andric til::SExpr *Self) { 1190b57cec5SDimitry Andric // If we are processing a raw attribute expression, with no substitutions. 120bdd1243dSDimitry Andric if (!DeclExp && !Self) 1210b57cec5SDimitry Andric return translateAttrExpr(AttrExp, nullptr); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric CallingContext Ctx(nullptr, D); 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric // Examine DeclExp to find SelfArg and FunArgs, which are used to substitute 1260b57cec5SDimitry Andric // for formal parameters when we call buildMutexID later. 127bdd1243dSDimitry Andric if (!DeclExp) 128bdd1243dSDimitry Andric /* We'll use Self. */; 129bdd1243dSDimitry Andric else if (const auto *ME = dyn_cast<MemberExpr>(DeclExp)) { 1300b57cec5SDimitry Andric Ctx.SelfArg = ME->getBase(); 1310b57cec5SDimitry Andric Ctx.SelfArrow = ME->isArrow(); 1320b57cec5SDimitry Andric } else if (const auto *CE = dyn_cast<CXXMemberCallExpr>(DeclExp)) { 1330b57cec5SDimitry Andric Ctx.SelfArg = CE->getImplicitObjectArgument(); 1340b57cec5SDimitry Andric Ctx.SelfArrow = isCalleeArrow(CE->getCallee()); 1350b57cec5SDimitry Andric Ctx.NumArgs = CE->getNumArgs(); 1360b57cec5SDimitry Andric Ctx.FunArgs = CE->getArgs(); 1370b57cec5SDimitry Andric } else if (const auto *CE = dyn_cast<CallExpr>(DeclExp)) { 1380b57cec5SDimitry Andric Ctx.NumArgs = CE->getNumArgs(); 1390b57cec5SDimitry Andric Ctx.FunArgs = CE->getArgs(); 1400b57cec5SDimitry Andric } else if (const auto *CE = dyn_cast<CXXConstructExpr>(DeclExp)) { 1410b57cec5SDimitry Andric Ctx.SelfArg = nullptr; // Will be set below 1420b57cec5SDimitry Andric Ctx.NumArgs = CE->getNumArgs(); 1430b57cec5SDimitry Andric Ctx.FunArgs = CE->getArgs(); 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 146bdd1243dSDimitry Andric if (Self) { 147bdd1243dSDimitry Andric assert(!Ctx.SelfArg && "Ambiguous self argument"); 1485f757f3fSDimitry Andric assert(isa<FunctionDecl>(D) && "Self argument requires function"); 1495f757f3fSDimitry Andric if (isa<CXXMethodDecl>(D)) 150bdd1243dSDimitry Andric Ctx.SelfArg = Self; 1515f757f3fSDimitry Andric else 1525f757f3fSDimitry Andric Ctx.FunArgs = Self; 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric // If the attribute has no arguments, then assume the argument is "this". 1550b57cec5SDimitry Andric if (!AttrExp) 156bdd1243dSDimitry Andric return CapabilityExpr( 1575f757f3fSDimitry Andric Self, 1585f757f3fSDimitry Andric ClassifyDiagnostic( 1595f757f3fSDimitry Andric cast<CXXMethodDecl>(D)->getFunctionObjectParameterType()), 160bdd1243dSDimitry Andric false); 1610b57cec5SDimitry Andric else // For most attributes. 1620b57cec5SDimitry Andric return translateAttrExpr(AttrExp, &Ctx); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric // If the attribute has no arguments, then assume the argument is "this". 1660b57cec5SDimitry Andric if (!AttrExp) 167bdd1243dSDimitry Andric return translateAttrExpr(cast<const Expr *>(Ctx.SelfArg), nullptr); 1680b57cec5SDimitry Andric else // For most attributes. 1690b57cec5SDimitry Andric return translateAttrExpr(AttrExp, &Ctx); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric /// Translate a clang expression in an attribute to a til::SExpr. 1730b57cec5SDimitry Andric // This assumes a CallingContext has already been created. 1740b57cec5SDimitry Andric CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, 1750b57cec5SDimitry Andric CallingContext *Ctx) { 1760b57cec5SDimitry Andric if (!AttrExp) 17781ad6265SDimitry Andric return CapabilityExpr(); 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric if (const auto* SLit = dyn_cast<StringLiteral>(AttrExp)) { 180*0fca6ea1SDimitry Andric if (SLit->getString() == "*") 1810b57cec5SDimitry Andric // The "*" expr is a universal lock, which essentially turns off 1820b57cec5SDimitry Andric // checks until it is removed from the lockset. 18381ad6265SDimitry Andric return CapabilityExpr(new (Arena) til::Wildcard(), StringRef("wildcard"), 18481ad6265SDimitry Andric false); 1850b57cec5SDimitry Andric else 1860b57cec5SDimitry Andric // Ignore other string literals for now. 18781ad6265SDimitry Andric return CapabilityExpr(); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric bool Neg = false; 1910b57cec5SDimitry Andric if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(AttrExp)) { 1920b57cec5SDimitry Andric if (OE->getOperator() == OO_Exclaim) { 1930b57cec5SDimitry Andric Neg = true; 1940b57cec5SDimitry Andric AttrExp = OE->getArg(0); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric else if (const auto *UO = dyn_cast<UnaryOperator>(AttrExp)) { 1980b57cec5SDimitry Andric if (UO->getOpcode() == UO_LNot) { 1990b57cec5SDimitry Andric Neg = true; 200*0fca6ea1SDimitry Andric AttrExp = UO->getSubExpr()->IgnoreImplicit(); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric til::SExpr *E = translate(AttrExp, Ctx); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric // Trap mutex expressions like nullptr, or 0. 2070b57cec5SDimitry Andric // Any literal value is nonsense. 2080b57cec5SDimitry Andric if (!E || isa<til::Literal>(E)) 20981ad6265SDimitry Andric return CapabilityExpr(); 21081ad6265SDimitry Andric 21181ad6265SDimitry Andric StringRef Kind = ClassifyDiagnostic(AttrExp->getType()); 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric // Hack to deal with smart pointers -- strip off top-level pointer casts. 214e8d8bef9SDimitry Andric if (const auto *CE = dyn_cast<til::Cast>(E)) { 2150b57cec5SDimitry Andric if (CE->castOpcode() == til::CAST_objToPtr) 21681ad6265SDimitry Andric return CapabilityExpr(CE->expr(), Kind, Neg); 2170b57cec5SDimitry Andric } 21881ad6265SDimitry Andric return CapabilityExpr(E, Kind, Neg); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 221bdd1243dSDimitry Andric til::LiteralPtr *SExprBuilder::createVariable(const VarDecl *VD) { 222bdd1243dSDimitry Andric return new (Arena) til::LiteralPtr(VD); 223bdd1243dSDimitry Andric } 224bdd1243dSDimitry Andric 225bdd1243dSDimitry Andric std::pair<til::LiteralPtr *, StringRef> 226bdd1243dSDimitry Andric SExprBuilder::createThisPlaceholder(const Expr *Exp) { 227bdd1243dSDimitry Andric return {new (Arena) til::LiteralPtr(nullptr), 228bdd1243dSDimitry Andric ClassifyDiagnostic(Exp->getType())}; 229bdd1243dSDimitry Andric } 230bdd1243dSDimitry Andric 2310b57cec5SDimitry Andric // Translate a clang statement or expression to a TIL expression. 2320b57cec5SDimitry Andric // Also performs substitution of variables; Ctx provides the context. 2330b57cec5SDimitry Andric // Dispatches on the type of S. 2340b57cec5SDimitry Andric til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) { 2350b57cec5SDimitry Andric if (!S) 2360b57cec5SDimitry Andric return nullptr; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric // Check if S has already been translated and cached. 2390b57cec5SDimitry Andric // This handles the lookup of SSA names for DeclRefExprs here. 2400b57cec5SDimitry Andric if (til::SExpr *E = lookupStmt(S)) 2410b57cec5SDimitry Andric return E; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric switch (S->getStmtClass()) { 2440b57cec5SDimitry Andric case Stmt::DeclRefExprClass: 2450b57cec5SDimitry Andric return translateDeclRefExpr(cast<DeclRefExpr>(S), Ctx); 2460b57cec5SDimitry Andric case Stmt::CXXThisExprClass: 2470b57cec5SDimitry Andric return translateCXXThisExpr(cast<CXXThisExpr>(S), Ctx); 2480b57cec5SDimitry Andric case Stmt::MemberExprClass: 2490b57cec5SDimitry Andric return translateMemberExpr(cast<MemberExpr>(S), Ctx); 2500b57cec5SDimitry Andric case Stmt::ObjCIvarRefExprClass: 2510b57cec5SDimitry Andric return translateObjCIVarRefExpr(cast<ObjCIvarRefExpr>(S), Ctx); 2520b57cec5SDimitry Andric case Stmt::CallExprClass: 2530b57cec5SDimitry Andric return translateCallExpr(cast<CallExpr>(S), Ctx); 2540b57cec5SDimitry Andric case Stmt::CXXMemberCallExprClass: 2550b57cec5SDimitry Andric return translateCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), Ctx); 2560b57cec5SDimitry Andric case Stmt::CXXOperatorCallExprClass: 2570b57cec5SDimitry Andric return translateCXXOperatorCallExpr(cast<CXXOperatorCallExpr>(S), Ctx); 2580b57cec5SDimitry Andric case Stmt::UnaryOperatorClass: 2590b57cec5SDimitry Andric return translateUnaryOperator(cast<UnaryOperator>(S), Ctx); 2600b57cec5SDimitry Andric case Stmt::BinaryOperatorClass: 2610b57cec5SDimitry Andric case Stmt::CompoundAssignOperatorClass: 2620b57cec5SDimitry Andric return translateBinaryOperator(cast<BinaryOperator>(S), Ctx); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric case Stmt::ArraySubscriptExprClass: 2650b57cec5SDimitry Andric return translateArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Ctx); 2660b57cec5SDimitry Andric case Stmt::ConditionalOperatorClass: 2670b57cec5SDimitry Andric return translateAbstractConditionalOperator( 2680b57cec5SDimitry Andric cast<ConditionalOperator>(S), Ctx); 2690b57cec5SDimitry Andric case Stmt::BinaryConditionalOperatorClass: 2700b57cec5SDimitry Andric return translateAbstractConditionalOperator( 2710b57cec5SDimitry Andric cast<BinaryConditionalOperator>(S), Ctx); 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric // We treat these as no-ops 2740b57cec5SDimitry Andric case Stmt::ConstantExprClass: 2750b57cec5SDimitry Andric return translate(cast<ConstantExpr>(S)->getSubExpr(), Ctx); 2760b57cec5SDimitry Andric case Stmt::ParenExprClass: 2770b57cec5SDimitry Andric return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx); 2780b57cec5SDimitry Andric case Stmt::ExprWithCleanupsClass: 2790b57cec5SDimitry Andric return translate(cast<ExprWithCleanups>(S)->getSubExpr(), Ctx); 2800b57cec5SDimitry Andric case Stmt::CXXBindTemporaryExprClass: 2810b57cec5SDimitry Andric return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx); 2820b57cec5SDimitry Andric case Stmt::MaterializeTemporaryExprClass: 283480093f4SDimitry Andric return translate(cast<MaterializeTemporaryExpr>(S)->getSubExpr(), Ctx); 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric // Collect all literals 2860b57cec5SDimitry Andric case Stmt::CharacterLiteralClass: 2870b57cec5SDimitry Andric case Stmt::CXXNullPtrLiteralExprClass: 2880b57cec5SDimitry Andric case Stmt::GNUNullExprClass: 2890b57cec5SDimitry Andric case Stmt::CXXBoolLiteralExprClass: 2900b57cec5SDimitry Andric case Stmt::FloatingLiteralClass: 2910b57cec5SDimitry Andric case Stmt::ImaginaryLiteralClass: 2920b57cec5SDimitry Andric case Stmt::IntegerLiteralClass: 2930b57cec5SDimitry Andric case Stmt::StringLiteralClass: 2940b57cec5SDimitry Andric case Stmt::ObjCStringLiteralClass: 2950b57cec5SDimitry Andric return new (Arena) til::Literal(cast<Expr>(S)); 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric case Stmt::DeclStmtClass: 2980b57cec5SDimitry Andric return translateDeclStmt(cast<DeclStmt>(S), Ctx); 2990b57cec5SDimitry Andric default: 3000b57cec5SDimitry Andric break; 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric if (const auto *CE = dyn_cast<CastExpr>(S)) 3030b57cec5SDimitry Andric return translateCastExpr(CE, Ctx); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric return new (Arena) til::Undefined(S); 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE, 3090b57cec5SDimitry Andric CallingContext *Ctx) { 3100b57cec5SDimitry Andric const auto *VD = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl()); 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric // Function parameters require substitution and/or renaming. 313e8d8bef9SDimitry Andric if (const auto *PV = dyn_cast<ParmVarDecl>(VD)) { 3140b57cec5SDimitry Andric unsigned I = PV->getFunctionScopeIndex(); 3150b57cec5SDimitry Andric const DeclContext *D = PV->getDeclContext(); 3160b57cec5SDimitry Andric if (Ctx && Ctx->FunArgs) { 3170b57cec5SDimitry Andric const Decl *Canonical = Ctx->AttrDecl->getCanonicalDecl(); 3180b57cec5SDimitry Andric if (isa<FunctionDecl>(D) 3190b57cec5SDimitry Andric ? (cast<FunctionDecl>(D)->getCanonicalDecl() == Canonical) 3200b57cec5SDimitry Andric : (cast<ObjCMethodDecl>(D)->getCanonicalDecl() == Canonical)) { 3210b57cec5SDimitry Andric // Substitute call arguments for references to function parameters 3225f757f3fSDimitry Andric if (const Expr *const *FunArgs = 3235f757f3fSDimitry Andric Ctx->FunArgs.dyn_cast<const Expr *const *>()) { 3240b57cec5SDimitry Andric assert(I < Ctx->NumArgs); 3255f757f3fSDimitry Andric return translate(FunArgs[I], Ctx->Prev); 3265f757f3fSDimitry Andric } 3275f757f3fSDimitry Andric 3285f757f3fSDimitry Andric assert(I == 0); 3295f757f3fSDimitry Andric return Ctx->FunArgs.get<til::SExpr *>(); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric // Map the param back to the param of the original function declaration 3330b57cec5SDimitry Andric // for consistent comparisons. 3340b57cec5SDimitry Andric VD = isa<FunctionDecl>(D) 3350b57cec5SDimitry Andric ? cast<FunctionDecl>(D)->getCanonicalDecl()->getParamDecl(I) 3360b57cec5SDimitry Andric : cast<ObjCMethodDecl>(D)->getCanonicalDecl()->getParamDecl(I); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric // For non-local variables, treat it as a reference to a named object. 3400b57cec5SDimitry Andric return new (Arena) til::LiteralPtr(VD); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE, 3440b57cec5SDimitry Andric CallingContext *Ctx) { 3450b57cec5SDimitry Andric // Substitute for 'this' 346bdd1243dSDimitry Andric if (Ctx && Ctx->SelfArg) { 347bdd1243dSDimitry Andric if (const auto *SelfArg = dyn_cast<const Expr *>(Ctx->SelfArg)) 348bdd1243dSDimitry Andric return translate(SelfArg, Ctx->Prev); 349bdd1243dSDimitry Andric else 350bdd1243dSDimitry Andric return cast<til::SExpr *>(Ctx->SelfArg); 351bdd1243dSDimitry Andric } 3520b57cec5SDimitry Andric assert(SelfVar && "We have no variable for 'this'!"); 3530b57cec5SDimitry Andric return SelfVar; 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric static const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) { 3570b57cec5SDimitry Andric if (const auto *V = dyn_cast<til::Variable>(E)) 3580b57cec5SDimitry Andric return V->clangDecl(); 3590b57cec5SDimitry Andric if (const auto *Ph = dyn_cast<til::Phi>(E)) 3600b57cec5SDimitry Andric return Ph->clangDecl(); 3610b57cec5SDimitry Andric if (const auto *P = dyn_cast<til::Project>(E)) 3620b57cec5SDimitry Andric return P->clangDecl(); 3630b57cec5SDimitry Andric if (const auto *L = dyn_cast<til::LiteralPtr>(E)) 3640b57cec5SDimitry Andric return L->clangDecl(); 3650b57cec5SDimitry Andric return nullptr; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric static bool hasAnyPointerType(const til::SExpr *E) { 3690b57cec5SDimitry Andric auto *VD = getValueDeclFromSExpr(E); 3700b57cec5SDimitry Andric if (VD && VD->getType()->isAnyPointerType()) 3710b57cec5SDimitry Andric return true; 3720b57cec5SDimitry Andric if (const auto *C = dyn_cast<til::Cast>(E)) 3730b57cec5SDimitry Andric return C->castOpcode() == til::CAST_objToPtr; 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric return false; 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric // Grab the very first declaration of virtual method D 3790b57cec5SDimitry Andric static const CXXMethodDecl *getFirstVirtualDecl(const CXXMethodDecl *D) { 3800b57cec5SDimitry Andric while (true) { 3810b57cec5SDimitry Andric D = D->getCanonicalDecl(); 3820b57cec5SDimitry Andric auto OverriddenMethods = D->overridden_methods(); 3830b57cec5SDimitry Andric if (OverriddenMethods.begin() == OverriddenMethods.end()) 3840b57cec5SDimitry Andric return D; // Method does not override anything 3850b57cec5SDimitry Andric // FIXME: this does not work with multiple inheritance. 3860b57cec5SDimitry Andric D = *OverriddenMethods.begin(); 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric return nullptr; 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME, 3920b57cec5SDimitry Andric CallingContext *Ctx) { 3930b57cec5SDimitry Andric til::SExpr *BE = translate(ME->getBase(), Ctx); 3940b57cec5SDimitry Andric til::SExpr *E = new (Arena) til::SApply(BE); 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric const auto *D = cast<ValueDecl>(ME->getMemberDecl()->getCanonicalDecl()); 3970b57cec5SDimitry Andric if (const auto *VD = dyn_cast<CXXMethodDecl>(D)) 3980b57cec5SDimitry Andric D = getFirstVirtualDecl(VD); 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric til::Project *P = new (Arena) til::Project(E, D); 4010b57cec5SDimitry Andric if (hasAnyPointerType(BE)) 4020b57cec5SDimitry Andric P->setArrow(true); 4030b57cec5SDimitry Andric return P; 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateObjCIVarRefExpr(const ObjCIvarRefExpr *IVRE, 4070b57cec5SDimitry Andric CallingContext *Ctx) { 4080b57cec5SDimitry Andric til::SExpr *BE = translate(IVRE->getBase(), Ctx); 4090b57cec5SDimitry Andric til::SExpr *E = new (Arena) til::SApply(BE); 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric const auto *D = cast<ObjCIvarDecl>(IVRE->getDecl()->getCanonicalDecl()); 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric til::Project *P = new (Arena) til::Project(E, D); 4140b57cec5SDimitry Andric if (hasAnyPointerType(BE)) 4150b57cec5SDimitry Andric P->setArrow(true); 4160b57cec5SDimitry Andric return P; 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE, 4200b57cec5SDimitry Andric CallingContext *Ctx, 4210b57cec5SDimitry Andric const Expr *SelfE) { 4220b57cec5SDimitry Andric if (CapabilityExprMode) { 4230b57cec5SDimitry Andric // Handle LOCK_RETURNED 4240b57cec5SDimitry Andric if (const FunctionDecl *FD = CE->getDirectCallee()) { 4250b57cec5SDimitry Andric FD = FD->getMostRecentDecl(); 4260b57cec5SDimitry Andric if (LockReturnedAttr *At = FD->getAttr<LockReturnedAttr>()) { 4270b57cec5SDimitry Andric CallingContext LRCallCtx(Ctx); 4280b57cec5SDimitry Andric LRCallCtx.AttrDecl = CE->getDirectCallee(); 4290b57cec5SDimitry Andric LRCallCtx.SelfArg = SelfE; 4300b57cec5SDimitry Andric LRCallCtx.NumArgs = CE->getNumArgs(); 4310b57cec5SDimitry Andric LRCallCtx.FunArgs = CE->getArgs(); 4320b57cec5SDimitry Andric return const_cast<til::SExpr *>( 4330b57cec5SDimitry Andric translateAttrExpr(At->getArg(), &LRCallCtx).sexpr()); 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric til::SExpr *E = translate(CE->getCallee(), Ctx); 4390b57cec5SDimitry Andric for (const auto *Arg : CE->arguments()) { 4400b57cec5SDimitry Andric til::SExpr *A = translate(Arg, Ctx); 4410b57cec5SDimitry Andric E = new (Arena) til::Apply(E, A); 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric return new (Arena) til::Call(E, CE); 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateCXXMemberCallExpr( 4470b57cec5SDimitry Andric const CXXMemberCallExpr *ME, CallingContext *Ctx) { 4480b57cec5SDimitry Andric if (CapabilityExprMode) { 4490b57cec5SDimitry Andric // Ignore calls to get() on smart pointers. 4500b57cec5SDimitry Andric if (ME->getMethodDecl()->getNameAsString() == "get" && 4510b57cec5SDimitry Andric ME->getNumArgs() == 0) { 4520b57cec5SDimitry Andric auto *E = translate(ME->getImplicitObjectArgument(), Ctx); 4530b57cec5SDimitry Andric return new (Arena) til::Cast(til::CAST_objToPtr, E); 4540b57cec5SDimitry Andric // return E; 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric return translateCallExpr(cast<CallExpr>(ME), Ctx, 4580b57cec5SDimitry Andric ME->getImplicitObjectArgument()); 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateCXXOperatorCallExpr( 4620b57cec5SDimitry Andric const CXXOperatorCallExpr *OCE, CallingContext *Ctx) { 4630b57cec5SDimitry Andric if (CapabilityExprMode) { 4640b57cec5SDimitry Andric // Ignore operator * and operator -> on smart pointers. 4650b57cec5SDimitry Andric OverloadedOperatorKind k = OCE->getOperator(); 4660b57cec5SDimitry Andric if (k == OO_Star || k == OO_Arrow) { 4670b57cec5SDimitry Andric auto *E = translate(OCE->getArg(0), Ctx); 4680b57cec5SDimitry Andric return new (Arena) til::Cast(til::CAST_objToPtr, E); 4690b57cec5SDimitry Andric // return E; 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric return translateCallExpr(cast<CallExpr>(OCE), Ctx); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO, 4760b57cec5SDimitry Andric CallingContext *Ctx) { 4770b57cec5SDimitry Andric switch (UO->getOpcode()) { 4780b57cec5SDimitry Andric case UO_PostInc: 4790b57cec5SDimitry Andric case UO_PostDec: 4800b57cec5SDimitry Andric case UO_PreInc: 4810b57cec5SDimitry Andric case UO_PreDec: 4820b57cec5SDimitry Andric return new (Arena) til::Undefined(UO); 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric case UO_AddrOf: 4850b57cec5SDimitry Andric if (CapabilityExprMode) { 4860b57cec5SDimitry Andric // interpret &Graph::mu_ as an existential. 4870b57cec5SDimitry Andric if (const auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr())) { 4880b57cec5SDimitry Andric if (DRE->getDecl()->isCXXInstanceMember()) { 4890b57cec5SDimitry Andric // This is a pointer-to-member expression, e.g. &MyClass::mu_. 4900b57cec5SDimitry Andric // We interpret this syntax specially, as a wildcard. 4910b57cec5SDimitry Andric auto *W = new (Arena) til::Wildcard(); 4920b57cec5SDimitry Andric return new (Arena) til::Project(W, DRE->getDecl()); 4930b57cec5SDimitry Andric } 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric // otherwise, & is a no-op 4970b57cec5SDimitry Andric return translate(UO->getSubExpr(), Ctx); 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric // We treat these as no-ops 5000b57cec5SDimitry Andric case UO_Deref: 5010b57cec5SDimitry Andric case UO_Plus: 5020b57cec5SDimitry Andric return translate(UO->getSubExpr(), Ctx); 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric case UO_Minus: 5050b57cec5SDimitry Andric return new (Arena) 5060b57cec5SDimitry Andric til::UnaryOp(til::UOP_Minus, translate(UO->getSubExpr(), Ctx)); 5070b57cec5SDimitry Andric case UO_Not: 5080b57cec5SDimitry Andric return new (Arena) 5090b57cec5SDimitry Andric til::UnaryOp(til::UOP_BitNot, translate(UO->getSubExpr(), Ctx)); 5100b57cec5SDimitry Andric case UO_LNot: 5110b57cec5SDimitry Andric return new (Arena) 5120b57cec5SDimitry Andric til::UnaryOp(til::UOP_LogicNot, translate(UO->getSubExpr(), Ctx)); 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric // Currently unsupported 5150b57cec5SDimitry Andric case UO_Real: 5160b57cec5SDimitry Andric case UO_Imag: 5170b57cec5SDimitry Andric case UO_Extension: 5180b57cec5SDimitry Andric case UO_Coawait: 5190b57cec5SDimitry Andric return new (Arena) til::Undefined(UO); 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric return new (Arena) til::Undefined(UO); 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateBinOp(til::TIL_BinaryOpcode Op, 5250b57cec5SDimitry Andric const BinaryOperator *BO, 5260b57cec5SDimitry Andric CallingContext *Ctx, bool Reverse) { 5270b57cec5SDimitry Andric til::SExpr *E0 = translate(BO->getLHS(), Ctx); 5280b57cec5SDimitry Andric til::SExpr *E1 = translate(BO->getRHS(), Ctx); 5290b57cec5SDimitry Andric if (Reverse) 5300b57cec5SDimitry Andric return new (Arena) til::BinaryOp(Op, E1, E0); 5310b57cec5SDimitry Andric else 5320b57cec5SDimitry Andric return new (Arena) til::BinaryOp(Op, E0, E1); 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateBinAssign(til::TIL_BinaryOpcode Op, 5360b57cec5SDimitry Andric const BinaryOperator *BO, 5370b57cec5SDimitry Andric CallingContext *Ctx, 5380b57cec5SDimitry Andric bool Assign) { 5390b57cec5SDimitry Andric const Expr *LHS = BO->getLHS(); 5400b57cec5SDimitry Andric const Expr *RHS = BO->getRHS(); 5410b57cec5SDimitry Andric til::SExpr *E0 = translate(LHS, Ctx); 5420b57cec5SDimitry Andric til::SExpr *E1 = translate(RHS, Ctx); 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric const ValueDecl *VD = nullptr; 5450b57cec5SDimitry Andric til::SExpr *CV = nullptr; 5460b57cec5SDimitry Andric if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS)) { 5470b57cec5SDimitry Andric VD = DRE->getDecl(); 5480b57cec5SDimitry Andric CV = lookupVarDecl(VD); 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric if (!Assign) { 5520b57cec5SDimitry Andric til::SExpr *Arg = CV ? CV : new (Arena) til::Load(E0); 5530b57cec5SDimitry Andric E1 = new (Arena) til::BinaryOp(Op, Arg, E1); 5540b57cec5SDimitry Andric E1 = addStatement(E1, nullptr, VD); 5550b57cec5SDimitry Andric } 5560b57cec5SDimitry Andric if (VD && CV) 5570b57cec5SDimitry Andric return updateVarDecl(VD, E1); 5580b57cec5SDimitry Andric return new (Arena) til::Store(E0, E1); 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric 5610b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO, 5620b57cec5SDimitry Andric CallingContext *Ctx) { 5630b57cec5SDimitry Andric switch (BO->getOpcode()) { 5640b57cec5SDimitry Andric case BO_PtrMemD: 5650b57cec5SDimitry Andric case BO_PtrMemI: 5660b57cec5SDimitry Andric return new (Arena) til::Undefined(BO); 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric case BO_Mul: return translateBinOp(til::BOP_Mul, BO, Ctx); 5690b57cec5SDimitry Andric case BO_Div: return translateBinOp(til::BOP_Div, BO, Ctx); 5700b57cec5SDimitry Andric case BO_Rem: return translateBinOp(til::BOP_Rem, BO, Ctx); 5710b57cec5SDimitry Andric case BO_Add: return translateBinOp(til::BOP_Add, BO, Ctx); 5720b57cec5SDimitry Andric case BO_Sub: return translateBinOp(til::BOP_Sub, BO, Ctx); 5730b57cec5SDimitry Andric case BO_Shl: return translateBinOp(til::BOP_Shl, BO, Ctx); 5740b57cec5SDimitry Andric case BO_Shr: return translateBinOp(til::BOP_Shr, BO, Ctx); 5750b57cec5SDimitry Andric case BO_LT: return translateBinOp(til::BOP_Lt, BO, Ctx); 5760b57cec5SDimitry Andric case BO_GT: return translateBinOp(til::BOP_Lt, BO, Ctx, true); 5770b57cec5SDimitry Andric case BO_LE: return translateBinOp(til::BOP_Leq, BO, Ctx); 5780b57cec5SDimitry Andric case BO_GE: return translateBinOp(til::BOP_Leq, BO, Ctx, true); 5790b57cec5SDimitry Andric case BO_EQ: return translateBinOp(til::BOP_Eq, BO, Ctx); 5800b57cec5SDimitry Andric case BO_NE: return translateBinOp(til::BOP_Neq, BO, Ctx); 5810b57cec5SDimitry Andric case BO_Cmp: return translateBinOp(til::BOP_Cmp, BO, Ctx); 5820b57cec5SDimitry Andric case BO_And: return translateBinOp(til::BOP_BitAnd, BO, Ctx); 5830b57cec5SDimitry Andric case BO_Xor: return translateBinOp(til::BOP_BitXor, BO, Ctx); 5840b57cec5SDimitry Andric case BO_Or: return translateBinOp(til::BOP_BitOr, BO, Ctx); 5850b57cec5SDimitry Andric case BO_LAnd: return translateBinOp(til::BOP_LogicAnd, BO, Ctx); 5860b57cec5SDimitry Andric case BO_LOr: return translateBinOp(til::BOP_LogicOr, BO, Ctx); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric case BO_Assign: return translateBinAssign(til::BOP_Eq, BO, Ctx, true); 5890b57cec5SDimitry Andric case BO_MulAssign: return translateBinAssign(til::BOP_Mul, BO, Ctx); 5900b57cec5SDimitry Andric case BO_DivAssign: return translateBinAssign(til::BOP_Div, BO, Ctx); 5910b57cec5SDimitry Andric case BO_RemAssign: return translateBinAssign(til::BOP_Rem, BO, Ctx); 5920b57cec5SDimitry Andric case BO_AddAssign: return translateBinAssign(til::BOP_Add, BO, Ctx); 5930b57cec5SDimitry Andric case BO_SubAssign: return translateBinAssign(til::BOP_Sub, BO, Ctx); 5940b57cec5SDimitry Andric case BO_ShlAssign: return translateBinAssign(til::BOP_Shl, BO, Ctx); 5950b57cec5SDimitry Andric case BO_ShrAssign: return translateBinAssign(til::BOP_Shr, BO, Ctx); 5960b57cec5SDimitry Andric case BO_AndAssign: return translateBinAssign(til::BOP_BitAnd, BO, Ctx); 5970b57cec5SDimitry Andric case BO_XorAssign: return translateBinAssign(til::BOP_BitXor, BO, Ctx); 5980b57cec5SDimitry Andric case BO_OrAssign: return translateBinAssign(til::BOP_BitOr, BO, Ctx); 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric case BO_Comma: 6010b57cec5SDimitry Andric // The clang CFG should have already processed both sides. 6020b57cec5SDimitry Andric return translate(BO->getRHS(), Ctx); 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric return new (Arena) til::Undefined(BO); 6050b57cec5SDimitry Andric } 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE, 6080b57cec5SDimitry Andric CallingContext *Ctx) { 6090b57cec5SDimitry Andric CastKind K = CE->getCastKind(); 6100b57cec5SDimitry Andric switch (K) { 6110b57cec5SDimitry Andric case CK_LValueToRValue: { 6120b57cec5SDimitry Andric if (const auto *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) { 6130b57cec5SDimitry Andric til::SExpr *E0 = lookupVarDecl(DRE->getDecl()); 6140b57cec5SDimitry Andric if (E0) 6150b57cec5SDimitry Andric return E0; 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric til::SExpr *E0 = translate(CE->getSubExpr(), Ctx); 6180b57cec5SDimitry Andric return E0; 6190b57cec5SDimitry Andric // FIXME!! -- get Load working properly 6200b57cec5SDimitry Andric // return new (Arena) til::Load(E0); 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric case CK_NoOp: 6230b57cec5SDimitry Andric case CK_DerivedToBase: 6240b57cec5SDimitry Andric case CK_UncheckedDerivedToBase: 6250b57cec5SDimitry Andric case CK_ArrayToPointerDecay: 6260b57cec5SDimitry Andric case CK_FunctionToPointerDecay: { 6270b57cec5SDimitry Andric til::SExpr *E0 = translate(CE->getSubExpr(), Ctx); 6280b57cec5SDimitry Andric return E0; 6290b57cec5SDimitry Andric } 6300b57cec5SDimitry Andric default: { 6310b57cec5SDimitry Andric // FIXME: handle different kinds of casts. 6320b57cec5SDimitry Andric til::SExpr *E0 = translate(CE->getSubExpr(), Ctx); 6330b57cec5SDimitry Andric if (CapabilityExprMode) 6340b57cec5SDimitry Andric return E0; 6350b57cec5SDimitry Andric return new (Arena) til::Cast(til::CAST_none, E0); 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric } 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric til::SExpr * 6410b57cec5SDimitry Andric SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E, 6420b57cec5SDimitry Andric CallingContext *Ctx) { 6430b57cec5SDimitry Andric til::SExpr *E0 = translate(E->getBase(), Ctx); 6440b57cec5SDimitry Andric til::SExpr *E1 = translate(E->getIdx(), Ctx); 6450b57cec5SDimitry Andric return new (Arena) til::ArrayIndex(E0, E1); 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric til::SExpr * 6490b57cec5SDimitry Andric SExprBuilder::translateAbstractConditionalOperator( 6500b57cec5SDimitry Andric const AbstractConditionalOperator *CO, CallingContext *Ctx) { 6510b57cec5SDimitry Andric auto *C = translate(CO->getCond(), Ctx); 6520b57cec5SDimitry Andric auto *T = translate(CO->getTrueExpr(), Ctx); 6530b57cec5SDimitry Andric auto *E = translate(CO->getFalseExpr(), Ctx); 6540b57cec5SDimitry Andric return new (Arena) til::IfThenElse(C, T, E); 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric til::SExpr * 6580b57cec5SDimitry Andric SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) { 6590b57cec5SDimitry Andric DeclGroupRef DGrp = S->getDeclGroup(); 660bdd1243dSDimitry Andric for (auto *I : DGrp) { 6610b57cec5SDimitry Andric if (auto *VD = dyn_cast_or_null<VarDecl>(I)) { 6620b57cec5SDimitry Andric Expr *E = VD->getInit(); 6630b57cec5SDimitry Andric til::SExpr* SE = translate(E, Ctx); 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric // Add local variables with trivial type to the variable map 6660b57cec5SDimitry Andric QualType T = VD->getType(); 6670b57cec5SDimitry Andric if (T.isTrivialType(VD->getASTContext())) 6680b57cec5SDimitry Andric return addVarDecl(VD, SE); 6690b57cec5SDimitry Andric else { 6700b57cec5SDimitry Andric // TODO: add alloca 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric } 6740b57cec5SDimitry Andric return nullptr; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric // If (E) is non-trivial, then add it to the current basic block, and 6780b57cec5SDimitry Andric // update the statement map so that S refers to E. Returns a new variable 6790b57cec5SDimitry Andric // that refers to E. 6800b57cec5SDimitry Andric // If E is trivial returns E. 6810b57cec5SDimitry Andric til::SExpr *SExprBuilder::addStatement(til::SExpr* E, const Stmt *S, 6820b57cec5SDimitry Andric const ValueDecl *VD) { 6830b57cec5SDimitry Andric if (!E || !CurrentBB || E->block() || til::ThreadSafetyTIL::isTrivial(E)) 6840b57cec5SDimitry Andric return E; 6850b57cec5SDimitry Andric if (VD) 6860b57cec5SDimitry Andric E = new (Arena) til::Variable(E, VD); 6870b57cec5SDimitry Andric CurrentInstructions.push_back(E); 6880b57cec5SDimitry Andric if (S) 6890b57cec5SDimitry Andric insertStmt(S, E); 6900b57cec5SDimitry Andric return E; 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric // Returns the current value of VD, if known, and nullptr otherwise. 6940b57cec5SDimitry Andric til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) { 6950b57cec5SDimitry Andric auto It = LVarIdxMap.find(VD); 6960b57cec5SDimitry Andric if (It != LVarIdxMap.end()) { 6970b57cec5SDimitry Andric assert(CurrentLVarMap[It->second].first == VD); 6980b57cec5SDimitry Andric return CurrentLVarMap[It->second].second; 6990b57cec5SDimitry Andric } 7000b57cec5SDimitry Andric return nullptr; 7010b57cec5SDimitry Andric } 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric // if E is a til::Variable, update its clangDecl. 7040b57cec5SDimitry Andric static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) { 7050b57cec5SDimitry Andric if (!E) 7060b57cec5SDimitry Andric return; 7070b57cec5SDimitry Andric if (auto *V = dyn_cast<til::Variable>(E)) { 7080b57cec5SDimitry Andric if (!V->clangDecl()) 7090b57cec5SDimitry Andric V->setClangDecl(VD); 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric } 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric // Adds a new variable declaration. 7140b57cec5SDimitry Andric til::SExpr *SExprBuilder::addVarDecl(const ValueDecl *VD, til::SExpr *E) { 7150b57cec5SDimitry Andric maybeUpdateVD(E, VD); 7160b57cec5SDimitry Andric LVarIdxMap.insert(std::make_pair(VD, CurrentLVarMap.size())); 7170b57cec5SDimitry Andric CurrentLVarMap.makeWritable(); 7180b57cec5SDimitry Andric CurrentLVarMap.push_back(std::make_pair(VD, E)); 7190b57cec5SDimitry Andric return E; 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric // Updates a current variable declaration. (E.g. by assignment) 7230b57cec5SDimitry Andric til::SExpr *SExprBuilder::updateVarDecl(const ValueDecl *VD, til::SExpr *E) { 7240b57cec5SDimitry Andric maybeUpdateVD(E, VD); 7250b57cec5SDimitry Andric auto It = LVarIdxMap.find(VD); 7260b57cec5SDimitry Andric if (It == LVarIdxMap.end()) { 7270b57cec5SDimitry Andric til::SExpr *Ptr = new (Arena) til::LiteralPtr(VD); 7280b57cec5SDimitry Andric til::SExpr *St = new (Arena) til::Store(Ptr, E); 7290b57cec5SDimitry Andric return St; 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric CurrentLVarMap.makeWritable(); 7320b57cec5SDimitry Andric CurrentLVarMap.elem(It->second).second = E; 7330b57cec5SDimitry Andric return E; 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric // Make a Phi node in the current block for the i^th variable in CurrentVarMap. 7370b57cec5SDimitry Andric // If E != null, sets Phi[CurrentBlockInfo->ArgIndex] = E. 7380b57cec5SDimitry Andric // If E == null, this is a backedge and will be set later. 7390b57cec5SDimitry Andric void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) { 7400b57cec5SDimitry Andric unsigned ArgIndex = CurrentBlockInfo->ProcessedPredecessors; 7410b57cec5SDimitry Andric assert(ArgIndex > 0 && ArgIndex < NPreds); 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric til::SExpr *CurrE = CurrentLVarMap[i].second; 7440b57cec5SDimitry Andric if (CurrE->block() == CurrentBB) { 7450b57cec5SDimitry Andric // We already have a Phi node in the current block, 7460b57cec5SDimitry Andric // so just add the new variable to the Phi node. 7470b57cec5SDimitry Andric auto *Ph = dyn_cast<til::Phi>(CurrE); 7480b57cec5SDimitry Andric assert(Ph && "Expecting Phi node."); 7490b57cec5SDimitry Andric if (E) 7500b57cec5SDimitry Andric Ph->values()[ArgIndex] = E; 7510b57cec5SDimitry Andric return; 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric // Make a new phi node: phi(..., E) 7550b57cec5SDimitry Andric // All phi args up to the current index are set to the current value. 7560b57cec5SDimitry Andric til::Phi *Ph = new (Arena) til::Phi(Arena, NPreds); 7570b57cec5SDimitry Andric Ph->values().setValues(NPreds, nullptr); 7580b57cec5SDimitry Andric for (unsigned PIdx = 0; PIdx < ArgIndex; ++PIdx) 7590b57cec5SDimitry Andric Ph->values()[PIdx] = CurrE; 7600b57cec5SDimitry Andric if (E) 7610b57cec5SDimitry Andric Ph->values()[ArgIndex] = E; 7620b57cec5SDimitry Andric Ph->setClangDecl(CurrentLVarMap[i].first); 7630b57cec5SDimitry Andric // If E is from a back-edge, or either E or CurrE are incomplete, then 7640b57cec5SDimitry Andric // mark this node as incomplete; we may need to remove it later. 7650b57cec5SDimitry Andric if (!E || isIncompletePhi(E) || isIncompletePhi(CurrE)) 7660b57cec5SDimitry Andric Ph->setStatus(til::Phi::PH_Incomplete); 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric // Add Phi node to current block, and update CurrentLVarMap[i] 7690b57cec5SDimitry Andric CurrentArguments.push_back(Ph); 7700b57cec5SDimitry Andric if (Ph->status() == til::Phi::PH_Incomplete) 7710b57cec5SDimitry Andric IncompleteArgs.push_back(Ph); 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric CurrentLVarMap.makeWritable(); 7740b57cec5SDimitry Andric CurrentLVarMap.elem(i).second = Ph; 7750b57cec5SDimitry Andric } 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andric // Merge values from Map into the current variable map. 7780b57cec5SDimitry Andric // This will construct Phi nodes in the current basic block as necessary. 7790b57cec5SDimitry Andric void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map) { 7800b57cec5SDimitry Andric assert(CurrentBlockInfo && "Not processing a block!"); 7810b57cec5SDimitry Andric 7820b57cec5SDimitry Andric if (!CurrentLVarMap.valid()) { 7830b57cec5SDimitry Andric // Steal Map, using copy-on-write. 7840b57cec5SDimitry Andric CurrentLVarMap = std::move(Map); 7850b57cec5SDimitry Andric return; 7860b57cec5SDimitry Andric } 7870b57cec5SDimitry Andric if (CurrentLVarMap.sameAs(Map)) 7880b57cec5SDimitry Andric return; // Easy merge: maps from different predecessors are unchanged. 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric unsigned NPreds = CurrentBB->numPredecessors(); 7910b57cec5SDimitry Andric unsigned ESz = CurrentLVarMap.size(); 7920b57cec5SDimitry Andric unsigned MSz = Map.size(); 7930b57cec5SDimitry Andric unsigned Sz = std::min(ESz, MSz); 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric for (unsigned i = 0; i < Sz; ++i) { 7960b57cec5SDimitry Andric if (CurrentLVarMap[i].first != Map[i].first) { 7970b57cec5SDimitry Andric // We've reached the end of variables in common. 7980b57cec5SDimitry Andric CurrentLVarMap.makeWritable(); 7990b57cec5SDimitry Andric CurrentLVarMap.downsize(i); 8000b57cec5SDimitry Andric break; 8010b57cec5SDimitry Andric } 8020b57cec5SDimitry Andric if (CurrentLVarMap[i].second != Map[i].second) 8030b57cec5SDimitry Andric makePhiNodeVar(i, NPreds, Map[i].second); 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric if (ESz > MSz) { 8060b57cec5SDimitry Andric CurrentLVarMap.makeWritable(); 8070b57cec5SDimitry Andric CurrentLVarMap.downsize(Map.size()); 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric } 8100b57cec5SDimitry Andric 8110b57cec5SDimitry Andric // Merge a back edge into the current variable map. 8120b57cec5SDimitry Andric // This will create phi nodes for all variables in the variable map. 8130b57cec5SDimitry Andric void SExprBuilder::mergeEntryMapBackEdge() { 8140b57cec5SDimitry Andric // We don't have definitions for variables on the backedge, because we 8150b57cec5SDimitry Andric // haven't gotten that far in the CFG. Thus, when encountering a back edge, 8160b57cec5SDimitry Andric // we conservatively create Phi nodes for all variables. Unnecessary Phi 8170b57cec5SDimitry Andric // nodes will be marked as incomplete, and stripped out at the end. 8180b57cec5SDimitry Andric // 8190b57cec5SDimitry Andric // An Phi node is unnecessary if it only refers to itself and one other 8200b57cec5SDimitry Andric // variable, e.g. x = Phi(y, y, x) can be reduced to x = y. 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric assert(CurrentBlockInfo && "Not processing a block!"); 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric if (CurrentBlockInfo->HasBackEdges) 8250b57cec5SDimitry Andric return; 8260b57cec5SDimitry Andric CurrentBlockInfo->HasBackEdges = true; 8270b57cec5SDimitry Andric 8280b57cec5SDimitry Andric CurrentLVarMap.makeWritable(); 8290b57cec5SDimitry Andric unsigned Sz = CurrentLVarMap.size(); 8300b57cec5SDimitry Andric unsigned NPreds = CurrentBB->numPredecessors(); 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric for (unsigned i = 0; i < Sz; ++i) 8330b57cec5SDimitry Andric makePhiNodeVar(i, NPreds, nullptr); 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric // Update the phi nodes that were initially created for a back edge 8370b57cec5SDimitry Andric // once the variable definitions have been computed. 8380b57cec5SDimitry Andric // I.e., merge the current variable map into the phi nodes for Blk. 8390b57cec5SDimitry Andric void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *Blk) { 8400b57cec5SDimitry Andric til::BasicBlock *BB = lookupBlock(Blk); 8410b57cec5SDimitry Andric unsigned ArgIndex = BBInfo[Blk->getBlockID()].ProcessedPredecessors; 8420b57cec5SDimitry Andric assert(ArgIndex > 0 && ArgIndex < BB->numPredecessors()); 8430b57cec5SDimitry Andric 8440b57cec5SDimitry Andric for (til::SExpr *PE : BB->arguments()) { 8450b57cec5SDimitry Andric auto *Ph = dyn_cast_or_null<til::Phi>(PE); 8460b57cec5SDimitry Andric assert(Ph && "Expecting Phi Node."); 8470b57cec5SDimitry Andric assert(Ph->values()[ArgIndex] == nullptr && "Wrong index for back edge."); 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric til::SExpr *E = lookupVarDecl(Ph->clangDecl()); 8500b57cec5SDimitry Andric assert(E && "Couldn't find local variable for Phi node."); 8510b57cec5SDimitry Andric Ph->values()[ArgIndex] = E; 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric } 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D, 8560b57cec5SDimitry Andric const CFGBlock *First) { 8570b57cec5SDimitry Andric // Perform initial setup operations. 8580b57cec5SDimitry Andric unsigned NBlocks = Cfg->getNumBlockIDs(); 8590b57cec5SDimitry Andric Scfg = new (Arena) til::SCFG(Arena, NBlocks); 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric // allocate all basic blocks immediately, to handle forward references. 8620b57cec5SDimitry Andric BBInfo.resize(NBlocks); 8630b57cec5SDimitry Andric BlockMap.resize(NBlocks, nullptr); 8640b57cec5SDimitry Andric // create map from clang blockID to til::BasicBlocks 8650b57cec5SDimitry Andric for (auto *B : *Cfg) { 8660b57cec5SDimitry Andric auto *BB = new (Arena) til::BasicBlock(Arena); 8670b57cec5SDimitry Andric BB->reserveInstructions(B->size()); 8680b57cec5SDimitry Andric BlockMap[B->getBlockID()] = BB; 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric CurrentBB = lookupBlock(&Cfg->getEntry()); 8720b57cec5SDimitry Andric auto Parms = isa<ObjCMethodDecl>(D) ? cast<ObjCMethodDecl>(D)->parameters() 8730b57cec5SDimitry Andric : cast<FunctionDecl>(D)->parameters(); 8740b57cec5SDimitry Andric for (auto *Pm : Parms) { 8750b57cec5SDimitry Andric QualType T = Pm->getType(); 8760b57cec5SDimitry Andric if (!T.isTrivialType(Pm->getASTContext())) 8770b57cec5SDimitry Andric continue; 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric // Add parameters to local variable map. 8800b57cec5SDimitry Andric // FIXME: right now we emulate params with loads; that should be fixed. 8810b57cec5SDimitry Andric til::SExpr *Lp = new (Arena) til::LiteralPtr(Pm); 8820b57cec5SDimitry Andric til::SExpr *Ld = new (Arena) til::Load(Lp); 8830b57cec5SDimitry Andric til::SExpr *V = addStatement(Ld, nullptr, Pm); 8840b57cec5SDimitry Andric addVarDecl(Pm, V); 8850b57cec5SDimitry Andric } 8860b57cec5SDimitry Andric } 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric void SExprBuilder::enterCFGBlock(const CFGBlock *B) { 8890b57cec5SDimitry Andric // Initialize TIL basic block and add it to the CFG. 8900b57cec5SDimitry Andric CurrentBB = lookupBlock(B); 8910b57cec5SDimitry Andric CurrentBB->reservePredecessors(B->pred_size()); 8920b57cec5SDimitry Andric Scfg->add(CurrentBB); 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric CurrentBlockInfo = &BBInfo[B->getBlockID()]; 8950b57cec5SDimitry Andric 8960b57cec5SDimitry Andric // CurrentLVarMap is moved to ExitMap on block exit. 8970b57cec5SDimitry Andric // FIXME: the entry block will hold function parameters. 8980b57cec5SDimitry Andric // assert(!CurrentLVarMap.valid() && "CurrentLVarMap already initialized."); 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric void SExprBuilder::handlePredecessor(const CFGBlock *Pred) { 9020b57cec5SDimitry Andric // Compute CurrentLVarMap on entry from ExitMaps of predecessors 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric CurrentBB->addPredecessor(BlockMap[Pred->getBlockID()]); 9050b57cec5SDimitry Andric BlockInfo *PredInfo = &BBInfo[Pred->getBlockID()]; 9060b57cec5SDimitry Andric assert(PredInfo->UnprocessedSuccessors > 0); 9070b57cec5SDimitry Andric 9080b57cec5SDimitry Andric if (--PredInfo->UnprocessedSuccessors == 0) 9090b57cec5SDimitry Andric mergeEntryMap(std::move(PredInfo->ExitMap)); 9100b57cec5SDimitry Andric else 9110b57cec5SDimitry Andric mergeEntryMap(PredInfo->ExitMap.clone()); 9120b57cec5SDimitry Andric 9130b57cec5SDimitry Andric ++CurrentBlockInfo->ProcessedPredecessors; 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric void SExprBuilder::handlePredecessorBackEdge(const CFGBlock *Pred) { 9170b57cec5SDimitry Andric mergeEntryMapBackEdge(); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) { 9210b57cec5SDimitry Andric // The merge*() methods have created arguments. 9220b57cec5SDimitry Andric // Push those arguments onto the basic block. 9230b57cec5SDimitry Andric CurrentBB->arguments().reserve( 9240b57cec5SDimitry Andric static_cast<unsigned>(CurrentArguments.size()), Arena); 9250b57cec5SDimitry Andric for (auto *A : CurrentArguments) 9260b57cec5SDimitry Andric CurrentBB->addArgument(A); 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric void SExprBuilder::handleStatement(const Stmt *S) { 9300b57cec5SDimitry Andric til::SExpr *E = translate(S, nullptr); 9310b57cec5SDimitry Andric addStatement(E, S); 9320b57cec5SDimitry Andric } 9330b57cec5SDimitry Andric 9340b57cec5SDimitry Andric void SExprBuilder::handleDestructorCall(const VarDecl *VD, 9350b57cec5SDimitry Andric const CXXDestructorDecl *DD) { 9360b57cec5SDimitry Andric til::SExpr *Sf = new (Arena) til::LiteralPtr(VD); 9370b57cec5SDimitry Andric til::SExpr *Dr = new (Arena) til::LiteralPtr(DD); 9380b57cec5SDimitry Andric til::SExpr *Ap = new (Arena) til::Apply(Dr, Sf); 9390b57cec5SDimitry Andric til::SExpr *E = new (Arena) til::Call(Ap); 9400b57cec5SDimitry Andric addStatement(E, nullptr); 9410b57cec5SDimitry Andric } 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) { 9440b57cec5SDimitry Andric CurrentBB->instructions().reserve( 9450b57cec5SDimitry Andric static_cast<unsigned>(CurrentInstructions.size()), Arena); 9460b57cec5SDimitry Andric for (auto *V : CurrentInstructions) 9470b57cec5SDimitry Andric CurrentBB->addInstruction(V); 9480b57cec5SDimitry Andric 9490b57cec5SDimitry Andric // Create an appropriate terminator 9500b57cec5SDimitry Andric unsigned N = B->succ_size(); 9510b57cec5SDimitry Andric auto It = B->succ_begin(); 9520b57cec5SDimitry Andric if (N == 1) { 9530b57cec5SDimitry Andric til::BasicBlock *BB = *It ? lookupBlock(*It) : nullptr; 9540b57cec5SDimitry Andric // TODO: set index 9550b57cec5SDimitry Andric unsigned Idx = BB ? BB->findPredecessorIndex(CurrentBB) : 0; 9560b57cec5SDimitry Andric auto *Tm = new (Arena) til::Goto(BB, Idx); 9570b57cec5SDimitry Andric CurrentBB->setTerminator(Tm); 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric else if (N == 2) { 9600b57cec5SDimitry Andric til::SExpr *C = translate(B->getTerminatorCondition(true), nullptr); 9610b57cec5SDimitry Andric til::BasicBlock *BB1 = *It ? lookupBlock(*It) : nullptr; 9620b57cec5SDimitry Andric ++It; 9630b57cec5SDimitry Andric til::BasicBlock *BB2 = *It ? lookupBlock(*It) : nullptr; 9640b57cec5SDimitry Andric // FIXME: make sure these aren't critical edges. 9650b57cec5SDimitry Andric auto *Tm = new (Arena) til::Branch(C, BB1, BB2); 9660b57cec5SDimitry Andric CurrentBB->setTerminator(Tm); 9670b57cec5SDimitry Andric } 9680b57cec5SDimitry Andric } 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric void SExprBuilder::handleSuccessor(const CFGBlock *Succ) { 9710b57cec5SDimitry Andric ++CurrentBlockInfo->UnprocessedSuccessors; 9720b57cec5SDimitry Andric } 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric void SExprBuilder::handleSuccessorBackEdge(const CFGBlock *Succ) { 9750b57cec5SDimitry Andric mergePhiNodesBackEdge(Succ); 9760b57cec5SDimitry Andric ++BBInfo[Succ->getBlockID()].ProcessedPredecessors; 9770b57cec5SDimitry Andric } 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric void SExprBuilder::exitCFGBlock(const CFGBlock *B) { 9800b57cec5SDimitry Andric CurrentArguments.clear(); 9810b57cec5SDimitry Andric CurrentInstructions.clear(); 9820b57cec5SDimitry Andric CurrentBlockInfo->ExitMap = std::move(CurrentLVarMap); 9830b57cec5SDimitry Andric CurrentBB = nullptr; 9840b57cec5SDimitry Andric CurrentBlockInfo = nullptr; 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric void SExprBuilder::exitCFG(const CFGBlock *Last) { 9880b57cec5SDimitry Andric for (auto *Ph : IncompleteArgs) { 9890b57cec5SDimitry Andric if (Ph->status() == til::Phi::PH_Incomplete) 9900b57cec5SDimitry Andric simplifyIncompleteArg(Ph); 9910b57cec5SDimitry Andric } 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric CurrentArguments.clear(); 9940b57cec5SDimitry Andric CurrentInstructions.clear(); 9950b57cec5SDimitry Andric IncompleteArgs.clear(); 9960b57cec5SDimitry Andric } 9970b57cec5SDimitry Andric 998*0fca6ea1SDimitry Andric #ifndef NDEBUG 9990b57cec5SDimitry Andric namespace { 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric class TILPrinter : 10020b57cec5SDimitry Andric public til::PrettyPrinter<TILPrinter, llvm::raw_ostream> {}; 10030b57cec5SDimitry Andric 10040b57cec5SDimitry Andric } // namespace 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric namespace clang { 10070b57cec5SDimitry Andric namespace threadSafety { 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric void printSCFG(CFGWalker &Walker) { 10100b57cec5SDimitry Andric llvm::BumpPtrAllocator Bpa; 10110b57cec5SDimitry Andric til::MemRegionRef Arena(&Bpa); 10120b57cec5SDimitry Andric SExprBuilder SxBuilder(Arena); 10130b57cec5SDimitry Andric til::SCFG *Scfg = SxBuilder.buildCFG(Walker); 10140b57cec5SDimitry Andric TILPrinter::print(Scfg, llvm::errs()); 10150b57cec5SDimitry Andric } 10160b57cec5SDimitry Andric 10170b57cec5SDimitry Andric } // namespace threadSafety 10180b57cec5SDimitry Andric } // namespace clang 1019*0fca6ea1SDimitry Andric #endif // NDEBUG 1020