[cfe-commits] r41337 - /cfe/trunk/AST/CFG.cpp
Ted Kremenek
kremenek at apple.com
Thu Aug 23 14:42:29 PDT 2007
Author: kremenek
Date: Thu Aug 23 16:42:29 2007
New Revision: 41337
URL: http://llvm.org/viewvc/llvm-project?rev=41337&view=rev
Log:
No functionality change. Moved visitor methods for CFGBuilder out-of-line
from the class declaration. This enables a nice view of what visitor methods
have been implemented.
Modified:
cfe/trunk/AST/CFG.cpp
Modified: cfe/trunk/AST/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/CFG.cpp?rev=41337&r1=41336&r2=41337&view=diff
==============================================================================
--- cfe/trunk/AST/CFG.cpp (original)
+++ cfe/trunk/AST/CFG.cpp Thu Aug 23 16:42:29 2007
@@ -74,538 +74,564 @@
}
~CFGBuilder() { delete cfg; }
+
+ // buildCFG - Used by external clients to construct the CFG.
+ CFG* buildCFG(Stmt* Statement);
+
+ // Visitors to walk an AST and construct the CFG. Called by
+ // buildCFG. Do not call directly!
+
+ CFGBlock* VisitStmt(Stmt* Statement);
+ CFGBlock* VisitNullStmt(NullStmt* Statement);
+ CFGBlock* VisitCompoundStmt(CompoundStmt* C);
+ CFGBlock* VisitIfStmt(IfStmt* I);
+ CFGBlock* VisitReturnStmt(ReturnStmt* R);
+ CFGBlock* VisitLabelStmt(LabelStmt* L);
+ CFGBlock* VisitGotoStmt(GotoStmt* G);
+ CFGBlock* VisitForStmt(ForStmt* F);
+ CFGBlock* VisitWhileStmt(WhileStmt* W);
+ CFGBlock* VisitDoStmt(DoStmt* D);
+ CFGBlock* VisitContinueStmt(ContinueStmt* C);
+ CFGBlock* VisitBreakStmt(BreakStmt* B);
+ CFGBlock* VisitSwitchStmt(SwitchStmt* S);
+ CFGBlock* VisitSwitchCase(SwitchCase* S);
+
+private:
+ CFGBlock* createBlock(bool add_successor = true);
+ void FinishBlock(CFGBlock* B);
+
+};
- /// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can
- /// represent an arbitrary statement. Examples include a single expression
- /// or a function body (compound statement). The ownership of the returned
- /// CFG is transferred to the caller. If CFG construction fails, this method
- /// returns NULL.
- CFG* buildCFG(Stmt* Statement) {
- if (!Statement) return NULL;
-
- // Create an empty block that will serve as the exit block for the CFG.
- // Since this is the first block added to the CFG, it will be implicitly
- // registered as the exit block.
- Block = createBlock();
- assert (Block == &cfg->getExit());
-
- // Visit the statements and create the CFG.
- if (CFGBlock* B = Visit(Statement)) {
- // Finalize the last constructed block. This usually involves
- // reversing the order of the statements in the block.
- FinishBlock(B);
- cfg->setEntry(B);
-
- // 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 there is no target for the goto, then we are looking at an
- // incomplete AST. Handle this by not registering a successor.
- if (LI == LabelMap.end()) continue;
-
- B->addSuccessor(LI->second);
- }
-
- // NULL out cfg so that repeated calls
- CFG* t = cfg;
- cfg = NULL;
- return t;
- }
- else return NULL;
+/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can
+/// represent an arbitrary statement. Examples include a single expression
+/// or a function body (compound statement). The ownership of the returned
+/// CFG is transferred to the caller. If CFG construction fails, this method
+/// returns NULL.
+CFG* CFGBuilder::buildCFG(Stmt* Statement) {
+ if (!Statement) return NULL;
+
+ // Create an empty block that will serve as the exit block for the CFG.
+ // Since this is the first block added to the CFG, it will be implicitly
+ // registered as the exit block.
+ Block = createBlock();
+ assert (Block == &cfg->getExit());
+
+ // Visit the statements and create the CFG.
+ if (CFGBlock* B = Visit(Statement)) {
+ // Finalize the last constructed block. This usually involves
+ // reversing the order of the statements in the block.
+ FinishBlock(B);
+ cfg->setEntry(B);
+
+ // 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 there is no target for the goto, then we are looking at an
+ // incomplete AST. Handle this by not registering a successor.
+ if (LI == LabelMap.end()) continue;
+
+ B->addSuccessor(LI->second);
+ }
+
+ // NULL out cfg so that repeated calls
+ CFG* t = cfg;
+ cfg = NULL;
+ return t;
}
+ else return NULL;
+}
- // createBlock - Used to lazily create blocks that are connected
- // to the current (global) succcessor.
- CFGBlock* createBlock( bool add_successor = true ) {
- CFGBlock* B = cfg->createBlock(NumBlocks++);
- if (add_successor && Succ) B->addSuccessor(Succ);
- return B;
- }
-
- // FinishBlock - When the last statement has been added to the block,
- // usually we must reverse the statements because they have been inserted
- // in reverse order. When processing labels, however, there are cases
- // in the recursion where we may have already reversed the statements
- // in a block. This method safely tidies up a block: if the block
- // has a label at the front, it has already been reversed. Otherwise,
- // we reverse it.
- void FinishBlock(CFGBlock* B) {
- assert (B);
- CFGBlock::iterator I = B->begin();
- if (I != B->end()) {
- Stmt* S = *I;
-
- if (isa<LabelStmt>(S) || isa<SwitchCase>(S))
- return;
-
- B->reverseStmts();
- }
- }
+/// createBlock - Used to lazily create blocks that are connected
+/// to the current (global) succcessor.
+CFGBlock* CFGBuilder::createBlock(bool add_successor) {
+ CFGBlock* B = cfg->createBlock(NumBlocks++);
+ if (add_successor && Succ) B->addSuccessor(Succ);
+ return B;
+}
+
+/// FinishBlock - When the last statement has been added to the block,
+/// usually we must reverse the statements because they have been inserted
+/// in reverse order. When processing labels, however, there are cases
+/// in the recursion where we may have already reversed the statements
+/// in a block. This method safely tidies up a block: if the block
+/// has a label at the front, it has already been reversed. Otherwise,
+/// we reverse it.
+void CFGBuilder::FinishBlock(CFGBlock* B) {
+ assert (B);
+ CFGBlock::iterator I = B->begin();
+ if (I != B->end()) {
+ Stmt* S = *I;
- /// Here we handle statements with no branching control flow.
- CFGBlock* VisitStmt(Stmt* Statement) {
- // We cannot assume that we are in the middle of a basic block, since
- // the CFG might only be constructed for this single statement. If
- // we have no current basic block, just create one lazily.
- if (!Block) Block = createBlock();
-
- // Simply add the statement to the current block. We actually
- // insert statements in reverse order; this order is reversed later
- // when processing the containing element in the AST.
- Block->appendStmt(Statement);
-
- return Block;
+ if (isa<LabelStmt>(S) || isa<SwitchCase>(S))
+ return;
+
+ B->reverseStmts();
}
+}
+
+/// VisitStmt - Handle statements with no branching control flow.
+CFGBlock* CFGBuilder::VisitStmt(Stmt* Statement) {
+ // We cannot assume that we are in the middle of a basic block, since
+ // the CFG might only be constructed for this single statement. If
+ // we have no current basic block, just create one lazily.
+ if (!Block) Block = createBlock();
+
+ // Simply add the statement to the current block. We actually
+ // insert statements in reverse order; this order is reversed later
+ // when processing the containing element in the AST.
+ Block->appendStmt(Statement);
- CFGBlock* VisitNullStmt(NullStmt* Statement) {
- return Block;
- }
+ return Block;
+}
+
+CFGBlock* CFGBuilder::VisitNullStmt(NullStmt* Statement) {
+ return Block;
+}
+
+CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
+ // The value returned from this function is the last created CFGBlock
+ // that represents the "entry" point for the translated AST node.
+ CFGBlock* LastBlock;
+
+ for (CompoundStmt::reverse_body_iterator I = C->body_rbegin(),
+ E = C->body_rend(); I != E; ++I )
+ // Add the statement to the current block.
+ if (!(LastBlock=Visit(*I)))
+ return NULL;
+
+ return LastBlock;
+}
+
+CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
+ // We may see an if statement in the middle of a basic block, or
+ // it may be the first statement we are processing. In either case,
+ // we create a new basic block. First, we create the blocks for
+ // the then...else statements, and then we create the block containing
+ // the if statement. If we were in the middle of a block, we
+ // stop processing that block and reverse its statements. That block
+ // is then the implicit successor for the "then" and "else" clauses.
+
+ // The block we were proccessing is now finished. Make it the
+ // successor block.
+ if (Block) {
+ Succ = Block;
+ FinishBlock(Block);
+ }
+
+ // Process the false branch. NULL out Block so that the recursive
+ // call to Visit will create a new basic block.
+ // Null out Block so that all successor
+ CFGBlock* ElseBlock = Succ;
- CFGBlock* VisitCompoundStmt(CompoundStmt* C) {
- // The value returned from this function is the last created CFGBlock
- // that represents the "entry" point for the translated AST node.
- CFGBlock* LastBlock;
-
- for (CompoundStmt::reverse_body_iterator I = C->body_rbegin(),
- E = C->body_rend(); I != E; ++I )
- // Add the statement to the current block.
- if (!(LastBlock=Visit(*I)))
- return NULL;
-
- return LastBlock;
- }
-
- CFGBlock* VisitIfStmt(IfStmt* I) {
-
- // We may see an if statement in the middle of a basic block, or
- // it may be the first statement we are processing. In either case,
- // we create a new basic block. First, we create the blocks for
- // the then...else statements, and then we create the block containing
- // the if statement. If we were in the middle of a block, we
- // stop processing that block and reverse its statements. That block
- // is then the implicit successor for the "then" and "else" clauses.
-
- // The block we were proccessing is now finished. Make it the
- // successor block.
- if (Block) {
- Succ = Block;
- FinishBlock(Block);
- }
-
- // Process the false branch. NULL out Block so that the recursive
- // call to Visit will create a new basic block.
- // Null out Block so that all successor
- CFGBlock* ElseBlock = Succ;
+ if (Stmt* Else = I->getElse()) {
+ SaveAndRestore<CFGBlock*> sv(Succ);
- if (Stmt* Else = I->getElse()) {
- SaveAndRestore<CFGBlock*> sv(Succ);
-
- // NULL out Block so that the recursive call to Visit will
- // create a new basic block.
- Block = NULL;
- ElseBlock = Visit(Else);
- if (!ElseBlock) return NULL;
- FinishBlock(ElseBlock);
- }
+ // NULL out Block so that the recursive call to Visit will
+ // create a new basic block.
+ Block = NULL;
+ ElseBlock = Visit(Else);
+ if (!ElseBlock) return NULL;
+ FinishBlock(ElseBlock);
+ }
+
+ // Process the true branch. NULL out Block so that the recursive
+ // call to Visit will create a new basic block.
+ // Null out Block so that all successor
+ CFGBlock* ThenBlock;
+ {
+ Stmt* Then = I->getThen();
+ assert (Then);
+ SaveAndRestore<CFGBlock*> sv(Succ);
+ Block = NULL;
+ ThenBlock = Visit(Then);
+ if (!ThenBlock) return NULL;
+ FinishBlock(ThenBlock);
+ }
+
+ // Now create a new block containing the if statement.
+ Block = createBlock(false);
+
+ // Add the condition as the last statement in the new block.
+ Block->appendStmt(I->getCond());
+
+ // Set the terminator of the new block to the If statement.
+ Block->setTerminator(I);
+
+ // Now add the successors.
+ Block->addSuccessor(ThenBlock);
+ Block->addSuccessor(ElseBlock);
+
+ return Block;
+}
- // Process the true branch. NULL out Block so that the recursive
- // call to Visit will create a new basic block.
- // Null out Block so that all successor
- CFGBlock* ThenBlock;
- {
- Stmt* Then = I->getThen();
- assert (Then);
- SaveAndRestore<CFGBlock*> sv(Succ);
- Block = NULL;
- ThenBlock = Visit(Then);
- if (!ThenBlock) return NULL;
- FinishBlock(ThenBlock);
- }
+CFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) {
+ // If we were in the middle of a block we stop processing that block
+ // and reverse its statements.
+ //
+ // NOTE: If a "return" appears in the middle of a block, this means
+ // that the code afterwards is DEAD (unreachable). We still
+ // keep a basic block for that code; a simple "mark-and-sweep"
+ // from the entry block will be able to report such dead
+ // blocks.
+ if (Block) FinishBlock(Block);
+
+ // Create the new block.
+ Block = createBlock(false);
+
+ // The Exit block is the only successor.
+ Block->addSuccessor(&cfg->getExit());
+
+ // Add the return statement to the block.
+ Block->appendStmt(R);
+
+ // Also add the return statement as the terminator.
+ Block->setTerminator(R);
+
+ return Block;
+}
- // Now create a new block containing the if statement.
- Block = createBlock(false);
+CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) {
+ // Get the block of the labeled statement. Add it to our map.
+ CFGBlock* LabelBlock = Visit(L->getSubStmt());
+ assert (LabelBlock);
+
+ 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).
+ LabelBlock->appendStmt(L);
+ FinishBlock(LabelBlock);
+
+ // We set Block to NULL to allow lazy creation of a new block
+ // (if necessary);
+ Block = NULL;
- // Add the condition as the last statement in the new block.
- Block->appendStmt(I->getCond());
-
- // Set the terminator of the new block to the If statement.
- Block->setTerminator(I);
-
- // Now add the successors.
- Block->addSuccessor(ThenBlock);
- Block->addSuccessor(ElseBlock);
+ // This block is now the implicit successor of other blocks.
+ Succ = LabelBlock;
+
+ return LabelBlock;
+}
- return Block;
+CFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) {
+ // Goto is a control-flow statement. Thus we stop processing the
+ // current block and create a new one.
+ if (Block) FinishBlock(Block);
+ 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;
+}
+
+CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
+ // "for" is a control-flow statement. Thus we stop processing the
+ // current block.
+
+ CFGBlock* LoopSuccessor = NULL;
+
+ if (Block) {
+ FinishBlock(Block);
+ LoopSuccessor = Block;
}
-
- CFGBlock* VisitReturnStmt(ReturnStmt* R) {
- // If we were in the middle of a block we stop processing that block
- // and reverse its statements.
- //
- // NOTE: If a "return" appears in the middle of a block, this means
- // that the code afterwards is DEAD (unreachable). We still
- // keep a basic block for that code; a simple "mark-and-sweep"
- // from the entry block will be able to report such dead
- // blocks.
- if (Block) FinishBlock(Block);
-
- // Create the new block.
- Block = createBlock(false);
+ else LoopSuccessor = Succ;
+
+ // Create the condition block.
+ CFGBlock* ConditionBlock = createBlock(false);
+ ConditionBlock->setTerminator(F);
+ if (Stmt* C = F->getCond()) ConditionBlock->appendStmt(C);
+
+ // The condition block is the implicit successor for the loop body as
+ // well as any code above the loop.
+ Succ = ConditionBlock;
+
+ // Now create the loop body.
+ {
+ assert (F->getBody());
- // The Exit block is the only successor.
- Block->addSuccessor(&cfg->getExit());
+ // 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);
+
+ // All continues within this loop should go to the condition block
+ ContinueTargetBlock = ConditionBlock;
- // Add the return statement to the block.
- Block->appendStmt(R);
+ // All breaks should go to the code following the loop.
+ BreakTargetBlock = LoopSuccessor;
+
+ // Create a new block to contain the (bottom) of the loop body.
+ Block = createBlock();
- // Also add the return statement as the terminator.
- Block->setTerminator(R);
+ // If we have increment code, insert it at the end of the body block.
+ if (Stmt* I = F->getInc()) Block->appendStmt(I);
+ // Now populate the body block, and in the process create new blocks
+ // as we walk the body of the loop.
+ CFGBlock* BodyBlock = Visit(F->getBody());
+ assert (BodyBlock);
+ FinishBlock(BodyBlock);
+
+ // This new body block is a successor to our condition block.
+ ConditionBlock->addSuccessor(BodyBlock);
+ }
+
+ // Link up the condition block with the code that follows the loop.
+ // (the false branch).
+ ConditionBlock->addSuccessor(LoopSuccessor);
+
+ // If the loop contains initialization, create a new block for those
+ // statements. This block can also contain statements that precede
+ // the loop.
+ if (Stmt* I = F->getInit()) {
+ Block = createBlock();
+ Block->appendStmt(I);
return Block;
}
-
- CFGBlock* VisitLabelStmt(LabelStmt* L) {
- // Get the block of the labeled statement. Add it to our map.
- CFGBlock* LabelBlock = Visit(L->getSubStmt());
- assert (LabelBlock);
-
- 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).
- LabelBlock->appendStmt(L);
- FinishBlock(LabelBlock);
-
- // We set Block to NULL to allow lazy creation of a new block
- // (if necessary);
+ else {
+ // There is no loop initialization. We are thus basically a while
+ // loop. NULL out Block to force lazy block construction.
Block = NULL;
-
- // This block is now the implicit successor of other blocks.
- Succ = LabelBlock;
-
- return LabelBlock;
+ return ConditionBlock;
}
-
- CFGBlock* VisitGotoStmt(GotoStmt* G) {
- // Goto is a control-flow statement. Thus we stop processing the
- // current block and create a new one.
- if (Block) FinishBlock(Block);
- 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;
- }
-
- CFGBlock* VisitForStmt(ForStmt* F) {
- // "for" is a control-flow statement. Thus we stop processing the
- // current block.
+CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
+ // "while" is a control-flow statement. Thus we stop processing the
+ // current block.
+
+ CFGBlock* LoopSuccessor = NULL;
+
+ if (Block) {
+ FinishBlock(Block);
+ LoopSuccessor = Block;
+ }
+ else LoopSuccessor = Succ;
+
+ // Create the condition block.
+ CFGBlock* ConditionBlock = createBlock(false);
+ ConditionBlock->setTerminator(W);
+ if (Stmt* C = W->getCond()) ConditionBlock->appendStmt(C);
+
+ // The condition block is the implicit successor for the loop body as
+ // well as any code above the loop.
+ Succ = ConditionBlock;
+
+ // Process the loop body.
+ {
+ 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);
+
+ // All continues within this loop should go to the condition block
+ ContinueTargetBlock = ConditionBlock;
- CFGBlock* LoopSuccessor = NULL;
+ // All breaks should go to the code following the loop.
+ BreakTargetBlock = LoopSuccessor;
- if (Block) {
- FinishBlock(Block);
- LoopSuccessor = Block;
- }
- else LoopSuccessor = Succ;
+ // NULL out Block to force lazy instantiation of blocks for the body.
+ Block = NULL;
- // Create the condition block.
- CFGBlock* ConditionBlock = createBlock(false);
- ConditionBlock->setTerminator(F);
- if (Stmt* C = F->getCond()) ConditionBlock->appendStmt(C);
-
- // The condition block is the implicit successor for the loop body as
- // well as any code above the loop.
- Succ = ConditionBlock;
-
- // Now create the loop body.
- {
- assert (F->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);
+ // Create the body. The returned block is the entry to the loop body.
+ CFGBlock* BodyBlock = Visit(W->getBody());
+ assert (BodyBlock);
+ FinishBlock(BodyBlock);
+
+ // Add the loop body entry as a successor to the condition.
+ ConditionBlock->addSuccessor(BodyBlock);
+ }
+
+ // Link up the condition block with the code that follows the loop.
+ // (the false branch).
+ ConditionBlock->addSuccessor(LoopSuccessor);
+
+ // There can be no more statements in the condition block
+ // since we loop back to this block. NULL out Block to force
+ // lazy creation of another block.
+ Block = NULL;
+
+ // Return the condition block, which is the dominating block for the loop.
+ return ConditionBlock;
+}
- // All continues within this loop should go to the condition block
- ContinueTargetBlock = ConditionBlock;
-
- // All breaks should go to the code following the loop.
- BreakTargetBlock = LoopSuccessor;
-
- // Create a new block to contain the (bottom) of the loop body.
- Block = createBlock();
-
- // If we have increment code, insert it at the end of the body block.
- if (Stmt* I = F->getInc()) Block->appendStmt(I);
-
- // Now populate the body block, and in the process create new blocks
- // as we walk the body of the loop.
- CFGBlock* BodyBlock = Visit(F->getBody());
- assert (BodyBlock);
- FinishBlock(BodyBlock);
-
- // This new body block is a successor to our condition block.
- ConditionBlock->addSuccessor(BodyBlock);
- }
-
- // Link up the condition block with the code that follows the loop.
- // (the false branch).
- ConditionBlock->addSuccessor(LoopSuccessor);
-
- // If the loop contains initialization, create a new block for those
- // statements. This block can also contain statements that precede
- // the loop.
- if (Stmt* I = F->getInit()) {
- Block = createBlock();
- Block->appendStmt(I);
- return Block;
- }
- else {
- // There is no loop initialization. We are thus basically a while
- // loop. NULL out Block to force lazy block construction.
- Block = NULL;
- return ConditionBlock;
- }
- }
+CFGBlock* CFGBuilder::VisitDoStmt(DoStmt* D) {
+ // "do...while" is a control-flow statement. Thus we stop processing the
+ // current block.
- CFGBlock* VisitWhileStmt(WhileStmt* W) {
- // "while" is a control-flow statement. Thus we stop processing the
- // current block.
-
- CFGBlock* LoopSuccessor = NULL;
-
- if (Block) {
- FinishBlock(Block);
- LoopSuccessor = Block;
- }
- else LoopSuccessor = Succ;
-
- // Create the condition block.
- CFGBlock* ConditionBlock = createBlock(false);
- ConditionBlock->setTerminator(W);
- if (Stmt* C = W->getCond()) ConditionBlock->appendStmt(C);
-
- // The condition block is the implicit successor for the loop body as
- // well as any code above the loop.
- Succ = ConditionBlock;
-
- // Process the loop body.
- {
- 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);
-
- // All continues within this loop should go to the condition block
- ContinueTargetBlock = ConditionBlock;
-
- // All breaks should go to the code following the loop.
- BreakTargetBlock = LoopSuccessor;
-
- // NULL out Block to force lazy instantiation of blocks for the body.
- Block = NULL;
-
- // Create the body. The returned block is the entry to the loop body.
- CFGBlock* BodyBlock = Visit(W->getBody());
- assert (BodyBlock);
- FinishBlock(BodyBlock);
-
- // Add the loop body entry as a successor to the condition.
- ConditionBlock->addSuccessor(BodyBlock);
- }
-
- // Link up the condition block with the code that follows the loop.
- // (the false branch).
- ConditionBlock->addSuccessor(LoopSuccessor);
-
- // There can be no more statements in the condition block
- // since we loop back to this block. NULL out Block to force
- // lazy creation of another block.
- Block = NULL;
-
- // Return the condition block, which is the dominating block for the loop.
- return ConditionBlock;
+ CFGBlock* LoopSuccessor = NULL;
+
+ if (Block) {
+ FinishBlock(Block);
+ LoopSuccessor = Block;
}
+ else LoopSuccessor = Succ;
+
+ // Create the condition block.
+ CFGBlock* ConditionBlock = createBlock(false);
+ ConditionBlock->setTerminator(D);
+ if (Stmt* C = D->getCond()) ConditionBlock->appendStmt(C);
+
+ // The condition block is the implicit successor for the loop body.
+ Succ = ConditionBlock;
- CFGBlock* VisitDoStmt(DoStmt* D) {
- // "do...while" is a control-flow statement. Thus we stop processing the
- // current block.
+ CFGBlock* BodyBlock = NULL;
+ // Process the loop body.
+ {
+ assert (D->getBody());
- CFGBlock* LoopSuccessor = NULL;
+ // 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);
- if (Block) {
- FinishBlock(Block);
- LoopSuccessor = Block;
- }
- else LoopSuccessor = Succ;
+ // All continues within this loop should go to the condition block
+ ContinueTargetBlock = ConditionBlock;
- // Create the condition block.
- CFGBlock* ConditionBlock = createBlock(false);
- ConditionBlock->setTerminator(D);
- if (Stmt* C = D->getCond()) ConditionBlock->appendStmt(C);
-
- // The condition block is the implicit successor for the loop body.
- Succ = ConditionBlock;
-
- CFGBlock* BodyBlock = NULL;
- // Process the loop body.
- {
- 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);
-
- // All continues within this loop should go to the condition block
- ContinueTargetBlock = ConditionBlock;
-
- // All breaks should go to the code following the loop.
- BreakTargetBlock = LoopSuccessor;
-
- // NULL out Block to force lazy instantiation of blocks for the body.
- Block = NULL;
-
- // Create the body. The returned block is the entry to the loop body.
- BodyBlock = Visit(D->getBody());
- assert (BodyBlock);
- FinishBlock(BodyBlock);
-
- // Add the loop body entry as a successor to the condition.
- ConditionBlock->addSuccessor(BodyBlock);
- }
+ // All breaks should go to the code following the loop.
+ BreakTargetBlock = LoopSuccessor;
- // Link up the condition block with the code that follows the loop.
- // (the false branch).
- ConditionBlock->addSuccessor(LoopSuccessor);
-
- // There can be no more statements in the condition block
- // since we loop back to this block. NULL out Block to force
- // lazy creation of another block.
+ // NULL out Block to force lazy instantiation of blocks for the body.
Block = NULL;
- // Return the loop body, which is the dominating block for the loop.
- return BodyBlock;
- }
+ // Create the body. The returned block is the entry to the loop body.
+ BodyBlock = Visit(D->getBody());
+ assert (BodyBlock);
+ FinishBlock(BodyBlock);
+
+ // Add the loop body entry as a successor to the condition.
+ ConditionBlock->addSuccessor(BodyBlock);
+ }
+
+ // Link up the condition block with the code that follows the loop.
+ // (the false branch).
+ ConditionBlock->addSuccessor(LoopSuccessor);
+
+ // There can be no more statements in the condition block
+ // since we loop back to this block. NULL out Block to force
+ // lazy creation of another block.
+ Block = NULL;
- CFGBlock* VisitContinueStmt(ContinueStmt* C) {
- // "continue" is a control-flow statement. Thus we stop processing the
- // current block.
- if (Block) FinishBlock(Block);
-
- // Now create a new block that ends with the continue statement.
- Block = createBlock(false);
- Block->setTerminator(C);
-
- // If there is no target for the continue, then we are looking at an
- // incomplete AST. Handle this by not registering a successor.
- if (ContinueTargetBlock) Block->addSuccessor(ContinueTargetBlock);
-
- return Block;
+ // Return the loop body, which is the dominating block for the loop.
+ return BodyBlock;
+}
+
+CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) {
+ // "continue" is a control-flow statement. Thus we stop processing the
+ // current block.
+ if (Block) FinishBlock(Block);
+
+ // Now create a new block that ends with the continue statement.
+ Block = createBlock(false);
+ Block->setTerminator(C);
+
+ // If there is no target for the continue, then we are looking at an
+ // incomplete AST. Handle this by not registering a successor.
+ if (ContinueTargetBlock) Block->addSuccessor(ContinueTargetBlock);
+
+ return Block;
+}
+
+CFGBlock* CFGBuilder::VisitBreakStmt(BreakStmt* B) {
+ // "break" is a control-flow statement. Thus we stop processing the
+ // current block.
+ if (Block) FinishBlock(Block);
+
+ // Now create a new block that ends with the continue statement.
+ Block = createBlock(false);
+ Block->setTerminator(B);
+
+ // If there is no target for the break, then we are looking at an
+ // incomplete AST. Handle this by not registering a successor.
+ if (BreakTargetBlock) Block->addSuccessor(BreakTargetBlock);
+
+ return Block;
+}
+
+CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* S) {
+ // "switch" is a control-flow statement. Thus we stop processing the
+ // current block.
+ CFGBlock* SwitchSuccessor = NULL;
+
+ if (Block) {
+ FinishBlock(Block);
+ SwitchSuccessor = Block;
}
+ else SwitchSuccessor = Succ;
+
+ // Save the current "switch" context.
+ SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock),
+ save_break(BreakTargetBlock);
- CFGBlock* VisitBreakStmt(BreakStmt* B) {
- // "break" is a control-flow statement. Thus we stop processing the
- // current block.
- if (Block) FinishBlock(Block);
-
- // Now create a new block that ends with the continue statement.
- Block = createBlock(false);
- Block->setTerminator(B);
-
- // If there is no target for the break, then we are looking at an
- // incomplete AST. Handle this by not registering a successor.
- if (BreakTargetBlock) Block->addSuccessor(BreakTargetBlock);
-
- return Block;
- }
-
- CFGBlock* VisitSwitchStmt(SwitchStmt* S) {
- // "switch" is a control-flow statement. Thus we stop processing the
- // current block.
- CFGBlock* SwitchSuccessor = NULL;
-
- if (Block) {
- FinishBlock(Block);
- SwitchSuccessor = Block;
- }
- else SwitchSuccessor = Succ;
+ // Create a new block that will contain the switch statement.
+ SwitchTerminatedBlock = createBlock(false);
- // Save the current "switch" context.
- SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock),
- save_break(BreakTargetBlock);
-
- // Create a new block that will contain the switch statement.
- SwitchTerminatedBlock = createBlock(false);
-
- // Add the terminator and condition in the switch block.
- assert (S->getCond() && "switch condition must be non-NULL");
- SwitchTerminatedBlock->appendStmt(S->getCond());
- SwitchTerminatedBlock->setTerminator(S);
-
-
- // Now process the switch body. The code after the switch is the implicit
- // successor.
- Succ = SwitchSuccessor;
- BreakTargetBlock = SwitchSuccessor;
+ // Add the terminator and condition in the switch block.
+ assert (S->getCond() && "switch condition must be non-NULL");
+ SwitchTerminatedBlock->appendStmt(S->getCond());
+ SwitchTerminatedBlock->setTerminator(S);
+
+
+ // Now process the switch body. The code after the switch is the implicit
+ // successor.
+ Succ = SwitchSuccessor;
+ BreakTargetBlock = SwitchSuccessor;
+
+ assert (S->getBody() && "switch must contain a non-NULL body");
+ Block = NULL;
+
+ // 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 control-flow from the switch goes to case/default statements.
+ Visit(S->getBody());
+
+ Block = SwitchTerminatedBlock;
+ return SwitchTerminatedBlock;
+}
+
+CFGBlock* CFGBuilder::VisitSwitchCase(SwitchCase* S) {
+ // A SwitchCase is either a "default" or "case" statement. We handle
+ // both in the same way. They are essentially labels, so they are the
+ // first statement in a block.
+ CFGBlock* CaseBlock = Visit(S->getSubStmt());
+ assert (CaseBlock);
+
+ // Cases/Default statements parition block, so this is the top of
+ // the basic block we were processing (the case/default is the first stmt).
+ CaseBlock->appendStmt(S);
+ FinishBlock(CaseBlock);
+
+ // Add this block to the list of successors for the block with the
+ // switch statement.
+ if (SwitchTerminatedBlock) SwitchTerminatedBlock->addSuccessor(CaseBlock);
+
+ // 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 = CaseBlock;
+
+ return CaseBlock;
+}
- assert (S->getBody() && "switch must contain a non-NULL body");
- Block = NULL;
-
- // 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 control-flow from the switch goes to case/default statements.
- Visit(S->getBody());
-
- Block = SwitchTerminatedBlock;
- return SwitchTerminatedBlock;
- }
-
- CFGBlock* VisitSwitchCase(SwitchCase* S) {
- // A SwitchCase is either a "default" or "case" statement. We handle
- // both in the same way. They are essentially labels, so they are the
- // first statement in a block.
- CFGBlock* CaseBlock = Visit(S->getSubStmt());
- assert (CaseBlock);
-
- // Cases/Default statements parition block, so this is the top of
- // the basic block we were processing (the case/default is the first stmt).
- CaseBlock->appendStmt(S);
- FinishBlock(CaseBlock);
-
- // Add this block to the list of successors for the block with the
- // switch statement.
- if (SwitchTerminatedBlock) SwitchTerminatedBlock->addSuccessor(CaseBlock);
-
- // 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 = CaseBlock;
-
- return CaseBlock;
- }
-};
} // end anonymous namespace
/// createBlock - Constructs and adds a new CFGBlock to the CFG. The
@@ -640,7 +666,6 @@
/// print - A simple pretty printer of a CFG that outputs to an ostream.
void CFG::print(std::ostream& OS) {
-
// Print the Entry block.
if (begin() != end()) {
CFGBlock& Entry = getEntry();
@@ -656,58 +681,58 @@
OS << "\n [ B" << I->getBlockID() << " ]\n";
I->print(OS);
}
-
+
// Print the Exit Block.
if (begin() != end()) {
CFGBlock& Exit = getExit();
OS << "\n [ B" << Exit.getBlockID() << " (EXIT) ]\n";
Exit.print(OS);
}
-
+
OS << "\n";
}
namespace {
- class CFGBlockTerminatorPrint : public StmtVisitor<CFGBlockTerminatorPrint,
- void > {
- std::ostream& OS;
- public:
- CFGBlockTerminatorPrint(std::ostream& os) : OS(os) {}
-
- void VisitIfStmt(IfStmt* I) {
- OS << "if ";
- I->getCond()->printPretty(std::cerr);
- OS << "\n";
- }
-
- // Default case.
- void VisitStmt(Stmt* S) { S->printPretty(OS); }
-
- void VisitForStmt(ForStmt* F) {
- OS << "for (" ;
- if (Stmt* I = F->getInit()) I->printPretty(OS);
- OS << " ; ";
- if (Stmt* C = F->getCond()) C->printPretty(OS);
- OS << " ; ";
- if (Stmt* I = F->getInc()) I->printPretty(OS);
- OS << ")\n";
- }
-
- void VisitWhileStmt(WhileStmt* W) {
- OS << "while " ;
- if (Stmt* C = W->getCond()) C->printPretty(OS);
- OS << "\n";
- }
-
- void VisitDoStmt(DoStmt* D) {
- OS << "do ... while ";
- if (Stmt* C = D->getCond()) C->printPretty(OS);
- OS << "\n";
- }
- };
-}
+class CFGBlockTerminatorPrint : public StmtVisitor<CFGBlockTerminatorPrint,
+ void > {
+ std::ostream& OS;
+public:
+ CFGBlockTerminatorPrint(std::ostream& os) : OS(os) {}
+
+ void VisitIfStmt(IfStmt* I) {
+ OS << "if ";
+ I->getCond()->printPretty(std::cerr);
+ OS << "\n";
+ }
+
+ // Default case.
+ void VisitStmt(Stmt* S) { S->printPretty(OS); }
+
+ void VisitForStmt(ForStmt* F) {
+ OS << "for (" ;
+ if (Stmt* I = F->getInit()) I->printPretty(OS);
+ OS << " ; ";
+ if (Stmt* C = F->getCond()) C->printPretty(OS);
+ OS << " ; ";
+ if (Stmt* I = F->getInc()) I->printPretty(OS);
+ OS << ")\n";
+ }
+
+ void VisitWhileStmt(WhileStmt* W) {
+ OS << "while " ;
+ if (Stmt* C = W->getCond()) C->printPretty(OS);
+ OS << "\n";
+ }
+
+ void VisitDoStmt(DoStmt* D) {
+ OS << "do ... while ";
+ if (Stmt* C = D->getCond()) C->printPretty(OS);
+ OS << "\n";
+ }
+};
+} // end anonymous namespace
/// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
void CFGBlock::dump() { print(std::cerr); }
More information about the cfe-commits
mailing list