MWCC/compiler_and_linker/unsorted/IroFlowgraph.c

440 lines
13 KiB
C

#include "compiler/IroFlowgraph.h"
#include "compiler/IroCSE.h"
#include "compiler/IroLinearForm.h"
#include "compiler/IroPropagate.h"
#include "compiler/IROUseDef.h"
#include "compiler/IroUtil.h"
#include "compiler/CError.h"
#include "compiler/CFunc.h"
#include "compiler/CompilerTools.h"
#include "compiler/Exceptions.h"
#include "compiler/InlineAsmPPC.h"
UInt16 IRO_NumNodes;
IRONode *IRO_FirstNode;
IRONode *IRO_LastNode;
IRONode *IRO_EndNode;
IRONode **IRO_NodeTable;
BitVector *IRO_VarKills;
BitVector *IRO_Avail;
BitVector *IRO_FuncKills;
BitVector *IRO_ExprKills;
static IRONode *StartNode(IROLinear *linear) {
IRONode *node = oalloc(sizeof(IRONode));
node->index = IRO_NumNodes;
node->numsucc = 0;
node->succ = NULL;
node->numpred = 0;
node->pred = NULL;
node->first = linear;
node->last = linear;
node->x16 = NULL;
node->x1A = NULL;
node->x1E = NULL;
node->x22 = NULL;
node->x26 = 0;
node->x2A = NULL;
node->dom = NULL;
node->nextnode = NULL;
node->x36 = 0;
node->x37 = 0;
node->mustreach = 0;
node->x39 = 0;
node->loopdepth = 0;
node->x3C = 0;
node->addressed = NULL;
IRO_NumNodes++;
if (!IRO_FirstNode)
IRO_FirstNode = node;
else
IRO_LastNode->nextnode = node;
IRO_LastNode = node;
return node;
}
static void AddSucc(IRONode *a, IRONode *b) {
a->succ[a->numsucc++] = b->index;
b->numpred++;
}
static void AddLabelSucc(IRONode *node, CLabel *label) {
IRONode *targetnode = (IRONode *) label->stmt;
if (targetnode) {
AddSucc(node, targetnode);
targetnode->x39 = 1;
} else {
CError_FATAL(126);
}
}
static void AddSwitchSucc(IRONode *node) {
SwitchInfo *info = node->last->u.swtch.info;
SwitchCase *curcase = info->cases;
SInt32 i = 1;
while (curcase) {
curcase = curcase->next;
i++;
}
node->succ = oalloc(sizeof(UInt16) * i);
for (curcase = info->cases; curcase; curcase = curcase->next)
AddLabelSucc(node, curcase->label);
AddLabelSucc(node, info->defaultlabel);
}
static void AddPred(UInt32 a, UInt16 b) {
IRONode *node = IRO_NodeTable[a];
node->pred[node->numpred++] = b;
}
void IRO_ComputeSuccPred(void) {
CLabel *label;
IRONode *node;
SInt32 count;
IROLinear *linear;
ExceptionAction *action;
IAEffects effects;
UInt16 i;
for (label = Labels; label; label = label->next)
label->stmt = NULL;
for (node = IRO_FirstNode; node; node = node->nextnode) {
node->x39 = 0;
node->numsucc = 0;
node->numpred = 0;
node->x36 = 0;
node->x37 = 0;
if (node->first && node->first->type == IROLinearLabel)
node->first->u.label.label->stmt = (Statement *) node;
}
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (!node->first) {
if (node->nextnode) {
node->succ = oalloc(sizeof(UInt16));
AddSucc(node, node->nextnode);
}
} else {
linear = node->last;
next_linear:
switch (linear->type) {
case IROLinearReturn:
case IROLinearEnd:
break;
case IROLinearGoto:
node->succ = oalloc(sizeof(UInt16));
AddLabelSucc(node, linear->u.label.label);
break;
case IROLinearIf:
case IROLinearIfNot:
node->succ = oalloc(sizeof(UInt16) * 2);
AddSucc(node, node->nextnode);
AddLabelSucc(node, linear->u.label.label);
break;
case IROLinearSwitch:
AddSwitchSucc(node);
break;
case IROLinearFunccall:
count = 1;
if (IRO_FunctionCallMightThrowException(linear)) {
for (action = linear->stmt->dobjstack; action; action = action->prev) {
if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION)
count++;
}
}
node->succ = oalloc(sizeof(UInt16) * count);
AddSucc(node, node->nextnode);
if (IRO_FunctionCallMightThrowException(linear)) {
for (action = linear->stmt->dobjstack; action; action = action->prev) {
if (action->type == EAT_CATCHBLOCK)
AddLabelSucc(node, action->data.catch_block.catch_label);
else if (action->type == EAT_SPECIFICATION)
AddLabelSucc(node, action->data.specification.unexp_label);
}
}
break;
case IROLinearAsm:
CodeGen_GetAsmEffects(linear->u.asm_stmt, &effects);
node->succ = oalloc(sizeof(UInt16) * (!effects.x5 + effects.numlabels));
if (!effects.x5)
AddSucc(node, node->nextnode);
for (i = 0; i < effects.numlabels; i++)
AddLabelSucc(node, effects.labels[i]);
break;
case IROLinearOp2Arg:
if (linear->nodetype == ECOMMA) {
linear = linear->u.diadic.right;
goto next_linear;
}
default:
if (node->nextnode) {
node->succ = oalloc(sizeof(UInt16));
AddSucc(node, node->nextnode);
}
}
}
}
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->numpred)
node->pred = oalloc(sizeof(UInt16) * node->numpred);
else
node->pred = NULL;
node->numpred = 0;
}
for (node = IRO_FirstNode; node; node = node->nextnode) {
for (i = 0; i < node->numsucc; i++)
AddPred(node->succ[i], node->index);
}
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->first && node->first->type == IROLinearLabel) {
IROLinear *linear = node->first;
do {
if (linear->type == IROLinearBeginCatch || linear->type == IROLinearEndCatch || linear->type == IROLinearEndCatchDtor) {
node->x39 = 1;
break;
}
} while (linear != node->last && (linear = linear->next));
}
}
}
void IRO_ComputeDom(void) {
IRONode *node;
BitVector *bv;
SInt32 i;
int repeat;
Bv_AllocVector(&IRO_FirstNode->dom, IRO_NumNodes);
Bv_SetBit(IRO_FirstNode->index, IRO_FirstNode->dom);
for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) {
Bv_AllocVector(&node->dom, IRO_NumNodes);
Bv_Set(node->dom);
}
Bv_AllocVector(&bv, IRO_NumNodes);
do {
repeat = 0;
for (node = IRO_FirstNode->nextnode; node; node = node->nextnode) {
if (node->numpred) {
Bv_Set(bv);
for (i = 0; i < node->numpred; i++) {
Bv_And(IRO_NodeTable[node->pred[i]]->dom, bv);
}
Bv_SetBit(node->index, bv);
} else {
Bv_Clear(bv);
Bv_SetBit(node->index, bv);
}
if (!Bv_Compare(bv, node->dom)) {
Bv_Copy(bv, node->dom);
repeat = 1;
}
}
} while (repeat);
}
void IRO_BuildFlowgraph(IROLinear *linear) {
IROLinear *scan;
CLabel *label;
ExceptionAction *action;
IAEffects effects;
IRONode *node;
SInt32 i;
int flag;
for (label = Labels; label; label = label->next)
label->stmt = NULL;
scan = linear;
IRO_NumNodes = 0;
IRO_FirstNode = IRO_LastNode = IRO_EndNode = NULL;
while (scan) {
StartNode(scan);
if (scan->type == IROLinearLabel)
scan->u.label.label->stmt = (Statement *) IRO_LastNode;
flag = 0;
while (!flag && scan->next && !(scan->next->flags & IROLF_1)) {
switch (scan->type) {
case IROLinearGoto:
case IROLinearReturn:
case IROLinearEntry:
case IROLinearExit:
case IROLinearEnd:
flag = 1;
break;
case IROLinearIf:
case IROLinearIfNot:
case IROLinearSwitch:
flag = 1;
skip:
if (scan->next->type == IROLinearLabel) {
IROLinear *nw = IRO_NewLinear(IROLinearNop);
nw->index = ++IRO_NumLinear;
nw->next = scan->next;
scan->next = nw;
}
break;
case IROLinearFunccall:
if (IRO_FunctionCallMightThrowException(scan)) {
for (action = scan->stmt->dobjstack; action; action = action->prev) {
if (action->type == EAT_CATCHBLOCK || action->type == EAT_SPECIFICATION) {
flag = 1;
goto skip;
}
}
}
break;
case IROLinearAsm:
CodeGen_GetAsmEffects(scan->u.asm_stmt, &effects);
if (effects.numlabels)
flag = 1;
break;
}
if (!flag)
scan = scan->next;
}
if (scan->type == IROLinearEnd)
IRO_EndNode = IRO_LastNode;
IRO_LastNode->last = scan;
scan = scan->next;
}
IRO_NodeTable = oalloc(IRO_NumNodes * sizeof(IRONode *));
memset(IRO_NodeTable, 0, IRO_NumNodes * sizeof(IRONode *));
for (node = IRO_FirstNode, i = 0; node; node = node->nextnode)
IRO_NodeTable[i++] = node;
IRO_ComputeSuccPred();
IRO_ComputeDom();
IRO_CheckForUserBreak();
}
IRONode *IRO_NewFlowGraphNode(void) {
IRONode *node = oalloc(sizeof(IRONode));
memset(node, 0, sizeof(IRONode));
node->index = IRO_NumNodes;
IRO_NumNodes++;
node->nextnode = NULL;
return node;
}
IRONode *IRO_MergeFlowGraphNodes(IRONode *a, IRONode *b) {
IRONode *succ;
Boolean found;
UInt32 i;
UInt32 j;
UInt32 k;
if (a->nextnode == b && a->last && b->first && a->last->next == b->first) {
if (b->first->type == IROLinearLabel)
IRO_NopOut(b->first);
a->nextnode = b->nextnode;
a->last = b->last;
for (i = 0; i < a->numsucc; i++) {
if (b->index == a->succ[i]) {
for (j = i; j < a->numsucc; j++) {
if ((j + 1) < a->numsucc)
a->succ[j] = a->succ[j + 1];
else
a->succ[j] = 0;
}
a->numsucc--;
break;
}
}
for (i = 0; i < b->numsucc; i++) {
succ = IRO_NodeTable[b->succ[i]];
for (j = 0; j < a->numsucc; j++) {
if (b->succ[i] == a->succ[j])
break;
}
if (j == a->numsucc) {
AddSucc(a, IRO_NodeTable[b->succ[i]]);
succ->numpred--;
}
found = 0;
for (j = 0; j < succ->numpred; j++) {
if (a->index == succ->pred[j]) {
found = 1;
break;
}
}
for (j = 0; j < succ->numpred; j++) {
if (b->index == succ->pred[j]) {
if (!found) {
succ->pred[j] = a->index;
} else {
for (k = j; k < succ->numpred; k++) {
if ((k + 1) < succ->numpred)
succ->pred[k] = succ->pred[k + 1];
else
succ->pred[k] = 0;
}
succ->numpred--;
}
break;
}
}
}
b->numsucc = b->numpred = 0;
b->first = b->last = NULL;
b->nextnode = NULL;
b->x36 = 0;
b->x37 = 0;
b->mustreach = 0;
b->x39 = 0;
b->loopdepth = 0;
if (IRO_LastNode == b)
IRO_LastNode = a;
if (IRO_FirstExpr && IRO_LastExpr) {
IROExpr *expr;
for (expr = IRO_FirstExpr; expr && expr != IRO_LastExpr->next; expr = expr->next) {
if (expr->node == b)
expr->node = a;
}
}
if (IRO_FirstAssign && IRO_LastAssign) {
IROAssign *assign;
for (assign = IRO_FirstAssign; assign && assign != IRO_LastAssign->next; assign = assign->next) {
if (assign->node == b)
assign->node = a;
}
}
if (IRO_FirstVarUse && IRO_LastVarUse) {
IROUse *use;
for (use = IRO_FirstVarUse; use && use != IRO_LastVarUse->globalnext; use = use->globalnext) {
if (use->node == b)
use->node = a;
}
}
IRO_NodeTable[b->index] = NULL;
return a;
}
return NULL;
}