Program Listing for File divAnalysis.h#
↰ Return to documentation for file (src/midend/programAnalysis/genericDataflow/simpleAnalyses/divAnalysis.h)
#include <featureTests.h>
#ifdef ROSE_ENABLE_SOURCE_ANALYSIS
#ifndef DIV_ANALYSIS_H
#define DIV_ANALYSIS_H
#include "genericDataflowCommon.h"
#include "VirtualCFGIterator.h"
#include "cfgUtils.h"
#include "CallGraphTraverse.h"
#include "analysisCommon.h"
#include "analysis.h"
#include "dataflow.h"
#include "latticeFull.h"
#include "liveDeadVarAnalysis.h"
#include "printAnalysisStates.h"
#include "VariableStateTransfer.h"
#include <map>
#include <string>
#include <vector>
#include <memory>
extern int divAnalysisDebugLevel;
// Maintains value information about live variables. If a given variable may have more than one value,
// this object maintains divisibility information about all the possible values (i.e. they're all divisible
// by x, with y as the remainder), with the divisior,remainder = (1,0) if nothing better can be found.
// There is one DivLattice object for every variable
class DivLattice : public FiniteLattice
{
private:
// the current value of the variable (if known)
long value;
// the <divisor, remainder> pair where for all possible values v of the variable
// there exists a multiplier m s.t v = div * m + rem
long div;
long rem;
public:
// The different levels of this lattice
// no information is known about the value of the variable
static const int bottom=1;
// the value of the variable is known
static const int valKnown=2;
// value is unknown but the divisibility (div and rem) of this variable is known
static const int divKnown=3;
// this variable holds more values than can be represented using a single value and divisibility
static const int top=4;
private:
// this object's current level in the lattice: (bottom, valKnown, divKnown, top)
short level;
public:
DivLattice()
{
value=0;
div=-1;
rem=-1;
level=bottom;
}
DivLattice(long value) {
this->value = value;
div = -1;
rem = -1;
level = valKnown;
}
DivLattice(long div, long rem) {
value = 0;
this->div = div;
this->rem = rem;
level = divKnown;
}
DivLattice(const DivLattice& that)
{
this->value = that.value;
this->div = that.div;
this->rem = that.rem;
this->level = that.level;
}
// initializes this Lattice to its default state
void initialize()
{ }
// returns a copy of this lattice
Lattice* copy() const;
// overwrites the state of this Lattice with that of that Lattice
void copy(Lattice* that);
// returns true if the given value matches the given div, rem combo and false otherwise
static bool matchDiv(long value, long div, long rem);
// Takes two lattices at level divKnown. If the two objects have matching div, rem pairs, returns
// true and sets div and rem to those mathching values. Otherwise, returns false;
static bool matchDiv(DivLattice* one, DivLattice* two, long& div, long& rem);
// Takes two lattices at level divKnown. If the two objects have div, rem pairs that make it
// possible to add or subtract them them and produce div/rem information where div>1,
// returns true and sets div and rem to correspond to the sum of these values.
// Otherwise, returns false.
// plus - true if the caller want to see one+two and false if one-two
static bool matchDivAddSubt(DivLattice* one, DivLattice* two, long& div, long& rem, bool plus);
// computes the meet of this and that and saves the result in this
// returns true if this causes this to change and false otherwise
bool meetUpdate(Lattice* that);
// computes the meet of this and that and returns the result
//Lattice* meet(Lattice* that) const;
bool operator==(Lattice* that);
/*// widens this from that and saves the result in this
// returns true if this causes this to change and false otherwise
bool widenUpdate(InfiniteLattice* that);*/
// returns the current state of this object
long getValue() const;
long getDiv() const;
long getRem() const;
short getLevel() const;
// Sets the state of this lattice to bottom
// returns true if this causes the lattice's state to change, false otherwise
bool setBot();
// Sets the state of this lattice to the given value.
// returns true if this causes the lattice's state to change, false otherwise
bool set(long value);
// Sets the state of this lattice to the given div/rem state.
// returns true if this causes the lattice's state to change, false otherwise
bool set(long div, long rem);
// Sets the state of this lattice to top
// returns true if this causes the lattice's state to change, false otherwise
bool setTop();
// Increments the state of this object by increment
// returns true if this causes the lattice's state to change, false otherwise
bool incr(long increment);
// Multiplies the state of this object by value
// returns true if this causes the lattice's state to change, false otherwise
bool mult(long multiplier);
std::string str(std::string indent="");
};
class DivAnalysisTransfer : public VariableStateTransfer<DivLattice>
{
template <class T>
void visitIntegerValue(T *sgn);
void transferIncrement(SgUnaryOp *sgn);
void transferCompoundAdd(SgBinaryOp *sgn);
typedef void (DivAnalysisTransfer::*TransferOp)(DivLattice *, DivLattice *, DivLattice *);
template <typename T>
void transferArith(SgBinaryOp *sgn, T transferOp);
void transferArith(SgBinaryOp *sgn, TransferOp transferOp);
void transferAdditive(DivLattice *arg1Lat, DivLattice *arg2Lat, DivLattice *resLat, bool isAddition);
void transferMultiplicative(DivLattice *arg1Lat, DivLattice *arg2Lat, DivLattice *resLat);
void transferDivision(DivLattice *arg1Lat, DivLattice *arg2Lat, DivLattice *resLat);
void transferMod(DivLattice *arg1Lat, DivLattice *arg2Lat, DivLattice *resLat);
public:
// void visit(SgNode *);
void visit(SgLongLongIntVal *sgn);
void visit(SgLongIntVal *sgn);
void visit(SgIntVal *sgn);
void visit(SgShortVal *sgn);
void visit(SgUnsignedLongLongIntVal *sgn);
void visit(SgUnsignedLongVal *sgn);
void visit(SgUnsignedIntVal *sgn);
void visit(SgUnsignedShortVal *sgn);
void visit(SgValueExp *sgn);
void visit(SgPlusAssignOp *sgn);
void visit(SgMinusAssignOp *sgn);
void visit(SgMultAssignOp *sgn);
void visit(SgDivAssignOp *sgn);
void visit(SgModAssignOp *sgn);
void visit(SgAddOp *sgn);
void visit(SgSubtractOp *sgn);
void visit(SgMultiplyOp *sgn);
void visit(SgDivideOp *sgn);
void visit(SgModOp *sgn);
void visit(SgPlusPlusOp *sgn);
void visit(SgMinusMinusOp *sgn);
void visit(SgUnaryAddOp *sgn);
void visit(SgMinusOp *sgn);
bool finish() { return modified; }
DivAnalysisTransfer(const Function& func, const DataflowNode& n, NodeState& state, const std::vector<Lattice*>& dfInfo);
};
class DivAnalysis : public IntraFWDataflow
{
protected:
static std::map<varID, Lattice*> constVars;
static bool constVars_init;
// The LiveDeadVarsAnalysis that identifies the live/dead state of all application variables.
// Needed to create a FiniteVarsExprsProductLattice.
LiveDeadVarsAnalysis* ldva;
public:
DivAnalysis(LiveDeadVarsAnalysis* ldva)
{
this->ldva = ldva;
}
/*// generates the initial variable-specific lattice state for a dataflow node
Lattice* genInitVarState(const Function& func, const DataflowNode& n, const NodeState& state);
// generates the initial non-variable-specific lattice state for a dataflow node
Lattice* genInitNonVarState(const Function& func, const DataflowNode& n, const NodeState& state);*/
// generates the initial lattice state for the given dataflow node, in the given function, with the given NodeState
//std::vector<Lattice*> genInitState(const Function& func, const DataflowNode& n, const NodeState& state);
void genInitState(const Function& func, const DataflowNode& n, const NodeState& state,
std::vector<Lattice*>& initLattices, std::vector<NodeFact*>& initFacts);
// Returns a map of special constant variables (such as zeroVar) and the lattices that correspond to them
// These lattices are assumed to be constants: it is assumed that they are never modified and it is legal to
// maintain only one copy of each lattice may for the duration of the analysis.
//std::map<varID, Lattice*>& genConstVarLattices() const;
bool transfer(const Function& func, const DataflowNode& n, NodeState& state, const std::vector<Lattice*>& dfInfo)
{ ROSE_ABORT(); }
std::shared_ptr<IntraDFTransferVisitor> getTransferVisitor(const Function& func, const DataflowNode& n,
NodeState& state, const std::vector<Lattice*>& dfInfo)
{ return std::shared_ptr<IntraDFTransferVisitor>(new DivAnalysisTransfer(func, n, state, dfInfo)); }
};
// prints the Lattices set by the given DivAnalysis
void printDivAnalysisStates(DivAnalysis* da, std::string indent="");
#endif
#endif