Skip to content

Commit

Permalink
Add reaching definitions analysis to StackAnalysis.
Browse files Browse the repository at this point in the history
The reaching definitions analysis keeps track of where stack
pointers are defined so that StackMod can modify those definitions
if necessary.  StackMod currently modifies definitions only when
there are multiple possible stack slots a pointer could point to
and then that pointer is dereferenced.  In that scenario, we cannot
modify just the access since we would need to have two different
displacements depending on the value of the pointer.  Instead,
StackMod modifies the pointers at their definition points so that
they point to their new stack locations.
  • Loading branch information
morehouse committed Apr 20, 2017
1 parent c706392 commit 5191cab
Show file tree
Hide file tree
Showing 10 changed files with 905 additions and 273 deletions.
84 changes: 80 additions & 4 deletions dataflowAPI/h/stackanalysis.h
Expand Up @@ -77,6 +77,56 @@ class StackAnalysis {
typedef boost::shared_ptr<InstructionAPI::Instruction> InstructionPtr;
typedef boost::shared_ptr<InstructionAPI::Expression> ExpressionPtr;

class DATAFLOW_EXPORT Definition {
public:
typedef enum {TOP, BOTTOM, DEF} Type;
Address addr;
ParseAPI::Block *block;
Absloc origLoc;
Type type;

Definition(ParseAPI::Block *b, Address a, Absloc l) : addr(a),
block(b), origLoc(l), type(DEF) {}
Definition(ParseAPI::Block *b, Absloc l) : addr(0), block(b),
origLoc(l), type(DEF) {}
Definition(Address a, Absloc l) : addr(a), block(NULL), origLoc(l),
type(DEF) {}
Definition() : addr(0), block(NULL), type(TOP) {}

bool operator==(const Definition &other) const {
// FIXME: To pass checks in StackAnalysis::summarize(), we consider
// definitions equivalent as long as one is not BOTTOM and the other
// something else. This is not proper.
//return type == other.type && block == other.block;
if (type == BOTTOM && other.type != BOTTOM) return false;
if (type != BOTTOM && other.type == BOTTOM) return false;
return true;
}

bool operator<(const Definition &rhs) const {
if (type == TOP) return false;
if (type == BOTTOM && rhs.type == BOTTOM) return false;
if (type == BOTTOM) return true;

if (rhs.type == TOP) return true;
if (rhs.type == BOTTOM) return false;

// At this point we know both are DEFs
return block < rhs.block;
}

std::string format() const;

static Definition meet(const Definition &lhs, const Definition &rhs) {
if (lhs.type == TOP) return rhs;
if (rhs.type == TOP) return lhs;
if (lhs == rhs) return rhs;
Definition bottom;
bottom.type = BOTTOM;
return bottom;
}
};

class DATAFLOW_EXPORT Height {
public:
typedef signed long Height_t;
Expand Down Expand Up @@ -178,6 +228,9 @@ class StackAnalysis {
Type type_;
};

typedef std::pair<Definition, Height> DefHeight;
DATAFLOW_EXPORT static bool isTopSet(const std::set<DefHeight> &s);
DATAFLOW_EXPORT static bool isBottomSet(const std::set<DefHeight> &s);

// We need to represent the effects of instructions. We do this in terms of
// transfer functions. We recognize the following effects on the stack.
Expand All @@ -199,8 +252,8 @@ class StackAnalysis {
// they are fixed) and RV as a parameter. Note that a transfer function is a
// function T : (RegisterVector, RegisterID, RegisterID, value) ->
// (RegisterVector).
typedef std::map<Absloc, Height> AbslocState;
class TransferFunc {
typedef std::map<Absloc, std::set<DefHeight> > AbslocState;
class DATAFLOW_EXPORT TransferFunc {
public:
typedef enum {TOP, BOTTOM, OTHER} Type;

Expand Down Expand Up @@ -255,7 +308,7 @@ class StackAnalysis {
return !(*this == rhs);
}

Height apply(const AbslocState &inputs) const;
std::set<DefHeight> apply(const AbslocState &inputs) const;
void accumulate(std::map<Absloc, TransferFunc> &inputs);
TransferFunc summaryAccumulate(
const std::map<Absloc, TransferFunc> &inputs) const;
Expand Down Expand Up @@ -302,7 +355,8 @@ class StackAnalysis {

SummaryFunc() {};

void apply(const AbslocState &in, AbslocState &out) const;
void apply(ParseAPI::Block *block, const AbslocState &in,
AbslocState &out) const;
void accumulate(const TransferSet &in, TransferSet &out) const;

std::string format() const;
Expand Down Expand Up @@ -351,10 +405,15 @@ class StackAnalysis {
DATAFLOW_EXPORT virtual ~StackAnalysis();

DATAFLOW_EXPORT Height find(ParseAPI::Block *, Address addr, Absloc loc);
DATAFLOW_EXPORT std::set<DefHeight> findDefHeight(ParseAPI::Block *block,
Address addr, Absloc loc);
DATAFLOW_EXPORT Height findSP(ParseAPI::Block *, Address addr);
DATAFLOW_EXPORT Height findFP(ParseAPI::Block *, Address addr);
DATAFLOW_EXPORT void findDefinedHeights(ParseAPI::Block* b, Address addr,
std::vector<std::pair<Absloc, Height> >& heights);
// TODO: Update DataflowAPI manual
DATAFLOW_EXPORT void findDefHeightPairs(ParseAPI::Block *b, Address addr,
std::vector<std::pair<Absloc, std::set<DefHeight> > > &defHeights);

// TODO: Update DataflowAPI manual
DATAFLOW_EXPORT bool canGetFunctionSummary();
Expand Down Expand Up @@ -385,6 +444,9 @@ class StackAnalysis {
AbslocState &input);
void meetSummaryInputs(ParseAPI::Block *b, TransferSet &blockInput,
TransferSet &input);
DefHeight meetDefHeight(const DefHeight &dh1, const DefHeight &dh2);
std::set<DefHeight> meetDefHeights(const std::set<DefHeight> &s1,
const std::set<DefHeight> &s2);
void meet(const AbslocState &source, AbslocState &accum);
void meetSummary(const TransferSet &source, TransferSet &accum);
AbslocState getSrcOutputLocs(ParseAPI::Edge* e);
Expand Down Expand Up @@ -433,8 +495,22 @@ class StackAnalysis {
void copyBaseSubReg(const MachRegister &reg, TransferFuncs &xferFuncs);
void bottomBaseSubReg(const MachRegister &reg, TransferFuncs &xferFuncs);

static void makeTopSet(std::set<DefHeight> &s);
static void makeBottomSet(std::set<DefHeight> &s);
static void makeNewSet(ParseAPI::Block *b, Address addr,
const Absloc &origLoc, const Height &h, std::set<DefHeight> &s);
static void addInitSet(const Height &h, std::set<DefHeight> &s);
static void addDeltaSet(long delta, std::set<DefHeight> &s);
static Height getHeightSet(const std::set<DefHeight> &s);
static Definition getDefSet(const std::set<DefHeight> &s);


Height getStackCleanAmount(ParseAPI::Function *func);

// This constant limits the number of definitions we track per register. If
// more than this many definitions are found, the register is considered to
// be BOTTOM, and the definitions tracked so far are dropped.
static const unsigned DEF_LIMIT = 2;

ParseAPI::Function *func;

Expand Down

0 comments on commit 5191cab

Please sign in to comment.