ThreadSafetyCommon.h revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===- ThreadSafetyCommon.h ------------------------------------*- C++ --*-===// 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// The LLVM Compiler Infrastructure 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This file is distributed under the University of Illinois Open Source 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// License. See LICENSE.TXT for details. 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===// 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Parts of thread safety analysis that are not specific to thread safety 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// itself have been factored into classes here, where they can be potentially 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// used by other analyses. Currently these include: 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// * Generalize clang CFG visitors. 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// * Conversion of the clang CFG to SSA form. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// * Translation of clang Exprs to TIL SExprs 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// UNDER CONSTRUCTION. USE AT YOUR OWN RISK. 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===// 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifndef LLVM_CLANG_THREAD_SAFETY_COMMON_H 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define LLVM_CLANG_THREAD_SAFETY_COMMON_H 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "clang/Analysis/Analyses/PostOrderCFGView.h" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "clang/Analysis/Analyses/ThreadSafetyTIL.h" 27271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyry#include "clang/Analysis/AnalysisContext.h" 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "clang/Basic/OperatorKinds.h" 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <memory> 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector> 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace clang { 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace threadSafety { 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This class defines the interface of a clang CFG Visitor. 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CFGWalker will invoke the following methods. 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Note that methods are not virtual; the visitor is templatized. 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CFGVisitor { 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Enter the CFG for Decl D, and perform any initial setup operations. 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First) {} 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Enter a CFGBlock. 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void enterCFGBlock(const CFGBlock *B) {} 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Returns true if this visitor implements handlePredecessor 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool visitPredecessors() { return true; } 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process a predecessor edge. 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handlePredecessor(const CFGBlock *Pred) {} 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process a successor back edge to a previously visited block. 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handlePredecessorBackEdge(const CFGBlock *Pred) {} 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Called just before processing statements. 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void enterCFGBlockBody(const CFGBlock *B) {} 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process an ordinary statement. 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handleStatement(const Stmt *S) {} 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process a destructor call 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {} 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Called after all statements have been handled. 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void exitCFGBlockBody(const CFGBlock *B) {} 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Return true 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool visitSuccessors() { return true; } 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process a successor edge. 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handleSuccessor(const CFGBlock *Succ) {} 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process a successor back edge to a previously visited block. 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handleSuccessorBackEdge(const CFGBlock *Succ) {} 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Leave a CFGBlock. 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void exitCFGBlock(const CFGBlock *B) {} 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Leave the CFG, and perform any final cleanup operations. 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void exitCFG(const CFGBlock *Last) {} 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Walks the clang CFG, and invokes methods on a given CFGVisitor. 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CFGWalker { 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CFGWalker() : CFGraph(nullptr), ACtx(nullptr), SortedGraph(nullptr) {} 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Initialize the CFGWalker. This setup only needs to be done once, even 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // if there are multiple passes over the CFG. 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool init(AnalysisDeclContext &AC) { 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ACtx = &AC; 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CFGraph = AC.getCFG(); 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!CFGraph) 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Ignore anonymous functions. 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!dyn_cast_or_null<NamedDecl>(AC.getDecl())) 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SortedGraph = AC.getAnalysis<PostOrderCFGView>(); 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!SortedGraph) 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return false; 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return true; 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Traverse the CFG, calling methods on V as appropriate. 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry template <class Visitor> 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void walk(Visitor &V) { 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph); 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.enterCFG(CFGraph, getDecl(), &CFGraph->getEntry()); 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (const auto *CurrBlock : *SortedGraph) { 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VisitedBlocks.insert(CurrBlock); 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.enterCFGBlock(CurrBlock); 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process predecessors, handling back edges last 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (V.visitPredecessors()) { 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SmallVector<CFGBlock*, 4> BackEdges; 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process successors 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (CFGBlock::const_pred_iterator SI = CurrBlock->pred_begin(), 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SE = CurrBlock->pred_end(); 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SI != SE; ++SI) { 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (*SI == nullptr) 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!VisitedBlocks.alreadySet(*SI)) { 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BackEdges.push_back(*SI); 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.handlePredecessor(*SI); 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (auto *Blk : BackEdges) 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.handlePredecessorBackEdge(Blk); 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.enterCFGBlockBody(CurrBlock); 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process statements 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (const auto &BI : *CurrBlock) { 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (BI.getKind()) { 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case CFGElement::Statement: { 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.handleStatement(BI.castAs<CFGStmt>().getStmt()); 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case CFGElement::AutomaticObjectDtor: { 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>(); 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>( 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry AD.getDestructorDecl(ACtx->getASTContext())); 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl()); 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.handleDestructorCall(VD, DD); 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry default: 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry break; 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.exitCFGBlockBody(CurrBlock); 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process successors, handling back edges first. 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (V.visitSuccessors()) { 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SmallVector<CFGBlock*, 8> ForwardEdges; 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Process successors 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(), 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SE = CurrBlock->succ_end(); 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SI != SE; ++SI) { 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (*SI == nullptr) 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!VisitedBlocks.alreadySet(*SI)) { 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ForwardEdges.push_back(*SI); 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry continue; 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.handleSuccessorBackEdge(*SI); 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (auto *Blk : ForwardEdges) 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.handleSuccessor(Blk); 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.exitCFGBlock(CurrBlock); 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry V.exitCFG(&CFGraph->getExit()); 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const CFG *getGraph() const { return CFGraph; } 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CFG *getGraph() { return CFGraph; } 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const NamedDecl *getDecl() const { 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return dyn_cast<NamedDecl>(ACtx->getDecl()); 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const PostOrderCFGView *getSortedGraph() const { return SortedGraph; } 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CFG *CFGraph; 2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry AnalysisDeclContext *ACtx; 2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry PostOrderCFGView *SortedGraph; 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Translate clang::Expr to til::SExpr. 2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass SExprBuilder { 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /// \brief Encapsulates the lexical context of a function call. The lexical 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /// context includes the arguments to the call, including the implicit object 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /// argument. When an attribute containing a mutex expression is attached to 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /// a method, the expression may refer to formal parameters of the method. 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /// Actual arguments must be substituted for formal parameters to derive 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /// the appropriate mutex expression in the lexical context where the function 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /// is called. PrevCtx holds the context in which the arguments themselves 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /// should be evaluated; multiple calling contexts can be chained together 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /// by the lock_returned attribute. 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry struct CallingContext { 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const NamedDecl *AttrDecl; // The decl to which the attr is attached. 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Expr *SelfArg; // Implicit object argument -- e.g. 'this' 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry unsigned NumArgs; // Number of funArgs 2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const Expr *const *FunArgs; // Function arguments 2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *Prev; // The previous context; or 0 if none. 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool SelfArrow; // is Self referred to with -> or .? 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext(const NamedDecl *D = nullptr, const Expr *S = nullptr, 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry unsigned N = 0, const Expr *const *A = nullptr, 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *P = nullptr) 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : AttrDecl(D), SelfArg(S), NumArgs(N), FunArgs(A), Prev(P), 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SelfArrow(false) 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry {} 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SExprBuilder(til::MemRegionRef A) 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : Arena(A), SelfVar(nullptr), Scfg(nullptr), CurrentBB(nullptr), 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CurrentBlockInfo(nullptr) { 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // FIXME: we don't always have a self-variable. 2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SelfVar = new (Arena) til::Variable(); 2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SelfVar->setKind(til::Variable::VK_SFun); 2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Translate a clang statement or expression to a TIL expression. 2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Also performs substitution of variables; Ctx provides the context. 2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Dispatches on the type of S. 2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translate(const Stmt *S, CallingContext *Ctx); 2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SCFG *buildCFG(CFGWalker &Walker); 2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *lookupStmt(const Stmt *S); 2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::BasicBlock *lookupBlock(const CFGBlock *B) { 2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return BlockMap[B->getBlockID()]; 2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const til::SCFG *getCFG() const { return Scfg; } 2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SCFG *getCFG() { return Scfg; } 2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE, 2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *Ctx) ; 2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx); 2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateMemberExpr(const MemberExpr *ME, CallingContext *Ctx); 2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx); 2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME, 2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *Ctx); 2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE, 2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *Ctx); 2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateUnaryOperator(const UnaryOperator *UO, 2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *Ctx); 2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateBinOp(til::TIL_BinaryOpcode Op, 2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const BinaryOperator *BO, 2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *Ctx, bool Reverse = false); 2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateBinAssign(til::TIL_BinaryOpcode Op, 2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const BinaryOperator *BO, 2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *Ctx, bool Assign = false); 2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateBinaryOperator(const BinaryOperator *BO, 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *Ctx); 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateCastExpr(const CastExpr *CE, CallingContext *Ctx); 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateArraySubscriptExpr(const ArraySubscriptExpr *E, 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *Ctx); 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateConditionalOperator(const ConditionalOperator *C, 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry CallingContext *Ctx); 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateBinaryConditionalOperator( 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const BinaryConditionalOperator *C, CallingContext *Ctx); 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx); 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Map from statements in the clang CFG to SExprs in the til::SCFG. 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typedef llvm::DenseMap<const Stmt*, til::SExpr*> StatementMap; 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Map from clang local variables to indices in a LVarDefinitionMap. 2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typedef llvm::DenseMap<const ValueDecl *, unsigned> LVarIndexMap; 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Map from local variable indices to SSA variables (or constants). 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typedef std::pair<const ValueDecl *, til::SExpr *> NameVarPair; 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typedef CopyOnWriteVector<NameVarPair> LVarDefinitionMap; 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry struct BlockInfo { 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LVarDefinitionMap ExitMap; 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool HasBackEdges; 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry unsigned UnprocessedSuccessors; // Successors yet to be processed 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry unsigned ProcessedPredecessors; // Predecessors already processed 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BlockInfo() 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : HasBackEdges(false), UnprocessedSuccessors(0), 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ProcessedPredecessors(0) {} 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BlockInfo(BlockInfo &&RHS) 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : ExitMap(std::move(RHS.ExitMap)), 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry HasBackEdges(RHS.HasBackEdges), 3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UnprocessedSuccessors(RHS.UnprocessedSuccessors), 3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ProcessedPredecessors(RHS.ProcessedPredecessors) {} 3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BlockInfo &operator=(BlockInfo &&RHS) { 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (this != &RHS) { 3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ExitMap = std::move(RHS.ExitMap); 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry HasBackEdges = RHS.HasBackEdges; 3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UnprocessedSuccessors = RHS.UnprocessedSuccessors; 3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ProcessedPredecessors = RHS.ProcessedPredecessors; 3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return *this; 3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry private: 3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BlockInfo(const BlockInfo &) LLVM_DELETED_FUNCTION; 3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void operator=(const BlockInfo &) LLVM_DELETED_FUNCTION; 3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // We implement the CFGVisitor API 3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry friend class CFGWalker; 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First); 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void enterCFGBlock(const CFGBlock *B); 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool visitPredecessors() { return true; } 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handlePredecessor(const CFGBlock *Pred); 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handlePredecessorBackEdge(const CFGBlock *Pred); 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void enterCFGBlockBody(const CFGBlock *B); 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handleStatement(const Stmt *S); 3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD); 3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void exitCFGBlockBody(const CFGBlock *B); 3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool visitSuccessors() { return true; } 3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handleSuccessor(const CFGBlock *Succ); 3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void handleSuccessorBackEdge(const CFGBlock *Succ); 3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void exitCFGBlock(const CFGBlock *B); 3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void exitCFG(const CFGBlock *Last); 3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void insertStmt(const Stmt *S, til::SExpr *E) { 3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry SMap.insert(std::make_pair(S, E)); 3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD); 3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *addStatement(til::SExpr *E, const Stmt *S, 3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const ValueDecl *VD = nullptr); 3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *lookupVarDecl(const ValueDecl *VD); 3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *addVarDecl(const ValueDecl *VD, til::SExpr *E); 3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SExpr *updateVarDecl(const ValueDecl *VD, til::SExpr *E); 3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E); 3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void mergeEntryMap(LVarDefinitionMap Map); 3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void mergeEntryMapBackEdge(); 3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void mergePhiNodesBackEdge(const CFGBlock *Blk); 3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::MemRegionRef Arena; 3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::Variable *SelfVar; // Variable to use for 'this'. May be null. 3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::SCFG *Scfg; 3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry StatementMap SMap; // Map from Stmt to TIL Variables 3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LVarIndexMap LVarIdxMap; // Indices of clang local vars. 3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::vector<til::BasicBlock *> BlockMap; // Map from clang to til BBs. 3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::vector<BlockInfo> BBInfo; // Extra information per BB. 3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Indexed by clang BlockID. 3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::unique_ptr<SExprBuilder::CallingContext> CallCtx; // Root calling context 3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry LVarDefinitionMap CurrentLVarMap; 3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::vector<til::Variable*> CurrentArguments; 3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::vector<til::Variable*> CurrentInstructions; 3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::vector<til::Variable*> IncompleteArgs; 3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry til::BasicBlock *CurrentBB; 3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry BlockInfo *CurrentBlockInfo; 3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 385271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyry// Dump an SCFG to llvm::errs(). 386271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyryvoid printSCFG(CFGWalker &Walker); 387271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyry 388271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyry 389271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyry} // end namespace threadSafety 390271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyry 391271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyry} // end namespace clang 392271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyry 393271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyry#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H 394271c2654cc44f23492888c7ef40c36c2fd810c77Jarkko Pöyry