2007-09-21 05:42:55 +08:00
|
|
|
//=- LiveVariables.cpp - Live Variable Analysis for Source CFGs -*- C++ --*-==//
|
2007-09-06 08:17:54 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file was developed by Ted Kremenek and is distributed under
|
|
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements Live Variables analysis for source-level CFGs.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/Analysis/LiveVariables.h"
|
2007-09-07 05:26:58 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2007-09-06 08:17:54 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
|
|
|
#include "clang/AST/CFG.h"
|
2007-09-21 05:42:55 +08:00
|
|
|
#include "clang/Analysis/Visitors/DataflowStmtVisitor.h"
|
2007-09-06 08:17:54 +08:00
|
|
|
#include "clang/Lex/IdentifierTable.h"
|
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2007-09-06 08:17:54 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RegisterDecls - Utility class to create VarInfo objects for all
|
|
|
|
// Decls referenced in a function.
|
|
|
|
//
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class RegisterDecls : public StmtVisitor<RegisterDecls,void> {
|
|
|
|
LiveVariables& L;
|
|
|
|
const CFG& cfg;
|
|
|
|
public:
|
|
|
|
RegisterDecls(LiveVariables& l, const CFG& c)
|
|
|
|
: L(l), cfg(c) {}
|
|
|
|
|
|
|
|
void VisitStmt(Stmt* S);
|
|
|
|
void VisitDeclRefExpr(DeclRefExpr* DR);
|
2007-09-07 07:25:10 +08:00
|
|
|
void VisitDeclStmt(DeclStmt* DS);
|
2007-09-14 07:52:58 +08:00
|
|
|
void Register(ScopedDecl* D);
|
|
|
|
void RegisterDeclChain(ScopedDecl* D);
|
2007-09-06 08:17:54 +08:00
|
|
|
void RegisterUsedDecls();
|
|
|
|
};
|
|
|
|
|
|
|
|
void RegisterDecls::VisitStmt(Stmt* S) {
|
|
|
|
for (Stmt::child_iterator I = S->child_begin(),E = S->child_end(); I != E;++I)
|
|
|
|
Visit(*I);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RegisterDecls::VisitDeclRefExpr(DeclRefExpr* DR) {
|
2007-09-07 07:25:10 +08:00
|
|
|
RegisterDeclChain(DR->getDecl());
|
|
|
|
}
|
|
|
|
|
|
|
|
void RegisterDecls::VisitDeclStmt(DeclStmt* DS) {
|
|
|
|
RegisterDeclChain(DS->getDecl());
|
|
|
|
}
|
|
|
|
|
2007-09-14 07:52:58 +08:00
|
|
|
void RegisterDecls::RegisterDeclChain(ScopedDecl* D) {
|
2007-09-07 07:25:10 +08:00
|
|
|
for (; D != NULL ; D = D->getNextDeclarator())
|
2007-09-06 08:17:54 +08:00
|
|
|
Register(D);
|
|
|
|
}
|
|
|
|
|
2007-09-14 07:52:58 +08:00
|
|
|
void RegisterDecls::Register(ScopedDecl* D) {
|
2007-09-11 01:36:42 +08:00
|
|
|
if (VarDecl* V = dyn_cast<VarDecl>(D)) {
|
|
|
|
LiveVariables::VPair& VP = L.getVarInfoMap()[V];
|
2007-09-06 08:17:54 +08:00
|
|
|
|
2007-09-11 01:36:42 +08:00
|
|
|
VP.V.AliveBlocks.resize(cfg.getNumBlockIDs());
|
|
|
|
VP.Idx = L.getNumDecls()++;
|
|
|
|
}
|
2007-09-06 08:17:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void RegisterDecls::RegisterUsedDecls() {
|
|
|
|
for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI)
|
|
|
|
for (CFGBlock::const_iterator SI=BI->begin(),SE = BI->end();SI != SE;++SI)
|
|
|
|
Visit(const_cast<Stmt*>(*SI));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// WorkList - Data structure representing the liveness algorithm worklist.
|
|
|
|
//
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class WorkListTy {
|
|
|
|
typedef llvm::SmallPtrSet<const CFGBlock*,20> BlockSet;
|
|
|
|
BlockSet wlist;
|
|
|
|
public:
|
|
|
|
void enqueue(const CFGBlock* B) { wlist.insert(B); }
|
|
|
|
|
|
|
|
const CFGBlock* dequeue() {
|
|
|
|
assert (!wlist.empty());
|
|
|
|
const CFGBlock* B = *wlist.begin();
|
|
|
|
wlist.erase(B);
|
|
|
|
return B;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isEmpty() const { return wlist.empty(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TFuncs
|
|
|
|
//
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2007-09-13 03:10:52 +08:00
|
|
|
class LivenessTFuncs : public DataflowStmtVisitor<LivenessTFuncs,
|
|
|
|
dataflow::backward_analysis_tag> {
|
2007-09-06 08:17:54 +08:00
|
|
|
LiveVariables& L;
|
|
|
|
llvm::BitVector Live;
|
2007-09-07 05:26:58 +08:00
|
|
|
llvm::BitVector KilledAtLeastOnce;
|
|
|
|
Stmt* CurrentStmt;
|
|
|
|
const CFGBlock* CurrentBlock;
|
|
|
|
bool blockPreviouslyProcessed;
|
2007-09-10 23:56:38 +08:00
|
|
|
LiveVariablesObserver* Observer;
|
2007-09-13 03:10:52 +08:00
|
|
|
|
2007-09-06 08:17:54 +08:00
|
|
|
public:
|
2007-09-10 23:56:38 +08:00
|
|
|
LivenessTFuncs(LiveVariables& l, LiveVariablesObserver* A = NULL)
|
2007-09-07 05:26:58 +08:00
|
|
|
: L(l), CurrentStmt(NULL), CurrentBlock(NULL),
|
2007-09-13 03:10:52 +08:00
|
|
|
blockPreviouslyProcessed(false), Observer(A) {
|
2007-09-06 08:17:54 +08:00
|
|
|
Live.resize(l.getNumDecls());
|
2007-09-07 05:26:58 +08:00
|
|
|
KilledAtLeastOnce.resize(l.getNumDecls());
|
2007-09-06 08:17:54 +08:00
|
|
|
}
|
2007-09-13 03:10:52 +08:00
|
|
|
|
2007-09-06 08:17:54 +08:00
|
|
|
void VisitDeclRefExpr(DeclRefExpr* DR);
|
|
|
|
void VisitBinaryOperator(BinaryOperator* B);
|
|
|
|
void VisitAssign(BinaryOperator* B);
|
2007-09-07 05:26:58 +08:00
|
|
|
void VisitDeclStmt(DeclStmt* DS);
|
|
|
|
void VisitUnaryOperator(UnaryOperator* U);
|
2007-09-13 03:10:52 +08:00
|
|
|
void ObserveStmt(Stmt* S);
|
2007-09-06 08:17:54 +08:00
|
|
|
|
2007-09-11 01:36:42 +08:00
|
|
|
unsigned getIdx(const VarDecl* D) {
|
2007-09-06 08:17:54 +08:00
|
|
|
LiveVariables::VarInfoMap& V = L.getVarInfoMap();
|
|
|
|
LiveVariables::VarInfoMap::iterator I = V.find(D);
|
|
|
|
assert (I != V.end());
|
|
|
|
return I->second.Idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ProcessBlock(const CFGBlock* B);
|
2007-09-07 05:26:58 +08:00
|
|
|
llvm::BitVector* getBlockEntryLiveness(const CFGBlock* B);
|
2007-09-11 01:36:42 +08:00
|
|
|
LiveVariables::VarInfo& KillVar(VarDecl* D);
|
2007-09-06 08:17:54 +08:00
|
|
|
};
|
|
|
|
|
2007-09-13 03:10:52 +08:00
|
|
|
void LivenessTFuncs::ObserveStmt(Stmt* S) {
|
|
|
|
if (Observer) Observer->ObserveStmt(S,L,Live);
|
2007-09-06 08:17:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void LivenessTFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
|
|
|
|
// Register a use of the variable.
|
2007-09-11 01:36:42 +08:00
|
|
|
if (VarDecl* V = dyn_cast<VarDecl>(DR->getDecl()))
|
|
|
|
Live.set(getIdx(V));
|
2007-09-06 08:17:54 +08:00
|
|
|
}
|
|
|
|
|
2007-09-13 03:10:52 +08:00
|
|
|
void LivenessTFuncs::VisitBinaryOperator(BinaryOperator* B) {
|
|
|
|
if (B->isAssignmentOp()) VisitAssign(B);
|
|
|
|
else VisitStmt(B);
|
2007-09-06 08:17:54 +08:00
|
|
|
}
|
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
void LivenessTFuncs::VisitUnaryOperator(UnaryOperator* U) {
|
|
|
|
switch (U->getOpcode()) {
|
|
|
|
case UnaryOperator::PostInc:
|
|
|
|
case UnaryOperator::PostDec:
|
|
|
|
case UnaryOperator::PreInc:
|
|
|
|
case UnaryOperator::PreDec:
|
2007-09-13 04:28:48 +08:00
|
|
|
case UnaryOperator::AddrOf:
|
2007-09-07 05:26:58 +08:00
|
|
|
// Walk through the subexpressions, blasting through ParenExprs until
|
|
|
|
// we either find a DeclRefExpr or some non-DeclRefExpr expression.
|
|
|
|
for (Stmt* S = U->getSubExpr() ; ; ) {
|
|
|
|
if (ParenExpr* P = dyn_cast<ParenExpr>(S)) {
|
|
|
|
S = P->getSubExpr();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
|
|
|
|
// Treat the --/++/& operator as a kill.
|
2007-09-11 01:36:42 +08:00
|
|
|
LiveVariables::VarInfo& V =
|
|
|
|
KillVar(cast<VarDecl>(DR->getDecl()));
|
2007-09-07 05:26:58 +08:00
|
|
|
|
|
|
|
if (!blockPreviouslyProcessed)
|
|
|
|
V.AddKill(CurrentStmt,DR);
|
|
|
|
|
|
|
|
VisitDeclRefExpr(DR);
|
|
|
|
}
|
2007-09-13 04:28:48 +08:00
|
|
|
else Visit(S);
|
2007-09-07 05:26:58 +08:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2007-09-13 04:11:39 +08:00
|
|
|
Visit(U->getSubExpr());
|
2007-09-07 05:26:58 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-11 01:36:42 +08:00
|
|
|
LiveVariables::VarInfo& LivenessTFuncs::KillVar(VarDecl* D) {
|
2007-09-07 05:26:58 +08:00
|
|
|
LiveVariables::VarInfoMap::iterator I = L.getVarInfoMap().find(D);
|
|
|
|
|
|
|
|
assert (I != L.getVarInfoMap().end() &&
|
|
|
|
"Declaration not managed by variable map in LiveVariables");
|
|
|
|
|
|
|
|
// Mark the variable dead, and remove the current block from
|
|
|
|
// the set of blocks where the variable may be alive the entire time.
|
|
|
|
Live.reset(I->second.Idx);
|
|
|
|
I->second.V.AliveBlocks.reset(CurrentBlock->getBlockID());
|
|
|
|
|
|
|
|
return I->second.V;
|
|
|
|
}
|
2007-09-06 08:17:54 +08:00
|
|
|
|
2007-09-13 03:10:52 +08:00
|
|
|
void LivenessTFuncs::VisitAssign(BinaryOperator* B) {
|
2007-09-07 05:26:58 +08:00
|
|
|
// Check if we are assigning to a variable.
|
2007-09-06 08:17:54 +08:00
|
|
|
Stmt* LHS = B->getLHS();
|
2007-09-07 05:26:58 +08:00
|
|
|
|
2007-09-06 08:17:54 +08:00
|
|
|
if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
|
2007-09-11 01:36:42 +08:00
|
|
|
LiveVariables::VarInfo& V = KillVar(cast<VarDecl>(DR->getDecl()));
|
2007-09-07 05:26:58 +08:00
|
|
|
|
|
|
|
// We only need to register kills once, so we check if this block
|
|
|
|
// has been previously processed.
|
|
|
|
if (!blockPreviouslyProcessed)
|
2007-09-07 07:39:53 +08:00
|
|
|
V.AddKill(CurrentStmt,DR);
|
|
|
|
|
|
|
|
if (B->getOpcode() != BinaryOperator::Assign)
|
|
|
|
Visit(LHS);
|
2007-09-06 08:17:54 +08:00
|
|
|
}
|
2007-09-07 05:26:58 +08:00
|
|
|
else
|
|
|
|
Visit(LHS);
|
2007-09-06 08:17:54 +08:00
|
|
|
|
|
|
|
Visit(B->getRHS());
|
|
|
|
}
|
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
void LivenessTFuncs::VisitDeclStmt(DeclStmt* DS) {
|
|
|
|
// Declarations effectively "kill" a variable since they cannot possibly
|
|
|
|
// be live before they are declared. Declarations, however, are not kills
|
|
|
|
// in the sense that the value is obliterated, so we do not register
|
|
|
|
// DeclStmts as a "kill site" for a variable.
|
2007-09-14 07:52:58 +08:00
|
|
|
for (ScopedDecl* D = DS->getDecl(); D != NULL ; D = D->getNextDeclarator())
|
2007-09-11 01:36:42 +08:00
|
|
|
KillVar(cast<VarDecl>(D));
|
2007-09-07 05:26:58 +08:00
|
|
|
}
|
2007-09-06 08:17:54 +08:00
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
llvm::BitVector* LivenessTFuncs::getBlockEntryLiveness(const CFGBlock* B) {
|
2007-09-06 08:17:54 +08:00
|
|
|
LiveVariables::BlockLivenessMap& BMap = L.getLiveAtBlockEntryMap();
|
|
|
|
|
|
|
|
LiveVariables::BlockLivenessMap::iterator I = BMap.find(B);
|
|
|
|
return (I == BMap.end()) ? NULL : &(I->second);
|
|
|
|
}
|
|
|
|
|
2007-09-13 03:10:52 +08:00
|
|
|
|
2007-09-06 08:17:54 +08:00
|
|
|
bool LivenessTFuncs::ProcessBlock(const CFGBlock* B) {
|
2007-09-07 05:26:58 +08:00
|
|
|
|
|
|
|
CurrentBlock = B;
|
2007-09-06 08:17:54 +08:00
|
|
|
Live.reset();
|
2007-09-07 05:26:58 +08:00
|
|
|
KilledAtLeastOnce.reset();
|
|
|
|
|
|
|
|
// Check if this block has been previously processed.
|
|
|
|
LiveVariables::BlockLivenessMap& BMap = L.getLiveAtBlockEntryMap();
|
|
|
|
LiveVariables::BlockLivenessMap::iterator BI = BMap.find(B);
|
|
|
|
|
|
|
|
blockPreviouslyProcessed = BI != BMap.end();
|
2007-09-06 08:17:54 +08:00
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
// Merge liveness information from all predecessors.
|
2007-09-06 08:17:54 +08:00
|
|
|
for (CFGBlock::const_succ_iterator I=B->succ_begin(),E=B->succ_end();I!=E;++I)
|
2007-09-07 05:26:58 +08:00
|
|
|
if (llvm::BitVector* V = getBlockEntryLiveness(*I))
|
2007-09-06 08:17:54 +08:00
|
|
|
Live |= *V;
|
2007-09-07 05:26:58 +08:00
|
|
|
|
2007-09-10 23:56:38 +08:00
|
|
|
if (Observer)
|
2007-09-13 03:10:52 +08:00
|
|
|
Observer->ObserveBlockExit(B,L,Live);
|
2007-09-07 05:26:58 +08:00
|
|
|
|
|
|
|
// Tentatively mark all variables alive at the end of the current block
|
|
|
|
// as being alive during the whole block. We then cull these out as
|
|
|
|
// we process the statements of this block.
|
|
|
|
for (LiveVariables::VarInfoMap::iterator
|
|
|
|
I=L.getVarInfoMap().begin(), E=L.getVarInfoMap().end(); I != E; ++I)
|
|
|
|
if (Live[I->second.Idx])
|
|
|
|
I->second.V.AliveBlocks.set(B->getBlockID());
|
2007-09-06 08:17:54 +08:00
|
|
|
|
2007-09-13 03:10:52 +08:00
|
|
|
// Visit the statements in reverse order;
|
|
|
|
VisitBlock(B);
|
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
// Compare the computed "Live" values with what we already have
|
|
|
|
// for the entry to this block.
|
2007-09-06 08:17:54 +08:00
|
|
|
bool hasChanged = false;
|
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
if (!blockPreviouslyProcessed) {
|
|
|
|
// We have not previously calculated liveness information for this block.
|
|
|
|
// Lazily instantiate a bitvector, and copy the bits from Live.
|
2007-09-06 08:17:54 +08:00
|
|
|
hasChanged = true;
|
|
|
|
llvm::BitVector& V = BMap[B];
|
|
|
|
V.resize(L.getNumDecls());
|
2007-09-07 05:26:58 +08:00
|
|
|
V = Live;
|
2007-09-06 08:17:54 +08:00
|
|
|
}
|
2007-09-07 05:26:58 +08:00
|
|
|
else if (BI->second != Live) {
|
2007-09-06 08:17:54 +08:00
|
|
|
hasChanged = true;
|
2007-09-07 05:26:58 +08:00
|
|
|
BI->second = Live;
|
2007-09-06 08:17:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return hasChanged;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// runOnCFG - Method to run the actual liveness computation.
|
|
|
|
//
|
|
|
|
|
2007-09-10 23:56:38 +08:00
|
|
|
void LiveVariables::runOnCFG(const CFG& cfg, LiveVariablesObserver* Observer) {
|
2007-09-06 08:17:54 +08:00
|
|
|
// Scan a CFG for DeclRefStmts. For each one, create a VarInfo object.
|
|
|
|
{
|
|
|
|
RegisterDecls R(*this,cfg);
|
|
|
|
R.RegisterUsedDecls();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the worklist and enqueue the exit block.
|
|
|
|
WorkListTy WorkList;
|
|
|
|
WorkList.enqueue(&cfg.getExit());
|
|
|
|
|
|
|
|
// Create the state for transfer functions.
|
2007-09-10 23:56:38 +08:00
|
|
|
LivenessTFuncs TF(*this,Observer);
|
2007-09-06 08:17:54 +08:00
|
|
|
|
|
|
|
// Process the worklist until it is empty.
|
|
|
|
|
|
|
|
while (!WorkList.isEmpty()) {
|
|
|
|
const CFGBlock* B = WorkList.dequeue();
|
|
|
|
if (TF.ProcessBlock(B))
|
|
|
|
for (CFGBlock::const_pred_iterator I = B->pred_begin(), E = B->pred_end();
|
|
|
|
I != E; ++I)
|
|
|
|
WorkList.enqueue(*I);
|
|
|
|
}
|
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
// Go through each block and reserve a bitvector. This is needed if
|
|
|
|
// a block was never visited by the worklist algorithm.
|
2007-09-06 08:17:54 +08:00
|
|
|
for (CFG::const_iterator I = cfg.begin(), E = cfg.end(); I != E; ++I)
|
|
|
|
LiveAtBlockEntryMap[&(*I)].resize(NumDecls);
|
|
|
|
}
|
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
|
2007-09-10 23:56:38 +08:00
|
|
|
void LiveVariables::runOnBlock(const CFGBlock* B,
|
|
|
|
LiveVariablesObserver* Observer)
|
2007-09-07 05:26:58 +08:00
|
|
|
{
|
2007-09-10 23:56:38 +08:00
|
|
|
LivenessTFuncs TF(*this,Observer);
|
2007-09-07 05:26:58 +08:00
|
|
|
TF.ProcessBlock(B);
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// liveness queries
|
|
|
|
//
|
|
|
|
|
2007-09-11 01:36:42 +08:00
|
|
|
bool LiveVariables::isLive(const CFGBlock* B, const VarDecl* D) const {
|
2007-09-07 05:26:58 +08:00
|
|
|
BlockLivenessMap::const_iterator I = LiveAtBlockEntryMap.find(B);
|
|
|
|
assert (I != LiveAtBlockEntryMap.end());
|
|
|
|
|
|
|
|
VarInfoMap::const_iterator VI = VarInfos.find(D);
|
|
|
|
assert (VI != VarInfos.end());
|
|
|
|
|
|
|
|
return I->second[VI->second.Idx];
|
|
|
|
}
|
|
|
|
|
2007-09-11 01:36:42 +08:00
|
|
|
bool LiveVariables::isLive(llvm::BitVector& Live, const VarDecl* D) const {
|
2007-09-07 07:00:42 +08:00
|
|
|
VarInfoMap::const_iterator VI = VarInfos.find(D);
|
|
|
|
assert (VI != VarInfos.end());
|
|
|
|
return Live[VI->second.Idx];
|
|
|
|
}
|
|
|
|
|
2007-09-11 01:36:42 +08:00
|
|
|
bool LiveVariables::KillsVar(const Stmt* S, const VarDecl* D) const {
|
2007-09-07 05:26:58 +08:00
|
|
|
VarInfoMap::const_iterator VI = VarInfos.find(D);
|
|
|
|
assert (VI != VarInfos.end());
|
|
|
|
|
|
|
|
for (VarInfo::KillsSet::const_iterator
|
|
|
|
I = VI->second.V.Kills.begin(), E = VI->second.V.Kills.end(); I!=E;++I)
|
|
|
|
if (I->first == S)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-09-11 01:36:42 +08:00
|
|
|
LiveVariables::VarInfo& LiveVariables::getVarInfo(const VarDecl* D) {
|
2007-09-07 05:26:58 +08:00
|
|
|
VarInfoMap::iterator VI = VarInfos.find(D);
|
|
|
|
assert (VI != VarInfos.end());
|
|
|
|
return VI->second.V;
|
|
|
|
}
|
|
|
|
|
2007-09-11 01:36:42 +08:00
|
|
|
const LiveVariables::VarInfo& LiveVariables::getVarInfo(const VarDecl* D) const{
|
2007-09-07 05:26:58 +08:00
|
|
|
return const_cast<LiveVariables*>(this)->getVarInfo(D);
|
|
|
|
}
|
|
|
|
|
2007-09-06 08:17:54 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2007-09-10 23:56:38 +08:00
|
|
|
// Defaults for LiveVariablesObserver
|
2007-09-07 07:00:42 +08:00
|
|
|
|
2007-09-10 23:56:38 +08:00
|
|
|
void LiveVariablesObserver::ObserveStmt(Stmt* S, LiveVariables& L,
|
|
|
|
llvm::BitVector& V) {}
|
2007-09-07 07:00:42 +08:00
|
|
|
|
2007-09-10 23:56:38 +08:00
|
|
|
void LiveVariablesObserver::ObserveBlockExit(const CFGBlock* B,
|
|
|
|
LiveVariables& L,
|
|
|
|
llvm::BitVector& V) {}
|
2007-09-07 07:00:42 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
2007-09-06 08:17:54 +08:00
|
|
|
// printing liveness state for debugging
|
|
|
|
//
|
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
void LiveVariables::dumpLiveness(const llvm::BitVector& V,
|
|
|
|
SourceManager& SM) const {
|
2007-09-06 08:17:54 +08:00
|
|
|
|
|
|
|
for (VarInfoMap::iterator I = VarInfos.begin(), E=VarInfos.end(); I!=E; ++I) {
|
|
|
|
if (V[I->second.Idx]) {
|
2007-09-07 05:26:58 +08:00
|
|
|
|
|
|
|
SourceLocation PhysLoc = SM.getPhysicalLoc(I->first->getLocation());
|
|
|
|
|
|
|
|
fprintf(stderr, " %s <%s:%u:%u>\n",
|
|
|
|
I->first->getIdentifier()->getName(),
|
|
|
|
SM.getSourceName(PhysLoc),
|
|
|
|
SM.getLineNumber(PhysLoc),
|
|
|
|
SM.getColumnNumber(PhysLoc));
|
2007-09-06 08:17:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
void LiveVariables::dumpBlockLiveness(SourceManager& M) const {
|
2007-09-06 08:17:54 +08:00
|
|
|
for (BlockLivenessMap::iterator I = LiveAtBlockEntryMap.begin(),
|
|
|
|
E = LiveAtBlockEntryMap.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
|
2007-09-07 05:26:58 +08:00
|
|
|
fprintf(stderr,
|
|
|
|
"\n[ B%d (live variables at block entry) ]\n",
|
|
|
|
I->first->getBlockID());
|
|
|
|
|
|
|
|
dumpLiveness(I->second,M);
|
|
|
|
}
|
2007-09-11 01:36:42 +08:00
|
|
|
|
|
|
|
fprintf(stderr,"\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void LiveVariables::dumpVarLiveness(SourceManager& SM) const {
|
|
|
|
|
|
|
|
for (VarInfoMap::iterator I = VarInfos.begin(), E=VarInfos.end(); I!=E; ++I) {
|
|
|
|
SourceLocation PhysLoc = SM.getPhysicalLoc(I->first->getLocation());
|
|
|
|
|
|
|
|
fprintf(stderr, "[ %s <%s:%u:%u> ]\n",
|
|
|
|
I->first->getIdentifier()->getName(),
|
|
|
|
SM.getSourceName(PhysLoc),
|
|
|
|
SM.getLineNumber(PhysLoc),
|
|
|
|
SM.getColumnNumber(PhysLoc));
|
|
|
|
|
|
|
|
I->second.V.Dump(SM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LiveVariables::VarInfo::Dump(SourceManager& SM) const {
|
|
|
|
fprintf(stderr," Blocks Alive:");
|
|
|
|
for (unsigned i = 0; i < AliveBlocks.size(); ++i) {
|
|
|
|
if (i % 5 == 0)
|
|
|
|
fprintf(stderr,"\n ");
|
|
|
|
|
|
|
|
fprintf(stderr," B%d", i);
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr,"\n Kill Sites:\n");
|
|
|
|
for (KillsSet::const_iterator I = Kills.begin(), E = Kills.end(); I!=E; ++I) {
|
|
|
|
SourceLocation PhysLoc =
|
|
|
|
SM.getPhysicalLoc(I->second->getSourceRange().Begin());
|
|
|
|
|
|
|
|
fprintf(stderr, " <%s:%u:%u>\n",
|
|
|
|
SM.getSourceName(PhysLoc),
|
|
|
|
SM.getLineNumber(PhysLoc),
|
|
|
|
SM.getColumnNumber(PhysLoc));
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr,"\n");
|
2007-09-11 23:32:40 +08:00
|
|
|
}
|