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