LabelMap[ L ] = LabelBlock;
// Labels partition blocks, so this is the end of the basic block
- // we were processing (the label is the first statement). Add the label
- // the to end (really the beginning) of the block. Because this is
+ // we were processing (L is the block's label). Because this is
// label (and we have already processed the substatement) there is no
// extra control-flow to worry about.
- LabelBlock->appendStmt(L);
+ LabelBlock->setLabel(L);
FinishBlock(LabelBlock);
// We set Block to NULL to allow lazy creation of a new 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);
+ // Cases/Default statements partition block, so this is the top of
+ // the basic block we were processing (the case/default is the label).
+ CaseBlock->setLabel(S);
FinishBlock(CaseBlock);
// Add this block to the list of successors for the block with the
// Print the exit block.
getExit().print(OS,this);
-
- OS << "\n";
}
namespace {
/// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
/// 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.
OS << "\n [ B" << getBlockID();
}
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.
- OS << " ------------------------\n";
unsigned j = 1;
for (const_iterator I = Stmts.begin(), E = Stmts.end() ; I != E ; ++I, ++j ) {
- // 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);
-
+ // Print the statement # in the basic block and the statement itself.
+ if (print_edges) OS << " ";
+ OS << std::setw(3) << j << ": ";
+ (*I)->printPretty(OS);
+
// Expressions need a newline.
if (isa<Expr>(*I)) OS << '\n';
}
- OS << " ------------------------\n";
-
- // Print the predecessors of this block.
- OS << " Predecessors (" << pred_size() << "):";
- unsigned i = 0;
- for (const_pred_iterator I = pred_begin(), E = pred_end(); I != E; ++I, ++i) {
- if (i == 8 || (i-8) == 0) {
- OS << "\n ";
- }
- OS << " B" << (*I)->getBlockID();
+
+ // Print the terminator of this block.
+ if (getTerminator()) {
+ if (print_edges) OS << " ";
+ OS << " T: ";
+ CFGBlockTerminatorPrint(OS).Visit(const_cast<Stmt*>(getTerminator()));
}
- // Print the terminator of this block.
- OS << "\n Terminator: ";
- if (ControlFlowStmt)
- CFGBlockTerminatorPrint(OS).Visit(ControlFlowStmt);
- else
- OS << "<NULL>\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 ";
+ if (print_edges) {
+ // Print the predecessors of this block.
+ OS << " Predecessors (" << pred_size() << "):";
+ unsigned i = 0;
+ for (const_pred_iterator I = pred_begin(), E = pred_end(); I != E; ++I, ++i) {
+ if (i == 8 || (i-8) == 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 << " B" << (*I)->getBlockID();
+ OS << '\n';
}
- OS << '\n';
}
//===----------------------------------------------------------------------===//
static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) {
std::ostringstream Out;
- Node->print(Out,Graph);
+ Node->print(Out,Graph,false);
std::string OutStr = Out.str();
if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
/// Terminator Successor Ordering
/// -----------------------------------------------------
/// if Then Block; Else Block
+/// ? operator LHS expression; RHS expression
+/// &&, || expression that uses result of && or ||, RHS
///
class CFGBlock {
typedef std::vector<Stmt*> StatementListTy;
/// Stmts - The set of statements in the basic block.
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
/// and its successors.
- Stmt* ControlFlowStmt;
+ Stmt* Terminator;
+
/// BlockID - A numerical ID assigned to a CFGBlock during construction
/// of the CFG.
unsigned BlockID;
AdjacentBlocks Succs;
public:
- explicit CFGBlock(unsigned blockid) : ControlFlowStmt(NULL),
+ explicit CFGBlock(unsigned blockid) : Label(NULL), Terminator(NULL),
BlockID(blockid) {}
~CFGBlock() {};
// Manipulation of block contents
void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); }
- void setTerminator(Stmt* Statement) { ControlFlowStmt = Statement; }
- Stmt* getTerminator() { return ControlFlowStmt; }
+ void setTerminator(Stmt* Statement) { Terminator = Statement; }
+ 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();
unsigned getBlockID() const { return BlockID; }
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;
};