More simplifications on BB creation
This commit is contained in:
@@ -19,7 +19,7 @@ BB *BB::Create(void */*ctx*/, const string &/*s*/, Function *parent, BB */*inser
|
||||
* @arg start - basic block starts here, might be parent->Icode.end()
|
||||
* @arg fin - last of basic block's instructions
|
||||
*/
|
||||
BB *BB::Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent)
|
||||
BB *BB::Create(const rCODE &r,uint8_t _nodeType, Function *parent)
|
||||
{
|
||||
BB* pnewBB;
|
||||
pnewBB = new BB;
|
||||
@@ -27,47 +27,28 @@ BB *BB::Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Fun
|
||||
pnewBB->immedDom = NO_DOM;
|
||||
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
|
||||
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
|
||||
pnewBB->instructions = make_iterator_range(start,fin);
|
||||
if(start==parent->Icode.end())
|
||||
{
|
||||
pnewBB->instructions = make_iterator_range(parent->Icode.end(),parent->Icode.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
pnewBB->instructions.advance_end(1); // 1 after fin, to create range where fin is inclusive
|
||||
}
|
||||
if (numOutEdges)
|
||||
pnewBB->edges.resize(numOutEdges);
|
||||
pnewBB->instructions = r;
|
||||
|
||||
/* Mark the basic block to which the icodes belong to, but only for
|
||||
* real code basic blocks (ie. not interval bbs) */
|
||||
* real code basic blocks (ie. not interval bbs) */
|
||||
if(parent)
|
||||
{
|
||||
if (start != parent->Icode.end())
|
||||
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
|
||||
//setInBB should automatically handle if our range is empty
|
||||
parent->Icode.SetInBB(pnewBB->instructions, pnewBB);
|
||||
parent->heldBBs.push_back(pnewBB);
|
||||
parent->m_cfg.push_back(pnewBB);
|
||||
pnewBB->Parent = parent;
|
||||
}
|
||||
if ( start != parent->Icode.end() ) /* Only for code BB's */
|
||||
|
||||
if ( r.begin() != parent->Icode.end() ) /* Only for code BB's */
|
||||
stats.numBBbef++;
|
||||
return pnewBB;
|
||||
|
||||
}
|
||||
BB *BB::Create(int start, int ip, uint8_t _nodeType, int numOutEdges, Function *parent)
|
||||
BB *BB::CreateIntervalBB(Function *parent)
|
||||
{
|
||||
iICODE st(parent->Icode.begin());
|
||||
iICODE fin(parent->Icode.begin());
|
||||
if(start==-1)
|
||||
{
|
||||
st = parent->Icode.end();
|
||||
fin = parent->Icode.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
advance(st,start);
|
||||
advance(fin,ip);
|
||||
}
|
||||
return Create(st,fin,_nodeType,numOutEdges,parent);
|
||||
iICODE endOfParent = parent->Icode.end();
|
||||
return Create(make_iterator_range(endOfParent,endOfParent),INTERVAL_NODE,parent);
|
||||
}
|
||||
|
||||
static const char *const s_nodeType[] = {"branch", "if", "case", "fall", "return", "call",
|
||||
|
||||
@@ -336,9 +336,7 @@ void Function::structLoops(derSeq *derivedG)
|
||||
* h. Note that h is a case node. */
|
||||
static bool successor (int s, int h, Function * pProc)
|
||||
{
|
||||
BB * header;
|
||||
|
||||
header = pProc->m_dfsLast[h];
|
||||
BB * header = pProc->m_dfsLast[h];
|
||||
auto iter = std::find_if(header->edges.begin(),
|
||||
header->edges.end(),
|
||||
[s](const TYPEADR_TYPE &te)->bool{ return te.BBptr->dfsLastNum == s;});
|
||||
@@ -431,9 +429,9 @@ static void flagNodes (nodeList &l, int f, Function * pProc)
|
||||
/* Structures if statements */
|
||||
void Function::structIfs ()
|
||||
{
|
||||
size_t followInEdges; /* Largest # in-edges so far */
|
||||
int curr, /* Index for linear scan of nodes */
|
||||
/*desc,*/ /* Index for descendant */
|
||||
followInEdges, /* Largest # in-edges so far */
|
||||
follow; /* Possible follow node */
|
||||
nodeList domDesc, /* List of nodes dominated by curr */
|
||||
unresolved /* List of unresolved if nodes */
|
||||
|
||||
162
src/graph.cpp
162
src/graph.cpp
@@ -3,11 +3,17 @@
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include <string.h>
|
||||
#include <malloc.h> /* For free() */
|
||||
#include <boost/range/rbegin.hpp>
|
||||
#include <boost/range/rend.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
|
||||
#include "dcc.h"
|
||||
#include "graph.h"
|
||||
#include "project.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
extern Project g_proj;
|
||||
//static BB * rmJMP(Function * pProc, int marker, BB * pBB);
|
||||
//static void mergeFallThrough(Function * pProc, BB * pBB);
|
||||
@@ -33,116 +39,98 @@ void Function::createCFG()
|
||||
BB * psBB;
|
||||
BB * pBB;
|
||||
iICODE pIcode = Icode.begin();
|
||||
iICODE iStart = Icode.begin();
|
||||
|
||||
stats.numBBbef = stats.numBBaft = 0;
|
||||
for (; pIcode!=Icode.end(); ++pIcode)
|
||||
rICODE current_range=make_iterator_range(pIcode,++iICODE(pIcode));
|
||||
for (; pIcode!=Icode.end(); ++pIcode,current_range.advance_end(1))
|
||||
{
|
||||
iICODE nextIcode = ++iICODE(pIcode);
|
||||
pBB = nullptr;
|
||||
|
||||
LLInst *ll = pIcode->ll();
|
||||
/* Only process icodes that have valid instructions */
|
||||
if(ll->testFlags(NO_CODE))
|
||||
continue;
|
||||
/* Stick a NOWHERE_NODE on the end if we terminate
|
||||
* with anything other than a ret, jump or terminate */
|
||||
* with anything other than a ret, jump or terminate */
|
||||
if (nextIcode == Icode.end() and
|
||||
(not ll->testFlags(TERMINATES)) and
|
||||
(not ll->match(iJMP)) and (not ll->match(iJMPF)) and
|
||||
(not ll->match(iRET)) and (not ll->match(iRETF)))
|
||||
{
|
||||
//pBB=BB::Create(start, ip, NOWHERE_NODE, 0, this);
|
||||
pBB=BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
|
||||
|
||||
pBB=BB::Create(current_range, NOWHERE_NODE, this);
|
||||
}
|
||||
|
||||
/* Only process icodes that have valid instructions */
|
||||
else if (not ll->testFlags(NO_CODE) )
|
||||
{
|
||||
else
|
||||
switch (ll->getOpcode()) {
|
||||
case iJB: case iJBE: case iJAE: case iJA:
|
||||
case iJL: case iJLE: case iJGE: case iJG:
|
||||
case iJE: case iJNE: case iJS: case iJNS:
|
||||
case iJO: case iJNO: case iJP: case iJNP:
|
||||
case iJCXZ:
|
||||
pBB = BB::Create(iStart, pIcode, TWO_BRANCH, 2, this);
|
||||
pBB = BB::Create(current_range, TWO_BRANCH, this);
|
||||
CondJumps:
|
||||
//start = ip + 1;
|
||||
iStart = ++iICODE(pIcode);
|
||||
pBB->edges[0].ip = (uint32_t)iStart->loc_ip;
|
||||
/* This is for jumps off into nowhere */
|
||||
if ( ll->testFlags(NO_LABEL) )
|
||||
{
|
||||
pBB->edges.pop_back();
|
||||
}
|
||||
else
|
||||
pBB->edges[1].ip = ll->src().getImm2();
|
||||
pBB->addOutEdge(nextIcode->loc_ip);
|
||||
/* This is checking for jumps off into nowhere */
|
||||
if ( not ll->testFlags(NO_LABEL) )
|
||||
pBB->addOutEdge(ll->src().getImm2());
|
||||
break;
|
||||
|
||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
||||
//pBB = BB::Create(start, ip, LOOP_NODE, 2, this);
|
||||
pBB = BB::Create(iStart, pIcode, LOOP_NODE, 2, this);
|
||||
pBB = BB::Create(current_range, LOOP_NODE, this);
|
||||
goto CondJumps;
|
||||
|
||||
case iJMPF: case iJMP:
|
||||
if (ll->testFlags(SWITCH))
|
||||
{
|
||||
//pBB = BB::Create(start, ip, MULTI_BRANCH, ll->caseTbl.numEntries, this);
|
||||
pBB = BB::Create(iStart, pIcode, MULTI_BRANCH, ll->caseTbl2.size(), this);
|
||||
pBB = BB::Create(current_range, MULTI_BRANCH, this);
|
||||
for (size_t i = 0; i < ll->caseTbl2.size(); i++)
|
||||
pBB->edges[i].ip = ll->caseTbl2[i];
|
||||
pBB->addOutEdge(ll->caseTbl2[i]);
|
||||
hasCase = true;
|
||||
}
|
||||
else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT
|
||||
{
|
||||
//pBB = BB::Create(start, ip, ONE_BRANCH, 1, this);
|
||||
pBB = BB::Create(iStart, pIcode, ONE_BRANCH, 1, this);
|
||||
|
||||
pBB->edges[0].ip = ll->src().getImm2();
|
||||
pBB = BB::Create(current_range, ONE_BRANCH, this);
|
||||
pBB->addOutEdge(ll->src().getImm2());
|
||||
}
|
||||
else
|
||||
BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode);
|
||||
pBB = BB::Create(current_range, NOWHERE_NODE, this);
|
||||
break;
|
||||
|
||||
case iCALLF: case iCALL:
|
||||
{
|
||||
Function * p = ll->src().proc.proc;
|
||||
if (p)
|
||||
i = ((p->flg) & TERMINATES) ? 0 : 1;
|
||||
else
|
||||
i = 1;
|
||||
pBB = BB::Create(iStart, pIcode, CALL_NODE, i, this);
|
||||
iStart = ++iICODE(pIcode);//start = ip + 1;
|
||||
if (i)
|
||||
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
|
||||
}
|
||||
pBB = BB::Create(current_range, CALL_NODE, this);
|
||||
if (p && not ((p->flg) & TERMINATES) )
|
||||
pBB->addOutEdge(nextIcode->loc_ip);
|
||||
break;
|
||||
}
|
||||
|
||||
case iRET: case iRETF:
|
||||
//BB::Create(start, ip, RETURN_NODE, 0, this);
|
||||
BB::Create(iStart, pIcode, RETURN_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode);
|
||||
pBB = BB::Create(current_range, RETURN_NODE, this);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Check for exit to DOS */
|
||||
iICODE next1=++iICODE(pIcode);
|
||||
if ( ll->testFlags(TERMINATES) )
|
||||
{
|
||||
pBB = BB::Create(iStart, pIcode, TERMINATE_NODE, 0, this);
|
||||
//pBB = BB::Create(start, ip, TERMINATE_NODE, 0, this);
|
||||
iStart = ++iICODE(pIcode); // start = ip + 1;
|
||||
pBB = BB::Create(current_range, TERMINATE_NODE, this);
|
||||
}
|
||||
/* Check for a fall through */
|
||||
else if (next1 != Icode.end())
|
||||
else if (nextIcode != Icode.end())
|
||||
{
|
||||
if (next1->ll()->testFlags(TARGET | CASE))
|
||||
if (nextIcode->ll()->testFlags(TARGET | CASE))
|
||||
{
|
||||
//pBB = BB::Create(start, ip, FALL_NODE, 1, this);
|
||||
pBB = BB::Create(iStart, pIcode, FALL_NODE, 1, this);
|
||||
iStart = ++iICODE(pIcode); // start = ip + 1;
|
||||
pBB->addOutEdge(iStart->loc_ip);
|
||||
pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start;
|
||||
pBB = BB::Create(current_range, FALL_NODE, this);
|
||||
pBB->addOutEdge(nextIcode->loc_ip);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(pBB!=nullptr) // created a new Basic block
|
||||
{
|
||||
// restart the range
|
||||
// end iterator will be updated by expression in for statement
|
||||
current_range=make_iterator_range(nextIcode,nextIcode);
|
||||
}
|
||||
}
|
||||
auto iter=heldBBs.begin();
|
||||
@@ -160,14 +148,14 @@ CondJumps:
|
||||
}
|
||||
auto iter2=std::find_if(heldBBs.begin(),heldBBs.end(),
|
||||
[ip](BB *psBB)->bool {return psBB->begin()->loc_ip==ip;});
|
||||
if(iter2==heldBBs.end())
|
||||
fatalError(NO_BB, ip, name.c_str());
|
||||
psBB = *iter2;
|
||||
pBB->edges[edeg_idx].BBptr = psBB;
|
||||
psBB->inEdges.push_back((BB *)nullptr);
|
||||
}
|
||||
if(iter2==heldBBs.end())
|
||||
fatalError(NO_BB, ip, name.c_str());
|
||||
psBB = *iter2;
|
||||
pBB->edges[edeg_idx].BBptr = psBB;
|
||||
psBB->inEdges.push_back((BB *)nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Function::markImpure()
|
||||
{
|
||||
@@ -350,33 +338,33 @@ void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
auto iter=std::find_if(this->end(),pChild->begin(),[](ICODE &c)
|
||||
{return not c.ll()->testFlags(NO_CODE);});
|
||||
|
||||
if (iter != pChild->begin())
|
||||
break;
|
||||
back().ll()->setFlags(NO_CODE);
|
||||
back().invalidate();
|
||||
nodeType = FALL_NODE;
|
||||
//instructions.advance_end(-1); //TODO: causes creation of empty BB
|
||||
}
|
||||
/* If there's no other edges into child can merge */
|
||||
if (pChild->inEdges.size() != 1)
|
||||
if (iter != pChild->begin())
|
||||
break;
|
||||
|
||||
nodeType = pChild->nodeType;
|
||||
instructions = boost::make_iterator_range(begin(),pChild->end());
|
||||
pChild->front().ll()->clrFlags(TARGET);
|
||||
edges.swap(pChild->edges);
|
||||
|
||||
pChild->inEdges.clear();
|
||||
pChild->edges.clear();
|
||||
back().ll()->setFlags(NO_CODE);
|
||||
back().invalidate();
|
||||
nodeType = FALL_NODE;
|
||||
//instructions.advance_end(-1); //TODO: causes creation of empty BB
|
||||
}
|
||||
traversed = DFS_MERGE;
|
||||
/* If there's no other edges into child can merge */
|
||||
if (pChild->inEdges.size() != 1)
|
||||
break;
|
||||
|
||||
/* Process all out edges recursively */
|
||||
for (size_t i = 0; i < edges.size(); i++)
|
||||
{
|
||||
if (edges[i].BBptr->traversed != DFS_MERGE)
|
||||
edges[i].BBptr->mergeFallThrough(Icode);
|
||||
}
|
||||
nodeType = pChild->nodeType;
|
||||
instructions = boost::make_iterator_range(begin(),pChild->end());
|
||||
pChild->front().ll()->clrFlags(TARGET);
|
||||
edges.swap(pChild->edges);
|
||||
|
||||
pChild->inEdges.clear();
|
||||
pChild->edges.clear();
|
||||
}
|
||||
traversed = DFS_MERGE;
|
||||
|
||||
/* Process all out edges recursively */
|
||||
for (size_t i = 0; i < edges.size(); i++)
|
||||
{
|
||||
if (edges[i].BBptr->traversed != DFS_MERGE)
|
||||
edges[i].BBptr->mergeFallThrough(Icode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ OPTION option; /* Command line options */
|
||||
Project *Project::s_instance = 0;
|
||||
Project::Project() : callGraph(nullptr)
|
||||
{
|
||||
|
||||
memset(&prog,0,sizeof(prog));
|
||||
}
|
||||
void Project::initialize()
|
||||
{
|
||||
@@ -49,8 +49,7 @@ ilFunction Project::findByEntry(uint32_t entry)
|
||||
{
|
||||
/* Search procedure list for one with appropriate entry point */
|
||||
ilFunction iter= std::find_if(pProcList.begin(),pProcList.end(),
|
||||
[entry](const Function &f) ->
|
||||
bool { return f.procEntry==entry; });
|
||||
[entry](const Function &f) { return f.procEntry==entry; });
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
@@ -540,20 +540,19 @@ void Function::propLong()
|
||||
for (size_t i = 0; i < localId.csym(); i++)
|
||||
{
|
||||
const ID &pLocId(localId.id_arr[i]);
|
||||
if ((pLocId.type==TYPE_LONG_SIGN) || (pLocId.type==TYPE_LONG_UNSIGN))
|
||||
if ((pLocId.type!=TYPE_LONG_SIGN) and (pLocId.type!=TYPE_LONG_UNSIGN))
|
||||
continue;
|
||||
switch (pLocId.loc)
|
||||
{
|
||||
switch (pLocId.loc)
|
||||
{
|
||||
case STK_FRAME:
|
||||
propLongStk (i, pLocId);
|
||||
break;
|
||||
case REG_FRAME:
|
||||
propLongReg (i, pLocId);
|
||||
break;
|
||||
case GLB_FRAME:
|
||||
propLongGlb (i, pLocId);
|
||||
break;
|
||||
}
|
||||
case STK_FRAME:
|
||||
propLongStk (i, pLocId);
|
||||
break;
|
||||
case REG_FRAME:
|
||||
propLongReg (i, pLocId);
|
||||
break;
|
||||
case GLB_FRAME:
|
||||
propLongGlb (i, pLocId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,29 +236,23 @@ derSeq_Entry::~derSeq_Entry()
|
||||
bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
{
|
||||
interval *Ii; /* Interval being processed */
|
||||
BB *BBnode, /* New basic block of intervals */
|
||||
//*curr, /* BB being checked for out edges */
|
||||
*succ /* Successor node */
|
||||
;
|
||||
//queue *listIi; /* List of intervals */
|
||||
int i; /* Index to outEdges array */
|
||||
/*j;*/ /* Index to successors */
|
||||
boolT sameGraph; /* Boolean, isomorphic graphs */
|
||||
BB *BBnode; /* New basic block of intervals */
|
||||
bool sameGraph; /* Boolean, isomorphic graphs */
|
||||
|
||||
/* Process Gi's intervals */
|
||||
derSeq_Entry &prev_entry(derivedGi.back());
|
||||
derivedGi.push_back(derSeq_Entry());
|
||||
derSeq_Entry &new_entry(derivedGi.back());
|
||||
Ii = prev_entry.Ii;
|
||||
|
||||
sameGraph = true;
|
||||
BBnode = 0;
|
||||
std::vector<BB *> bbs;
|
||||
while (Ii)
|
||||
for(Ii = prev_entry.Ii; Ii != nullptr; Ii = Ii->next)
|
||||
{
|
||||
i = 0;
|
||||
bbs.push_back(BB::Create(-1, -1, INTERVAL_NODE, Ii->numOutEdges, this));
|
||||
BBnode = bbs.back();
|
||||
|
||||
BBnode = BB::CreateIntervalBB(this);
|
||||
BBnode->correspInt = Ii;
|
||||
bbs.push_back(BBnode);
|
||||
const queue &listIi(Ii->nodes);
|
||||
|
||||
/* Check for more than 1 interval */
|
||||
@@ -267,21 +261,17 @@ bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
|
||||
/* Find out edges */
|
||||
|
||||
if (BBnode->edges.size() > 0)
|
||||
if (Ii->numOutEdges <= 0)
|
||||
continue;
|
||||
for(BB *curr : listIi)
|
||||
{
|
||||
for(BB *curr : listIi)
|
||||
for (size_t j = 0; j < curr->edges.size(); j++)
|
||||
{
|
||||
for (size_t j = 0; j < curr->edges.size(); j++)
|
||||
{
|
||||
succ = curr->edges[j].BBptr;
|
||||
if (succ->inInterval != curr->inInterval)
|
||||
BBnode->edges[i++].intPtr = succ->inInterval;
|
||||
}
|
||||
BB *successor_node = curr->edges[j].BBptr;
|
||||
if (successor_node->inInterval != curr->inInterval)
|
||||
BBnode->addOutEdgeInterval(successor_node->inInterval);
|
||||
}
|
||||
}
|
||||
|
||||
/* Next interval */
|
||||
Ii = Ii->next;
|
||||
}
|
||||
|
||||
/* Convert list of pointers to intervals into a real graph.
|
||||
@@ -303,7 +293,7 @@ bool Function::nextOrderGraph (derSeq &derivedGi)
|
||||
(*iter)->inEdgeCount++;
|
||||
}
|
||||
}
|
||||
return (boolT)(! sameGraph);
|
||||
return not sameGraph;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -357,8 +357,7 @@ static void fixFloatEmulation(x86_insn_t &insn)
|
||||
if ((wOp < 0x34) || (wOp > 0x3B))
|
||||
return;
|
||||
uint8_t buf[16];
|
||||
/* This is a Borland/Microsoft floating point emulation instruction.
|
||||
Treat as if it is an ESC opcode */
|
||||
/* This is a Borland/Microsoft floating point emulation instruction. Treat as if it is an ESC opcode */
|
||||
|
||||
int actual_valid_bytes=std::min(16U,prog.cbImage-insn.offset);
|
||||
memcpy(buf,prog.Image+insn.offset,actual_valid_bytes);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "dcc.h"
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include "dcc.h"
|
||||
|
||||
TEST(CowriteTest, HandlesZeroInput) {
|
||||
EXPECT_EQ(1, 1);
|
||||
|
||||
@@ -13,8 +13,8 @@ TEST(Project, NewProjectIsInitalized) {
|
||||
|
||||
TEST(Project, CreatedProjectHasValidNames) {
|
||||
Project p;
|
||||
std::vector<std::string> strs = {"./Project1.EXE","/home/Project2.EXE","/home/Pro ject3"};
|
||||
std::vector<std::string> expected = {"Project1","Project2","Pro ject3"};
|
||||
std::vector<std::string> strs = {"./Project1.EXE","/home/Project2.EXE","/home/Pro\\ ject3"};
|
||||
std::vector<std::string> expected = {"Project1","Project2","Pro\\ ject3"};
|
||||
for(size_t i=0; i<strs.size(); i++)
|
||||
{
|
||||
p.create(strs[i]);
|
||||
|
||||
Reference in New Issue
Block a user