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