Added preliminary support for while loops within source-level CFGs.
Adjusted printing of source-level CFGs to account that the entry block
may not be the first block in the list of blocks a CFG object maintains.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41294 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/CFG.cpp b/AST/CFG.cpp
index 27bf16a..8235137 100644
--- a/AST/CFG.cpp
+++ b/AST/CFG.cpp
@@ -72,12 +72,12 @@
~CFGBuilder() { delete cfg; }
- /// buildCFG - Constructs a CFG from an AST (a Stmt*). The AST can
+ /// 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) {
+ CFG* BuildCFG(Stmt* Statement) {
if (!Statement) return NULL;
assert (!Exit && "CFGBuilder should only be used to construct one CFG");
@@ -91,6 +91,7 @@
// 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.
@@ -105,7 +106,7 @@
return NULL; // No matching label. Bad CFG.
B->addSuccessor(LI->second);
- }
+ }
// NULL out cfg so that repeated calls
CFG* t = cfg;
@@ -357,12 +358,47 @@
if (Stmt* I = F->getInit()) Block->appendStmt(I);
return Block;
}
+
+ CFGBlock* VisitWhileStmt(WhileStmt* W) {
+ // While is a control-flow statement. Thus we stop processing the
+ // current block.
+ if (Block) FinishBlock(Block);
+
+ CFGBlock* ConditionBlock = createBlock(false);
+ ConditionBlock->setTerminator(W);
+ if (Stmt* C = W->getCond()) ConditionBlock->appendStmt(C);
+
+ // Process the loop body.
+ {
+ assert (W->getBody());
+ SaveAndRestore<CFGBlock*> sv(Block);
+
+ Succ = ConditionBlock;
+ Block = NULL;
+ CFGBlock* BodyBlock = Visit(W->getBody());
+
+ assert (BodyBlock);
+
+ ConditionBlock->addSuccessor(BodyBlock);
+ }
+
+ ConditionBlock->addSuccessor(Block);
+
+ // 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;
+ Succ = ConditionBlock;
+
+ return ConditionBlock;
+ }
+
};
// BuildCFG - A helper function that builds CFGs from ASTS.
CFG* CFG::BuildCFG(Stmt* Statement) {
CFGBuilder Builder;
- return Builder.buildCFG(Statement);
+ return Builder.BuildCFG(Statement);
}
// reverseStmts - A method that reverses the order of the statements within
@@ -374,13 +410,26 @@
// print - A simple pretty printer of a CFG that outputs to an ostream.
void CFG::print(std::ostream& OS) {
+ // First print out the Entry block, which may not be the first block
+ // in our list of blocks
+ if (begin() != end()) {
+ CFGBlock& Entry = getEntry();
+ OS << "\n [ B" << Entry.getBlockID() << " (ENTRY) ]\n";
+ Entry.print(OS);
+ }
+
// Iterate through the CFGBlocks and print them one by one. Specially
// designate the Entry and Exit blocks.
for (iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
+ // Skip the entry block, because we already printed it.
+ if (&(*I) == &getEntry())
+ continue;
+
OS << "\n [ B" << I->getBlockID();
+
if (&(*I) == &getExit()) OS << " (EXIT) ]\n";
- else if (&(*I) == &getEntry()) OS << " (ENTRY) ]\n";
else OS << " ]\n";
+
I->print(OS);
}
OS << "\n";
@@ -412,7 +461,13 @@
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";
+ }
};
}