summaryrefslogtreecommitdiffstats
path: root/clang/include
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include')
-rw-r--r--clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h87
-rw-r--r--clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h45
-rw-r--r--clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h2
-rw-r--r--clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h11
4 files changed, 102 insertions, 43 deletions
diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index 2b693cf0e46..6adef3471f6 100644
--- a/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -117,8 +117,9 @@ public:
V.enterCFGBlock(CurrBlock);
- // Process predecessors
+ // Process predecessors, handling back edges last
if (V.visitPredecessors()) {
+ SmallVector<CFGBlock*, 4> BackEdges;
// Process successors
for (CFGBlock::const_pred_iterator SI = CurrBlock->pred_begin(),
SE = CurrBlock->pred_end();
@@ -127,11 +128,14 @@ public:
continue;
if (!VisitedBlocks.alreadySet(*SI)) {
- V.handlePredecessorBackEdge(*SI);
+ BackEdges.push_back(*SI);
continue;
}
V.handlePredecessor(*SI);
}
+
+ for (auto *Blk : BackEdges)
+ V.handlePredecessorBackEdge(Blk);
}
V.enterCFGBlockBody(CurrBlock);
@@ -158,8 +162,10 @@ public:
V.exitCFGBlockBody(CurrBlock);
- // Process successors
+ // Process successors, handling back edges first.
if (V.visitSuccessors()) {
+ SmallVector<CFGBlock*, 8> ForwardEdges;
+
// Process successors
for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
SE = CurrBlock->succ_end();
@@ -167,12 +173,15 @@ public:
if (*SI == nullptr)
continue;
- if (VisitedBlocks.alreadySet(*SI)) {
- V.handleSuccessorBackEdge(*SI);
+ if (!VisitedBlocks.alreadySet(*SI)) {
+ ForwardEdges.push_back(*SI);
continue;
}
- V.handleSuccessor(*SI);
+ V.handleSuccessorBackEdge(*SI);
}
+
+ for (auto *Blk : ForwardEdges)
+ V.handleSuccessor(Blk);
}
V.exitCFGBlock(CurrBlock);
@@ -197,8 +206,6 @@ private:
// Translate clang::Expr to til::SExpr.
class SExprBuilder {
public:
- typedef llvm::DenseMap<const Stmt*, til::Variable*> StatementMap;
-
/// \brief Encapsulates the lexical context of a function call. The lexical
/// context includes the arguments to the call, including the implicit object
/// argument. When an attribute containing a mutex expression is attached to
@@ -226,10 +233,9 @@ public:
SExprBuilder(til::MemRegionRef A)
: Arena(A), SelfVar(nullptr), Scfg(nullptr), CallCtx(nullptr),
- CurrentBB(nullptr), CurrentBlockID(0), CurrentVarID(0),
- CurrentArgIndex(0) {
+ CurrentBB(nullptr), CurrentBlockInfo(nullptr) {
// FIXME: we don't always have a self-variable.
- SelfVar = new (Arena)til::Variable(til::Variable::VK_SFun);
+ SelfVar = new (Arena) til::Variable(til::Variable::VK_SFun);
}
// Translate a clang statement or expression to a TIL expression.
@@ -239,6 +245,11 @@ public:
til::SCFG *buildCFG(CFGWalker &Walker);
til::SExpr *lookupStmt(const Stmt *S);
+
+ til::BasicBlock *lookupBlock(const CFGBlock *B) {
+ return BlockMap[B->getBlockID()];
+ }
+
const til::SCFG *getCFG() const { return Scfg; }
til::SCFG *getCFF() { return Scfg; }
@@ -266,30 +277,41 @@ private:
til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx);
- // Used for looking the index of a name.
- typedef llvm::DenseMap<const ValueDecl *, unsigned> NameIndexMap;
+ // Map from statements in the clang CFG to SExprs in the til::SCFG.
+ typedef llvm::DenseMap<const Stmt*, til::SExpr*> StatementMap;
+
+ // Map from clang local variables to indices in a LVarDefinitionMap.
+ typedef llvm::DenseMap<const ValueDecl *, unsigned> LVarIndexMap;
- // Used for looking up the current SSA variable for a name, by index.
- typedef CopyOnWriteVector<std::pair<const ValueDecl *, til::SExpr *>>
- NameVarMap;
+ // Map from local variable indices to SSA variables (or constants).
+ typedef std::pair<const ValueDecl *, til::SExpr *> NameVarPair;
+ typedef CopyOnWriteVector<NameVarPair> LVarDefinitionMap;
struct BlockInfo {
- NameVarMap ExitMap;
+ LVarDefinitionMap ExitMap;
bool HasBackEdges;
- unsigned SuccessorsToProcess;
- BlockInfo() : HasBackEdges(false), SuccessorsToProcess(0) {}
+ unsigned UnprocessedSuccessors; // Successors yet to be processed
+ unsigned ProcessedPredecessors; // Predecessors already processed
+
+ BlockInfo()
+ : HasBackEdges(false), UnprocessedSuccessors(0),
+ ProcessedPredecessors(0) {}
BlockInfo(BlockInfo &&RHS)
- : ExitMap(std::move(RHS.ExitMap)), HasBackEdges(RHS.HasBackEdges),
- SuccessorsToProcess(RHS.SuccessorsToProcess) {}
+ : ExitMap(std::move(RHS.ExitMap)),
+ HasBackEdges(RHS.HasBackEdges),
+ UnprocessedSuccessors(RHS.UnprocessedSuccessors),
+ ProcessedPredecessors(RHS.ProcessedPredecessors) {}
BlockInfo &operator=(BlockInfo &&RHS) {
if (this != &RHS) {
ExitMap = std::move(RHS.ExitMap);
HasBackEdges = RHS.HasBackEdges;
- SuccessorsToProcess = RHS.SuccessorsToProcess;
+ UnprocessedSuccessors = RHS.UnprocessedSuccessors;
+ ProcessedPredecessors = RHS.ProcessedPredecessors;
}
return *this;
}
+
private:
BlockInfo(const BlockInfo &) LLVM_DELETED_FUNCTION;
void operator=(const BlockInfo &) LLVM_DELETED_FUNCTION;
@@ -313,31 +335,38 @@ private:
void exitCFGBlock(const CFGBlock *B);
void exitCFG(const CFGBlock *Last);
- void insertStmt(const Stmt *S, til::Variable *V);
+ void insertStmt(const Stmt *S, til::SExpr *E) {
+ SMap.insert(std::make_pair(S, E));
+ }
+ til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD);
+
til::SExpr *addStatement(til::SExpr *E, const Stmt *S, const ValueDecl *VD=0);
til::SExpr *lookupVarDecl(const ValueDecl *VD);
til::SExpr *addVarDecl(const ValueDecl *VD, til::SExpr *E);
til::SExpr *updateVarDecl(const ValueDecl *VD, til::SExpr *E);
- void mergeEntryMap(NameVarMap Map);
+ void makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E);
+ void mergeEntryMap(LVarDefinitionMap Map);
+ void mergeEntryMapBackEdge();
+ void mergePhiNodesBackEdge(const CFGBlock *Blk);
+private:
til::MemRegionRef Arena;
til::Variable *SelfVar; // Variable to use for 'this'. May be null.
til::SCFG *Scfg;
StatementMap SMap; // Map from Stmt to TIL Variables
- NameIndexMap IdxMap; // Indices of clang local vars.
+ LVarIndexMap LVarIdxMap; // Indices of clang local vars.
std::vector<til::BasicBlock *> BlockMap; // Map from clang to til BBs.
std::vector<BlockInfo> BBInfo; // Extra information per BB.
// Indexed by clang BlockID.
SExprBuilder::CallingContext *CallCtx; // Root calling context
- NameVarMap CurrentNameMap;
+ LVarDefinitionMap CurrentLVarMap;
+ std::vector<til::Variable*> CurrentArguments;
+ std::vector<til::Variable*> CurrentInstructions;
til::BasicBlock *CurrentBB;
BlockInfo *CurrentBlockInfo;
- unsigned CurrentBlockID;
- unsigned CurrentVarID;
- unsigned CurrentArgIndex;
};
diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
index 331e885178e..94ef9b3951b 100644
--- a/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
+++ b/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -952,7 +952,8 @@ public:
static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
SCFG(MemRegionRef A, unsigned Nblocks)
- : SExpr(COP_SCFG), Blocks(A, Nblocks), Entry(nullptr), Exit(nullptr) {}
+ : SExpr(COP_SCFG), Blocks(A, Nblocks),
+ Entry(nullptr), Exit(nullptr) {}
SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
: SExpr(COP_SCFG), Blocks(std::move(Ba)), Entry(nullptr), Exit(nullptr) {
// TODO: set entry and exit!
@@ -972,7 +973,7 @@ public:
const BasicBlock *exit() const { return Exit; }
BasicBlock *exit() { return Exit; }
- void add(BasicBlock *BB) { Blocks.push_back(BB); }
+ void add(BasicBlock *BB);
void setEntry(BasicBlock *BB) { Entry = BB; }
void setExit(BasicBlock *BB) { Exit = BB; }
@@ -1001,12 +1002,12 @@ public:
BasicBlock(MemRegionRef A, unsigned Nargs, unsigned Nins,
SExpr *Term = nullptr)
- : BlockID(0), Parent(nullptr), NumPredecessors(0),
+ : BlockID(0), NumVars(0), NumPredecessors(0), Parent(nullptr),
Args(A, Nargs), Instrs(A, Nins), Terminator(Term) {}
BasicBlock(const BasicBlock &B, VarArray &&As, VarArray &&Is, SExpr *T)
- : BlockID(0), Parent(nullptr), NumPredecessors(B.NumPredecessors),
- Args(std::move(As)), Instrs(std::move(Is)), Terminator(T)
- {}
+ : BlockID(0), NumVars(B.NumVars), NumPredecessors(B.NumPredecessors),
+ Parent(nullptr), Args(std::move(As)), Instrs(std::move(Is)),
+ Terminator(T) {}
unsigned blockID() const { return BlockID; }
unsigned numPredecessors() const { return NumPredecessors; }
@@ -1027,8 +1028,15 @@ public:
void setParent(BasicBlock *P) { Parent = P; }
void setNumPredecessors(unsigned NP) { NumPredecessors = NP; }
void setTerminator(SExpr *E) { Terminator.reset(E); }
- void addArgument(Variable *V) { Args.push_back(V); }
- void addInstr(Variable *V) { Args.push_back(V); }
+
+ void addArgument(Variable *V) {
+ V->setID(BlockID, NumVars++);
+ Args.push_back(V);
+ }
+ void addInstruction(Variable *V) {
+ V->setID(BlockID, NumVars++);
+ Instrs.push_back(V);
+ }
template <class V> BasicBlock *traverse(V &Visitor) {
typename V::template Container<Variable*> Nas(Visitor, Args.size());
@@ -1064,14 +1072,23 @@ private:
friend class SCFG;
unsigned BlockID;
+ unsigned NumVars;
+ unsigned NumPredecessors; // Number of blocks which jump to this one.
+
BasicBlock *Parent; // The parent block is the enclosing lexical scope.
// The parent dominates this block.
- unsigned NumPredecessors; // Number of blocks which jump to this one.
VarArray Args; // Phi nodes. One argument per predecessor.
VarArray Instrs;
SExprRef Terminator;
};
+
+inline void SCFG::add(BasicBlock *BB) {
+ BB->setBlockID(Blocks.size());
+ Blocks.push_back(BB);
+}
+
+
template <class V>
typename V::R_SExpr SCFG::traverse(V &Visitor) {
Visitor.enterCFG(*this);
@@ -1084,6 +1101,7 @@ typename V::R_SExpr SCFG::traverse(V &Visitor) {
return Visitor.reduceSCFG(*this, Bbs);
}
+
class Phi : public SExpr {
public:
// TODO: change to SExprRef
@@ -1098,6 +1116,15 @@ public:
const ValArray &values() const { return Values; }
ValArray &values() { return Values; }
+ // Incomplete phi nodes are constructed during SSA conversion, and
+ // may not be necessary.
+ bool incomplete() const { return Flags == 1; }
+
+ void setIncomplete(bool b) {
+ if (b) Flags = 1;
+ else Flags = 0;
+ }
+
template <class V> typename V::R_SExpr traverse(V &Visitor) {
typename V::template Container<typename V::R_SExpr> Nvs(Visitor,
Values.size());
diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
index 603c5f556c0..dd10a34531a 100644
--- a/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
+++ b/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
@@ -510,7 +510,7 @@ protected:
}
void printLiteralPtr(LiteralPtr *E, StreamType &SS) {
- SS << E->clangDecl()->getName();
+ SS << E->clangDecl()->getNameAsString();
}
void printVariable(Variable *E, StreamType &SS) {
diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
index 4ca49dfbd99..3b768c5a692 100644
--- a/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
+++ b/clang/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
@@ -80,7 +80,7 @@ public:
SimpleArray(T *Dat, size_t Cp, size_t Sz = 0)
: Data(Dat), Size(Sz), Capacity(Cp) {}
SimpleArray(MemRegionRef A, size_t Cp)
- : Data(A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {}
+ : Data(Cp == 0 ? nullptr : A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {}
SimpleArray(SimpleArray<T> &&A)
: Data(A.Data), Size(A.Size), Capacity(A.Capacity) {
A.Data = nullptr;
@@ -100,11 +100,14 @@ public:
return *this;
}
- T *resize(size_t Ncp, MemRegionRef A) {
+ void reserve(size_t Ncp, MemRegionRef A) {
+ if (Ncp < Capacity)
+ return;
T *Odata = Data;
Data = A.allocateT<T>(Ncp);
+ Capacity = Ncp;
memcpy(Data, Odata, sizeof(T) * Size);
- return Odata;
+ return;
}
typedef T *iterator;
@@ -134,7 +137,7 @@ public:
}
void setValues(unsigned Sz, const T& C) {
- assert(Sz < Capacity);
+ assert(Sz <= Capacity);
Size = Sz;
for (unsigned i = 0; i < Sz; ++i) {
Data[i] = C;
OpenPOWER on IntegriCloud