[cfe-commits] r114790 - /cfe/trunk/lib/Analysis/CFG.cpp

Marcin Swiderski marcin.sfider at gmail.com
Sat Sep 25 04:05:21 PDT 2010


Author: sfider
Date: Sat Sep 25 06:05:21 2010
New Revision: 114790

URL: http://llvm.org/viewvc/llvm-project?rev=114790&view=rev
Log:
In preparation for adding generation of destructors for objects with automatic storage added:
- LocalScope class with iterator used to pointing into it,
- fat doxygen comment for LocalScope indended usage,
- BlockScopePosPair class used for storing jump targets/sources (for: goto, break, continue), that replaces raw CFGBlock pointer used earlier for this purpose.

Modified:
    cfe/trunk/lib/Analysis/CFG.cpp

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=114790&r1=114789&r2=114790&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Sat Sep 25 06:05:21 2010
@@ -52,6 +52,116 @@
   Kind k;
 };
 
+/// LocalScope - Node in tree of local scopes created for C++ implicit
+/// destructor calls generation. It contains list of automatic variables
+/// declared in the scope and link to position in previous scope this scope
+/// began in.
+///
+/// The process of creating local scopes is as follows:
+/// - Init CFGBuilder::ScopePos with invalid position (equivalent for null),
+/// - Before processing statements in scope (e.g. CompoundStmt) create
+///   LocalScope object using CFGBuilder::ScopePos as link to previous scope
+///   and set CFGBuilder::ScopePos to the end of new scope,
+/// - On every occurance of VarDecl increase CFGBuilder::ScopePos if it points
+///   at this VarDecl,
+/// - For every normal (without jump) end of scope add to CFGBlock destructors
+///   for objects in the current scope,
+/// - For every jump add to CFGBlock destructors for objects
+///   between CFGBuilder::ScopePos and local scope position saved for jump
+///   target. Thanks to C++ restrictions on goto jumps we can be sure that
+///   jump target position will be on the path to root from CFGBuilder::ScopePos
+///   (adding any variable that doesn't need constructor to be called to
+///   LocalScope can break this assumption),
+///
+class LocalScope {
+public:
+  typedef llvm::SmallVector<VarDecl*, 4> AutomaticVarsTy;
+
+  /// const_iterator - Iterates local scope backwards and jumps to previous
+  /// scope on reaching the begining of currently iterated scope.
+  class const_iterator {
+    const LocalScope* Scope;
+
+    /// VarIter is guaranteed to be greater then 0 for every valid iterator.
+    /// Invalid iterator (with null Scope) has VarIter equal to 0.
+    unsigned VarIter;
+
+  public:
+    /// Create invalid iterator. Dereferencing invalid iterator is not allowed.
+    /// Incrementing invalid iterator is allowed and will result in invalid
+    /// iterator.
+    const_iterator()
+        : Scope(NULL), VarIter(0) {}
+
+    /// Create valid iterator. In case when S.Prev is an invalid iterator and
+    /// I is equal to 0, this will create invalid iterator.
+    const_iterator(const LocalScope& S, unsigned I)
+        : Scope(&S), VarIter(I) {
+      // Iterator to "end" of scope is not allowed. Handle it by going up
+      // in scopes tree possibly up to invalid iterator in the root.
+      if (VarIter == 0 && Scope)
+        *this = Scope->Prev;
+    }
+
+    VarDecl* const* operator->() const {
+      assert (Scope && "Dereferencing invalid iterator is not allowed");
+      assert (VarIter != 0 && "Iterator has invalid value of VarIter member");
+      return &Scope->Vars[VarIter - 1];
+    }
+    VarDecl* operator*() const {
+      return *this->operator->();
+    }
+
+    const_iterator& operator++() {
+      if (!Scope)
+        return *this;
+
+      assert (VarIter != 0 && "Iterator has invalid value of VarIter member");
+      --VarIter;
+      if (VarIter == 0)
+        *this = Scope->Prev;
+      return *this;
+    }
+
+    bool operator==(const const_iterator& rhs) const {
+      return Scope == rhs.Scope && VarIter == rhs.VarIter;
+    }
+    bool operator!=(const const_iterator& rhs) const {
+      return !(*this == rhs);
+    }
+  };
+
+  friend class const_iterator;
+
+private:
+  /// Automatic variables in order of declaration.
+  AutomaticVarsTy Vars;
+  /// Iterator to variable in previous scope that was declared just before
+  /// begin of this scope.
+  const_iterator Prev;
+
+public:
+  /// Constructs empty scope linked to previous scope in specified place.
+  LocalScope(const_iterator P)
+      : Vars()
+      , Prev(P) {}
+
+  /// Begin of scope in direction of CFG building (backwards).
+  const_iterator begin() const { return const_iterator(*this, Vars.size()); }
+};
+
+/// BlockScopePosPair - Structure for specifing position in CFG during its build
+/// proces. It consists of CFGBlock that specifies position in CFG graph and
+/// LocalScope::const_iterator that specifies position in LocalScope graph.
+struct BlockScopePosPair {
+  BlockScopePosPair() {}
+  BlockScopePosPair(CFGBlock* B, LocalScope::const_iterator S)
+      : Block(B), ScopePos(S) {}
+
+  CFGBlock*                   Block;
+  LocalScope::const_iterator  ScopePos;
+};
+
 /// CFGBuilder - This class implements CFG construction from an AST.
 ///   The builder is stateful: an instance of the builder should be used to only
 ///   construct a single CFG.
@@ -67,24 +177,30 @@
 ///  implicit fall-throughs without extra basic blocks.
 ///
 class CFGBuilder {
+  typedef BlockScopePosPair JumpTarget;
+  typedef BlockScopePosPair JumpSource;
+
   ASTContext *Context;
   llvm::OwningPtr<CFG> cfg;
 
   CFGBlock* Block;
   CFGBlock* Succ;
-  CFGBlock* ContinueTargetBlock;
-  CFGBlock* BreakTargetBlock;
+  JumpTarget ContinueJumpTarget;
+  JumpTarget BreakJumpTarget;
   CFGBlock* SwitchTerminatedBlock;
   CFGBlock* DefaultCaseBlock;
   CFGBlock* TryTerminatedBlock;
 
-  // LabelMap records the mapping from Label expressions to their blocks.
-  typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy;
+  // Current position in local scope.
+  LocalScope::const_iterator ScopePos;
+
+  // LabelMap records the mapping from Label expressions to their jump targets.
+  typedef llvm::DenseMap<LabelStmt*, JumpTarget> LabelMapTy;
   LabelMapTy LabelMap;
 
   // A list of blocks that end with a "goto" that must be backpatched to their
   // resolved targets upon completion of CFG construction.
-  typedef std::vector<CFGBlock*> BackpatchBlocksTy;
+  typedef std::vector<JumpSource> BackpatchBlocksTy;
   BackpatchBlocksTy BackpatchBlocks;
 
   // A list of labels whose address has been taken (for indirect gotos).
@@ -97,7 +213,6 @@
 public:
   explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG
                           Block(NULL), Succ(NULL),
-                          ContinueTargetBlock(NULL), BreakTargetBlock(NULL),
                           SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
                           TryTerminatedBlock(NULL), badCFG(false) {}
 
@@ -259,7 +374,7 @@
   for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
                                    E = BackpatchBlocks.end(); I != E; ++I ) {
 
-    CFGBlock* B = *I;
+    CFGBlock* B = I->Block;
     GotoStmt* G = cast<GotoStmt>(B->getTerminator());
     LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
 
@@ -267,7 +382,8 @@
     // incomplete AST.  Handle this by not registering a successor.
     if (LI == LabelMap.end()) continue;
 
-    AddSuccessor(B, LI->second);
+    JumpTarget JT = LI->second;
+    AddSuccessor(B, JT.Block);
   }
 
   // Add successors to the Indirect Goto Dispatch block (if we have one).
@@ -282,7 +398,7 @@
       // at an incomplete AST.  Handle this by not registering a successor.
       if (LI == LabelMap.end()) continue;
       
-      AddSuccessor(B, LI->second);
+      AddSuccessor(B, LI->second.Block);
     }
 
   // Create an empty entry block that has no predecessors.
@@ -549,9 +665,9 @@
 
   // If there is no target for the break, then we are looking at an incomplete
   // AST.  This means that the CFG cannot be constructed.
-  if (BreakTargetBlock)
-    AddSuccessor(Block, BreakTargetBlock);
-  else
+  if (BreakJumpTarget.Block) {
+    AddSuccessor(Block, BreakJumpTarget.Block);
+  } else
     badCFG = true;
 
 
@@ -921,7 +1037,7 @@
     LabelBlock = createBlock(); // scopes that only contains NullStmts.
 
   assert(LabelMap.find(L) == LabelMap.end() && "label already in map");
-  LabelMap[ L ] = LabelBlock;
+  LabelMap[ L ] = JumpTarget(LabelBlock, ScopePos);
 
   // Labels partition blocks, so this is the end of the basic block we were
   // processing (L is the block's label).  Because this is label (and we have
@@ -952,9 +1068,11 @@
 
   if (I == LabelMap.end())
     // We will need to backpatch this block later.
-    BackpatchBlocks.push_back(Block);
-  else
-    AddSuccessor(Block, I->second);
+    BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
+  else {
+    JumpTarget JT = I->second;
+    AddSuccessor(Block, JT.Block);
+  }
 
   return Block;
 }
@@ -962,6 +1080,8 @@
 CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
   CFGBlock* LoopSuccessor = NULL;
 
+  LocalScope::const_iterator LoopBeginScopePos = ScopePos;
+
   // "for" is a control-flow statement.  Thus we stop processing the current
   // block.
   if (Block) {
@@ -973,8 +1093,8 @@
 
   // Save the current value for the break targets.
   // All breaks should go to the code following the loop.
-  SaveAndRestore<CFGBlock*> save_break(BreakTargetBlock);
-  BreakTargetBlock = LoopSuccessor;
+  SaveAndRestore<JumpTarget> save_break(BreakJumpTarget);
+  BreakJumpTarget = JumpTarget(LoopSuccessor, LoopBeginScopePos);
 
   // Because of short-circuit evaluation, the condition of the loop can span
   // multiple basic blocks.  Thus we need the "Entry" and "Exit" blocks that
@@ -1025,8 +1145,8 @@
     assert(F->getBody());
 
    // Save the current values for Block, Succ, and continue targets.
-   SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
-      save_continue(ContinueTargetBlock);
+   SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
+   SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget);
 
     // Create a new block to contain the (bottom) of the loop body.
     Block = NULL;
@@ -1050,18 +1170,18 @@
       Block = 0;
     }
 
-    ContinueTargetBlock = Succ;
+    ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
 
     // The starting block for the loop increment is the block that should
     // represent the 'loop target' for looping back to the start of the loop.
-    ContinueTargetBlock->setLoopTarget(F);
+    ContinueJumpTarget.Block->setLoopTarget(F);
 
     // Now populate the body block, and in the process create new blocks as we
     // walk the body of the loop.
     CFGBlock* BodyBlock = addStmt(F->getBody());
 
     if (!BodyBlock)
-      BodyBlock = ContinueTargetBlock; // can happen for "for (...;...;...) ;"
+      BodyBlock = ContinueJumpTarget.Block;//can happen for "for (...;...;...);"
     else if (badCFG)
       return 0;
 
@@ -1170,11 +1290,12 @@
   // Now create the true branch.
   {
     // Save the current values for Succ, continue and break targets.
-    SaveAndRestore<CFGBlock*> save_Succ(Succ),
-      save_continue(ContinueTargetBlock), save_break(BreakTargetBlock);
+    SaveAndRestore<CFGBlock*> save_Succ(Succ);
+    SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget),
+        save_break(BreakJumpTarget);
 
-    BreakTargetBlock = LoopSuccessor;
-    ContinueTargetBlock = EntryConditionBlock;
+    BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
+    ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
 
     CFGBlock* BodyBlock = addStmt(S->getBody());
 
@@ -1230,6 +1351,8 @@
 CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
   CFGBlock* LoopSuccessor = NULL;
 
+  LocalScope::const_iterator LoopBeginScopePos = ScopePos;
+
   // "while" is a control-flow statement.  Thus we stop processing the current
   // block.
   if (Block) {
@@ -1285,9 +1408,9 @@
     assert(W->getBody());
 
     // Save the current values for Block, Succ, and continue and break targets
-    SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
-                              save_continue(ContinueTargetBlock),
-                              save_break(BreakTargetBlock);
+    SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
+    SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget),
+        save_break(BreakJumpTarget);
 
     // Create an empty block to represent the transition block for looping back
     // to the head of the loop.
@@ -1295,10 +1418,10 @@
     assert(Succ == EntryConditionBlock);
     Succ = createBlock();
     Succ->setLoopTarget(W);
-    ContinueTargetBlock = Succ;
+    ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos);
 
     // All breaks should go to the code following the loop.
-    BreakTargetBlock = LoopSuccessor;
+    BreakJumpTarget = JumpTarget(LoopSuccessor, LoopBeginScopePos);
 
     // NULL out Block to force lazy instantiation of blocks for the body.
     Block = NULL;
@@ -1307,7 +1430,7 @@
     CFGBlock* BodyBlock = addStmt(W->getBody());
 
     if (!BodyBlock)
-      BodyBlock = ContinueTargetBlock; // can happen for "while(...) ;"
+      BodyBlock = ContinueJumpTarget.Block; // can happen for "while(...) ;"
     else if (Block) {
       if (badCFG)
         return 0;
@@ -1420,15 +1543,15 @@
     assert(D->getBody());
 
     // Save the current values for Block, Succ, and continue and break targets
-    SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
-      save_continue(ContinueTargetBlock),
-      save_break(BreakTargetBlock);
+    SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ);
+    SaveAndRestore<JumpTarget> save_continue(ContinueJumpTarget),
+        save_break(BreakJumpTarget);
 
     // All continues within this loop should go to the condition block
-    ContinueTargetBlock = EntryConditionBlock;
+    ContinueJumpTarget = JumpTarget(EntryConditionBlock, ScopePos);
 
     // All breaks should go to the code following the loop.
-    BreakTargetBlock = LoopSuccessor;
+    BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos);
 
     // NULL out Block to force lazy instantiation of blocks for the body.
     Block = NULL;
@@ -1486,9 +1609,9 @@
 
   // If there is no target for the continue, then we are looking at an
   // incomplete AST.  This means the CFG cannot be constructed.
-  if (ContinueTargetBlock)
-    AddSuccessor(Block, ContinueTargetBlock);
-  else
+  if (ContinueJumpTarget.Block) {
+    AddSuccessor(Block, ContinueJumpTarget.Block);
+  } else
     badCFG = true;
 
   return Block;
@@ -1535,8 +1658,8 @@
 
   // Save the current "switch" context.
   SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock),
-                            save_break(BreakTargetBlock),
                             save_default(DefaultCaseBlock);
+  SaveAndRestore<JumpTarget> save_break(BreakJumpTarget);
 
   // Set the "default" case to be the block after the switch statement.  If the
   // switch statement contains a "default:", this value will be overwritten with
@@ -1549,7 +1672,7 @@
   // Now process the switch body.  The code after the switch is the implicit
   // successor.
   Succ = SwitchSuccessor;
-  BreakTargetBlock = SwitchSuccessor;
+  BreakJumpTarget = JumpTarget(SwitchSuccessor, ScopePos);
 
   // When visiting the body, the case statements should automatically get linked
   // up to the switch.  We also don't keep a pointer to the body, since all





More information about the cfe-commits mailing list