More simplifications on BB creation

This commit is contained in:
Artur K
2012-07-14 23:04:09 +02:00
parent ba110a64cb
commit 5087a051b5
19 changed files with 989 additions and 1027 deletions

View File

@@ -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",

View File

@@ -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 */

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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]);