r206338 - Thread Safety Analysis: rewrite SSA pass to use the new SExpr and CFG
Timur Iskhodzhanov
timurrrr at google.com
Wed Apr 16 01:48:34 PDT 2014
... or is it?
After fixing another compile-time error I get this:
C:\Program Files (x86)\Microsoft Visual Studio
12.0\VC\INCLUDE\xutility(829) : error C2280:
'clang::threadSafety::CopyOnWriteVector<std::pair<const
clang::ValueDecl *,clang::threadSafety::til::SExpr
*>>::CopyOnWriteVector(const
clang::threadSafety::CopyOnWriteVector<std::pair<const
clang::ValueDecl *,clang::threadSafety::til::SExpr *>> &)' :
attempting to reference a deleted function
tools\clang\include\clang/Analysis/Analyses/ThreadSafetyUtil.h(172)
: see declaration of
'clang::threadSafety::CopyOnWriteVector<std::pair<const
clang::ValueDecl *,clang::threadSafety::til::SExpr
*>>::CopyOnWriteVector'
2014-04-16 12:22 GMT+04:00 Timur Iskhodzhanov <timurrrr at google.com>:
> Ah, sorry -- the build is broken due to a different reason now.
>
> 2014-04-16 12:16 GMT+04:00 Timur Iskhodzhanov <timurrrr at google.com>:
>> Request timeout -- I'm going to revert the change.
>>
>> 2014-04-16 7:24 GMT+04:00 Renato Golin <renato.golin at linaro.org>:
>>> Hi DeLesley,
>>>
>>> Have you seen this error?
>>>
>>> http://lab.llvm.org:8011/builders/clang-native-arm-lnt/builds/5991/steps/compile/logs/stdio
>>>
>>> /external/buildbot/clang-native-arm-lnt/llvm.src/tools/clang/lib/Analysis/../../include/clang/Analysis/Analyses/ThreadSafetyUtil.h:105:16:
>>> error: ‘Sz’ was not declared in this scope
>>> assert(i < Sz && "Array index out of bounds.");
>>>
>>> cheers,
>>> --renato
>>>
>>> On 15 April 2014 20:23, DeLesley Hutchins <delesley at google.com> wrote:
>>>> Author: delesley
>>>> Date: Tue Apr 15 18:23:19 2014
>>>> New Revision: 206338
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=206338&view=rev
>>>> Log:
>>>> Thread Safety Analysis: rewrite SSA pass to use the new SExpr and CFG
>>>> traversal system. The new pass is still undergoing testing; no change in
>>>> functionality.
>>>>
>>>> Modified:
>>>> cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
>>>> cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
>>>> cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
>>>> cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
>>>> cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp
>>>>
>>>> Modified: cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h?rev=206338&r1=206337&r2=206338&view=diff
>>>> ==============================================================================
>>>> --- cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h (original)
>>>> +++ cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h Tue Apr 15 18:23:19 2014
>>>> @@ -33,32 +33,53 @@
>>>> namespace clang {
>>>> namespace threadSafety {
>>>>
>>>> -// CFG traversal uses templates instead of virtual function dispatch. Visitors
>>>> -// must implement the following functions:
>>>> -//
>>>> -// Enter the CFG for Decl D, and perform any initial setup operations.
>>>> -// void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First) {}
>>>> -//
>>>> -// Enter a CFGBlock.
>>>> -// void enterCFGBlock(const CFGBlock *B) {}
>>>> -//
>>>> -// Process an ordinary statement.
>>>> -// void handleStatement(const Stmt *S) {}
>>>> -//
>>>> -// Process a destructor call
>>>> -// void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {}
>>>> -//
>>>> -// Process a successor edge.
>>>> -// void handleSuccessor(const CFGBlock *Succ) {}
>>>> -//
>>>> -// Process a successor back edge to a previously visited block.
>>>> -// void handleSuccessorBackEdge(const CFGBlock *Succ) {}
>>>> -//
>>>> -// Leave a CFGBlock.
>>>> -// void exitCFGBlock(const CFGBlock *B) {}
>>>> -//
>>>> -// Leave the CFG, and perform any final cleanup operations.
>>>> -// void exitCFG(const CFGBlock *Last) {}
>>>> +// This class defines the interface of a clang CFG Visitor.
>>>> +// CFGWalker will invoke the following methods.
>>>> +// Note that methods are not virtual; the visitor is templatized.
>>>> +class CFGVisitor {
>>>> + // Enter the CFG for Decl D, and perform any initial setup operations.
>>>> + void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First) {}
>>>> +
>>>> + // Enter a CFGBlock.
>>>> + void enterCFGBlock(const CFGBlock *B) {}
>>>> +
>>>> + // Returns true if this visitor implements handlePredecessor
>>>> + bool visitPredecessors() { return true; }
>>>> +
>>>> + // Process a predecessor edge.
>>>> + void handlePredecessor(const CFGBlock *Pred) {}
>>>> +
>>>> + // Process a successor back edge to a previously visited block.
>>>> + void handlePredecessorBackEdge(const CFGBlock *Pred) {}
>>>> +
>>>> + // Called just before processing statements.
>>>> + void enterCFGBlockBody(const CFGBlock *B) {}
>>>> +
>>>> + // Process an ordinary statement.
>>>> + void handleStatement(const Stmt *S) {}
>>>> +
>>>> + // Process a destructor call
>>>> + void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {}
>>>> +
>>>> + // Called after all statements have been handled.
>>>> + void exitCFGBlockBody(const CFGBlock *B) {}
>>>> +
>>>> + // Return true
>>>> + bool visitSuccessors() { return true; }
>>>> +
>>>> + // Process a successor edge.
>>>> + void handleSuccessor(const CFGBlock *Succ) {}
>>>> +
>>>> + // Process a successor back edge to a previously visited block.
>>>> + void handleSuccessorBackEdge(const CFGBlock *Succ) {}
>>>> +
>>>> + // Leave a CFGBlock.
>>>> + void exitCFGBlock(const CFGBlock *B) {}
>>>> +
>>>> + // Leave the CFG, and perform any final cleanup operations.
>>>> + void exitCFG(const CFGBlock *Last) {}
>>>> +};
>>>> +
>>>>
>>>> // Walks the clang CFG, and invokes methods on a given CFGVisitor.
>>>> class CFGWalker {
>>>> @@ -97,6 +118,25 @@ public:
>>>>
>>>> V.enterCFGBlock(CurrBlock);
>>>>
>>>> + // Process predecessors
>>>> + if (V.visitPredecessors()) {
>>>> + // Process successors
>>>> + for (CFGBlock::const_pred_iterator SI = CurrBlock->pred_begin(),
>>>> + SE = CurrBlock->pred_end();
>>>> + SI != SE; ++SI) {
>>>> + if (*SI == nullptr)
>>>> + continue;
>>>> +
>>>> + if (!VisitedBlocks.alreadySet(*SI)) {
>>>> + V.handlePredecessorBackEdge(*SI);
>>>> + continue;
>>>> + }
>>>> + V.handlePredecessor(*SI);
>>>> + }
>>>> + }
>>>> +
>>>> + V.enterCFGBlockBody(CurrBlock);
>>>> +
>>>> // Process statements
>>>> for (const auto &BI : *CurrBlock) {
>>>> switch (BI.getKind()) {
>>>> @@ -117,18 +157,23 @@ public:
>>>> }
>>>> }
>>>>
>>>> + V.exitCFGBlockBody(CurrBlock);
>>>> +
>>>> // Process successors
>>>> - for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
>>>> - SE = CurrBlock->succ_end();
>>>> - SI != SE; ++SI) {
>>>> - if (*SI == nullptr)
>>>> - continue;
>>>> -
>>>> - if (VisitedBlocks.alreadySet(*SI)) {
>>>> - V.handleSuccessorBackEdge(*SI);
>>>> - continue;
>>>> + if (V.visitSuccessors()) {
>>>> + // Process successors
>>>> + for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
>>>> + SE = CurrBlock->succ_end();
>>>> + SI != SE; ++SI) {
>>>> + if (*SI == nullptr)
>>>> + continue;
>>>> +
>>>> + if (VisitedBlocks.alreadySet(*SI)) {
>>>> + V.handleSuccessorBackEdge(*SI);
>>>> + continue;
>>>> + }
>>>> + V.handleSuccessor(*SI);
>>>> }
>>>> - V.handleSuccessor(*SI);
>>>> }
>>>>
>>>> V.exitCFGBlock(CurrBlock);
>>>> @@ -174,15 +219,16 @@ public:
>>>> {}
>>>> };
>>>>
>>>> - til::SExpr *lookupStmt(const Stmt *S);
>>>> - void insertStmt(const Stmt *S, til::Variable *V);
>>>> -
>>>> // Translate a clang statement or expression to a TIL expression.
>>>> // Also performs substitution of variables; Ctx provides the context.
>>>> // Dispatches on the type of S.
>>>> til::SExpr *translate(const Stmt *S, CallingContext *Ctx);
>>>> + til::SCFG *buildCFG(CFGWalker &Walker);
>>>>
>>>> -protected:
>>>> + til::SExpr *lookupStmt(const Stmt *S);
>>>> + til::SCFG *getCFG() const { return Scfg; }
>>>> +
>>>> +private:
>>>> til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE,
>>>> CallingContext *Ctx) ;
>>>> til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx);
>>>> @@ -204,24 +250,86 @@ protected:
>>>> til::SExpr *translateBinaryConditionalOperator(
>>>> const BinaryConditionalOperator *C, CallingContext *Ctx);
>>>>
>>>> + til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx);
>>>> +
>>>> +private:
>>>> + // Used for looking the index of a name.
>>>> + typedef llvm::DenseMap<const ValueDecl*, unsigned> NameIndexMap;
>>>> +
>>>> + // Used for looking up the current SSA variable for a name, by index.
>>>> + typedef CopyOnWriteVector<std::pair<const ValueDecl*, til::SExpr*> >
>>>> + NameVarMap;
>>>> +
>>>> + struct BlockInfo {
>>>> + NameVarMap ExitMap;
>>>> + bool HasBackEdges = false;
>>>> + unsigned SuccessorsToProcess = 0;
>>>> + };
>>>> +
>>>> + // We implement the CFGVisitor API
>>>> + friend class CFGWalker;
>>>> +
>>>> + void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First);
>>>> + void enterCFGBlock(const CFGBlock *B);
>>>> + bool visitPredecessors() { return true; }
>>>> + void handlePredecessor(const CFGBlock *Pred);
>>>> + void handlePredecessorBackEdge(const CFGBlock *Pred);
>>>> + void enterCFGBlockBody(const CFGBlock *B);
>>>> + void handleStatement(const Stmt *S);
>>>> + void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD);
>>>> + void exitCFGBlockBody(const CFGBlock *B);
>>>> + bool visitSuccessors() { return true; }
>>>> + void handleSuccessor(const CFGBlock *Succ);
>>>> + void handleSuccessorBackEdge(const CFGBlock *Succ);
>>>> + void exitCFGBlock(const CFGBlock *B);
>>>> + void exitCFG(const CFGBlock *Last);
>>>> +
>>>> + void insertStmt(const Stmt *S, til::Variable *V);
>>>> + 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);
>>>>
>>>> public:
>>>> - SExprBuilder(til::MemRegionRef A, StatementMap *SM = nullptr)
>>>> - : Arena(A), SMap(SM), SelfVar(nullptr), CurrentBlock(nullptr) {
>>>> + SExprBuilder(til::MemRegionRef A)
>>>> + : Arena(A), SelfVar(nullptr), Scfg(nullptr), CallCtx(nullptr),
>>>> + CurrentBB(nullptr), CurrentBlockID(0), CurrentVarID(0),
>>>> + CurrentArgIndex(0)
>>>> + {
>>>> // FIXME: we don't always have a self-variable.
>>>> SelfVar = new (Arena) til::Variable(til::Variable::VK_SFun);
>>>> }
>>>>
>>>> -protected:
>>>> + ~SExprBuilder() {
>>>> + if (CallCtx)
>>>> + delete CallCtx;
>>>> + }
>>>> +
>>>> +private:
>>>> til::MemRegionRef Arena;
>>>> - StatementMap *SMap; // Map from Stmt to TIL Variables
>>>> - til::Variable *SelfVar; // Variable to use for 'this'. May be null.
>>>> - til::BasicBlock* CurrentBlock; // Current basic block. May be null.
>>>> + 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.
>>>> + 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;
>>>> + til::BasicBlock *CurrentBB;
>>>> + BlockInfo *CurrentBlockInfo;
>>>> + unsigned CurrentBlockID;
>>>> + unsigned CurrentVarID;
>>>> + unsigned CurrentArgIndex;
>>>> };
>>>>
>>>>
>>>> // Dump an SCFG to llvm::errs().
>>>> -void printSCFG(CFGWalker &walker);
>>>> +void printSCFG(CFGWalker &Walker);
>>>>
>>>>
>>>> } // end namespace threadSafety
>>>>
>>>> Modified: cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h?rev=206338&r1=206337&r2=206338&view=diff
>>>> ==============================================================================
>>>> --- cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h (original)
>>>> +++ cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h Tue Apr 15 18:23:19 2014
>>>> @@ -199,7 +199,7 @@ public:
>>>> // These are defined after SExprRef contructor, below
>>>> inline Variable(VariableKind K, SExpr *D = nullptr,
>>>> const clang::ValueDecl *Cvd = nullptr);
>>>> - inline Variable(const clang::ValueDecl *Cvd, SExpr *D = nullptr);
>>>> + inline Variable(SExpr *D = nullptr, const clang::ValueDecl *Cvd = nullptr);
>>>> inline Variable(const Variable &Vd, SExpr *D);
>>>>
>>>> VariableKind kind() const { return static_cast<VariableKind>(Flags); }
>>>> @@ -220,6 +220,7 @@ public:
>>>> BlockID = static_cast<unsigned short>(Bid);
>>>> Id = static_cast<unsigned short>(I);
>>>> }
>>>> + void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; }
>>>>
>>>> template <class V> typename V::R_SExpr traverse(V &Visitor) {
>>>> // This routine is only called for variable references.
>>>> @@ -353,7 +354,7 @@ Variable::Variable(VariableKind K, SExpr
>>>> Flags = K;
>>>> }
>>>>
>>>> -Variable::Variable(const clang::ValueDecl *Cvd, SExpr *D)
>>>> +Variable::Variable(SExpr *D, const clang::ValueDecl *Cvd)
>>>> : SExpr(COP_Variable), Definition(D), Cvdecl(Cvd),
>>>> BlockID(0), Id(0), NumUses(0) {
>>>> Flags = VK_Let;
>>>> @@ -935,6 +936,8 @@ private:
>>>> SExprRef Expr0;
>>>> };
>>>>
>>>> +
>>>> +
>>>> class BasicBlock;
>>>>
>>>> // An SCFG is a control-flow graph. It consists of a set of basic blocks, each
>>>> @@ -998,13 +1001,16 @@ public:
>>>>
>>>> BasicBlock(MemRegionRef A, unsigned Nargs, unsigned Nins,
>>>> SExpr *Term = nullptr)
>>>> - : BlockID(0), Parent(nullptr), Args(A, Nargs), Instrs(A, Nins),
>>>> - Terminator(Term) {}
>>>> + : BlockID(0), Parent(nullptr), NumPredecessors(0),
>>>> + Args(A, Nargs), Instrs(A, Nins), Terminator(Term) {}
>>>> BasicBlock(const BasicBlock &B, VarArray &&As, VarArray &&Is, SExpr *T)
>>>> - : BlockID(0), Parent(nullptr), Args(std::move(As)), Instrs(std::move(Is)),
>>>> - Terminator(T) {}
>>>> + : BlockID(0), Parent(nullptr), NumPredecessors(B.NumPredecessors),
>>>> + Args(std::move(As)), Instrs(std::move(Is)), Terminator(T)
>>>> + {}
>>>>
>>>> unsigned blockID() const { return BlockID; }
>>>> + unsigned numPredecessors() const { return NumPredecessors; }
>>>> +
>>>> const BasicBlock *parent() const { return Parent; }
>>>> BasicBlock *parent() { return Parent; }
>>>>
>>>> @@ -1017,8 +1023,9 @@ public:
>>>> const SExpr *terminator() const { return Terminator.get(); }
>>>> SExpr *terminator() { return Terminator.get(); }
>>>>
>>>> - void setParent(BasicBlock *P) { Parent = P; }
>>>> void setBlockID(unsigned i) { BlockID = i; }
>>>> + 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); }
>>>> @@ -1057,9 +1064,10 @@ private:
>>>> friend class SCFG;
>>>>
>>>> unsigned BlockID;
>>>> - BasicBlock *Parent; // The parent block is the enclosing lexical scope.
>>>> - // The parent dominates this block.
>>>> - VarArray Args; // Phi nodes
>>>> + 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;
>>>> };
>>>> @@ -1100,8 +1108,8 @@ public:
>>>> return Visitor.reducePhi(*this, Nvs);
>>>> }
>>>>
>>>> - template <class C> typename C::CType compare(Phi *E, C &Cmp) {
>>>> - // TODO -- implement CFG comparisons
>>>> + template <class C> typename C::CType compare(Phi* E, C &Cmp) {
>>>> + // TODO: implement CFG comparisons
>>>> return Cmp.comparePointers(this, E);
>>>> }
>>>>
>>>> @@ -1146,17 +1154,26 @@ public:
>>>> static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
>>>>
>>>> Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
>>>> - : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E) {}
>>>> + : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E),
>>>> + ThenIndex(0), ElseIndex(0)
>>>> + {}
>>>> Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
>>>> - : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E) {}
>>>> + : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E),
>>>> + ThenIndex(0), ElseIndex(0)
>>>> + {}
>>>>
>>>> const SExpr *condition() const { return Condition; }
>>>> SExpr *condition() { return Condition; }
>>>> +
>>>> const BasicBlock *thenBlock() const { return ThenBlock; }
>>>> BasicBlock *thenBlock() { return ThenBlock; }
>>>> +
>>>> const BasicBlock *elseBlock() const { return ElseBlock; }
>>>> BasicBlock *elseBlock() { return ElseBlock; }
>>>>
>>>> + unsigned thenIndex() const { return ThenIndex; }
>>>> + unsigned elseIndex() const { return ElseIndex; }
>>>> +
>>>> template <class V> typename V::R_SExpr traverse(V &Visitor) {
>>>> typename V::R_SExpr Nc = Visitor.traverse(Condition);
>>>> BasicBlock *Ntb = Visitor.reduceBasicBlockRef(ThenBlock);
>>>> @@ -1173,6 +1190,8 @@ private:
>>>> SExpr *Condition;
>>>> BasicBlock *ThenBlock;
>>>> BasicBlock *ElseBlock;
>>>> + unsigned ThenIndex;
>>>> + unsigned ElseIndex;
>>>> };
>>>>
>>>>
>>>>
>>>> Modified: cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h?rev=206338&r1=206337&r2=206338&view=diff
>>>> ==============================================================================
>>>> --- cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h (original)
>>>> +++ cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h Tue Apr 15 18:23:19 2014
>>>> @@ -409,6 +409,15 @@ protected:
>>>> SS << "\n";
>>>> }
>>>>
>>>> + void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) {
>>>> + if (!BB) {
>>>> + SS << "BB_null";
>>>> + return;
>>>> + }
>>>> + SS << "BB_";
>>>> + SS << BB->blockID();
>>>> + }
>>>> +
>>>> // TODO: further distinguish between binary operations.
>>>> static const unsigned Prec_Atom = 0;
>>>> static const unsigned Prec_Postfix = 1;
>>>> @@ -560,9 +569,11 @@ protected:
>>>>
>>>> void printSApply(SApply *E, StreamType &SS) {
>>>> self()->printSExpr(E->sfun(), SS, Prec_Postfix);
>>>> - SS << "@(";
>>>> - self()->printSExpr(E->arg(), SS, Prec_MAX);
>>>> - SS << ")";
>>>> + if (E->isDelegation()) {
>>>> + SS << "@(";
>>>> + self()->printSExpr(E->arg(), SS, Prec_MAX);
>>>> + SS << ")";
>>>> + }
>>>> }
>>>>
>>>> void printProject(Project *E, StreamType &SS) {
>>>> @@ -584,7 +595,7 @@ protected:
>>>> }
>>>>
>>>> void printAlloc(Alloc *E, StreamType &SS) {
>>>> - SS << "#alloc ";
>>>> + SS << "new ";
>>>> self()->printSExpr(E->dataType(), SS, Prec_Other-1);
>>>> }
>>>>
>>>> @@ -595,7 +606,7 @@ protected:
>>>>
>>>> void printStore(Store *E, StreamType &SS) {
>>>> self()->printSExpr(E->destination(), SS, Prec_Other-1);
>>>> - SS << " = ";
>>>> + SS << " := ";
>>>> self()->printSExpr(E->source(), SS, Prec_Other-1);
>>>> }
>>>>
>>>> @@ -628,9 +639,11 @@ protected:
>>>> newline(SS);
>>>> }
>>>> for (auto I : BBI->instructions()) {
>>>> - SS << "let ";
>>>> - self()->printVariable(I, SS);
>>>> - SS << " = ";
>>>> + if (I->definition()->opcode() != COP_Store) {
>>>> + SS << "let ";
>>>> + self()->printVariable(I, SS);
>>>> + SS << " = ";
>>>> + }
>>>> self()->printSExpr(I->definition(), SS, Prec_MAX);
>>>> SS << ";";
>>>> newline(SS);
>>>> @@ -648,31 +661,29 @@ protected:
>>>> }
>>>>
>>>> void printPhi(Phi *E, StreamType &SS) {
>>>> - SS << "#phi(";
>>>> + SS << "phi(";
>>>> unsigned i = 0;
>>>> for (auto V : E->values()) {
>>>> - ++i;
>>>> if (i > 0)
>>>> SS << ", ";
>>>> self()->printSExpr(V, SS, Prec_MAX);
>>>> + ++i;
>>>> }
>>>> SS << ")";
>>>> }
>>>>
>>>> void printGoto(Goto *E, StreamType &SS) {
>>>> - SS << "#goto BB_";
>>>> - SS << E->targetBlock()->blockID();
>>>> - SS << ":";
>>>> - SS << E->index();
>>>> + SS << "goto ";
>>>> + printBlockLabel(SS, E->targetBlock(), E->index());
>>>> }
>>>>
>>>> void printBranch(Branch *E, StreamType &SS) {
>>>> - SS << "#branch (";
>>>> + SS << "branch (";
>>>> self()->printSExpr(E->condition(), SS, Prec_MAX);
>>>> - SS << ") BB_";
>>>> - SS << E->thenBlock()->blockID();
>>>> - SS << " BB_";
>>>> - SS << E->elseBlock()->blockID();
>>>> + SS << ") ";
>>>> + printBlockLabel(SS, E->thenBlock(), E->thenIndex());
>>>> + SS << " ";
>>>> + printBlockLabel(SS, E->elseBlock(), E->elseIndex());
>>>> }
>>>> };
>>>>
>>>>
>>>> Modified: cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyUtil.h?rev=206338&r1=206337&r2=206338&view=diff
>>>> ==============================================================================
>>>> --- cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyUtil.h (original)
>>>> +++ cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyUtil.h Tue Apr 15 18:23:19 2014
>>>> @@ -78,7 +78,7 @@ template <class T> class SimpleArray {
>>>> public:
>>>> SimpleArray() : Data(nullptr), Size(0), Capacity(0) {}
>>>> SimpleArray(T *Dat, size_t Cp, size_t Sz = 0)
>>>> - : Data(Dat), Size(0), Capacity(Cp) {}
>>>> + : Data(Dat), Size(Sz), Capacity(Cp) {}
>>>> SimpleArray(MemRegionRef A, size_t Cp)
>>>> : Data(A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {}
>>>> SimpleArray(SimpleArray<T> &&A)
>>>> @@ -101,8 +101,14 @@ public:
>>>> size_t size() const { return Size; }
>>>> size_t capacity() const { return Capacity; }
>>>>
>>>> - T &operator[](unsigned I) { return Data[I]; }
>>>> - const T &operator[](unsigned I) const { return Data[I]; }
>>>> + T &operator[](unsigned i) {
>>>> + assert(i < Sz && "Array index out of bounds.");
>>>> + return Data[i];
>>>> + }
>>>> + const T &operator[](unsigned i) const {
>>>> + assert(i < Size && "Array index out of bounds.");
>>>> + return Data[i];
>>>> + }
>>>>
>>>> iterator begin() { return Data; }
>>>> iterator end() { return Data + Size; }
>>>> @@ -115,6 +121,14 @@ public:
>>>> Data[Size++] = Elem;
>>>> }
>>>>
>>>> + void setValues(unsigned Sz, const T& C) {
>>>> + assert(Sz < Capacity);
>>>> + Size = Sz;
>>>> + for (unsigned i = 0; i < Sz; ++i) {
>>>> + Data[i] = C;
>>>> + }
>>>> + }
>>>> +
>>>> template <class Iter> unsigned append(Iter I, Iter E) {
>>>> size_t Osz = Size;
>>>> size_t J = Osz;
>>>> @@ -132,8 +146,135 @@ private:
>>>> size_t Capacity;
>>>> };
>>>>
>>>> -
>>>> } // end namespace til
>>>> +
>>>> +
>>>> +// A copy on write vector.
>>>> +// The vector can be in one of three states:
>>>> +// * invalid -- no operations are permitted.
>>>> +// * read-only -- read operations are permitted.
>>>> +// * writable -- read and write operations are permitted.
>>>> +// The init(), destroy(), and makeWritable() methods will change state.
>>>> +template<typename T>
>>>> +class CopyOnWriteVector {
>>>> +private:
>>>> + class VectorData {
>>>> + public:
>>>> + VectorData() : NumRefs(1) { }
>>>> + VectorData(const VectorData &VD) : NumRefs(1), Vect(VD.Vect) { }
>>>> +
>>>> + unsigned NumRefs;
>>>> + std::vector<T> Vect;
>>>> + };
>>>> +
>>>> +public:
>>>> + CopyOnWriteVector() : Data(0) { }
>>>> + CopyOnWriteVector(const CopyOnWriteVector &V) = delete;
>>>> + CopyOnWriteVector(CopyOnWriteVector &&V) : Data(V.Data) {
>>>> + V.Data = 0;
>>>> + }
>>>> + ~CopyOnWriteVector() {
>>>> + destroy();
>>>> + }
>>>> +
>>>> + // Returns true if this holds a valid vector.
>>>> + bool valid() { return Data; }
>>>> +
>>>> + // Returns true if this vector is writable.
>>>> + bool writable() { return Data && Data->NumRefs == 1; }
>>>> +
>>>> + // If this vector is not valid, initialize it to a valid vector.
>>>> + void init() {
>>>> + if (!Data) {
>>>> + Data = new VectorData();
>>>> + }
>>>> + }
>>>> +
>>>> + // Destroy this vector; thus making it invalid.
>>>> + void destroy() {
>>>> + if (!Data)
>>>> + return;
>>>> + if (Data->NumRefs <= 1)
>>>> + delete Data;
>>>> + else
>>>> + --Data->NumRefs;
>>>> + Data = 0;
>>>> + }
>>>> +
>>>> + // Make this vector writable, creating a copy if needed.
>>>> + void makeWritable() {
>>>> + if (!Data) {
>>>> + Data = new VectorData();
>>>> + return;
>>>> + }
>>>> + if (Data->NumRefs == 1)
>>>> + return; // already writeable.
>>>> + --Data->NumRefs;
>>>> + Data = new VectorData(*Data);
>>>> + }
>>>> +
>>>> + // Create a lazy copy of this vector.
>>>> + CopyOnWriteVector clone() { return CopyOnWriteVector(Data); }
>>>> +
>>>> + // No copy constructor or copy assignment. Use clone() with move assignment.
>>>> + void operator=(const CopyOnWriteVector &V) = delete;
>>>> +
>>>> + void operator=(CopyOnWriteVector &&V) {
>>>> + destroy();
>>>> + Data = V.Data;
>>>> + V.Data = 0;
>>>> + }
>>>> +
>>>> + typedef typename std::vector<T>::const_iterator iterator;
>>>> +
>>>> + const std::vector<T> &elements() const { return Data->Vect; }
>>>> +
>>>> + iterator begin() const { return elements().cbegin(); }
>>>> + iterator end() const { return elements().cend(); }
>>>> +
>>>> + const T& operator[](unsigned i) const { return elements()[i]; }
>>>> +
>>>> + unsigned size() const { return Data ? elements().size() : 0; }
>>>> +
>>>> + // Return true if V and this vector refer to the same data.
>>>> + bool sameAs(const CopyOnWriteVector& V) { return Data == V.Data; }
>>>> +
>>>> + // Clear vector. The vector must be writable.
>>>> + void clear() {
>>>> + assert(writable() && "Vector is not writable!");
>>>> + Data->Vect.clear();
>>>> + }
>>>> +
>>>> + // Push a new element onto the end. The vector must be writable.
>>>> + void push_back(const T& Elem) {
>>>> + assert(writable() && "Vector is not writable!");
>>>> + Data->Vect.push_back(Elem);
>>>> + }
>>>> +
>>>> + // Gets a mutable reference to the element at index(i).
>>>> + // The vector must be writable.
>>>> + T& elem(unsigned i) {
>>>> + assert(writable() && "Vector is not writable!");
>>>> + return Data->Vect[i];
>>>> + }
>>>> +
>>>> + // Drops elements from the back until the vector has size i.
>>>> + void downsize(unsigned i) {
>>>> + assert(writable() && "Vector is not writable!");
>>>> + Data->Vect.erase(Data->Vect.begin() + i, Data->Vect.end());
>>>> + }
>>>> +
>>>> +private:
>>>> + CopyOnWriteVector(VectorData *D) : Data(D) {
>>>> + if (!Data)
>>>> + return;
>>>> + ++Data->NumRefs;
>>>> + }
>>>> +
>>>> + VectorData *Data;
>>>> +};
>>>> +
>>>> +
>>>> } // end namespace threadSafety
>>>> } // end namespace clang
>>>>
>>>>
>>>> Modified: cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp
>>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp?rev=206338&r1=206337&r2=206338&view=diff
>>>> ==============================================================================
>>>> --- cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp (original)
>>>> +++ cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp Tue Apr 15 18:23:19 2014
>>>> @@ -28,6 +28,8 @@
>>>> #include "llvm/ADT/SmallVector.h"
>>>> #include "llvm/ADT/StringRef.h"
>>>>
>>>> +#include <algorithm>
>>>> +#include <climits>
>>>> #include <vector>
>>>>
>>>>
>>>> @@ -38,16 +40,20 @@ typedef SExprBuilder::CallingContext Cal
>>>>
>>>>
>>>> til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) {
>>>> - if (!SMap)
>>>> - return nullptr;
>>>> - auto It = SMap->find(S);
>>>> - if (It != SMap->end())
>>>> + auto It = SMap.find(S);
>>>> + if (It != SMap.end())
>>>> return It->second;
>>>> return nullptr;
>>>> }
>>>>
>>>> void SExprBuilder::insertStmt(const Stmt *S, til::Variable *V) {
>>>> - SMap->insert(std::make_pair(S, V));
>>>> + SMap.insert(std::make_pair(S, V));
>>>> +}
>>>> +
>>>> +
>>>> +til::SCFG *SExprBuilder::buildCFG(CFGWalker &Walker) {
>>>> + Walker.walk(*this);
>>>> + return Scfg;
>>>> }
>>>>
>>>>
>>>> @@ -55,6 +61,9 @@ void SExprBuilder::insertStmt(const Stmt
>>>> // Also performs substitution of variables; Ctx provides the context.
>>>> // Dispatches on the type of S.
>>>> til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
>>>> + if (!S)
>>>> + return nullptr;
>>>> +
>>>> // Check if S has already been translated and cached.
>>>> // This handles the lookup of SSA names for DeclRefExprs here.
>>>> if (til::SExpr *E = lookupStmt(S))
>>>> @@ -105,6 +114,9 @@ til::SExpr *SExprBuilder::translate(cons
>>>> case Stmt::StringLiteralClass:
>>>> case Stmt::ObjCStringLiteralClass:
>>>> return new (Arena) til::Literal(cast<Expr>(S));
>>>> +
>>>> + case Stmt::DeclStmtClass:
>>>> + return translateDeclStmt(cast<DeclStmt>(S), Ctx);
>>>> default:
>>>> break;
>>>> }
>>>> @@ -209,6 +221,7 @@ til::SExpr *SExprBuilder::translateUnary
>>>> return new (Arena) til::Undefined(UO);
>>>> }
>>>>
>>>> +
>>>> til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO,
>>>> CallingContext *Ctx) {
>>>> switch (BO->getOpcode()) {
>>>> @@ -238,10 +251,17 @@ til::SExpr *SExprBuilder::translateBinar
>>>> til::BinaryOp(BO->getOpcode(), translate(BO->getLHS(), Ctx),
>>>> translate(BO->getRHS(), Ctx));
>>>>
>>>> - case BO_Assign:
>>>> - return new (Arena)
>>>> - til::Store(translate(BO->getLHS(), Ctx), translate(BO->getRHS(), Ctx));
>>>> -
>>>> + case BO_Assign: {
>>>> + const Expr *LHS = BO->getLHS();
>>>> + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHS)) {
>>>> + const Expr *RHS = BO->getRHS();
>>>> + til::SExpr *E1 = translate(RHS, Ctx);
>>>> + return updateVarDecl(DRE->getDecl(), E1);
>>>> + }
>>>> + til::SExpr *E0 = translate(LHS, Ctx);
>>>> + til::SExpr *E1 = translate(BO->getRHS(), Ctx);
>>>> + return new (Arena) til::Store(E0, E1);
>>>> + }
>>>> case BO_MulAssign:
>>>> case BO_DivAssign:
>>>> case BO_RemAssign:
>>>> @@ -265,145 +285,332 @@ til::SExpr *SExprBuilder::translateBinar
>>>>
>>>> til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE,
>>>> CallingContext *Ctx) {
>>>> - til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
>>>> -
>>>> clang::CastKind K = CE->getCastKind();
>>>> switch (K) {
>>>> - case CK_LValueToRValue:
>>>> + case CK_LValueToRValue: {
>>>> + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
>>>> + til::SExpr *E0 = lookupVarDecl(DRE->getDecl());
>>>> + if (E0)
>>>> + return E0;
>>>> + }
>>>> + til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
>>>> return new (Arena) til::Load(E0);
>>>> -
>>>> + }
>>>> case CK_NoOp:
>>>> case CK_DerivedToBase:
>>>> case CK_UncheckedDerivedToBase:
>>>> case CK_ArrayToPointerDecay:
>>>> - case CK_FunctionToPointerDecay:
>>>> + case CK_FunctionToPointerDecay: {
>>>> + til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
>>>> return E0;
>>>> -
>>>> - default:
>>>> + }
>>>> + default: {
>>>> + til::SExpr *E0 = translate(CE->getSubExpr(), Ctx);
>>>> return new (Arena) til::Cast(K, E0);
>>>> }
>>>> + }
>>>> }
>>>>
>>>> +
>>>> til::SExpr *
>>>> SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E,
>>>> CallingContext *Ctx) {
>>>> return new (Arena) til::Undefined(E);
>>>> }
>>>>
>>>> +
>>>> til::SExpr *
>>>> SExprBuilder::translateConditionalOperator(const ConditionalOperator *C,
>>>> CallingContext *Ctx) {
>>>> return new (Arena) til::Undefined(C);
>>>> }
>>>>
>>>> +
>>>> til::SExpr *SExprBuilder::translateBinaryConditionalOperator(
>>>> const BinaryConditionalOperator *C, CallingContext *Ctx) {
>>>> return new (Arena) til::Undefined(C);
>>>> }
>>>>
>>>>
>>>> +til::SExpr *
>>>> +SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) {
>>>> + DeclGroupRef DGrp = S->getDeclGroup();
>>>> + for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
>>>> + if (VarDecl *VD = dyn_cast_or_null<VarDecl>(*I)) {
>>>> + Expr *E = VD->getInit();
>>>> + til::SExpr* SE = translate(E, Ctx);
>>>> +
>>>> + // Add local variables with trivial type to the variable map
>>>> + QualType T = VD->getType();
>>>> + if (T.isTrivialType(VD->getASTContext())) {
>>>> + return addVarDecl(VD, SE);
>>>> + }
>>>> + else {
>>>> + // TODO: add alloca
>>>> + }
>>>> + }
>>>> + }
>>>> + return nullptr;
>>>> +}
>>>>
>>>> -// Build a complete SCFG from a clang CFG.
>>>> -class SCFGBuilder {
>>>> - class BBInfo {
>>>>
>>>> - };
>>>> +// If (E) is non-trivial, then add it to the current basic block, and
>>>> +// update the statement map so that S refers to E. Returns a new variable
>>>> +// that refers to E.
>>>> +// If E is trivial returns E.
>>>> +til::SExpr *SExprBuilder::addStatement(til::SExpr* E, const Stmt *S,
>>>> + const ValueDecl *VD) {
>>>> + if (!E)
>>>> + return nullptr;
>>>> + if (til::ThreadSafetyTIL::isTrivial(E))
>>>> + return E;
>>>>
>>>> - void addStatement(til::SExpr* E, const Stmt *S) {
>>>> - if (!E)
>>>> - return;
>>>> - if (til::ThreadSafetyTIL::isTrivial(E))
>>>> - return;
>>>> + til::Variable *V = new (Arena) til::Variable(E, VD);
>>>> + V->setID(CurrentBlockID, CurrentVarID++);
>>>> + CurrentBB->addInstr(V);
>>>> + if (S)
>>>> + insertStmt(S, V);
>>>> + return V;
>>>> +}
>>>>
>>>> - til::Variable *V = new (Arena) til::Variable(til::Variable::VK_Let, E);
>>>> - V->setID(CurrentBlockID, CurrentVarID++);
>>>> - CurrentBB->addInstr(V);
>>>> - if (S)
>>>> - BuildEx.insertStmt(S, V);
>>>> - }
>>>>
>>>> -public:
>>>> - // Enter the CFG for Decl D, and perform any initial setup operations.
>>>> - void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First) {
>>>> - Scfg = new (Arena) til::SCFG(Arena, Cfg->getNumBlockIDs());
>>>> - CallCtx = new SExprBuilder::CallingContext(D);
>>>> - }
>>>> +// Returns the current value of VD, if known, and nullptr otherwise.
>>>> +til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) {
>>>> + auto It = IdxMap.find(VD);
>>>> + if (It != IdxMap.end())
>>>> + return CurrentNameMap[It->second].second;
>>>> + return nullptr;
>>>> +}
>>>>
>>>> - // Enter a CFGBlock.
>>>> - void enterCFGBlock(const CFGBlock *B) {
>>>> - CurrentBB = new (Arena) til::BasicBlock(Arena, 0, B->size());
>>>> - CurrentBB->setBlockID(CurrentBlockID);
>>>> - CurrentVarID = 0;
>>>> - Scfg->add(CurrentBB);
>>>> - }
>>>>
>>>> - // Process an ordinary statement.
>>>> - void handleStatement(const Stmt *S) {
>>>> - til::SExpr *E = BuildEx.translate(S, CallCtx);
>>>> - addStatement(E, S);
>>>> +// if E is a til::Variable, update its clangDecl.
>>>> +inline void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) {
>>>> + if (!E)
>>>> + return;
>>>> + if (til::Variable *V = dyn_cast<til::Variable>(E)) {
>>>> + if (!V->clangDecl())
>>>> + V->setClangDecl(VD);
>>>> }
>>>> +}
>>>> +
>>>> +// Adds a new variable declaration.
>>>> +til::SExpr *SExprBuilder::addVarDecl(const ValueDecl *VD, til::SExpr *E) {
>>>> + maybeUpdateVD(E, VD);
>>>> + IdxMap.insert(std::make_pair(VD, CurrentNameMap.size()));
>>>> + CurrentNameMap.makeWritable();
>>>> + CurrentNameMap.push_back(std::make_pair(VD, E));
>>>> + return E;
>>>> +}
>>>> +
>>>> +
>>>> +// Updates a current variable declaration. (E.g. by assignment)
>>>> +til::SExpr *SExprBuilder::updateVarDecl(const ValueDecl *VD, til::SExpr *E) {
>>>> + maybeUpdateVD(E, VD);
>>>> + auto It = IdxMap.find(VD);
>>>> + if (It == IdxMap.end()) {
>>>> + til::SExpr *Ptr = new (Arena) til::LiteralPtr(VD);
>>>> + til::SExpr *St = new (Arena) til::Store(Ptr, E);
>>>> + return St;
>>>> + }
>>>> + CurrentNameMap.makeWritable();
>>>> + CurrentNameMap.elem(It->second).second = E;
>>>> + return E;
>>>> +}
>>>> +
>>>>
>>>> - // Process a destructor call
>>>> - void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {
>>>> - til::SExpr *Sf = new (Arena) til::LiteralPtr(VD);
>>>> - til::SExpr *Dr = new (Arena) til::LiteralPtr(DD);
>>>> - til::SExpr *Ap = new (Arena) til::Apply(Dr, Sf);
>>>> - til::SExpr *E = new (Arena) til::Call(Ap);
>>>> - addStatement(E, nullptr);
>>>> +// Merge values from Map into the current entry map.
>>>> +void SExprBuilder::mergeEntryMap(NameVarMap Map) {
>>>> + assert(CurrentBlockInfo && "Not processing a block!");
>>>> +
>>>> + if (!CurrentNameMap.valid()) {
>>>> + // Steal Map, using copy-on-write.
>>>> + CurrentNameMap = std::move(Map);
>>>> + return;
>>>> + }
>>>> + if (CurrentNameMap.sameAs(Map))
>>>> + return; // Easy merge: maps from different predecessors are unchanged.
>>>> +
>>>> + unsigned ESz = CurrentNameMap.size();
>>>> + unsigned MSz = Map.size();
>>>> + unsigned Sz = std::max(ESz, MSz);
>>>> + bool W = CurrentNameMap.writable();
>>>> + for (unsigned i=0; i<Sz; ++i) {
>>>> + if (CurrentNameMap[i].first != Map[i].first) {
>>>> + if (!W)
>>>> + CurrentNameMap.makeWritable();
>>>> + CurrentNameMap.downsize(i);
>>>> + break;
>>>> + }
>>>> + if (CurrentNameMap[i].second != Map[i].second) {
>>>> + til::Variable *V =
>>>> + dyn_cast<til::Variable>(CurrentNameMap[i].second);
>>>> + if (V && V->getBlockID() == CurrentBB->blockID()) {
>>>> + // We already have a Phi node, so add the new variable.
>>>> + til::Phi *Ph = dyn_cast<til::Phi>(V->definition());
>>>> + assert(Ph && "Expecting Phi node.");
>>>> + Ph->values()[CurrentArgIndex] = Map[i].second;
>>>> + }
>>>> + else {
>>>> + if (!W)
>>>> + CurrentNameMap.makeWritable();
>>>> + unsigned NPreds = CurrentBB->numPredecessors();
>>>> + assert(CurrentArgIndex > 0 && CurrentArgIndex < NPreds);
>>>> +
>>>> + // Make a new phi node. All phi args up to the current index must
>>>> + // be the same, and equal to the current NameMap value.
>>>> + auto *Ph = new (Arena) til::Phi(Arena, NPreds);
>>>> + Ph->values().setValues(NPreds, nullptr);
>>>> + for (unsigned PIdx = 0; PIdx < CurrentArgIndex; ++PIdx)
>>>> + Ph->values()[PIdx] = CurrentNameMap[i].second;
>>>> + Ph->values()[CurrentArgIndex] = Map[i].second;
>>>> +
>>>> + // Add phi node to current basic block.
>>>> + auto *Var = new (Arena) til::Variable(Ph, CurrentNameMap[i].first);
>>>> + Var->setID(CurrentBlockID, CurrentVarID++);
>>>> + CurrentBB->addArgument(Var);
>>>> + CurrentNameMap.elem(i).second = Var;
>>>> + }
>>>> + }
>>>> + }
>>>> + if (ESz > MSz) {
>>>> + if (!W)
>>>> + CurrentNameMap.makeWritable();
>>>> + CurrentNameMap.downsize(Map.size());
>>>> }
>>>> +}
>>>> +
>>>>
>>>> - // Process a successor edge.
>>>> - void handleSuccessor(const CFGBlock *Succ) {}
>>>>
>>>> - // Process a successor back edge to a previously visited block.
>>>> - void handleSuccessorBackEdge(const CFGBlock *Succ) {}
>>>> +void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D,
>>>> + const CFGBlock *First) {
>>>> + // Perform initial setup operations.
>>>> + unsigned NBlocks = Cfg->getNumBlockIDs();
>>>> + Scfg = new (Arena) til::SCFG(Arena, NBlocks);
>>>>
>>>> - // Leave a CFGBlock.
>>>> - void exitCFGBlock(const CFGBlock *B) {
>>>> - CurrentBlockID++;
>>>> - CurrentBB = 0;
>>>> + // allocate all basic blocks immediately, to handle forward references.
>>>> + BlockMap.reserve(NBlocks);
>>>> + BBInfo.resize(NBlocks);
>>>> + for (auto *B : *Cfg) {
>>>> + auto *BB = new (Arena) til::BasicBlock(Arena, 0, B->size());
>>>> + BlockMap.push_back(BB);
>>>> }
>>>> + CallCtx = new SExprBuilder::CallingContext(D);
>>>> +}
>>>> +
>>>> +
>>>> +
>>>> +void SExprBuilder::enterCFGBlock(const CFGBlock *B) {
>>>> + // Intialize TIL basic block and add it to the CFG.
>>>> + CurrentBB = BlockMap[B->getBlockID()];
>>>> + CurrentBB->setBlockID(CurrentBlockID);
>>>> + CurrentBB->setNumPredecessors(B->pred_size());
>>>> + Scfg->add(CurrentBB);
>>>> +
>>>> + CurrentBlockInfo = &BBInfo[B->getBlockID()];
>>>> + CurrentVarID = 0;
>>>> + CurrentArgIndex = 0;
>>>> +
>>>> + assert(!CurrentNameMap.valid() && "CurrentNameMap already initialized.");
>>>> +}
>>>> +
>>>> +
>>>> +void SExprBuilder::handlePredecessor(const CFGBlock *Pred) {
>>>> + // Compute CurrentNameMap on entry from ExitMaps of predecessors
>>>> +
>>>> + BlockInfo *PredInfo = &BBInfo[Pred->getBlockID()];
>>>> + assert(PredInfo->SuccessorsToProcess > 0);
>>>> +
>>>> + if (--PredInfo->SuccessorsToProcess == 0)
>>>> + mergeEntryMap(std::move(PredInfo->ExitMap));
>>>> + else
>>>> + mergeEntryMap(PredInfo->ExitMap.clone());
>>>> +
>>>> + ++CurrentArgIndex;
>>>> +}
>>>> +
>>>> +
>>>> +void SExprBuilder::handlePredecessorBackEdge(const CFGBlock *Pred) {
>>>> + CurrentBlockInfo->HasBackEdges = true;
>>>> +}
>>>> +
>>>>
>>>> - // Leave the CFG, and perform any final cleanup operations.
>>>> - void exitCFG(const CFGBlock *Last) {
>>>> - delete CallCtx;
>>>> - CallCtx = nullptr;
>>>> +void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) { }
>>>> +
>>>> +
>>>> +void SExprBuilder::handleStatement(const Stmt *S) {
>>>> + til::SExpr *E = translate(S, CallCtx);
>>>> + addStatement(E, S);
>>>> +}
>>>> +
>>>> +
>>>> +void SExprBuilder::handleDestructorCall(const VarDecl *VD,
>>>> + const CXXDestructorDecl *DD) {
>>>> + til::SExpr *Sf = new (Arena) til::LiteralPtr(VD);
>>>> + til::SExpr *Dr = new (Arena) til::LiteralPtr(DD);
>>>> + til::SExpr *Ap = new (Arena) til::Apply(Dr, Sf);
>>>> + til::SExpr *E = new (Arena) til::Call(Ap);
>>>> + addStatement(E, nullptr);
>>>> +}
>>>> +
>>>> +
>>>> +
>>>> +void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {
>>>> + unsigned N = B->succ_size();
>>>> + auto It = B->succ_begin();
>>>> + if (N == 1) {
>>>> + til::BasicBlock *BB = *It ? BlockMap[(*It)->getBlockID()] : nullptr;
>>>> + // TODO: set index
>>>> + til::SExpr *Tm = new (Arena) til::Goto(BB, 0);
>>>> + CurrentBB->setTerminator(Tm);
>>>> }
>>>> + else if (N == 2) {
>>>> + til::SExpr *C = translate(B->getTerminatorCondition(true), CallCtx);
>>>> + til::BasicBlock *BB1 = *It ? BlockMap[(*It)->getBlockID()] : nullptr;
>>>> + ++It;
>>>> + til::BasicBlock *BB2 = *It ? BlockMap[(*It)->getBlockID()] : nullptr;
>>>> + // TODO: set conditional, set index
>>>> + til::SExpr *Tm = new (Arena) til::Branch(C, BB1, BB2);
>>>> + CurrentBB->setTerminator(Tm);
>>>> + }
>>>> +}
>>>>
>>>> - SCFGBuilder(til::MemRegionRef A)
>>>> - : Arena(A), Scfg(nullptr), CurrentBB(nullptr), CurrentBlockID(0),
>>>> - CurrentVarID(0), CallCtx(nullptr),
>>>> - SMap(new SExprBuilder::StatementMap()), BuildEx(A, SMap) {}
>>>> - ~SCFGBuilder() { delete SMap; }
>>>>
>>>> - til::SCFG *getCFG() const { return Scfg; }
>>>> +void SExprBuilder::handleSuccessor(const CFGBlock *Succ) {
>>>> + ++CurrentBlockInfo->SuccessorsToProcess;
>>>> +}
>>>>
>>>> -private:
>>>> - til::MemRegionRef Arena;
>>>> - til::SCFG *Scfg;
>>>> - til::BasicBlock *CurrentBB;
>>>> - unsigned CurrentBlockID;
>>>> - unsigned CurrentVarID;
>>>>
>>>> - SExprBuilder::CallingContext *CallCtx;
>>>> - SExprBuilder::StatementMap *SMap;
>>>> - SExprBuilder BuildEx;
>>>> -};
>>>> +void SExprBuilder::handleSuccessorBackEdge(const CFGBlock *Succ) {
>>>> +
>>>> +}
>>>> +
>>>> +
>>>> +void SExprBuilder::exitCFGBlock(const CFGBlock *B) {
>>>> + CurrentBlockInfo->ExitMap = std::move(CurrentNameMap);
>>>> + CurrentBlockID++;
>>>> + CurrentBB = nullptr;
>>>> + CurrentBlockInfo = nullptr;
>>>> +}
>>>> +
>>>> +
>>>> +void SExprBuilder::exitCFG(const CFGBlock *Last) {
>>>> + CurrentBlockID = 0;
>>>> + CurrentVarID = 0;
>>>> + CurrentArgIndex = 0;
>>>> +}
>>>>
>>>>
>>>>
>>>> -class LLVMPrinter :
>>>> - public til::PrettyPrinter<LLVMPrinter, llvm::raw_ostream> {
>>>> +class LLVMPrinter : public til::PrettyPrinter<LLVMPrinter, llvm::raw_ostream> {
>>>> };
>>>>
>>>>
>>>> -void printSCFG(CFGWalker &walker) {
>>>> +void printSCFG(CFGWalker &Walker) {
>>>> llvm::BumpPtrAllocator Bpa;
>>>> til::MemRegionRef Arena(&Bpa);
>>>> - SCFGBuilder builder(Arena);
>>>> - // CFGVisitor visitor;
>>>> - walker.walk(builder);
>>>> - LLVMPrinter::print(builder.getCFG(), llvm::errs());
>>>> + SExprBuilder builder(Arena);
>>>> + til::SCFG *Cfg = builder.buildCFG(Walker);
>>>> + LLVMPrinter::print(Cfg, llvm::errs());
>>>> }
>>>>
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> cfe-commits mailing list
>>>> cfe-commits at cs.uiuc.edu
>>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list