MWCC/compiler_and_linker/unsorted/IroJump.c

268 lines
9.3 KiB
C

#include "compiler/IroJump.h"
#include "compiler/IroDump.h"
#include "compiler/IroFlowgraph.h"
#include "compiler/IroLinearForm.h"
#include "compiler/IroUtil.h"
#include "compiler/CFunc.h"
#include "compiler/Exceptions.h"
static Boolean CheckChain(CLabel **labelptr) {
IRONode *node;
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->first && node->first->type == IROLinearLabel && node->first->u.label.label == *labelptr) {
IROLinear *linear;
CLabel *lab;
for (linear = node->first->next, lab = NULL; linear && (linear->type == IROLinearLabel || linear->type == IROLinearNop); linear = linear->next) {
if (linear->type == IROLinearLabel)
lab = linear->u.label.label;
}
if (linear->type == IROLinearGoto && *labelptr != linear->u.label.label) {
*labelptr = linear->u.label.label;
IRO_Dump("Chaining goto at %d\n", linear->index);
return 1;
}
if (lab && *labelptr != lab)
*labelptr = lab;
return 0;
}
}
return 0;
}
Boolean IRO_DoJumpChaining(void) {
IRONode *node;
IROLinear *linear;
Boolean flag;
SwitchInfo *info;
SwitchCase *curcase;
Boolean result;
result = 0;
do {
flag = 0;
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->first) {
linear = node->last;
switch (linear->type) {
case IROLinearGoto:
if (CheckChain(&linear->u.label.label))
flag = 1;
break;
case IROLinearIf:
case IROLinearIfNot:
if (CheckChain(&linear->u.label.label))
flag = 1;
break;
case IROLinearSwitch:
info = linear->u.swtch.info;
for (curcase = info->cases; curcase; curcase = curcase->next) {
if (CheckChain(&curcase->label))
flag = 1;
}
if (CheckChain(&info->defaultlabel))
flag = 1;
break;
}
}
}
result |= flag;
IRO_CheckForUserBreak();
} while (flag);
return result;
}
void IRO_MakeReachable(IRONode *node) {
UInt16 i;
Boolean flag;
node->x36 = 1;
do {
flag = 0;
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->x36 && !node->x37) {
for (i = 0; i < node->numsucc; i++) {
if (!IRO_NodeTable[node->succ[i]]->x36) {
flag = 1;
IRO_NodeTable[node->succ[i]]->x36 = 1;
}
}
node->x37 = 1;
}
}
} while (flag);
}
Boolean IRO_RemoveUnreachable(void) {
IRONode *node2;
IRONode *node1;
IROLinear *scan;
IROLinear *linear;
Boolean result;
ExceptionAction **actptr;
ExceptionAction *act;
result = 0;
IRO_ComputeSuccPred();
IRO_MakeReachable(IRO_FirstNode);
node1 = IRO_FirstNode;
for (node2 = IRO_FirstNode->nextnode; node2; node2 = node2->nextnode) {
if (node2->first && !node2->x36) {
IRO_Dump("Removing unreachable code at: %d\n", node2->index);
node1->nextnode = node2->nextnode;
node1->last->next = node2->last->next;
result = 1;
for (linear = node2->first; linear && linear->type == IROLinearLabel && linear != node2->last->next; linear = linear->next) {
for (scan = IRO_FirstLinear; scan; scan = scan->next) {
if (scan->stmt)
scan->stmt->marked = 0;
}
for (scan = IRO_FirstLinear; scan; scan = scan->next) {
if (scan->stmt && !scan->stmt->marked) {
scan->stmt->marked = 1;
for (actptr = &scan->stmt->dobjstack; (act = *actptr); actptr = &act->prev) {
if (
(act->type == EAT_CATCHBLOCK && act->data.catch_block.catch_label == linear->u.label.label) ||
(act->type == EAT_SPECIFICATION && act->data.specification.unexp_label == linear->u.label.label)) {
*actptr = act->prev;
}
}
}
}
}
if (node2 == IRO_LastNode)
IRO_LastNode = node1;
} else {
node1 = node2;
}
}
if (result) {
IRO_ComputeSuccPred();
IRO_ComputeDom();
}
IRO_CheckForUserBreak();
return result;
}
Boolean IRO_RemoveRedundantJumps(void) {
IRONode *node;
IROLinear *linear;
IROLinear *scan;
IROLinear *scan2;
SwitchInfo *info;
SwitchCase *curcase;
Boolean result;
result = 0;
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->first) {
linear = node->last;
switch (linear->type) {
case IROLinearGoto:
scan = linear->next;
while (scan && ((scan->type == IROLinearNop) || (scan->type == IROLinearLabel && scan->u.label.label != linear->u.label.label)))
scan = scan->next;
while (1) {
if (!scan) break;
if (scan->type != IROLinearLabel) break;
if (scan->u.label.label == linear->u.label.label) {
IRO_Dump("Removing goto next at %d\n", linear->index);
linear->type = IROLinearNop;
result = 1;
break;
}
scan = scan->next;
}
break;
case IROLinearIf:
case IROLinearIfNot:
scan = linear->next;
while (scan && scan->type == IROLinearNop)
scan = scan->next;
if (scan && scan->type == IROLinearGoto) {
scan2 = scan->next;
while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label)))
scan2 = scan2->next;
if (scan2 && scan2->type == IROLinearLabel && scan2->u.label.label == linear->u.label.label) {
if (linear->type == IROLinearIf)
linear->type = IROLinearIfNot;
else
linear->type = IROLinearIf;
linear->u.label.label = scan->u.label.label;
scan->type = IROLinearNop;
IRO_Dump("Removing branch around goto at %d\n", linear->index);
result = 1;
}
}
scan2 = linear->next;
while (scan2 && ((scan2->type == IROLinearNop) || (scan2->type == IROLinearLabel && scan2->u.label.label != linear->u.label.label)))
scan2 = scan2->next;
while (1) {
if (!scan2) break;
if (scan2->type != IROLinearLabel) break;
if (scan2->u.label.label == linear->u.label.label) {
IRO_Dump("Removing If/IfNot_Goto next at %d\n", linear->index);
linear->type = IROLinearNop;
IRO_CheckSideEffect(linear->u.label.x4);
result = 1;
break;
}
scan2 = scan2->next;
}
break;
case IROLinearSwitch:
info = linear->u.swtch.info;
curcase = info->cases;
while (curcase && curcase->label == info->defaultlabel)
curcase = curcase->next;
if (!curcase) {
IRO_Dump("Removing Switch next at %d\n", linear->index);
IRO_CheckSideEffect(linear->u.swtch.x4);
linear->type = IROLinearGoto;
linear->u.label.label = info->defaultlabel;
result = 1;
}
break;
}
}
}
if (result) {
IRO_ComputeSuccPred();
IRO_ComputeDom();
}
IRO_CheckForUserBreak();
return result;
}
Boolean IRO_RemoveLabels(void) {
Boolean result;
IRONode *node;
result = 0;
IRO_ComputeSuccPred();
for (node = IRO_FirstNode; node; node = node->nextnode) {
if (node->first && node->first->type == IROLinearLabel && !node->x39) {
node->first->type = IROLinearNop;
node->first->flags &= ~IROLF_1;
result = 1;
}
}
IRO_CheckForUserBreak();
return result;
}