[cfe-commits] r41258 - in /cfe/trunk: AST/CFG.cpp include/clang/AST/CFG.h

Ted Kremenek kremenek at apple.com
Tue Aug 21 16:26:27 PDT 2007


Author: kremenek
Date: Tue Aug 21 18:26:17 2007
New Revision: 41258

URL: http://llvm.org/viewvc/llvm-project?rev=41258&view=rev
Log:
Added CFG support for gotos and labels.

Modified CFG so that getEntry(), getExit(), front() and back() return
CFGBlock& instead of CFGBlock*.

Modified:
    cfe/trunk/AST/CFG.cpp
    cfe/trunk/include/clang/AST/CFG.h

Modified: cfe/trunk/AST/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/CFG.cpp?rev=41258&r1=41257&r2=41258&view=diff

==============================================================================
--- cfe/trunk/AST/CFG.cpp (original)
+++ cfe/trunk/AST/CFG.cpp Tue Aug 21 18:26:17 2007
@@ -15,6 +15,7 @@
 #include "clang/AST/CFG.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/StmtVisitor.h"
+#include "llvm/ADT/DenseMap.h"
 #include <iostream>
 #include <iomanip>
 #include <algorithm>
@@ -56,6 +57,12 @@
   CFGBlock* Succ;
   unsigned NumBlocks;
   
+  typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy;
+  LabelMapTy LabelMap;
+  
+  typedef std::list<CFGBlock*> BackpatchBlocksTy;
+  BackpatchBlocksTy BackpatchBlocks;
+  
 public:  
   explicit CFGBuilder() : cfg(NULL), Block(NULL), Exit(NULL), Succ(NULL), 
                           NumBlocks(0) {
@@ -73,7 +80,7 @@
   CFG* buildCFG(Stmt* Statement) {
     if (!Statement) return NULL;
   
-    assert (cfg && "CFGBuilder should only be used to construct one CFG");
+    assert (!Exit && "CFGBuilder should only be used to construct one CFG");
 
     // Create the exit block.
     Block = createBlock();
@@ -84,17 +91,28 @@
       // Reverse the statements in the last constructed block.  Statements
       // are inserted into the blocks in reverse order.
       B->reverseStmts();
+      
+      // Backpatch the gotos whose label -> block mappings we didn't know
+      // when we encountered them.
+      for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(), 
+           E = BackpatchBlocks.end(); I != E; ++I ) {
+       
+        CFGBlock* B = *I;
+        GotoStmt* G = cast<GotoStmt>(B->getTerminator());
+        LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
+
+        if (LI == LabelMap.end())
+          return NULL; // No matching label.  Bad CFG.
+        
+        B->addSuccessor(LI->second);                   
+      }        
+      
       // NULL out cfg so that repeated calls
       CFG* t = cfg;
       cfg = NULL;
       return t;
     }
-    else {
-      // Error occured while building CFG: Delete the partially constructed CFG.
-      delete cfg;
-      cfg = NULL;
-      return NULL;
-    }
+    else return NULL;
   }
   
   // createBlock - Used to lazily create blocks that are connected
@@ -218,7 +236,51 @@
     if (R->getRetValue()) Block->appendStmt(R->getRetValue());
     
     return Block;
-  }  
+  }
+  
+  CFGBlock* VisitLabelStmt(LabelStmt* L) {
+    // Get the block of the labeled statement.  Add it to our map.
+    CFGBlock* LabelBlock = Visit(L->getSubStmt());
+    
+
+    assert (LabelMap.find(L) == LabelMap.end() && "label already in map");
+    LabelMap[ L ] = LabelBlock;
+    
+    // Labels partition blocks, so this is the end of the basic block
+    // we were processing (the label is the first statement).    
+    assert (Block);
+    Block->appendStmt(L);
+    Block->reverseStmts();
+    
+    // We set Block to NULL to allow lazy creation of a new block
+    // (if necessary);
+    Block = NULL;
+    
+    // This block is now the implicit successor of other blocks.
+    Succ = LabelBlock;
+    
+    return LabelBlock;
+  }
+  
+  CFGBlock* VisitGotoStmt(GotoStmt* G) {
+    // Goto is a control-flow statement.  Thus we stop processing the
+    // current block and create a new one.
+    if (Block) Block->reverseStmts();
+    Block = createBlock(false);
+    Block->setTerminator(G);
+    
+    // If we already know the mapping to the label block add the
+    // successor now.
+    LabelMapTy::iterator I = LabelMap.find(G->getLabel());
+    
+    if (I == LabelMap.end())
+      // We will need to backpatch this block later.
+      BackpatchBlocks.push_back(Block);
+    else
+      Block->addSuccessor(I->second);
+
+    return Block;            
+  }
 };
 
 // BuildCFG - A helper function that builds CFGs from ASTS.
@@ -240,8 +302,8 @@
   // designate the Entry and Exit blocks.
   for (iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
     OS << "\n  [ B" << I->getBlockID();
-    if (&(*I) == getExit()) OS << " (EXIT) ]\n";
-    else if (&(*I) == getEntry()) OS << " (ENTRY) ]\n";
+    if (&(*I) == &getExit()) OS << " (EXIT) ]\n";
+    else if (&(*I) == &getEntry()) OS << " (ENTRY) ]\n";
     else OS << " ]\n";
     I->print(OS);
   }
@@ -259,8 +321,18 @@
   OS << "    ------------------------\n";
   unsigned j = 1;
   for (iterator I = Stmts.begin(), E = Stmts.end() ; I != E ; ++I, ++j ) {
-    OS << "    " << std::setw(3) << j << ": ";
-    (*I)->printPretty(OS);
+    // Print the statement # in the basic block.
+    OS << "    " << std::setw(3) << j << ": ";    
+
+    // Print the statement/expression.
+    Stmt* S = *I;
+    
+    if (LabelStmt* L = dyn_cast<LabelStmt>(S))
+      OS << L->getName() << ": (LABEL)\n";
+    else
+      (*I)->printPretty(OS);
+      
+    // Expressions need a newline.
     if (isa<Expr>(*I)) OS << '\n';
   }
   OS << "    ------------------------\n";
@@ -287,14 +359,9 @@
         break;
       }
       
-      case Stmt::ReturnStmtClass: {
-        ReturnStmt* R = cast<ReturnStmt>(ControlFlowStmt);
-        R->printPretty(std::cerr);
-        break;
-      }
-      
       default:
-        assert(false && "terminator print not fully implemented");
+        ControlFlowStmt->printPretty(std::cerr);
+        break;
     }
   }
   else OS << "<NULL>\n";

Modified: cfe/trunk/include/clang/AST/CFG.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CFG.h?rev=41258&r1=41257&r2=41258&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/CFG.h (original)
+++ cfe/trunk/include/clang/AST/CFG.h Tue Aug 21 18:26:17 2007
@@ -128,6 +128,8 @@
   
   void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); }
   void setTerminator(Stmt* Statement) { ControlFlowStmt = Statement; }
+  Stmt* getTerminator() { return ControlFlowStmt; }
+  
   void reverseStmts();
   
   void addSuccessor(CFGBlock* Block) {
@@ -160,7 +162,7 @@
   
   CFGBlock* createBlock(unsigned blockID) { 
     Blocks.push_front(CFGBlock(blockID));
-    return front();
+    return &front();
   }
   
   // Block iterators
@@ -169,8 +171,8 @@
   typedef std::reverse_iterator<iterator>                     reverse_iterator;
   typedef std::reverse_iterator<const_iterator>         const_reverse_iterator;
 
-  CFGBlock*                    front()             { return &Blocks.front();  }
-  CFGBlock*                    back()              { return &Blocks.back();   }
+  CFGBlock&                    front()             { return Blocks.front();  }
+  CFGBlock&                    back()              { return Blocks.back();   }
   
   iterator                     begin()             { return Blocks.begin();   }
   iterator                     end()               { return Blocks.end();     }
@@ -182,8 +184,8 @@
   const_reverse_iterator       rbegin()      const { return Blocks.rbegin();  }
   const_reverse_iterator       rend()        const { return Blocks.rend();    }
   
-  CFGBlock*                    getEntry()          { return front();          }
-  CFGBlock*                    getExit()           { return back();           }
+  CFGBlock&                    getEntry()          { return front();          }
+  CFGBlock&                    getExit()           { return back();           }
   
   // Utility
   





More information about the cfe-commits mailing list