1483 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1483 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>
 | 
						|
 | 
						|
 | 
						|
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);
 | 
						|
  
 | 
						|
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);
 | 
						|
  CFGBlock* WalkAST_VisitCallExpr(CallExpr* C);
 | 
						|
  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* CFGBuilder::buildCFG(Stmt* Statement) {
 | 
						|
  assert (cfg);
 | 
						|
  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.
 | 
						|
  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.
 | 
						|
  if (CFGBlock* B = Visit(Statement)) {
 | 
						|
    // 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());
 | 
						|
    
 | 
						|
  // 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::CallExprClass:
 | 
						|
      return WalkAST_VisitCallExpr(cast<CallExpr>(S));
 | 
						|
      
 | 
						|
    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;
 | 
						|
    }
 | 
						|
    
 | 
						|
    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);
 | 
						|
  
 | 
						|
  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());  
 | 
						|
}
 | 
						|
 | 
						|
/// WalkAST_VisitCallExpr - Utility method to handle function calls that
 | 
						|
///  are nested in expressions.  The idea is that each function call should
 | 
						|
///  appear as a distinct statement in the CFGBlock.
 | 
						|
CFGBlock* CFGBuilder::WalkAST_VisitCallExpr(CallExpr* C) {
 | 
						|
  Block->appendStmt(C);
 | 
						|
  return WalkAST_VisitChildren(C);
 | 
						|
}
 | 
						|
 | 
						|
/// 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) {
 | 
						|
  //   The value returned from this function is the last created CFGBlock
 | 
						|
  //   that represents the "entry" point for the translated AST node.
 | 
						|
  CFGBlock* LastBlock = 0;
 | 
						|
  
 | 
						|
  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;
 | 
						|
  
 | 
						|
  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.
 | 
						|
  CFGBlock* LabelBlock = Visit(L->getSubStmt());
 | 
						|
  
 | 
						|
  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 = ExitConditionBlock; // 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;
 | 
						|
    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);
 | 
						|
    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 = ExitConditionBlock; // 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.
 | 
						|
  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 as
 | 
						|
  // well as any code above the loop.
 | 
						|
  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 = ExitConditionBlock; // 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.
 | 
						|
  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
 |