dcc/src/BasicBlock.cpp

409 lines
14 KiB
C++

#include <cassert>
#include <string>
#include "BasicBlock.h"
#include "Procedure.h"
#include "dcc.h"
using namespace std;
extern char *indent (int indLevel);
BB *BB::Create(void *ctx, const string &s, Function *parent, BB *insertBefore)
{
BB *pnewBB = new BB;
pnewBB->Parent = parent;
return pnewBB;
}
BB *BB::Create(int start, int ip, uint8_t nodeType, int numOutEdges, Function *parent)
{
parent->m_cfg;
BB* pnewBB;
pnewBB = new BB;
pnewBB->nodeType = nodeType; /* Initialise */
pnewBB->start = start;
pnewBB->length = ip - start + 1;
pnewBB->immedDom = NO_DOM;
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
if (numOutEdges)
pnewBB->edges.resize(numOutEdges);
/* Mark the basic block to which the icodes belong to, but only for
* real code basic blocks (ie. not interval bbs) */
if(parent)
{
if (start >= 0)
parent->Icode.SetInBB(start, ip, pnewBB);
parent->heldBBs.push_back(pnewBB);
parent->m_cfg.push_back(pnewBB);
pnewBB->Parent = parent;
}
if (start != -1) /* Only for code BB's */
stats.numBBbef++;
return pnewBB;
}
static const char *const s_nodeType[] = {"branch", "if", "case", "fall", "return", "call",
"loop", "repeat", "interval", "cycleHead",
"caseHead", "terminate",
"nowhere" };
static const char *const s_loopType[] = {"noLoop", "while", "repeat", "loop", "for"};
void BB::display()
{
printf("\nnode type = %s, ", s_nodeType[nodeType]);
printf("start = %ld, length = %ld, #out edges = %ld\n", start, length, edges.size());
for (int i = 0; i < edges.size(); i++)
printf(" outEdge[%2d] = %ld\n",i, edges[i].BBptr->start);
}
/*****************************************************************************
* displayDfs - Displays the CFG using a depth first traversal
****************************************************************************/
void BB::displayDfs()
{
int i;
assert(this);
traversed = DFS_DISP;
printf("node type = %s, ", s_nodeType[nodeType]);
printf("start = %ld, length = %ld, #in-edges = %ld, #out-edges = %ld\n",
start, length, inEdges.size(), edges.size());
printf("dfsFirst = %ld, dfsLast = %ld, immed dom = %ld\n",
dfsFirstNum, dfsLastNum,
immedDom == MAX ? -1 : immedDom);
printf("loopType = %s, loopHead = %ld, latchNode = %ld, follow = %ld\n",
s_loopType[loopType],
loopHead == MAX ? -1 : loopHead,
latchNode == MAX ? -1 : latchNode,
loopFollow == MAX ? -1 : loopFollow);
printf ("ifFollow = %ld, caseHead = %ld, caseTail = %ld\n",
ifFollow == MAX ? -1 : ifFollow,
caseHead == MAX ? -1 : caseHead,
caseTail == MAX ? -1 : caseTail);
if (nodeType == INTERVAL_NODE)
printf("corresponding interval = %ld\n", correspInt->numInt);
else
for (i = 0; i < inEdges.size(); i++)
printf (" inEdge[%ld] = %ld\n", i, inEdges[i]->begin());
/* Display out edges information */
for (i = 0; i < edges.size(); i++)
if (nodeType == INTERVAL_NODE)
printf(" outEdge[%ld] = %ld\n", i,
edges[i].BBptr->correspInt->numInt);
else
printf(" outEdge[%d] = %ld\n", i, edges[i].BBptr->begin());
printf("----\n");
/* Recursive call on successors of current node */
for(TYPEADR_TYPE &pb : edges)
{
if (pb.BBptr->traversed != DFS_DISP)
pb.BBptr->displayDfs();
}
}
/* Recursive procedure that writes the code for the given procedure, pointed
* to by pBB.
* Parameters: pBB: pointer to the cfg.
* Icode: pointer to the Icode array for the cfg graph of the
* current procedure.
* indLevel: indentation level - used for formatting.
* numLoc: last # assigned to local variables */
void BB::writeCode (int indLevel, Function * pProc , int *numLoc,int latchNode, int _ifFollow)
{
int follow, /* ifFollow */
_loopType, /* Type of loop, if any */
_nodeType; /* Type of node */
BB * succ, *latch; /* Successor and latching node */
ICODE * picode; /* Pointer to HLI_JCOND instruction */
char *l; /* Pointer to HLI_JCOND expression */
boolT emptyThen, /* THEN clause is empty */
repCond; /* Repeat condition for while() */
/* Check if this basic block should be analysed */
if ((_ifFollow != UN_INIT) && (this == pProc->m_dfsLast[_ifFollow]))
return;
if (traversed == DFS_ALPHA)
return;
traversed = DFS_ALPHA;
/* Check for start of loop */
repCond = FALSE;
latch = NULL;
_loopType = loopType;
if (_loopType)
{
latch = pProc->m_dfsLast[this->latchNode];
switch (_loopType)
{
case WHILE_TYPE:
picode = &this->back();
/* Check for error in while condition */
if (picode->hl()->opcode != HLI_JCOND)
reportError (WHILE_FAIL);
/* Check if condition is more than 1 HL instruction */
if (numHlIcodes > 1)
{
/* Write the code for this basic block */
writeBB(indLevel, pProc, numLoc);
repCond = true;
}
/* Condition needs to be inverted if the loop body is along
* the THEN path of the header node */
if (edges[ELSE].BBptr->dfsLastNum == loopFollow)
{
COND_EXPR *old_expr=picode->hl()->expr();
string e=walkCondExpr (old_expr, pProc, numLoc);
picode->hl()->expr(picode->hl()->expr()->inverse());
delete old_expr;
}
{
string e=walkCondExpr (picode->hl()->expr(), pProc, numLoc);
cCode.appendCode( "\n%swhile (%s) {\n", indent(indLevel),e.c_str());
}
picode->invalidate();
break;
case REPEAT_TYPE:
cCode.appendCode( "\n%sdo {\n", indent(indLevel));
picode = &latch->back();
picode->invalidate();
break;
case ENDLESS_TYPE:
cCode.appendCode( "\n%sfor (;;) {\n", indent(indLevel));
}
stats.numHLIcode += 1;
indLevel++;
}
/* Write the code for this basic block */
if (repCond == FALSE)
writeBB (indLevel, pProc, numLoc);
/* Check for end of path */
_nodeType = nodeType;
if (_nodeType == RETURN_NODE || _nodeType == TERMINATE_NODE ||
_nodeType == NOWHERE_NODE || (dfsLastNum == latchNode))
return;
/* Check type of loop/node and process code */
if (_loopType) /* there is a loop */
{
assert(latch);
if (this != latch) /* loop is over several bbs */
{
if (_loopType == WHILE_TYPE)
{
succ = edges[THEN].BBptr;
if (succ->dfsLastNum == loopFollow)
succ = edges[ELSE].BBptr;
}
else
succ = edges[0].BBptr;
if (succ->traversed != DFS_ALPHA)
succ->writeCode (indLevel, pProc, numLoc, latch->dfsLastNum,_ifFollow);
else /* has been traversed so we need a goto */
succ->front().ll()->emitGotoLabel (indLevel);
}
/* Loop epilogue: generate the loop trailer */
indLevel--;
if (_loopType == WHILE_TYPE)
{
/* Check if there is need to repeat other statements involved
* in while condition, then, emit the loop trailer */
if (repCond)
writeBB (indLevel+1, pProc, numLoc);
cCode.appendCode( "%s} /* end of while */\n",indent(indLevel));
}
else if (_loopType == ENDLESS_TYPE)
cCode.appendCode( "%s} /* end of loop */\n",indent(indLevel));
else if (_loopType == REPEAT_TYPE)
{
if (picode->hl()->opcode != HLI_JCOND)
reportError (REPEAT_FAIL);
{
string e=walkCondExpr (picode->hl()->expr(), pProc, numLoc);
cCode.appendCode( "%s} while (%s);\n", indent(indLevel),e.c_str());
}
}
/* Recurse on the loop follow */
if (loopFollow != MAX)
{
succ = pProc->m_dfsLast[loopFollow];
if (succ->traversed != DFS_ALPHA)
succ->writeCode (indLevel, pProc, numLoc, latchNode, _ifFollow);
else /* has been traversed so we need a goto */
succ->front().ll()->emitGotoLabel (indLevel);
}
}
else /* no loop, process nodeType of the graph */
{
if (_nodeType == TWO_BRANCH) /* if-then[-else] */
{
stats.numHLIcode++;
indLevel++;
emptyThen = FALSE;
if (ifFollow != MAX) /* there is a follow */
{
/* process the THEN part */
follow = ifFollow;
succ = edges[THEN].BBptr;
if (succ->traversed != DFS_ALPHA) /* not visited */
{
if (succ->dfsLastNum != follow) /* THEN part */
{
l = writeJcond ( *back().hl(), pProc, numLoc);
cCode.appendCode( "\n%s%s", indent(indLevel-1), l);
succ->writeCode (indLevel, pProc, numLoc, latchNode,follow);
}
else /* empty THEN part => negate ELSE part */
{
l = writeJcondInv ( *back().hl(), pProc, numLoc);
cCode.appendCode( "\n%s%s", indent(indLevel-1), l);
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, latchNode, follow);
emptyThen = true;
}
}
else /* already visited => emit label */
succ->front().ll()->emitGotoLabel(indLevel);
/* process the ELSE part */
succ = edges[ELSE].BBptr;
if (succ->traversed != DFS_ALPHA) /* not visited */
{
if (succ->dfsLastNum != follow) /* ELSE part */
{
cCode.appendCode( "%s}\n%selse {\n",
indent(indLevel-1), indent(indLevel - 1));
succ->writeCode (indLevel, pProc, numLoc, latchNode, follow);
}
/* else (empty ELSE part) */
}
else if (! emptyThen) /* already visited => emit label */
{
cCode.appendCode( "%s}\n%selse {\n",
indent(indLevel-1), indent(indLevel - 1));
succ->front().ll()->emitGotoLabel (indLevel);
}
cCode.appendCode( "%s}\n", indent(--indLevel));
/* Continue with the follow */
succ = pProc->m_dfsLast[follow];
if (succ->traversed != DFS_ALPHA)
succ->writeCode (indLevel, pProc, numLoc, latchNode,_ifFollow);
}
else /* no follow => if..then..else */
{
l = writeJcond ( *back().hl(), pProc, numLoc);
cCode.appendCode( "%s%s", indent(indLevel-1), l);
edges[THEN].BBptr->writeCode (indLevel, pProc, numLoc, latchNode, _ifFollow);
cCode.appendCode( "%s}\n%selse {\n", indent(indLevel-1), indent(indLevel - 1));
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, latchNode, _ifFollow);
cCode.appendCode( "%s}\n", indent(--indLevel));
}
}
else /* fall, call, 1w */
{
succ = edges[0].BBptr; /* fall-through edge */
if (succ->traversed != DFS_ALPHA)
succ->writeCode (indLevel, pProc,numLoc, latchNode,_ifFollow);
}
}
}
/* Writes the code for the current basic block.
* Args: pBB: pointer to the current basic block.
* Icode: pointer to the array of icodes for current procedure.
* lev: indentation level - used for formatting. */
void BB::writeBB(int lev, Function * pProc, int *numLoc)
{
/* Save the index into the code table in case there is a later goto
* into this instruction (first instruction of the BB) */
front().ll()->codeIdx = nextBundleIdx (&cCode.code);
//hli[start].codeIdx = nextBundleIdx (&cCode.code);
//for (i = start, last = i + length; i < last; i++)
/* Generate code for each hlicode that is not a HLI_JCOND */
int idx=start;
for(iICODE hli=begin2(); hli!=end2(); ++hli)
{
if ((hli->type == HIGH_LEVEL) && (hli->invalid == FALSE))
{
std::string line = hli->hl()->write1HlIcode(pProc, numLoc);
if (!line.empty())
{
cCode.appendCode( "%s%s", indent(lev), line.c_str());
stats.numHLIcode++;
}
if (option.verbose)
hli->writeDU(idx);
}
idx++;
}
}
int BB::begin()
{
return start;
}
iICODE BB::begin2()
{
iICODE result(Parent->Icode.begin());
advance(result,start);
return result;
}
iICODE BB::end2()
{
iICODE result(Parent->Icode.begin());
advance(result,start+length);
return result;
}
int BB::rbegin()
{
return start+length-1;
}
int BB::end()
{
return start+length;
}
ICODE &BB::back()
{
return *rbegin2();
}
size_t BB::size()
{
return length;
}
ICODE &BB::front()
{
return *begin2();
}
riICODE BB::rbegin2()
{
riICODE res(end2());
assert(res->loc_ip==rbegin());
return res;
}
riICODE BB::rend2()
{
return riICODE(begin2());
}