[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