mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 19:46:05 +00:00

lib dir and move all the libraries into it. This follows the main llvm tree, and allows the libraries to be built in parallel. The top level now enforces that all the libs are built before Driver, but we don't care what order the libs are built in. This speeds up parallel builds, particularly incremental ones. llvm-svn: 48402
1510 lines
47 KiB
C++
1510 lines
47 KiB
C++
//===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the CFG and CFGBuilder classes for representing and
|
|
// building Control-Flow Graphs (CFGs) from ASTs.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/AST/CFG.h"
|
|
#include "clang/AST/Expr.h"
|
|
#include "clang/AST/StmtVisitor.h"
|
|
#include "clang/AST/PrettyPrinter.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
#include "llvm/Support/GraphWriter.h"
|
|
#include "llvm/Support/Streams.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
#include <set>
|
|
#include <iomanip>
|
|
#include <algorithm>
|
|
#include <sstream>
|
|
#include <iostream>
|
|
|
|
using namespace clang;
|
|
|
|
namespace {
|
|
|
|
// SaveAndRestore - A utility class that uses RIIA to save and restore
|
|
// the value of a variable.
|
|
template<typename T>
|
|
struct VISIBILITY_HIDDEN SaveAndRestore {
|
|
SaveAndRestore(T& x) : X(x), old_value(x) {}
|
|
~SaveAndRestore() { X = old_value; }
|
|
T get() { return old_value; }
|
|
|
|
T& X;
|
|
T old_value;
|
|
};
|
|
|
|
/// CFGBuilder - This class is implements CFG construction from an AST.
|
|
/// The builder is stateful: an instance of the builder should be used to only
|
|
/// construct a single CFG.
|
|
///
|
|
/// Example usage:
|
|
///
|
|
/// CFGBuilder builder;
|
|
/// CFG* cfg = builder.BuildAST(stmt1);
|
|
///
|
|
/// CFG construction is done via a recursive walk of an AST.
|
|
/// We actually parse the AST in reverse order so that the successor
|
|
/// of a basic block is constructed prior to its predecessor. This
|
|
/// allows us to nicely capture implicit fall-throughs without extra
|
|
/// basic blocks.
|
|
///
|
|
class VISIBILITY_HIDDEN CFGBuilder : public StmtVisitor<CFGBuilder,CFGBlock*> {
|
|
CFG* cfg;
|
|
CFGBlock* Block;
|
|
CFGBlock* Succ;
|
|
CFGBlock* ContinueTargetBlock;
|
|
CFGBlock* BreakTargetBlock;
|
|
CFGBlock* SwitchTerminatedBlock;
|
|
CFGBlock* DefaultCaseBlock;
|
|
|
|
// LabelMap records the mapping from Label expressions to their blocks.
|
|
typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy;
|
|
LabelMapTy LabelMap;
|
|
|
|
// A list of blocks that end with a "goto" that must be backpatched to
|
|
// their resolved targets upon completion of CFG construction.
|
|
typedef std::vector<CFGBlock*> BackpatchBlocksTy;
|
|
BackpatchBlocksTy BackpatchBlocks;
|
|
|
|
// A list of labels whose address has been taken (for indirect gotos).
|
|
typedef llvm::SmallPtrSet<LabelStmt*,5> LabelSetTy;
|
|
LabelSetTy AddressTakenLabels;
|
|
|
|
public:
|
|
explicit CFGBuilder() : cfg(NULL), Block(NULL), Succ(NULL),
|
|
ContinueTargetBlock(NULL), BreakTargetBlock(NULL),
|
|
SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL) {
|
|
// Create an empty CFG.
|
|
cfg = new CFG();
|
|
}
|
|
|
|
~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* VisitCaseStmt(CaseStmt* S);
|
|
CFGBlock* VisitDefaultStmt(DefaultStmt* D);
|
|
CFGBlock* VisitIndirectGotoStmt(IndirectGotoStmt* I);
|
|
|
|
// FIXME: Add support for ObjC-specific control-flow structures.
|
|
|
|
CFGBlock* VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
|
|
badCFG = true;
|
|
return Block;
|
|
}
|
|
|
|
CFGBlock* VisitObjCAtTryStmt(ObjCAtTryStmt* S) {
|
|
badCFG = true;
|
|
return Block;
|
|
}
|
|
|
|
private:
|
|
CFGBlock* createBlock(bool add_successor = true);
|
|
CFGBlock* addStmt(Stmt* S);
|
|
CFGBlock* WalkAST(Stmt* S, bool AlwaysAddStmt);
|
|
CFGBlock* WalkAST_VisitChildren(Stmt* S);
|
|
CFGBlock* WalkAST_VisitDeclSubExprs(StmtIterator& I);
|
|
CFGBlock* WalkAST_VisitStmtExpr(StmtExpr* S);
|
|
void FinishBlock(CFGBlock* B);
|
|
|
|
bool badCFG;
|
|
};
|
|
|
|
/// 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) {
|
|
assert (cfg);
|
|
if (!Statement) return NULL;
|
|
|
|
badCFG = false;
|
|
|
|
// 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.
|
|
Succ = createBlock();
|
|
assert (Succ == &cfg->getExit());
|
|
Block = NULL; // the EXIT block is empty. Create all other blocks lazily.
|
|
|
|
// Visit the statements and create the CFG.
|
|
CFGBlock* B = Visit(Statement);
|
|
if (!B) B = Succ;
|
|
|
|
if (B) {
|
|
// Finalize the last constructed block. This usually involves
|
|
// reversing the order of the statements in the block.
|
|
if (Block) FinishBlock(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);
|
|
}
|
|
|
|
// Add successors to the Indirect Goto Dispatch block (if we have one).
|
|
if (CFGBlock* B = cfg->getIndirectGotoBlock())
|
|
for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
|
|
E = AddressTakenLabels.end(); I != E; ++I ) {
|
|
|
|
// Lookup the target block.
|
|
LabelMapTy::iterator LI = LabelMap.find(*I);
|
|
|
|
// If there is no target block that contains label, then we are looking
|
|
// at an incomplete AST. Handle this by not registering a successor.
|
|
if (LI == LabelMap.end()) continue;
|
|
|
|
B->addSuccessor(LI->second);
|
|
}
|
|
|
|
Succ = B;
|
|
}
|
|
|
|
// Create an empty entry block that has no predecessors.
|
|
cfg->setEntry(createBlock());
|
|
|
|
if (badCFG) {
|
|
delete cfg;
|
|
cfg = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
// NULL out cfg so that repeated calls to the builder will fail and that
|
|
// the ownership of the constructed CFG is passed to the caller.
|
|
CFG* t = cfg;
|
|
cfg = NULL;
|
|
return t;
|
|
}
|
|
|
|
/// createBlock - Used to lazily create blocks that are connected
|
|
/// to the current (global) succcessor.
|
|
CFGBlock* CFGBuilder::createBlock(bool add_successor) {
|
|
CFGBlock* B = cfg->createBlock();
|
|
if (add_successor && Succ) B->addSuccessor(Succ);
|
|
return B;
|
|
}
|
|
|
|
/// FinishBlock - When the last statement has been added to the block,
|
|
/// we must reverse the statements because they have been inserted
|
|
/// in reverse order.
|
|
void CFGBuilder::FinishBlock(CFGBlock* B) {
|
|
assert (B);
|
|
B->reverseStmts();
|
|
}
|
|
|
|
/// addStmt - Used to add statements/expressions to the current CFGBlock
|
|
/// "Block". This method calls WalkAST on the passed statement to see if it
|
|
/// contains any short-circuit expressions. If so, it recursively creates
|
|
/// the necessary blocks for such expressions. It returns the "topmost" block
|
|
/// of the created blocks, or the original value of "Block" when this method
|
|
/// was called if no additional blocks are created.
|
|
CFGBlock* CFGBuilder::addStmt(Stmt* S) {
|
|
if (!Block) Block = createBlock();
|
|
return WalkAST(S,true);
|
|
}
|
|
|
|
/// WalkAST - Used by addStmt to walk the subtree of a statement and
|
|
/// add extra blocks for ternary operators, &&, and ||. We also
|
|
/// process "," and DeclStmts (which may contain nested control-flow).
|
|
CFGBlock* CFGBuilder::WalkAST(Stmt* S, bool AlwaysAddStmt = false) {
|
|
switch (S->getStmtClass()) {
|
|
case Stmt::ConditionalOperatorClass: {
|
|
ConditionalOperator* C = cast<ConditionalOperator>(S);
|
|
|
|
// Create the confluence block that will "merge" the results
|
|
// of the ternary expression.
|
|
CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock();
|
|
ConfluenceBlock->appendStmt(C);
|
|
FinishBlock(ConfluenceBlock);
|
|
|
|
// Create a block for the LHS expression if there is an LHS expression.
|
|
// A GCC extension allows LHS to be NULL, causing the condition to
|
|
// be the value that is returned instead.
|
|
// e.g: x ?: y is shorthand for: x ? x : y;
|
|
Succ = ConfluenceBlock;
|
|
Block = NULL;
|
|
CFGBlock* LHSBlock = NULL;
|
|
if (C->getLHS()) {
|
|
LHSBlock = Visit(C->getLHS());
|
|
FinishBlock(LHSBlock);
|
|
Block = NULL;
|
|
}
|
|
|
|
// Create the block for the RHS expression.
|
|
Succ = ConfluenceBlock;
|
|
CFGBlock* RHSBlock = Visit(C->getRHS());
|
|
FinishBlock(RHSBlock);
|
|
|
|
// Create the block that will contain the condition.
|
|
Block = createBlock(false);
|
|
|
|
if (LHSBlock)
|
|
Block->addSuccessor(LHSBlock);
|
|
else {
|
|
// If we have no LHS expression, add the ConfluenceBlock as a direct
|
|
// successor for the block containing the condition. Moreover,
|
|
// we need to reverse the order of the predecessors in the
|
|
// ConfluenceBlock because the RHSBlock will have been added to
|
|
// the succcessors already, and we want the first predecessor to the
|
|
// the block containing the expression for the case when the ternary
|
|
// expression evaluates to true.
|
|
Block->addSuccessor(ConfluenceBlock);
|
|
assert (ConfluenceBlock->pred_size() == 2);
|
|
std::reverse(ConfluenceBlock->pred_begin(),
|
|
ConfluenceBlock->pred_end());
|
|
}
|
|
|
|
Block->addSuccessor(RHSBlock);
|
|
|
|
Block->setTerminator(C);
|
|
return addStmt(C->getCond());
|
|
}
|
|
|
|
case Stmt::ChooseExprClass: {
|
|
ChooseExpr* C = cast<ChooseExpr>(S);
|
|
|
|
CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock();
|
|
ConfluenceBlock->appendStmt(C);
|
|
FinishBlock(ConfluenceBlock);
|
|
|
|
Succ = ConfluenceBlock;
|
|
Block = NULL;
|
|
CFGBlock* LHSBlock = Visit(C->getLHS());
|
|
FinishBlock(LHSBlock);
|
|
|
|
Succ = ConfluenceBlock;
|
|
Block = NULL;
|
|
CFGBlock* RHSBlock = Visit(C->getRHS());
|
|
FinishBlock(RHSBlock);
|
|
|
|
Block = createBlock(false);
|
|
Block->addSuccessor(LHSBlock);
|
|
Block->addSuccessor(RHSBlock);
|
|
Block->setTerminator(C);
|
|
return addStmt(C->getCond());
|
|
}
|
|
|
|
case Stmt::DeclStmtClass: {
|
|
ScopedDecl* D = cast<DeclStmt>(S)->getDecl();
|
|
Block->appendStmt(S);
|
|
|
|
StmtIterator I(D);
|
|
return WalkAST_VisitDeclSubExprs(I);
|
|
}
|
|
|
|
case Stmt::AddrLabelExprClass: {
|
|
AddrLabelExpr* A = cast<AddrLabelExpr>(S);
|
|
AddressTakenLabels.insert(A->getLabel());
|
|
|
|
if (AlwaysAddStmt) Block->appendStmt(S);
|
|
return Block;
|
|
}
|
|
|
|
case Stmt::StmtExprClass:
|
|
return WalkAST_VisitStmtExpr(cast<StmtExpr>(S));
|
|
|
|
case Stmt::UnaryOperatorClass: {
|
|
UnaryOperator* U = cast<UnaryOperator>(S);
|
|
|
|
// sizeof(expressions). For such expressions,
|
|
// the subexpression is not really evaluated, so
|
|
// we don't care about control-flow within the sizeof.
|
|
if (U->getOpcode() == UnaryOperator::SizeOf) {
|
|
Block->appendStmt(S);
|
|
return Block;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case Stmt::BinaryOperatorClass: {
|
|
BinaryOperator* B = cast<BinaryOperator>(S);
|
|
|
|
if (B->isLogicalOp()) { // && or ||
|
|
CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock();
|
|
ConfluenceBlock->appendStmt(B);
|
|
FinishBlock(ConfluenceBlock);
|
|
|
|
// create the block evaluating the LHS
|
|
CFGBlock* LHSBlock = createBlock(false);
|
|
LHSBlock->setTerminator(B);
|
|
|
|
// create the block evaluating the RHS
|
|
Succ = ConfluenceBlock;
|
|
Block = NULL;
|
|
CFGBlock* RHSBlock = Visit(B->getRHS());
|
|
|
|
// Now link the LHSBlock with RHSBlock.
|
|
if (B->getOpcode() == BinaryOperator::LOr) {
|
|
LHSBlock->addSuccessor(ConfluenceBlock);
|
|
LHSBlock->addSuccessor(RHSBlock);
|
|
}
|
|
else {
|
|
assert (B->getOpcode() == BinaryOperator::LAnd);
|
|
LHSBlock->addSuccessor(RHSBlock);
|
|
LHSBlock->addSuccessor(ConfluenceBlock);
|
|
}
|
|
|
|
// Generate the blocks for evaluating the LHS.
|
|
Block = LHSBlock;
|
|
return addStmt(B->getLHS());
|
|
}
|
|
else if (B->getOpcode() == BinaryOperator::Comma) { // ,
|
|
Block->appendStmt(B);
|
|
addStmt(B->getRHS());
|
|
return addStmt(B->getLHS());
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case Stmt::ParenExprClass:
|
|
return WalkAST(cast<ParenExpr>(S)->getSubExpr(), AlwaysAddStmt);
|
|
|
|
default:
|
|
break;
|
|
};
|
|
|
|
if (AlwaysAddStmt) Block->appendStmt(S);
|
|
return WalkAST_VisitChildren(S);
|
|
}
|
|
|
|
/// WalkAST_VisitDeclSubExprs - Utility method to handle Decls contained in
|
|
/// DeclStmts. Because the initialization code (and sometimes the
|
|
/// the type declarations) for DeclStmts can contain arbitrary expressions,
|
|
/// we must linearize declarations to handle arbitrary control-flow induced by
|
|
/// those expressions.
|
|
CFGBlock* CFGBuilder::WalkAST_VisitDeclSubExprs(StmtIterator& I) {
|
|
if (I == StmtIterator())
|
|
return Block;
|
|
|
|
Stmt* S = *I;
|
|
++I;
|
|
WalkAST_VisitDeclSubExprs(I);
|
|
|
|
// Optimization: Don't create separate block-level statements for literals.
|
|
|
|
switch (S->getStmtClass()) {
|
|
case Stmt::IntegerLiteralClass:
|
|
case Stmt::CharacterLiteralClass:
|
|
case Stmt::StringLiteralClass:
|
|
break;
|
|
|
|
// All other cases.
|
|
|
|
default:
|
|
Block = addStmt(S);
|
|
}
|
|
|
|
return Block;
|
|
}
|
|
|
|
/// WalkAST_VisitChildren - Utility method to call WalkAST on the
|
|
/// children of a Stmt.
|
|
CFGBlock* CFGBuilder::WalkAST_VisitChildren(Stmt* S) {
|
|
CFGBlock* B = Block;
|
|
for (Stmt::child_iterator I = S->child_begin(), E = S->child_end() ;
|
|
I != E; ++I)
|
|
if (*I) B = WalkAST(*I);
|
|
|
|
return B;
|
|
}
|
|
|
|
/// WalkAST_VisitStmtExpr - Utility method to handle (nested) statement
|
|
/// expressions (a GCC extension).
|
|
CFGBlock* CFGBuilder::WalkAST_VisitStmtExpr(StmtExpr* S) {
|
|
Block->appendStmt(S);
|
|
return VisitCompoundStmt(S->getSubStmt());
|
|
}
|
|
|
|
/// 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.
|
|
addStmt(Statement);
|
|
|
|
return Block;
|
|
}
|
|
|
|
CFGBlock* CFGBuilder::VisitNullStmt(NullStmt* Statement) {
|
|
return Block;
|
|
}
|
|
|
|
CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
|
|
|
|
for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
|
|
I != E; ++I ) {
|
|
Visit(*I);
|
|
}
|
|
|
|
return Block;
|
|
}
|
|
|
|
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;
|
|
|
|
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) // Can occur when the Else body has all NullStmts.
|
|
ElseBlock = sv.get();
|
|
else if (Block)
|
|
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) // Can occur when the Then body has all NullStmts.
|
|
ThenBlock = sv.get();
|
|
else if (Block)
|
|
FinishBlock(ThenBlock);
|
|
}
|
|
|
|
// Now create a new block containing the if statement.
|
|
Block = createBlock(false);
|
|
|
|
// Set the terminator of the new block to the If statement.
|
|
Block->setTerminator(I);
|
|
|
|
// Now add the successors.
|
|
Block->addSuccessor(ThenBlock);
|
|
Block->addSuccessor(ElseBlock);
|
|
|
|
// Add the condition as the last statement in the new block. This
|
|
// may create new blocks as the condition may contain control-flow. Any
|
|
// newly created blocks will be pointed to be "Block".
|
|
return addStmt(I->getCond()->IgnoreParens());
|
|
}
|
|
|
|
|
|
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. This may create new blocks
|
|
// if R contains control-flow (short-circuit operations).
|
|
return addStmt(R);
|
|
}
|
|
|
|
CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) {
|
|
// Get the block of the labeled statement. Add it to our map.
|
|
Visit(L->getSubStmt());
|
|
CFGBlock* LabelBlock = Block;
|
|
|
|
if (!LabelBlock) // This can happen when the body is empty, i.e.
|
|
LabelBlock=createBlock(); // scopes that only contains NullStmts.
|
|
|
|
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 (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->setLabel(L);
|
|
FinishBlock(LabelBlock);
|
|
|
|
// 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* 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;
|
|
}
|
|
else LoopSuccessor = Succ;
|
|
|
|
// Because of short-circuit evaluation, the condition of the loop
|
|
// can span multiple basic blocks. Thus we need the "Entry" and "Exit"
|
|
// blocks that evaluate the condition.
|
|
CFGBlock* ExitConditionBlock = createBlock(false);
|
|
CFGBlock* EntryConditionBlock = ExitConditionBlock;
|
|
|
|
// Set the terminator for the "exit" condition block.
|
|
ExitConditionBlock->setTerminator(F);
|
|
|
|
// Now add the actual condition to the condition block. Because the
|
|
// condition itself may contain control-flow, new blocks may be created.
|
|
if (Stmt* C = F->getCond()) {
|
|
Block = ExitConditionBlock;
|
|
EntryConditionBlock = addStmt(C);
|
|
if (Block) FinishBlock(EntryConditionBlock);
|
|
}
|
|
|
|
// The condition block is the implicit successor for the loop body as
|
|
// well as any code above the loop.
|
|
Succ = EntryConditionBlock;
|
|
|
|
// 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);
|
|
|
|
// All continues within this loop should go to the condition block
|
|
ContinueTargetBlock = EntryConditionBlock;
|
|
|
|
// 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 = NULL;
|
|
|
|
// If we have increment code, insert it at the end of the body block.
|
|
if (Stmt* I = F->getInc()) Block = addStmt(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());
|
|
|
|
if (!BodyBlock)
|
|
BodyBlock = EntryConditionBlock; // can happen for "for (...;...; ) ;"
|
|
else if (Block)
|
|
FinishBlock(BodyBlock);
|
|
|
|
// This new body block is a successor to our "exit" condition block.
|
|
ExitConditionBlock->addSuccessor(BodyBlock);
|
|
}
|
|
|
|
// Link up the condition block with the code that follows the loop.
|
|
// (the false branch).
|
|
ExitConditionBlock->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();
|
|
return addStmt(I);
|
|
}
|
|
else {
|
|
// There is no loop initialization. We are thus basically a while
|
|
// loop. NULL out Block to force lazy block construction.
|
|
Block = NULL;
|
|
Succ = EntryConditionBlock;
|
|
return EntryConditionBlock;
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
// Because of short-circuit evaluation, the condition of the loop
|
|
// can span multiple basic blocks. Thus we need the "Entry" and "Exit"
|
|
// blocks that evaluate the condition.
|
|
CFGBlock* ExitConditionBlock = createBlock(false);
|
|
CFGBlock* EntryConditionBlock = ExitConditionBlock;
|
|
|
|
// Set the terminator for the "exit" condition block.
|
|
ExitConditionBlock->setTerminator(W);
|
|
|
|
// Now add the actual condition to the condition block. Because the
|
|
// condition itself may contain control-flow, new blocks may be created.
|
|
// Thus we update "Succ" after adding the condition.
|
|
if (Stmt* C = W->getCond()) {
|
|
Block = ExitConditionBlock;
|
|
EntryConditionBlock = addStmt(C);
|
|
assert (Block == EntryConditionBlock);
|
|
if (Block) FinishBlock(EntryConditionBlock);
|
|
}
|
|
|
|
// The condition block is the implicit successor for the loop body as
|
|
// well as any code above the loop.
|
|
Succ = EntryConditionBlock;
|
|
|
|
// 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 = EntryConditionBlock;
|
|
|
|
// 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());
|
|
|
|
if (!BodyBlock)
|
|
BodyBlock = EntryConditionBlock; // can happen for "while(...) ;"
|
|
else if (Block)
|
|
FinishBlock(BodyBlock);
|
|
|
|
// Add the loop body entry as a successor to the condition.
|
|
ExitConditionBlock->addSuccessor(BodyBlock);
|
|
}
|
|
|
|
// Link up the condition block with the code that follows the loop.
|
|
// (the false branch).
|
|
ExitConditionBlock->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.
|
|
Succ = EntryConditionBlock;
|
|
return EntryConditionBlock;
|
|
}
|
|
|
|
CFGBlock* CFGBuilder::VisitDoStmt(DoStmt* D) {
|
|
// "do...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;
|
|
|
|
// Because of short-circuit evaluation, the condition of the loop
|
|
// can span multiple basic blocks. Thus we need the "Entry" and "Exit"
|
|
// blocks that evaluate the condition.
|
|
CFGBlock* ExitConditionBlock = createBlock(false);
|
|
CFGBlock* EntryConditionBlock = ExitConditionBlock;
|
|
|
|
// Set the terminator for the "exit" condition block.
|
|
ExitConditionBlock->setTerminator(D);
|
|
|
|
// Now add the actual condition to the condition block. Because the
|
|
// condition itself may contain control-flow, new blocks may be created.
|
|
if (Stmt* C = D->getCond()) {
|
|
Block = ExitConditionBlock;
|
|
EntryConditionBlock = addStmt(C);
|
|
if (Block) FinishBlock(EntryConditionBlock);
|
|
}
|
|
|
|
// The condition block is the implicit successor for the loop body.
|
|
Succ = EntryConditionBlock;
|
|
|
|
// Process the loop body.
|
|
CFGBlock* BodyBlock = NULL;
|
|
{
|
|
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 = EntryConditionBlock;
|
|
|
|
// 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());
|
|
|
|
if (!BodyBlock)
|
|
BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)"
|
|
else if (Block)
|
|
FinishBlock(BodyBlock);
|
|
|
|
// Add the loop body entry as a successor to the condition.
|
|
ExitConditionBlock->addSuccessor(BodyBlock);
|
|
}
|
|
|
|
// Link up the condition block with the code that follows the loop.
|
|
// (the false branch).
|
|
ExitConditionBlock->addSuccessor(LoopSuccessor);
|
|
|
|
// There can be no more statements in the body block(s)
|
|
// since we loop back to the body. NULL out Block to force
|
|
// lazy creation of another block.
|
|
Block = NULL;
|
|
|
|
// Return the loop body, which is the dominating block for the loop.
|
|
Succ = BodyBlock;
|
|
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),
|
|
save_default(DefaultCaseBlock);
|
|
|
|
// Set the "default" case to be the block after the switch statement.
|
|
// If the switch statement contains a "default:", this value will
|
|
// be overwritten with the block for that code.
|
|
DefaultCaseBlock = SwitchSuccessor;
|
|
|
|
// Create a new block that will contain the switch statement.
|
|
SwitchTerminatedBlock = createBlock(false);
|
|
|
|
// Now process the switch body. The code after the switch is the implicit
|
|
// successor.
|
|
Succ = SwitchSuccessor;
|
|
BreakTargetBlock = SwitchSuccessor;
|
|
|
|
// 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.
|
|
assert (S->getBody() && "switch must contain a non-NULL body");
|
|
Block = NULL;
|
|
CFGBlock *BodyBlock = Visit(S->getBody());
|
|
if (Block) FinishBlock(BodyBlock);
|
|
|
|
// If we have no "default:" case, the default transition is to the
|
|
// code following the switch body.
|
|
SwitchTerminatedBlock->addSuccessor(DefaultCaseBlock);
|
|
|
|
// Add the terminator and condition in the switch block.
|
|
SwitchTerminatedBlock->setTerminator(S);
|
|
assert (S->getCond() && "switch condition must be non-NULL");
|
|
Block = SwitchTerminatedBlock;
|
|
|
|
return addStmt(S->getCond());
|
|
}
|
|
|
|
CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* S) {
|
|
// CaseStmts are essentially labels, so they are the
|
|
// first statement in a block.
|
|
|
|
if (S->getSubStmt()) Visit(S->getSubStmt());
|
|
CFGBlock* CaseBlock = Block;
|
|
if (!CaseBlock) CaseBlock = createBlock();
|
|
|
|
// Cases statements partition blocks, so this is the top of
|
|
// the basic block we were processing (the "case XXX:" is the label).
|
|
CaseBlock->setLabel(S);
|
|
FinishBlock(CaseBlock);
|
|
|
|
// Add this block to the list of successors for the block with the
|
|
// switch statement.
|
|
assert (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;
|
|
}
|
|
|
|
CFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* S) {
|
|
if (S->getSubStmt()) Visit(S->getSubStmt());
|
|
DefaultCaseBlock = Block;
|
|
if (!DefaultCaseBlock) DefaultCaseBlock = createBlock();
|
|
|
|
// Default statements partition blocks, so this is the top of
|
|
// the basic block we were processing (the "default:" is the label).
|
|
DefaultCaseBlock->setLabel(S);
|
|
FinishBlock(DefaultCaseBlock);
|
|
|
|
// Unlike case statements, we don't add the default block to the
|
|
// successors for the switch statement immediately. This is done
|
|
// when we finish processing the switch statement. This allows for
|
|
// the default case (including a fall-through to the code after the
|
|
// switch statement) to always be the last successor of a switch-terminated
|
|
// block.
|
|
|
|
// 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 = DefaultCaseBlock;
|
|
|
|
return DefaultCaseBlock;
|
|
}
|
|
|
|
CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) {
|
|
// Lazily create the indirect-goto dispatch block if there isn't one
|
|
// already.
|
|
CFGBlock* IBlock = cfg->getIndirectGotoBlock();
|
|
|
|
if (!IBlock) {
|
|
IBlock = createBlock(false);
|
|
cfg->setIndirectGotoBlock(IBlock);
|
|
}
|
|
|
|
// IndirectGoto 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(I);
|
|
Block->addSuccessor(IBlock);
|
|
return addStmt(I->getTarget());
|
|
}
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
/// createBlock - Constructs and adds a new CFGBlock to the CFG. The
|
|
/// block has no successors or predecessors. If this is the first block
|
|
/// created in the CFG, it is automatically set to be the Entry and Exit
|
|
/// of the CFG.
|
|
CFGBlock* CFG::createBlock() {
|
|
bool first_block = begin() == end();
|
|
|
|
// Create the block.
|
|
Blocks.push_front(CFGBlock(NumBlockIDs++));
|
|
|
|
// If this is the first block, set it as the Entry and Exit.
|
|
if (first_block) Entry = Exit = &front();
|
|
|
|
// Return the block.
|
|
return &front();
|
|
}
|
|
|
|
/// buildCFG - Constructs a CFG from an AST. Ownership of the returned
|
|
/// CFG is returned to the caller.
|
|
CFG* CFG::buildCFG(Stmt* Statement) {
|
|
CFGBuilder Builder;
|
|
return Builder.buildCFG(Statement);
|
|
}
|
|
|
|
/// reverseStmts - Reverses the orders of statements within a CFGBlock.
|
|
void CFGBlock::reverseStmts() { std::reverse(Stmts.begin(),Stmts.end()); }
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// CFG: Queries for BlkExprs.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy;
|
|
}
|
|
|
|
static void FindSubExprAssignments(Stmt* S, llvm::SmallPtrSet<Expr*,50>& Set) {
|
|
if (!S)
|
|
return;
|
|
|
|
for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) {
|
|
if (!*I) continue;
|
|
|
|
if (BinaryOperator* B = dyn_cast<BinaryOperator>(*I))
|
|
if (B->isAssignmentOp()) Set.insert(B);
|
|
|
|
FindSubExprAssignments(*I, Set);
|
|
}
|
|
}
|
|
|
|
static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) {
|
|
BlkExprMapTy* M = new BlkExprMapTy();
|
|
|
|
// Look for assignments that are used as subexpressions. These are the
|
|
// only assignments that we want to register as a block-level expression.
|
|
llvm::SmallPtrSet<Expr*,50> SubExprAssignments;
|
|
|
|
for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I)
|
|
for (CFGBlock::iterator BI=I->begin(), EI=I->end(); BI != EI; ++BI)
|
|
FindSubExprAssignments(*BI, SubExprAssignments);
|
|
|
|
// Iterate over the statements again on identify the Expr* and Stmt* at
|
|
// the block-level that are block-level expressions.
|
|
for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I)
|
|
for (CFGBlock::iterator BI=I->begin(), EI=I->end(); BI != EI; ++BI)
|
|
if (Expr* E = dyn_cast<Expr>(*BI)) {
|
|
|
|
if (BinaryOperator* B = dyn_cast<BinaryOperator>(E)) {
|
|
// Assignment expressions that are not nested within another
|
|
// expression are really "statements" whose value is never
|
|
// used by another expression.
|
|
if (B->isAssignmentOp() && !SubExprAssignments.count(E))
|
|
continue;
|
|
}
|
|
else if (const StmtExpr* S = dyn_cast<StmtExpr>(E)) {
|
|
// Special handling for statement expressions. The last statement
|
|
// in the statement expression is also a block-level expr.
|
|
const CompoundStmt* C = S->getSubStmt();
|
|
if (!C->body_empty()) {
|
|
unsigned x = M->size();
|
|
(*M)[C->body_back()] = x;
|
|
}
|
|
}
|
|
|
|
unsigned x = M->size();
|
|
(*M)[E] = x;
|
|
}
|
|
|
|
return M;
|
|
}
|
|
|
|
CFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) {
|
|
assert(S != NULL);
|
|
if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); }
|
|
|
|
BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap);
|
|
BlkExprMapTy::iterator I = M->find(S);
|
|
|
|
if (I == M->end()) return CFG::BlkExprNumTy();
|
|
else return CFG::BlkExprNumTy(I->second);
|
|
}
|
|
|
|
unsigned CFG::getNumBlkExprs() {
|
|
if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap))
|
|
return M->size();
|
|
else {
|
|
// We assume callers interested in the number of BlkExprs will want
|
|
// the map constructed if it doesn't already exist.
|
|
BlkExprMap = (void*) PopulateBlkExprMap(*this);
|
|
return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size();
|
|
}
|
|
}
|
|
|
|
typedef std::set<std::pair<CFGBlock*,CFGBlock*> > BlkEdgeSetTy;
|
|
|
|
const std::pair<CFGBlock*,CFGBlock*>*
|
|
CFG::getBlockEdgeImpl(const CFGBlock* B1, const CFGBlock* B2) {
|
|
|
|
BlkEdgeSetTy*& p = reinterpret_cast<BlkEdgeSetTy*&>(BlkEdgeSet);
|
|
if (!p) p = new BlkEdgeSetTy();
|
|
|
|
return &*(p->insert(std::make_pair(const_cast<CFGBlock*>(B1),
|
|
const_cast<CFGBlock*>(B2))).first);
|
|
}
|
|
|
|
CFG::~CFG() {
|
|
delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap);
|
|
delete reinterpret_cast<BlkEdgeSetTy*>(BlkEdgeSet);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// CFG pretty printing
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
|
|
class VISIBILITY_HIDDEN StmtPrinterHelper : public PrinterHelper {
|
|
|
|
typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
|
|
StmtMapTy StmtMap;
|
|
signed CurrentBlock;
|
|
unsigned CurrentStmt;
|
|
|
|
public:
|
|
|
|
StmtPrinterHelper(const CFG* cfg) : CurrentBlock(0), CurrentStmt(0) {
|
|
for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
|
|
unsigned j = 1;
|
|
for (CFGBlock::const_iterator BI = I->begin(), BEnd = I->end() ;
|
|
BI != BEnd; ++BI, ++j )
|
|
StmtMap[*BI] = std::make_pair(I->getBlockID(),j);
|
|
}
|
|
}
|
|
|
|
virtual ~StmtPrinterHelper() {}
|
|
|
|
void setBlockID(signed i) { CurrentBlock = i; }
|
|
void setStmtID(unsigned i) { CurrentStmt = i; }
|
|
|
|
virtual bool handledStmt(Stmt* S, std::ostream& OS) {
|
|
|
|
StmtMapTy::iterator I = StmtMap.find(S);
|
|
|
|
if (I == StmtMap.end())
|
|
return false;
|
|
|
|
if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock
|
|
&& I->second.second == CurrentStmt)
|
|
return false;
|
|
|
|
OS << "[B" << I->second.first << "." << I->second.second << "]";
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class VISIBILITY_HIDDEN CFGBlockTerminatorPrint
|
|
: public StmtVisitor<CFGBlockTerminatorPrint,void> {
|
|
|
|
std::ostream& OS;
|
|
StmtPrinterHelper* Helper;
|
|
public:
|
|
CFGBlockTerminatorPrint(std::ostream& os, StmtPrinterHelper* helper)
|
|
: OS(os), Helper(helper) {}
|
|
|
|
void VisitIfStmt(IfStmt* I) {
|
|
OS << "if ";
|
|
I->getCond()->printPretty(OS,Helper);
|
|
}
|
|
|
|
// Default case.
|
|
void VisitStmt(Stmt* S) { S->printPretty(OS); }
|
|
|
|
void VisitForStmt(ForStmt* F) {
|
|
OS << "for (" ;
|
|
if (F->getInit()) OS << "...";
|
|
OS << "; ";
|
|
if (Stmt* C = F->getCond()) C->printPretty(OS,Helper);
|
|
OS << "; ";
|
|
if (F->getInc()) OS << "...";
|
|
OS << ")";
|
|
}
|
|
|
|
void VisitWhileStmt(WhileStmt* W) {
|
|
OS << "while " ;
|
|
if (Stmt* C = W->getCond()) C->printPretty(OS,Helper);
|
|
}
|
|
|
|
void VisitDoStmt(DoStmt* D) {
|
|
OS << "do ... while ";
|
|
if (Stmt* C = D->getCond()) C->printPretty(OS,Helper);
|
|
}
|
|
|
|
void VisitSwitchStmt(SwitchStmt* S) {
|
|
OS << "switch ";
|
|
S->getCond()->printPretty(OS,Helper);
|
|
}
|
|
|
|
void VisitConditionalOperator(ConditionalOperator* C) {
|
|
C->getCond()->printPretty(OS,Helper);
|
|
OS << " ? ... : ...";
|
|
}
|
|
|
|
void VisitChooseExpr(ChooseExpr* C) {
|
|
OS << "__builtin_choose_expr( ";
|
|
C->getCond()->printPretty(OS,Helper);
|
|
OS << " )";
|
|
}
|
|
|
|
void VisitIndirectGotoStmt(IndirectGotoStmt* I) {
|
|
OS << "goto *";
|
|
I->getTarget()->printPretty(OS,Helper);
|
|
}
|
|
|
|
void VisitBinaryOperator(BinaryOperator* B) {
|
|
if (!B->isLogicalOp()) {
|
|
VisitExpr(B);
|
|
return;
|
|
}
|
|
|
|
B->getLHS()->printPretty(OS,Helper);
|
|
|
|
switch (B->getOpcode()) {
|
|
case BinaryOperator::LOr:
|
|
OS << " || ...";
|
|
return;
|
|
case BinaryOperator::LAnd:
|
|
OS << " && ...";
|
|
return;
|
|
default:
|
|
assert(false && "Invalid logical operator.");
|
|
}
|
|
}
|
|
|
|
void VisitExpr(Expr* E) {
|
|
E->printPretty(OS,Helper);
|
|
}
|
|
};
|
|
|
|
|
|
void print_stmt(std::ostream&OS, StmtPrinterHelper* Helper, Stmt* S) {
|
|
if (Helper) {
|
|
// special printing for statement-expressions.
|
|
if (StmtExpr* SE = dyn_cast<StmtExpr>(S)) {
|
|
CompoundStmt* Sub = SE->getSubStmt();
|
|
|
|
if (Sub->child_begin() != Sub->child_end()) {
|
|
OS << "({ ... ; ";
|
|
Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
|
|
OS << " })\n";
|
|
return;
|
|
}
|
|
}
|
|
|
|
// special printing for comma expressions.
|
|
if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
|
|
if (B->getOpcode() == BinaryOperator::Comma) {
|
|
OS << "... , ";
|
|
Helper->handledStmt(B->getRHS(),OS);
|
|
OS << '\n';
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
S->printPretty(OS, Helper);
|
|
|
|
// Expressions need a newline.
|
|
if (isa<Expr>(S)) OS << '\n';
|
|
}
|
|
|
|
void print_block(std::ostream& OS, const CFG* cfg, const CFGBlock& B,
|
|
StmtPrinterHelper* Helper, bool print_edges) {
|
|
|
|
if (Helper) Helper->setBlockID(B.getBlockID());
|
|
|
|
// Print the header.
|
|
OS << "\n [ B" << B.getBlockID();
|
|
|
|
if (&B == &cfg->getEntry())
|
|
OS << " (ENTRY) ]\n";
|
|
else if (&B == &cfg->getExit())
|
|
OS << " (EXIT) ]\n";
|
|
else if (&B == cfg->getIndirectGotoBlock())
|
|
OS << " (INDIRECT GOTO DISPATCH) ]\n";
|
|
else
|
|
OS << " ]\n";
|
|
|
|
// Print the label of this block.
|
|
if (Stmt* S = const_cast<Stmt*>(B.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 (isa<DefaultStmt>(S))
|
|
OS << "default";
|
|
else
|
|
assert(false && "Invalid label statement in CFGBlock.");
|
|
|
|
OS << ":\n";
|
|
}
|
|
|
|
// Iterate through the statements in the block and print them.
|
|
unsigned j = 1;
|
|
|
|
for (CFGBlock::const_iterator I = B.begin(), E = B.end() ;
|
|
I != E ; ++I, ++j ) {
|
|
|
|
// Print the statement # in the basic block and the statement itself.
|
|
if (print_edges)
|
|
OS << " ";
|
|
|
|
OS << std::setw(3) << j << ": ";
|
|
|
|
if (Helper)
|
|
Helper->setStmtID(j);
|
|
|
|
print_stmt(OS,Helper,*I);
|
|
}
|
|
|
|
// Print the terminator of this block.
|
|
if (B.getTerminator()) {
|
|
if (print_edges)
|
|
OS << " ";
|
|
|
|
OS << " T: ";
|
|
|
|
if (Helper) Helper->setBlockID(-1);
|
|
|
|
CFGBlockTerminatorPrint TPrinter(OS,Helper);
|
|
TPrinter.Visit(const_cast<Stmt*>(B.getTerminator()));
|
|
OS << '\n';
|
|
}
|
|
|
|
if (print_edges) {
|
|
// Print the predecessors of this block.
|
|
OS << " Predecessors (" << B.pred_size() << "):";
|
|
unsigned i = 0;
|
|
|
|
for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.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 (" << B.succ_size() << "):";
|
|
i = 0;
|
|
|
|
for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();
|
|
I != E; ++I, ++i) {
|
|
|
|
if (i == 8 || (i-8) % 10 == 0)
|
|
OS << "\n ";
|
|
|
|
OS << " B" << (*I)->getBlockID();
|
|
}
|
|
|
|
OS << '\n';
|
|
}
|
|
}
|
|
|
|
} // end anonymous namespace
|
|
|
|
/// dump - A simple pretty printer of a CFG that outputs to stderr.
|
|
void CFG::dump() const { print(*llvm::cerr.stream()); }
|
|
|
|
/// print - A simple pretty printer of a CFG that outputs to an ostream.
|
|
void CFG::print(std::ostream& OS) const {
|
|
|
|
StmtPrinterHelper Helper(this);
|
|
|
|
// Print the entry block.
|
|
print_block(OS, this, getEntry(), &Helper, true);
|
|
|
|
// Iterate through the CFGBlocks and print them one by one.
|
|
for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
|
|
// Skip the entry block, because we already printed it.
|
|
if (&(*I) == &getEntry() || &(*I) == &getExit())
|
|
continue;
|
|
|
|
print_block(OS, this, *I, &Helper, true);
|
|
}
|
|
|
|
// Print the exit block.
|
|
print_block(OS, this, getExit(), &Helper, true);
|
|
}
|
|
|
|
/// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
|
|
void CFGBlock::dump(const CFG* cfg) const { print(*llvm::cerr.stream(), cfg); }
|
|
|
|
/// 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 {
|
|
StmtPrinterHelper Helper(cfg);
|
|
print_block(OS, cfg, *this, &Helper, true);
|
|
}
|
|
|
|
/// printTerminator - A simple pretty printer of the terminator of a CFGBlock.
|
|
void CFGBlock::printTerminator(std::ostream& OS) const {
|
|
CFGBlockTerminatorPrint TPrinter(OS,NULL);
|
|
TPrinter.Visit(const_cast<Stmt*>(getTerminator()));
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// CFG Graphviz Visualization
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
#ifndef NDEBUG
|
|
static StmtPrinterHelper* GraphHelper;
|
|
#endif
|
|
|
|
void CFG::viewCFG() const {
|
|
#ifndef NDEBUG
|
|
StmtPrinterHelper H(this);
|
|
GraphHelper = &H;
|
|
llvm::ViewGraph(this,"CFG");
|
|
GraphHelper = NULL;
|
|
#else
|
|
std::cerr << "CFG::viewCFG is only available in debug builds on "
|
|
<< "systems with Graphviz or gv!\n";
|
|
#endif
|
|
}
|
|
|
|
namespace llvm {
|
|
template<>
|
|
struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
|
|
static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) {
|
|
|
|
#ifndef NDEBUG
|
|
std::ostringstream Out;
|
|
print_block(Out,Graph, *Node, GraphHelper, false);
|
|
std::string OutStr = Out.str();
|
|
|
|
if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
|
|
|
|
// Process string output to make it nicer...
|
|
for (unsigned i = 0; i != OutStr.length(); ++i)
|
|
if (OutStr[i] == '\n') { // Left justify
|
|
OutStr[i] = '\\';
|
|
OutStr.insert(OutStr.begin()+i+1, 'l');
|
|
}
|
|
|
|
return OutStr;
|
|
#else
|
|
return "";
|
|
#endif
|
|
}
|
|
};
|
|
} // end namespace llvm
|