Modified DataFlowValues and DataflowSolver to associate dataflow value
with CFG *edges* instead of blocks. This will fascilitate dataflow analyses that are sensitive to block terminators, and also simplifies some reasoning. Updated UninitializedValues to comply to this new interface. llvm-svn: 42099
This commit is contained in:
parent
1d77d76837
commit
584e21a349
|
@ -61,7 +61,7 @@ public:
|
||||||
|
|
||||||
typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag;
|
typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag;
|
||||||
typedef typename _DFValuesTy::ValTy ValTy;
|
typedef typename _DFValuesTy::ValTy ValTy;
|
||||||
typedef typename _DFValuesTy::BlockDataMapTy BlockDataMapTy;
|
typedef typename _DFValuesTy::EdgeDataMapTy EdgeDataMapTy;
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// External interface: constructing and running the solver.
|
// External interface: constructing and running the solver.
|
||||||
|
@ -75,8 +75,9 @@ public:
|
||||||
void runOnCFG(const CFG& cfg) {
|
void runOnCFG(const CFG& cfg) {
|
||||||
// Set initial dataflow values and boundary conditions.
|
// Set initial dataflow values and boundary conditions.
|
||||||
D.InitializeValues(cfg);
|
D.InitializeValues(cfg);
|
||||||
// Tag dispatch to the kind of analysis we do: forward or backwards.
|
// Solve the dataflow equations. This will populate D.EdgeDataMap
|
||||||
SolveDataflowEquations(cfg,typename _DFValuesTy::AnalysisDirTag());
|
// with dataflow values.
|
||||||
|
SolveDataflowEquations(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// runOnBlock - Computes dataflow values for a given block.
|
/// runOnBlock - Computes dataflow values for a given block.
|
||||||
|
@ -85,7 +86,7 @@ public:
|
||||||
/// only be used for querying the dataflow values within a block with
|
/// only be used for querying the dataflow values within a block with
|
||||||
/// and Observer object.
|
/// and Observer object.
|
||||||
void runOnBlock(const CFGBlock* B) {
|
void runOnBlock(const CFGBlock* B) {
|
||||||
if (D.getBlockDataMap().find(B) == D.getBlockDataMap().end())
|
if (!hasData(B,AnalysisDirTag()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TransferFuncsTy TF (D.getAnalysisData());
|
TransferFuncsTy TF (D.getAnalysisData());
|
||||||
|
@ -98,39 +99,11 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// SolveDataflowEquations (FORWARD ANALYSIS) - Perform the actual
|
/// SolveDataflowEquations - Perform the actual
|
||||||
/// worklist algorithm to compute dataflow values.
|
|
||||||
void SolveDataflowEquations(const CFG& cfg, dataflow::forward_analysis_tag) {
|
|
||||||
// Create the worklist.
|
|
||||||
DataflowWorkListTy WorkList;
|
|
||||||
|
|
||||||
// Enqueue the ENTRY block.
|
|
||||||
WorkList.enqueue(&cfg.getEntry());
|
|
||||||
|
|
||||||
// Create the state for transfer functions.
|
|
||||||
TransferFuncsTy TF(D.getAnalysisData());
|
|
||||||
|
|
||||||
// Process the worklist until it is empty.
|
|
||||||
while (!WorkList.isEmpty()) {
|
|
||||||
const CFGBlock* B = WorkList.dequeue();
|
|
||||||
// If the dataflow values at the block's exit have changed,
|
|
||||||
// enqueue all successor blocks onto the worklist to have
|
|
||||||
// their values updated.
|
|
||||||
if (ProcessBlock(B,TF,AnalysisDirTag()))
|
|
||||||
for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
|
|
||||||
I != E; ++I)
|
|
||||||
WorkList.enqueue(*I);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// SolveDataflowEquations (BACKWARD ANALYSIS) - Perform the actual
|
|
||||||
/// worklist algorithm to compute dataflow values.
|
/// worklist algorithm to compute dataflow values.
|
||||||
void SolveDataflowEquations(const CFG& cfg, dataflow::backward_analysis_tag) {
|
void SolveDataflowEquations(const CFG& cfg) {
|
||||||
// Create the worklist.
|
|
||||||
DataflowWorkListTy WorkList;
|
EnqueueFirstBlock(cfg,AnalysisDirTag());
|
||||||
|
|
||||||
// Enqueue the EXIT block.
|
|
||||||
WorkList.enqueue(&cfg.getExit());
|
|
||||||
|
|
||||||
// Create the state for transfer functions.
|
// Create the state for transfer functions.
|
||||||
TransferFuncsTy TF(D.getAnalysisData());
|
TransferFuncsTy TF(D.getAnalysisData());
|
||||||
|
@ -141,16 +114,22 @@ private:
|
||||||
// If the dataflow values at the block's entry have changed,
|
// If the dataflow values at the block's entry have changed,
|
||||||
// enqueue all predecessor blocks onto the worklist to have
|
// enqueue all predecessor blocks onto the worklist to have
|
||||||
// their values updated.
|
// their values updated.
|
||||||
if (ProcessBlock(B,TF,AnalysisDirTag()))
|
ProcessBlock(B,TF,AnalysisDirTag());
|
||||||
for (CFGBlock::const_pred_iterator I=B->pred_begin(), E=B->pred_end();
|
UpdateEdges(B,TF.getVal(),AnalysisDirTag());
|
||||||
I != E; ++I)
|
|
||||||
WorkList.enqueue(*I);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EnqueueFirstBlock(const CFG& cfg, dataflow::forward_analysis_tag) {
|
||||||
|
WorkList.enqueue(&cfg.getEntry());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnqueueFirstBlock(const CFG& cfg, dataflow::backward_analysis_tag) {
|
||||||
|
WorkList.enqueue(&cfg.getExit());
|
||||||
|
}
|
||||||
|
|
||||||
/// ProcessBlock (FORWARD ANALYSIS) - Process the transfer functions
|
/// ProcessBlock (FORWARD ANALYSIS) - Process the transfer functions
|
||||||
/// for a given block based on a forward analysis.
|
/// for a given block based on a forward analysis.
|
||||||
bool ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
|
void ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
|
||||||
dataflow::forward_analysis_tag) {
|
dataflow::forward_analysis_tag) {
|
||||||
|
|
||||||
ValTy& V = TF.getVal();
|
ValTy& V = TF.getVal();
|
||||||
|
@ -159,12 +138,12 @@ private:
|
||||||
V.resetValues(D.getAnalysisData());
|
V.resetValues(D.getAnalysisData());
|
||||||
MergeOperatorTy Merge;
|
MergeOperatorTy Merge;
|
||||||
|
|
||||||
BlockDataMapTy& M = D.getBlockDataMap();
|
EdgeDataMapTy& M = D.getEdgeDataMap();
|
||||||
bool firstMerge = true;
|
bool firstMerge = true;
|
||||||
|
|
||||||
for (CFGBlock::const_pred_iterator I=B->pred_begin(),
|
for (CFGBlock::const_pred_iterator I=B->pred_begin(),
|
||||||
E=B->pred_end(); I!=E; ++I) {
|
E=B->pred_end(); I!=E; ++I) {
|
||||||
typename BlockDataMapTy::iterator BI = M.find(*I);
|
typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(*I,B));
|
||||||
if (BI != M.end()) {
|
if (BI != M.end()) {
|
||||||
if (firstMerge) {
|
if (firstMerge) {
|
||||||
firstMerge = false;
|
firstMerge = false;
|
||||||
|
@ -177,14 +156,12 @@ private:
|
||||||
|
|
||||||
// Process the statements in the block in the forward direction.
|
// Process the statements in the block in the forward direction.
|
||||||
for (CFGBlock::const_iterator I=B->begin(), E=B->end(); I!=E; ++I)
|
for (CFGBlock::const_iterator I=B->begin(), E=B->end(); I!=E; ++I)
|
||||||
TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
|
TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
|
||||||
|
|
||||||
return UpdateBlockValue(B,V);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ProcessBlock (BACKWARD ANALYSIS) - Process the transfer functions
|
/// ProcessBlock (BACKWARD ANALYSIS) - Process the transfer functions
|
||||||
/// for a given block based on a forward analysis.
|
/// for a given block based on a forward analysis.
|
||||||
bool ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
|
void ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
|
||||||
dataflow::backward_analysis_tag) {
|
dataflow::backward_analysis_tag) {
|
||||||
|
|
||||||
ValTy& V = TF.getVal();
|
ValTy& V = TF.getVal();
|
||||||
|
@ -193,12 +170,12 @@ private:
|
||||||
V.resetValues(D.getAnalysisData());
|
V.resetValues(D.getAnalysisData());
|
||||||
MergeOperatorTy Merge;
|
MergeOperatorTy Merge;
|
||||||
|
|
||||||
BlockDataMapTy& M = D.getBlockDataMap();
|
EdgeDataMapTy& M = D.getEdgeDataMap();
|
||||||
bool firstMerge = true;
|
bool firstMerge = true;
|
||||||
|
|
||||||
for (CFGBlock::const_succ_iterator I=B->succ_begin(),
|
for (CFGBlock::const_succ_iterator I=B->succ_begin(),
|
||||||
E=B->succ_end(); I!=E; ++I) {
|
E=B->succ_end(); I!=E; ++I) {
|
||||||
typename BlockDataMapTy::iterator BI = M.find(*I);
|
typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(B,*I));
|
||||||
if (BI != M.end()) {
|
if (BI != M.end()) {
|
||||||
if (firstMerge) {
|
if (firstMerge) {
|
||||||
firstMerge = false;
|
firstMerge = false;
|
||||||
|
@ -211,34 +188,81 @@ private:
|
||||||
|
|
||||||
// Process the statements in the block in the forward direction.
|
// Process the statements in the block in the forward direction.
|
||||||
for (CFGBlock::const_reverse_iterator I=B->begin(), E=B->end(); I!=E; ++I)
|
for (CFGBlock::const_reverse_iterator I=B->begin(), E=B->end(); I!=E; ++I)
|
||||||
TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
|
TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
|
||||||
|
}
|
||||||
return UpdateBlockValue(B,V);
|
|
||||||
|
/// UpdateEdges (FORWARD ANALYSIS) - After processing the transfer
|
||||||
|
/// functions for a block, update the dataflow value associated with the
|
||||||
|
/// block's outgoing edges. Enqueue any successor blocks for an
|
||||||
|
/// outgoing edge whose value has changed.
|
||||||
|
void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::forward_analysis_tag) {
|
||||||
|
for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
|
||||||
|
I!=E; ++I) {
|
||||||
|
|
||||||
|
CFG::Edge E(B,*I);
|
||||||
|
UpdateEdgeValue(E,V,*I);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// UpdateBlockValue - After processing the transfer functions for a block,
|
/// UpdateEdges (BACKWARD ANALYSIS) - After processing the transfer
|
||||||
/// update the dataflow value associated with the block. Return true
|
/// functions for a block, update the dataflow value associated with the
|
||||||
/// if the block's value has changed. We do lazy instantiation of block
|
/// block's incoming edges. Enqueue any predecessor blocks for an
|
||||||
/// values, so if the block value has not been previously computed we
|
/// outgoing edge whose value has changed.
|
||||||
/// obviously return true.
|
void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::backward_analysis_tag){
|
||||||
bool UpdateBlockValue(const CFGBlock* B, ValTy& V) {
|
for (CFGBlock::const_pred_iterator I=B->succ_begin(), E=B->succ_end();
|
||||||
BlockDataMapTy& M = D.getBlockDataMap();
|
I!=E; ++I) {
|
||||||
typename BlockDataMapTy::iterator I = M.find(B);
|
|
||||||
|
CFG::Edge E(*I,B);
|
||||||
|
UpdateEdgeValue(E,V,*I);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// UpdateEdgeValue - Update the value associated with a given edge.
|
||||||
|
void UpdateEdgeValue(CFG::Edge& E, ValTy& V, const CFGBlock* TargetBlock) {
|
||||||
|
|
||||||
|
EdgeDataMapTy& M = D.getEdgeDataMap();
|
||||||
|
typename EdgeDataMapTy::iterator I = M.find(E);
|
||||||
|
|
||||||
if (I == M.end()) {
|
if (I == M.end()) {
|
||||||
M[B].copyValues(V);
|
// First value for this edge.
|
||||||
return true;
|
M[E].copyValues(V);
|
||||||
|
WorkList.enqueue(TargetBlock);
|
||||||
}
|
}
|
||||||
else if (!V.equal(I->second)) {
|
else if (!V.equal(I->second)) {
|
||||||
I->second.copyValues(V);
|
I->second.copyValues(V);
|
||||||
return true;
|
WorkList.enqueue(TargetBlock);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// hasData (FORWARD ANALYSIS) - Is there any dataflow values associated
|
||||||
|
/// with the incoming edges of a block?
|
||||||
|
bool hasData(const CFGBlock* B, dataflow::forward_analysis_tag) {
|
||||||
|
EdgeDataMapTy& M = D.getEdgeDataMap();
|
||||||
|
|
||||||
|
for (CFGBlock::const_pred_iterator I=B->pred_begin(), E=B->pred_end();
|
||||||
|
I!=E; ++I)
|
||||||
|
if (M.find(CFG::Edge(*I,B)) != M.end())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// hasData (BACKWARD ANALYSIS) - Is there any dataflow values associated
|
||||||
|
/// with the outgoing edges of a block?
|
||||||
|
bool hasData(const CFGBlock* B, dataflow::backward_analysis_tag) {
|
||||||
|
EdgeDataMapTy& M = D.getEdgeDataMap();
|
||||||
|
|
||||||
|
for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
|
||||||
|
I!=E; ++I)
|
||||||
|
if (M.find(CFG::Edge(B,*I)) != M.end())
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DFValuesTy& D;
|
DFValuesTy& D;
|
||||||
|
DataflowWorkListTy WorkList;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -73,10 +73,6 @@ void UninitializedValues::InitializeValues(const CFG& cfg) {
|
||||||
for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
|
for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
|
||||||
for (CFGBlock::const_iterator BI=I->begin(), BE=I->end(); BI!=BE; ++BI)
|
for (CFGBlock::const_iterator BI=I->begin(), BE=I->end(); BI!=BE; ++BI)
|
||||||
R.BlockStmt_Visit(*BI);
|
R.BlockStmt_Visit(*BI);
|
||||||
|
|
||||||
// Initialize the values of the last block.
|
|
||||||
// UninitializedValues::ValTy& V = getBlockDataMap()[&cfg.getEntry()];
|
|
||||||
// V.resetValues(getAnalysisData());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -19,22 +19,57 @@
|
||||||
#include "clang/AST/CFG.h"
|
#include "clang/AST/CFG.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
|
||||||
namespace clang {
|
//===----------------------------------------------------------------------===//
|
||||||
|
// DenseMapInfo for CFG::Edge for use with DenseMap
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
template <> struct DenseMapInfo<clang::CFG::Edge> {
|
||||||
|
static inline clang::CFG::Edge getEmptyKey() {
|
||||||
|
return clang::CFG::Edge(NULL,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline clang::CFG::Edge getTombstoneKey() {
|
||||||
|
return clang::CFG::Edge(NULL,reinterpret_cast<clang::CFGBlock*>(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned getHashValue(const clang::CFG::Edge& E) {
|
||||||
|
const clang::CFGBlock* P1 = E.getSrc();
|
||||||
|
const clang::CFGBlock* P2 = E.getDst();
|
||||||
|
return (reinterpret_cast<unsigned>(P1) >> 4) ^
|
||||||
|
(reinterpret_cast<unsigned>(P1) >> 9) ^
|
||||||
|
(reinterpret_cast<unsigned>(P2) >> 5) ^
|
||||||
|
(reinterpret_cast<unsigned>(P2) >> 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isEqual(const clang::CFG::Edge& LHS,
|
||||||
|
const clang::CFG::Edge& RHS) {
|
||||||
|
return LHS == RHS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isPod() { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
/// Dataflow Directional Tag Classes. These are used for tag dispatching
|
||||||
|
/// within the dataflow solver/transfer functions to determine what direction
|
||||||
|
/// a dataflow analysis flows.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
namespace clang {
|
||||||
namespace dataflow {
|
namespace dataflow {
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
/// Dataflow Directional Tag Classes. These are used for tag dispatching
|
|
||||||
/// within the dataflow solver/transfer functions to determine what direction
|
|
||||||
/// a dataflow analysis flows.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
struct forward_analysis_tag {};
|
struct forward_analysis_tag {};
|
||||||
struct backward_analysis_tag {};
|
struct backward_analysis_tag {};
|
||||||
|
|
||||||
} // end namespace dataflow
|
} // end namespace dataflow
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
/// DataflowValues. Container class to store dataflow values for a CFG.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
template <typename ValueTypes,
|
template <typename ValueTypes,
|
||||||
typename _AnalysisDirTag = dataflow::forward_analysis_tag >
|
typename _AnalysisDirTag = dataflow::forward_analysis_tag >
|
||||||
class DataflowValues {
|
class DataflowValues {
|
||||||
|
@ -46,8 +81,8 @@ class DataflowValues {
|
||||||
public:
|
public:
|
||||||
typedef typename ValueTypes::ValTy ValTy;
|
typedef typename ValueTypes::ValTy ValTy;
|
||||||
typedef typename ValueTypes::AnalysisDataTy AnalysisDataTy;
|
typedef typename ValueTypes::AnalysisDataTy AnalysisDataTy;
|
||||||
typedef _AnalysisDirTag AnalysisDirTag;
|
typedef _AnalysisDirTag AnalysisDirTag;
|
||||||
typedef llvm::DenseMap<const CFGBlock*, ValTy> BlockDataMapTy;
|
typedef llvm::DenseMap<CFG::Edge, ValTy> EdgeDataMapTy;
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Predicates.
|
// Predicates.
|
||||||
|
@ -55,19 +90,15 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// isForwardAnalysis - Returns true if the dataflow values are computed
|
/// isForwardAnalysis - Returns true if the dataflow values are computed
|
||||||
/// from a forward analysis. If this returns true, the value returned
|
/// from a forward analysis.
|
||||||
/// from getBlockData() is the dataflow values associated with the END of
|
|
||||||
/// the block.
|
|
||||||
bool isForwardAnalysis() { return isForwardAnalysis(AnalysisDirTag()); }
|
bool isForwardAnalysis() { return isForwardAnalysis(AnalysisDirTag()); }
|
||||||
|
|
||||||
/// isBackwardAnalysis - Returns true if the dataflow values are computed
|
/// isBackwardAnalysis - Returns true if the dataflow values are computed
|
||||||
/// from a backward analysis. If this returns true, the value returned
|
/// from a backward analysis.
|
||||||
/// from getBlockData() is the dataflow values associated with the ENTRY of
|
|
||||||
/// the block.
|
|
||||||
bool isBackwardAnalysis() { return !isForwardAnalysis(); }
|
bool isBackwardAnalysis() { return !isForwardAnalysis(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isForwardAnalysis(dataflow::forward_analysis_tag) { return true; }
|
bool isForwardAnalysis(dataflow::forward_analysis_tag) { return true; }
|
||||||
bool isForwardAnalysis(dataflow::backward_analysis_tag) { return false; }
|
bool isForwardAnalysis(dataflow::backward_analysis_tag) { return false; }
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
@ -79,25 +110,25 @@ public:
|
||||||
/// dataflow analysis. This method is usually specialized by subclasses.
|
/// dataflow analysis. This method is usually specialized by subclasses.
|
||||||
void InitializeValues(const CFG& cfg) {};
|
void InitializeValues(const CFG& cfg) {};
|
||||||
|
|
||||||
/// getBlockData - Retrieves the dataflow values associated with a
|
/// getEdgeData - Retrieves the dataflow values associated with a
|
||||||
/// specified CFGBlock. If the dataflow analysis is a forward analysis,
|
/// specified CFGBlock. If the dataflow analysis is a forward analysis,
|
||||||
/// this data is associated with the END of the block. If the analysis
|
/// this data is associated with the END of the block. If the analysis
|
||||||
/// is a backwards analysis, it is associated with the ENTRY of the block.
|
/// is a backwards analysis, it is associated with the ENTRY of the block.
|
||||||
ValTy& getBlockData(const CFGBlock* B) {
|
ValTy& getEdgeData(const CFG::Edge& E) {
|
||||||
typename BlockDataMapTy::iterator I = BlockDataMap.find(B);
|
typename EdgeDataMapTy::iterator I = EdgeDataMap.find(E);
|
||||||
assert (I != BlockDataMap.end() && "No data associated with CFGBlock.");
|
assert (I != EdgeDataMap.end() && "No data associated with Edge.");
|
||||||
return I->second;
|
return I->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ValTy& getBlockData(const CFGBlock*) const {
|
const ValTy& getEdgeData(const CFG::Edge& E) const {
|
||||||
return reinterpret_cast<DataflowValues*>(this)->getBlockData();
|
return reinterpret_cast<DataflowValues*>(this)->getEdgeData(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getBlockDataMap - Retrieves the internal map between CFGBlocks and
|
/// getEdgeDataMap - Retrieves the internal map between CFGBlocks and
|
||||||
/// dataflow values. Usually used by a dataflow solver to compute
|
/// dataflow values. Usually used by a dataflow solver to compute
|
||||||
/// values for blocks.
|
/// values for blocks.
|
||||||
BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
|
EdgeDataMapTy& getEdgeDataMap() { return EdgeDataMap; }
|
||||||
const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
|
const EdgeDataMapTy& getEdgeDataMap() const { return EdgeDataMap; }
|
||||||
|
|
||||||
/// getAnalysisData - Retrieves the meta data associated with a
|
/// getAnalysisData - Retrieves the meta data associated with a
|
||||||
/// dataflow analysis for analyzing a particular CFG.
|
/// dataflow analysis for analyzing a particular CFG.
|
||||||
|
@ -111,7 +142,7 @@ public:
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BlockDataMapTy BlockDataMap;
|
EdgeDataMapTy EdgeDataMap;
|
||||||
AnalysisDataTy AnalysisData;
|
AnalysisDataTy AnalysisData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue