Added an (optional) explicit "Label" statement to CFGBlock. If a

block begins with a label or case statement, CFGBlock::getLabel() will
return the corresponding LabelStmt/CaseStmt/DefaultStmt.

LabelStmts and SwitchCases no longer appear within the "executable"
statements of a CFGBlock.

More cleanups on visualization/pretty-printing of CFGs (less verbose).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41585 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ted Kremenek 2007-08-29 23:20:49 +00:00
Родитель 34870da70f
Коммит 9cffe7366e
2 изменённых файлов: 80 добавлений и 52 удалений

Просмотреть файл

@ -462,11 +462,10 @@ CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) {
LabelMap[ L ] = LabelBlock; LabelMap[ L ] = LabelBlock;
// Labels partition blocks, so this is the end of the basic block // Labels partition blocks, so this is the end of the basic block
// we were processing (the label is the first statement). Add the label // we were processing (L is the block's label). Because this is
// the to end (really the beginning) of the block. Because this is
// label (and we have already processed the substatement) there is no // label (and we have already processed the substatement) there is no
// extra control-flow to worry about. // extra control-flow to worry about.
LabelBlock->appendStmt(L); LabelBlock->setLabel(L);
FinishBlock(LabelBlock); FinishBlock(LabelBlock);
// We set Block to NULL to allow lazy creation of a new block // We set Block to NULL to allow lazy creation of a new block
@ -808,9 +807,9 @@ CFGBlock* CFGBuilder::VisitSwitchCase(SwitchCase* S) {
CFGBlock* CaseBlock = Visit(S->getSubStmt()); CFGBlock* CaseBlock = Visit(S->getSubStmt());
assert (CaseBlock); assert (CaseBlock);
// Cases/Default statements parition block, so this is the top of // Cases/Default statements partition block, so this is the top of
// the basic block we were processing (the case/default is the first stmt). // the basic block we were processing (the case/default is the label).
CaseBlock->appendStmt(S); CaseBlock->setLabel(S);
FinishBlock(CaseBlock); FinishBlock(CaseBlock);
// Add this block to the list of successors for the block with the // Add this block to the list of successors for the block with the
@ -898,8 +897,6 @@ void CFG::print(std::ostream& OS) const {
// Print the exit block. // Print the exit block.
getExit().print(OS,this); getExit().print(OS,this);
OS << "\n";
} }
namespace { namespace {
@ -959,7 +956,7 @@ void CFGBlock::dump(const CFG* cfg) const { print(std::cerr,cfg); }
/// print - A simple pretty printer of a CFGBlock that outputs to an ostream. /// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
/// Generally this will only be called from CFG::print. /// Generally this will only be called from CFG::print.
void CFGBlock::print(std::ostream& OS, const CFG* cfg) const { void CFGBlock::print(std::ostream& OS, const CFG* cfg, bool print_edges) const {
// Print the header. // Print the header.
OS << "\n [ B" << getBlockID(); OS << "\n [ B" << getBlockID();
@ -970,53 +967,69 @@ void CFGBlock::print(std::ostream& OS, const CFG* cfg) const {
} }
else OS << " ]\n"; else OS << " ]\n";
// Print the label of this block.
if (Stmt* S = const_cast<Stmt*>(getLabel())) {
if (print_edges) OS << " ";
if (LabelStmt* L = dyn_cast<LabelStmt>(S))
OS << L->getName();
else if (CaseStmt* C = dyn_cast<CaseStmt>(S)) {
OS << "case ";
C->getLHS()->printPretty(OS);
if (C->getRHS()) {
OS << " ... ";
C->getRHS()->printPretty(OS);
}
}
else if (DefaultStmt* D = dyn_cast<DefaultStmt>(D)) {
OS << "default";
}
else assert(false && "Invalid label statement in CFGBlock.");
OS << ":\n";
}
// Iterate through the statements in the block and print them. // Iterate through the statements in the block and print them.
OS << " ------------------------\n";
unsigned j = 1; unsigned j = 1;
for (const_iterator I = Stmts.begin(), E = Stmts.end() ; I != E ; ++I, ++j ) { for (const_iterator I = Stmts.begin(), E = Stmts.end() ; I != E ; ++I, ++j ) {
// Print the statement # in the basic block. // Print the statement # in the basic block and the statement itself.
OS << " " << std::setw(3) << j << ": "; if (print_edges) OS << " ";
OS << std::setw(3) << j << ": ";
// Print the statement/expression. (*I)->printPretty(OS);
Stmt* S = *I;
if (LabelStmt* L = dyn_cast<LabelStmt>(S))
OS << L->getName() << ": (LABEL)\n";
else
(*I)->printPretty(OS);
// Expressions need a newline. // Expressions need a newline.
if (isa<Expr>(*I)) OS << '\n'; if (isa<Expr>(*I)) OS << '\n';
} }
OS << " ------------------------\n";
// Print the predecessors of this block. // Print the terminator of this block.
OS << " Predecessors (" << pred_size() << "):"; if (getTerminator()) {
unsigned i = 0; if (print_edges) OS << " ";
for (const_pred_iterator I = pred_begin(), E = pred_end(); I != E; ++I, ++i) { OS << " T: ";
if (i == 8 || (i-8) == 0) { CFGBlockTerminatorPrint(OS).Visit(const_cast<Stmt*>(getTerminator()));
OS << "\n ";
}
OS << " B" << (*I)->getBlockID();
} }
// Print the terminator of this block. if (print_edges) {
OS << "\n Terminator: "; // Print the predecessors of this block.
if (ControlFlowStmt) OS << " Predecessors (" << pred_size() << "):";
CFGBlockTerminatorPrint(OS).Visit(ControlFlowStmt); unsigned i = 0;
else for (const_pred_iterator I = pred_begin(), E = pred_end(); I != E; ++I, ++i) {
OS << "<NULL>\n"; if (i == 8 || (i-8) == 0) {
OS << "\n ";
// Print the successors of this block. }
OS << " Successors (" << succ_size() << "):"; OS << " B" << (*I)->getBlockID();
i = 0;
for (const_succ_iterator I = succ_begin(), E = succ_end(); I != E; ++I, ++i) {
if (i == 8 || (i-8) % 10 == 0) {
OS << "\n ";
} }
OS << " B" << (*I)->getBlockID(); OS << '\n';
// Print the successors of this block.
OS << " Successors (" << succ_size() << "):";
i = 0;
for (const_succ_iterator I = succ_begin(), E = succ_end(); I != E; ++I, ++i) {
if (i == 8 || (i-8) % 10 == 0) {
OS << "\n ";
}
OS << " B" << (*I)->getBlockID();
}
OS << '\n';
} }
OS << '\n';
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -1029,7 +1042,7 @@ struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) { static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) {
std::ostringstream Out; std::ostringstream Out;
Node->print(Out,Graph); Node->print(Out,Graph,false);
std::string OutStr = Out.str(); std::string OutStr = Out.str();
if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());

Просмотреть файл

@ -43,15 +43,24 @@ class CFG;
/// Terminator Successor Ordering /// Terminator Successor Ordering
/// ----------------------------------------------------- /// -----------------------------------------------------
/// if Then Block; Else Block /// if Then Block; Else Block
/// ? operator LHS expression; RHS expression
/// &&, || expression that uses result of && or ||, RHS
/// ///
class CFGBlock { class CFGBlock {
typedef std::vector<Stmt*> StatementListTy; typedef std::vector<Stmt*> StatementListTy;
/// Stmts - The set of statements in the basic block. /// Stmts - The set of statements in the basic block.
StatementListTy Stmts; StatementListTy Stmts;
/// ControlFlowStmt - The terminator for a basic block that
/// Label - An (optional) label that prefixes the executable
/// statements in the block. When this variable is non-NULL, it is
/// either an instance of LabelStmt or SwitchCase.
Stmt* Label;
/// Terminator - The terminator for a basic block that
/// indicates the type of control-flow that occurs between a block /// indicates the type of control-flow that occurs between a block
/// and its successors. /// and its successors.
Stmt* ControlFlowStmt; Stmt* Terminator;
/// BlockID - A numerical ID assigned to a CFGBlock during construction /// BlockID - A numerical ID assigned to a CFGBlock during construction
/// of the CFG. /// of the CFG.
unsigned BlockID; unsigned BlockID;
@ -63,7 +72,7 @@ class CFGBlock {
AdjacentBlocks Succs; AdjacentBlocks Succs;
public: public:
explicit CFGBlock(unsigned blockid) : ControlFlowStmt(NULL), explicit CFGBlock(unsigned blockid) : Label(NULL), Terminator(NULL),
BlockID(blockid) {} BlockID(blockid) {}
~CFGBlock() {}; ~CFGBlock() {};
@ -129,8 +138,14 @@ public:
// Manipulation of block contents // Manipulation of block contents
void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); } void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); }
void setTerminator(Stmt* Statement) { ControlFlowStmt = Statement; } void setTerminator(Stmt* Statement) { Terminator = Statement; }
Stmt* getTerminator() { return ControlFlowStmt; } void setLabel(Stmt* Statement) { Label = Statement; }
Stmt* getTerminator() { return Terminator; }
const Stmt* getTerminator() const { return Terminator; }
Stmt* getLabel() { return Label; }
const Stmt* getLabel() const { return Label; }
void reverseStmts(); void reverseStmts();
@ -142,7 +157,7 @@ public:
unsigned getBlockID() const { return BlockID; } unsigned getBlockID() const { return BlockID; }
void dump(const CFG* cfg) const; void dump(const CFG* cfg) const;
void print(std::ostream& OS, const CFG* cfg) const; void print(std::ostream& OS, const CFG* cfg, bool print_edges = true) const;
}; };