diff options
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c | 1797 |
1 files changed, 1797 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c b/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c new file mode 100644 index 0000000..8c5b0d8 --- /dev/null +++ b/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c @@ -0,0 +1,1797 @@ +#include "IroLinearForm.h" +#include "IroDump.h" +#include "IroFlowgraph.h" +#include "IroUtil.h" +#include "IroVars.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInt64.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/InlineAsm.h" +#include "compiler/InlineAsmPPC.h" +#include "compiler/types.h" + +typedef struct NullCheckListNode { + SInt32 precompid; + Object *tempobj; + struct NullCheckListNode *next; +} NullCheckListNode; + +IROLinear *IRO_FirstLinear; +IROLinear *IRO_LastLinear; +UInt32 IRO_NumLinear; +Statement *CurStat; +static NullCheckListNode *NullCheckList; +static Statement *CurrStmt; +static Statement *PrevStmt; + +static void LinkLinear(IROLinear *linear) { + linear->index = IRO_NumLinear++; + if (IRO_FirstLinear) + IRO_LastLinear->next = linear; + else + IRO_FirstLinear = linear; + IRO_LastLinear = linear; +} + +IROLinear *IRO_NewLinear(IROLinearType type) { + IROLinear *linear = oalloc(sizeof(IROLinear)); + memset(linear, 0, sizeof(IROLinear)); + linear->stmt = CurStat; + linear->nodetype = EPOSTINC; + linear->next = NULL; + linear->type = type; + linear->rtype = NULL; + linear->flags = 0; + linear->nodeflags = 0; + linear->expr = NULL; + linear->x16 = 0; + return linear; +} + +static void MarkAssigned(IROLinear *linear, Boolean flag) { + IROLinear *inner; + IROAddrRecord *rec; + + if (IS_LINEAR_MONADIC(linear, EINDIRECT) && IS_LINEAR_MONADIC(linear->u.monadic, EBITFIELD)) { + linear->flags |= IROLF_Assigned; + inner = linear->u.monadic->u.monadic; + if (inner->type == IROLinearOperand) { + inner->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + inner->flags |= IROLF_Used; + } + } + + if (IS_LINEAR_DIADIC(inner, EADD)) { + if (IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + if (IS_LINEAR_ENODE(inner->u.diadic.right, EINTCONST)) + inner->u.diadic.left->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + inner->u.diadic.left->flags |= IROLF_Used; + } + } + + rec = IRO_InitAddrRecordPointer(inner); + IRO_DecomposeAddressExpression(inner, rec); + if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Used; + } + } + } + } + + if (IS_LINEAR_MONADIC(linear, EINDIRECT)) { + linear->flags |= IROLF_Assigned; + if (linear->u.monadic->type == IROLinearOperand) { + linear->u.monadic->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + linear->u.monadic->flags |= IROLF_Used; + } + } + } + + if (IS_LINEAR_MONADIC(linear, EINDIRECT)) { + linear->flags |= IROLF_Assigned; + inner = linear->u.monadic; + + if (IS_LINEAR_DIADIC(inner, EADD)) { + if (IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + if (IS_LINEAR_ENODE(inner->u.diadic.right, EINTCONST)) + inner->u.diadic.left->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + inner->u.diadic.left->flags |= IROLF_Used; + } + } + + rec = IRO_InitAddrRecordPointer(inner); + IRO_DecomposeAddressExpression(inner, rec); + if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(inner->u.diadic.left, EOBJREF)) { + ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Assigned; + if (flag) { + linear->flags |= IROLF_Used; + ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Used; + } + } + } + } +} + +static void MarkSubscript(IROLinear *linear) { + linear->flags |= IROLF_Subs; + if (IS_LINEAR_DIADIC(linear, EADD)) { + if (IRO_IsAddressMultiply(linear->u.diadic.left) || IS_LINEAR_MONADIC(linear->u.diadic.left, EINDIRECT)) + linear->u.diadic.left->flags |= IROLF_Subs; + if (IRO_IsAddressMultiply(linear->u.diadic.right) || IS_LINEAR_MONADIC(linear->u.diadic.right, EINDIRECT)) + linear->u.diadic.right->flags |= IROLF_Subs; + + if (IS_LINEAR_DIADIC(linear->u.diadic.left, EADD)) + MarkSubscript(linear->u.diadic.left); + if (IS_LINEAR_DIADIC(linear->u.diadic.right, EADD)) + MarkSubscript(linear->u.diadic.right); + } +} + +static void MarkArgs(IROLinear *linear) { + int i; + linear->flags |= IROLF_4000; + + switch (linear->type) { + case IROLinearEnd: + break; + case IROLinearOp1Arg: + case IROLinearBeginCatch: + case IROLinearEndCatch: + case IROLinearEndCatchDtor: + MarkArgs(linear->u.monadic); + break; + case IROLinearOp2Arg: + MarkArgs(linear->u.diadic.left); + MarkArgs(linear->u.diadic.right); + break; + case IROLinearIf: + case IROLinearIfNot: + MarkArgs(linear->u.label.x4); + break; + case IROLinearReturn: + if (linear->u.monadic) + MarkArgs(linear->u.monadic); + break; + case IROLinearSwitch: + MarkArgs(linear->u.swtch.x4); + break; + case IROLinearOp3Arg: + MarkArgs(linear->u.args3.a); + MarkArgs(linear->u.args3.b); + MarkArgs(linear->u.args3.c); + break; + case IROLinearFunccall: + MarkArgs(linear->u.funccall.linear8); + for (i = 0; i < linear->u.funccall.argCount; i++) + MarkArgs(linear->u.funccall.args[i]); + break; + } +} + +// assumed name, position +CW_INLINE void MarkSubExpr(IROLinear *linear) { + int i; + + switch (linear->type) { + case IROLinearNop: + case IROLinearOperand: + case IROLinearGoto: + case IROLinearLabel: + case IROLinearEntry: + case IROLinearExit: + case IROLinearAsm: + case IROLinearEnd: + break; + case IROLinearOp1Arg: + case IROLinearBeginCatch: + case IROLinearEndCatch: + case IROLinearEndCatchDtor: + linear->u.monadic->flags |= IROLF_Reffed; + break; + case IROLinearOp2Arg: + linear->u.diadic.left->flags |= IROLF_Reffed; + linear->u.diadic.right->flags |= IROLF_Reffed; + break; + case IROLinearIf: + case IROLinearIfNot: + linear->u.label.x4->flags |= IROLF_Reffed; + break; + case IROLinearReturn: + if (linear->u.monadic) + linear->u.monadic->flags |= IROLF_Reffed; + break; + case IROLinearSwitch: + linear->u.swtch.x4->flags |= IROLF_Reffed; + break; + case IROLinearOp3Arg: + linear->u.args3.a->flags |= IROLF_Reffed; + linear->u.args3.b->flags |= IROLF_Reffed; + linear->u.args3.c->flags |= IROLF_Reffed; + break; + case IROLinearFunccall: + linear->u.funccall.linear8->flags |= IROLF_Reffed; + for (i = 0; i < linear->u.funccall.argCount; i++) + linear->u.funccall.args[i]->flags |= IROLF_Reffed; + break; + default: + CError_FATAL(368); + } +} + +static void MarkSubs1(IROLinear *linear) { + IROAddrRecord *rec; + + if (IS_LINEAR_MONADIC(linear, EBITFIELD)) { + linear = linear->u.monadic; + if (IS_LINEAR_ENODE(linear, EOBJREF)) + linear->flags |= IROLF_Ind; + } + + if (IS_LINEAR_DIADIC(linear, EADD)) { + if (IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF) && IS_LINEAR_ENODE(linear->u.diadic.right, EINTCONST)) + linear->u.diadic.left->flags |= IROLF_Ind; + + rec = IRO_InitAddrRecordPointer(linear); + IRO_DecomposeAddressExpression(linear, rec); + if (rec->numObjRefs == 1 && IS_LINEAR_ENODE(linear->u.diadic.left, EOBJREF)) + ((IROLinear *) rec->objRefs->element)->flags |= IROLF_Ind; + } +} + +static void MakeLeftChildAsAssignment(ENode *enode) { + Statement *stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = enode->data.diadic.left; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void AssignCommaRToTemp(ENode *enode, Boolean flag) { + Statement *stmt; + + if (!IS_TYPE_VOID(enode->rtype) && !flag) { + Object *obj = create_temp_object(enode->rtype); + ENode *indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(obj); + + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(548); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.diadic.right; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(obj); + CError_ASSERT(580, !IS_TYPE_VOID(enode->rtype)); + } else { + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = enode->data.diadic.right; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINTCONST; + enode->data.intval = cint64_zero; + } +} + +static void AssignDangerousArgumentToTemp(ENode *enode) { + Statement *stmt; + Object *obj; + ENode *indnode; + ENode *rightnode; + + obj = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(obj); + + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(627); + + rightnode = IRO_NewENode(enode->type); + memcpy(rightnode, enode, sizeof(ENode)); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(obj); +} + +static void CreateTempAssignmentToZero(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(678); + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_zero; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void CreateTempAssignmentToOne(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(720); + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_one; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateCondExpression(ENode *enode, CLabel **label) { + Statement *stmt; + + *label = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = enode->data.cond.cond; + stmt->label = *label; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateGoToStmt(ENode *enode, CLabel **label) { + Statement *stmt; + + *label = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_GOTO; + stmt->label = *label; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void PutTempOnNullCheckList(ENode *expr, Object *obj) { + NullCheckListNode *n = lalloc(sizeof(NullCheckListNode)); + n->precompid = expr->data.nullcheck.precompid; + n->tempobj = obj; + n->next = NULL; + if (NullCheckList) { + n->next = NullCheckList; + NullCheckList = n; + } else { + NullCheckList = n; + } +} + +static Object *GetTempFromtheList(ENode *expr) { + NullCheckListNode *n; + + for (n = NullCheckList; n; n = n->next) { + if (n->precompid == expr->data.precompid) + break; + } + + CError_ASSERT(839, n); + return n->tempobj; +} + +static void GenerateNullcheckExprTempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) + *objptr = create_temp_object(enode->rtype); + else + *objptr = create_temp_object(enode->data.nullcheck.nullcheckexpr->rtype); + + PutTempOnNullCheckList(enode, *objptr); + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + indnode->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.nullcheck.nullcheckexpr; + if (!IS_TYPE_VOID(enode->rtype)) + stmt->expr->rtype = enode->rtype; + else + stmt->expr->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateExpr1TempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) { + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + indnode->rtype = enode->rtype; + CError_ASSERT(905, !IS_TYPE_VOID(enode->rtype)); + } + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + if (!IS_TYPE_VOID(enode->rtype)) { + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.cond.expr1; + stmt->expr->rtype = enode->rtype; + } else { + stmt->expr = enode->data.cond.expr1; + } + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateExpr2TempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) { + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + indnode->rtype = enode->rtype; + CError_ASSERT(953, !IS_TYPE_VOID(enode->rtype)); + } + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + if (!IS_TYPE_VOID(enode->rtype)) { + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.cond.expr2; + stmt->expr->rtype = enode->rtype; + } else { + stmt->expr = enode->data.cond.expr2; + } + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateForceLoadTempAssignment(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + if (!IS_TYPE_VOID(enode->rtype)) { + *objptr = create_temp_object(enode->rtype); + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + indnode->rtype = enode->rtype; + CError_ASSERT(1003, !IS_TYPE_VOID(enode->rtype)); + } + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + if (!IS_TYPE_VOID(enode->rtype)) { + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.monadic; + stmt->expr->rtype = enode->rtype; + } else { + stmt->expr = enode->data.monadic; + } + + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateLabel(CLabel **labelptr) { + Statement *stmt; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_LABEL; + stmt->label = *labelptr; + stmt->label->stmt = stmt; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateIfNotTemp(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + ENode *indnode; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + indnode->rtype = enode->data.monadic->rtype; + + *labelptr = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = indnode; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void GenerateNullcheckCondExpr(ENode *enode, Object **objptr) { + Statement *stmt; + ENode *indnode; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + indnode->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = enode->data.nullcheck.condexpr; + if (!IS_TYPE_VOID(enode->rtype)) + stmt->expr->rtype = enode->rtype; + else + stmt->expr->rtype = enode->data.nullcheck.nullcheckexpr->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void TransformLogicalAndLHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + + *labelptr = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = enode->data.diadic.left; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void TransformLogicalAndRHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFNGOTO; + stmt->expr = enode->data.diadic.right; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(1225); + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_one; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_LABEL; + stmt->label = *labelptr; + stmt->label->stmt = stmt; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(*objptr); + CError_ASSERT(1276, !IS_TYPE_VOID(enode->rtype)); +} + +static void TransformLogicalOrLHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + + *labelptr = IRO_NewLabel(); + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFGOTO; + stmt->expr = enode->data.diadic.left; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; +} + +static void TransformLogicalOrRHS(ENode *enode, Object **objptr, CLabel **labelptr) { + Statement *stmt; + ENode *indnode; + ENode *rightnode; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_IFGOTO; + stmt->expr = enode->data.diadic.right; + stmt->label = *labelptr; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + indnode = IRO_NewENode(EINDIRECT); + indnode->data.monadic = create_objectrefnode(*objptr); + if (!IS_TYPE_VOID(enode->rtype)) + indnode->rtype = enode->rtype; + else + CError_FATAL(1354); + + rightnode = IRO_NewENode(EINTCONST); + rightnode->data.intval = cint64_zero; + rightnode->rtype = enode->rtype; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_EXPRESSION; + stmt->expr = IRO_NewENode(EASS); + stmt->expr->data.diadic.left = indnode; + stmt->expr->data.diadic.right = rightnode; + stmt->expr->rtype = enode->rtype; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = ST_LABEL; + stmt->label = *labelptr; + stmt->label->stmt = stmt; + stmt->dobjstack = CurrStmt->dobjstack; + stmt->sourceoffset = CurrStmt->sourceoffset; + stmt->sourcefilepath = CurrStmt->sourcefilepath; + stmt->value = CurrStmt->value; + stmt->flags = CurrStmt->flags; + + if (PrevStmt) { + stmt->next = PrevStmt->next; + PrevStmt->next = stmt; + } else { + stmt->next = NULL; + } + PrevStmt = stmt; + + enode->type = EINDIRECT; + enode->data.monadic = create_objectrefnode(*objptr); + CError_ASSERT(1405, !IS_TYPE_VOID(enode->rtype)); +} + +static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) { + switch (a->type) { + ENODE_CASE_MONADIC: + LinearizeExpr1(a->data.monadic, a, 0, 0); + if (a->type == EFORCELOAD) { + Object *obj; + GenerateForceLoadTempAssignment(a, &obj); + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(obj); + CError_ASSERT(1428, !IS_TYPE_VOID(a->rtype)); + } + break; + ENODE_CASE_DIADIC_1: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBTST: + if (a->type == ECOMMA) { + LinearizeExpr1(a->data.diadic.left, a, 1, 0); + MakeLeftChildAsAssignment(a); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + AssignCommaRToTemp(a, flag); + } else if (a->data.diadic.right->cost >= a->data.diadic.left->cost) { + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + } else { + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + } + break; + ENODE_CASE_ASSIGN: + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + break; + case ELAND: + case ELOR: + if (a->type == ELAND) { + CLabel *label; + Object *obj; + CreateTempAssignmentToZero(a, &obj); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + TransformLogicalAndLHS(a, &obj, &label); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + TransformLogicalAndRHS(a, &obj, &label); + } else if (a->type == ELOR) { + CLabel *label; + Object *obj; + CreateTempAssignmentToOne(a, &obj); + LinearizeExpr1(a->data.diadic.left, a, 0, 0); + TransformLogicalOrLHS(a, &obj, &label); + LinearizeExpr1(a->data.diadic.right, a, 0, 0); + TransformLogicalOrRHS(a, &obj, &label); + } + break; + case ECOND: { + CLabel *label1, *label2; + Object *obj; + LinearizeExpr1(a->data.cond.cond, a, 0, 0); + GenerateCondExpression(a, &label1); + LinearizeExpr1(a->data.cond.expr1, a, 0, 0); + GenerateExpr1TempAssignment(a, &obj); + GenerateGoToStmt(a, &label2); + GenerateLabel(&label1); + LinearizeExpr1(a->data.cond.expr2, a, 0, 0); + GenerateExpr2TempAssignment(a, &obj); + GenerateLabel(&label2); + if (!IS_TYPE_VOID(a->rtype)) { + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(obj); + CError_ASSERT(1596, !IS_TYPE_VOID(a->rtype)); + } else { + a->type = EINTCONST; + a->data.intval = cint64_zero; + } + break; + } + case EPRECOMP: { + Object *temp = GetTempFromtheList(a); + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(temp); + CError_ASSERT(1614, !IS_TYPE_VOID(a->rtype)); + break; + } + case ENULLCHECK: { + CLabel *label; + Object *obj; + LinearizeExpr1(a->data.nullcheck.nullcheckexpr, a, 0, 0); + GenerateNullcheckExprTempAssignment(a, &obj); + GenerateIfNotTemp(a, &obj, &label); + LinearizeExpr1(a->data.nullcheck.condexpr, a, 0, 0); + GenerateNullcheckCondExpr(a, &obj); + GenerateLabel(&label); + if (!IS_TYPE_VOID(a->rtype)) { + a->type = EINDIRECT; + a->data.monadic = create_objectrefnode(obj); + CError_ASSERT(1639, !IS_TYPE_VOID(a->rtype)); + } else { + a->type = EINTCONST; + a->data.intval = cint64_zero; + } + break; + } + case EFUNCCALL: + case EFUNCCALLP: { + SInt32 count; + SInt32 i; + ENodeList *list; + ENode **arr; + SInt16 *arr2; + + IRO_IsLeafFunction = 0; + + list = a->data.funccall.args; + count = 0; + while (list) { + list = list->next; + count++; + } + + if (count) { + arr = oalloc(sizeof(ENode *) * count); + list = a->data.funccall.args; + count = 0; + while (list) { + arr[count] = list->node; + list = list->next; + count++; + } + + arr2 = oalloc(sizeof(SInt16) * count); + for (i = 0; i < count; i++) + arr2[i] = count - i - 1; + + for (i = 0; i < count; i++) + LinearizeExpr1(arr[arr2[i]], a, 0, 0); + } + + LinearizeExpr1(a->data.funccall.funcref, a, 0, 0); + break; + } + + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case ESETCONST: + case EVECTOR128CONST: + break; + + default: + CError_FATAL(1723); + } +} + +static IROLinear *LinearizeExpr(ENode *enode) { + IROLinear *linear = NULL; + + switch (enode->type) { + ENODE_CASE_MONADIC: + linear = IRO_NewLinear(IROLinearOp1Arg); + linear->u.monadic = LinearizeExpr(enode->data.monadic); + linear->nodetype = enode->type; + linear->rtype = enode->rtype; + linear->nodeflags = enode->flags; + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.monadic, 1); + if (linear->nodetype == EINDIRECT) { + MarkSubs1(linear->u.monadic); + linear->u.monadic->flags |= IROLF_Immind | IROLF_Ind; + if (IS_LINEAR_DIADIC(linear->u.monadic, EADD)) + MarkSubscript(linear->u.monadic); + } + break; + ENODE_CASE_DIADIC_1: + case ECOMMA: + case EPMODULO: + case EROTL: + case EROTR: + case EBTST: + linear = IRO_NewLinear(IROLinearOp2Arg); + linear->nodeflags = enode->flags; + if (!ENODE_IS(enode, ECOMMA) && enode->data.diadic.right->cost >= enode->data.diadic.left->cost) { + linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); + linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); + linear->flags |= IROLF_8000; + } else { + linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); + linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); + } + linear->nodetype = enode->type; + linear->rtype = enode->rtype; + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); + break; + ENODE_CASE_ASSIGN: + linear = IRO_NewLinear(IROLinearOp2Arg); + linear->nodeflags = enode->flags; + linear->u.diadic.right = LinearizeExpr(enode->data.diadic.right); + linear->u.diadic.left = LinearizeExpr(enode->data.diadic.left); + linear->flags |= IROLF_8000; + linear->nodetype = enode->type; + linear->rtype = enode->rtype; + MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); + break; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EVECTOR128CONST: + linear = IRO_NewLinear(IROLinearOperand); + linear->nodeflags = enode->flags; + linear->u.node = enode; + linear->rtype = enode->rtype; + break; + case EFUNCCALL: + case EFUNCCALLP: { + SInt32 count; + SInt32 i; + ENodeList *list; + ENode **arr; + SInt16 *arr2; + + linear = IRO_NewLinear(IROLinearFunccall); + linear->nodeflags = enode->flags; + linear->u.funccall.ispascal = enode->type == EFUNCCALLP; + + list = enode->data.funccall.args; + count = 0; + while (list) { + list = list->next; + count++; + } + + arr = NULL; + if (count) { + arr = oalloc(sizeof(ENode *) * count); + list = enode->data.funccall.args; + count = 0; + while (list) { + arr[count] = list->node; + list = list->next; + count++; + } + + arr2 = oalloc(sizeof(SInt16) * count); + for (i = 0; i < count; i++) + arr2[i] = count - i - 1; + + for (i = 0; i < count; i++) { + arr[arr2[i]] = (ENode *) LinearizeExpr(arr[arr2[i]]); + MarkArgs((IROLinear *) arr[arr2[i]]); + } + } + + linear->u.funccall.argCount = count; + linear->u.funccall.args = (IROLinear **) arr; + linear->u.funccall.linear8 = LinearizeExpr(enode->data.funccall.funcref); + linear->u.funccall.functype = enode->data.funccall.functype; + linear->rtype = enode->rtype; + break; + } + default: + CError_FATAL(1943); + } + + if (linear) + LinkLinear(linear); + return linear; +} + +void IRO_PreLinearize(Statement *stmt) { + IRO_FirstLinear = IRO_LastLinear = NULL; + IRO_NumLinear = 0; + CurrStmt = PrevStmt = NULL; + + while (stmt) { + CurStat = stmt; + CurrStmt = stmt; + NullCheckList = NULL; + + switch (stmt->type) { + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + break; + case ST_OVF: + CError_FATAL(1989); + case ST_EXPRESSION: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_SWITCH: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_IFGOTO: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_IFNGOTO: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_RETURN: + if (stmt->expr) + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_BEGINCATCH: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_ENDCATCH: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + case ST_ENDCATCHDTOR: + LinearizeExpr1(stmt->expr, NULL, 0, 0); + break; + + case ST_EXIT: + case ST_ENTRY: + case ST_ASM: + break; + + default: + CError_FATAL(2038); + } + + PrevStmt = stmt; + stmt = stmt->next; + } + + IRO_CheckForUserBreak(); +} + +static void MarkAllSubExprs(IROLinear *linear) { + IROLinear *scan; + int i; + + for (scan = linear; scan; scan = scan->next) + scan->flags &= ~IROLF_Reffed; + + for (scan = linear; scan; scan = scan->next) + MarkSubExpr(scan); +} + +void IRO_Linearize(Statement *stmt) { + IROLinear *linear; + + IRO_FirstLinear = IRO_LastLinear = NULL; + IRO_NumLinear = 0; + + while (stmt) { + CurStat = stmt; + linear = NULL; + + switch (stmt->type) { + case ST_NOP: + linear = IRO_NewLinear(IROLinearNop); + break; + case ST_LABEL: + linear = IRO_NewLinear(IROLinearLabel); + linear->u.label.label = stmt->label; + linear->flags |= IROLF_1; + break; + case ST_GOTO: + linear = IRO_NewLinear(IROLinearGoto); + linear->u.label.label = stmt->label; + break; + case ST_EXPRESSION: + LinearizeExpr(stmt->expr); + break; + case ST_SWITCH: + linear = IRO_NewLinear(IROLinearSwitch); + linear->u.swtch.x4 = LinearizeExpr(stmt->expr); + linear->u.swtch.info = (SwitchInfo *) stmt->label; + break; + case ST_IFGOTO: + linear = IRO_NewLinear(IROLinearIf); + linear->u.label.x4 = LinearizeExpr(stmt->expr); + linear->u.label.label = stmt->label; + break; + case ST_IFNGOTO: + linear = IRO_NewLinear(IROLinearIfNot); + linear->u.label.x4 = LinearizeExpr(stmt->expr); + linear->u.label.label = stmt->label; + break; + case ST_RETURN: + IRO_FunctionHasReturn = 1; + linear = IRO_NewLinear(IROLinearReturn); + if (stmt->expr) + linear->u.monadic = LinearizeExpr(stmt->expr); + else + linear->u.monadic = NULL; + break; + case ST_OVF: + CError_FATAL(2143); + break; + case ST_EXIT: + linear = IRO_NewLinear(IROLinearExit); + linear->u.label.label = stmt->label; + break; + case ST_ENTRY: + linear = IRO_NewLinear(IROLinearEntry); + linear->u.label.label = stmt->label; + linear->flags |= IROLF_1; + break; + case ST_BEGINCATCH: + linear = IRO_NewLinear(IROLinearBeginCatch); + linear->u.ctch.linear = LinearizeExpr(stmt->expr); + linear->u.ctch.x4 = 0; + linear->u.ctch.x8 = 0; + break; + case ST_ENDCATCH: + linear = IRO_NewLinear(IROLinearEndCatch); + linear->u.monadic = LinearizeExpr(stmt->expr); + break; + case ST_ENDCATCHDTOR: + linear = IRO_NewLinear(IROLinearEndCatchDtor); + linear->u.monadic = LinearizeExpr(stmt->expr); + break; + case ST_ASM: + linear = IRO_NewLinear(IROLinearAsm); + linear->u.asm_stmt = stmt; + if (copts.optimizewithasm) { + IAEffects effects; + CodeGen_GetAsmEffects(stmt, &effects); + if (effects.x0 || effects.x3) + DisableDueToAsm = 1; + } else { + DisableDueToAsm = 1; + } + break; + default: + CError_FATAL(2194); + } + + if (linear) + LinkLinear(linear); + stmt = stmt->next; + } + + linear = IRO_NewLinear(IROLinearEnd); + linear->flags |= IROLF_1; + LinkLinear(linear); + + MarkAllSubExprs(IRO_FirstLinear); + IRO_CheckForUserBreak(); +} + +static Statement *NewStatement(IROLinear *linear, StatementType sttype) { + Statement *stmt = lalloc(sizeof(Statement)); + memset(stmt, 0, sizeof(Statement)); + stmt->type = sttype; + stmt->value = 1; + if (linear->stmt) { + stmt->dobjstack = linear->stmt->dobjstack; + stmt->sourceoffset = linear->stmt->sourceoffset; + stmt->sourcefilepath = linear->stmt->sourcefilepath; + stmt->value = linear->stmt->value; + stmt->flags = linear->stmt->flags; + } else { + stmt->sourceoffset = -1; + stmt->sourcefilepath = NULL; + } + return stmt; +} + +ENode *IRO_NewENode(ENodeType nodetype) { + ENode *enode = lalloc(sizeof(ENode)); + memset(enode, 0, sizeof(ENode)); + enode->type = nodetype; + return enode; +} + +static ENode *BuildExpr(IROLinear *linear) { + ENode *enode; + + switch (linear->type) { + case IROLinearOperand: + enode = IRO_NewENode(linear->u.node->type); + enode->flags = linear->nodeflags; + *enode = *linear->u.node; + break; + case IROLinearOp1Arg: + enode = IRO_NewENode(linear->nodetype); + enode->flags = linear->nodeflags; + enode->data.monadic = BuildExpr(linear->u.monadic); + enode->rtype = linear->rtype; + enode->cost = enode->data.monadic->cost; + if (!enode->cost) + enode->cost = 1; + break; + case IROLinearOp2Arg: + enode = IRO_NewENode(linear->nodetype); + enode->flags = linear->nodeflags; + enode->data.diadic.left = BuildExpr(linear->u.diadic.left); + enode->data.diadic.right = BuildExpr(linear->u.diadic.right); + + enode->cost = enode->data.diadic.left->cost; + if (enode->data.diadic.right->cost > enode->cost) + enode->cost = enode->data.diadic.right->cost; + else if (enode->data.diadic.right->cost == enode->cost) + enode->cost += 1; + + if (ENODE_IS4(enode, ESHL, ESHR, EDIV, EMODULO)) + enode->cost += 2; + if (enode->cost > 200) + enode->cost = 200; + + enode->rtype = linear->rtype; + break; + case IROLinearOp3Arg: + enode = IRO_NewENode(linear->nodetype); + enode->flags = linear->nodeflags; + enode->data.cond.cond = BuildExpr(linear->u.args3.a); + enode->data.cond.expr1 = BuildExpr(linear->u.args3.b); + enode->data.cond.expr2 = BuildExpr(linear->u.args3.c); + enode->rtype = linear->rtype; + + enode->cost = enode->data.cond.cond->cost; + if (enode->data.cond.expr1->cost > enode->cost) + enode->cost = enode->data.cond.expr1->cost; + if (enode->data.cond.expr2->cost > enode->cost) + enode->cost = enode->data.cond.expr2->cost; + enode->cost += 1; + + if (enode->cost > 200) + enode->cost = 200; + + break; + + case IROLinearFunccall: { + int i; + enode = IRO_NewENode(linear->u.funccall.ispascal ? EFUNCCALLP : EFUNCCALL); + enode->flags = linear->nodeflags; + enode->data.funccall.funcref = BuildExpr(linear->u.funccall.linear8); + enode->data.funccall.functype = linear->u.funccall.functype; + enode->data.funccall.args = NULL; + enode->cost = 200; + for (i = linear->u.funccall.argCount - 1; i >= 0; i--) { + ENodeList *list = lalloc(sizeof(ENodeList)); + list->node = BuildExpr(linear->u.funccall.args[i]); + list->next = enode->data.funccall.args; + enode->data.funccall.args = list; + } + enode->rtype = linear->rtype; + break; + } + + default: + IRO_Dump("Oh, oh, bad expression type in BuildExpr at: %d\n", linear->index); + CError_FATAL(2390); + } + + enode->pointsTo = linear->pointsToFunction; + return enode; +} + +Statement *IRO_Delinearize(IRONode *node, IROLinear *linear) { + IROLinear *scanlin; + Statement *firstStmt; + Statement *lastStmt; + IRONode *scan; + Statement *stmt; + IRONode mynode; + + firstStmt = lastStmt = NULL; + + if (node) { + scan = node; + MarkAllSubExprs(IRO_FirstLinear); + } else { + memset(&mynode, 0, sizeof(IRONode)); + mynode.first = linear; + scan = &mynode; + MarkAllSubExprs(linear); + } + + while (scan) { + for (scanlin = scan->first; scanlin; scanlin = scanlin->next) { + stmt = NULL; + if (!(scanlin->flags & IROLF_Reffed)) { + switch (scanlin->type) { + case IROLinearNop: + if (scan == node) + stmt = NewStatement(scanlin, ST_NOP); + else + stmt = NULL; + break; + case IROLinearOperand: + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + stmt = NewStatement(scanlin, ST_EXPRESSION); + stmt->expr = BuildExpr(scanlin); + break; + case IROLinearGoto: + stmt = NewStatement(scanlin, ST_GOTO); + stmt->label = scanlin->u.label.label; + break; + case IROLinearExit: + stmt = NewStatement(scanlin, ST_EXIT); + stmt->label = scanlin->u.label.label; + break; + case IROLinearIf: + case IROLinearIfNot: + stmt = NewStatement(scanlin, (scanlin->type == IROLinearIf) ? ST_IFGOTO : ST_IFNGOTO); + stmt->label = scanlin->u.label.label; + stmt->expr = BuildExpr(scanlin->u.label.x4); + break; + case IROLinearReturn: + stmt = NewStatement(scanlin, ST_RETURN); + if (scanlin->u.monadic) + stmt->expr = BuildExpr(scanlin->u.monadic); + break; + case IROLinearLabel: + stmt = NewStatement(scanlin, ST_LABEL); + stmt->label = scanlin->u.label.label; + stmt->label->stmt = stmt; + break; + case IROLinearEntry: + stmt = NewStatement(scanlin, ST_ENTRY); + stmt->label = scanlin->u.label.label; + stmt->label->stmt = stmt; + break; + case IROLinearSwitch: + stmt = NewStatement(scanlin, ST_SWITCH); + stmt->expr = BuildExpr(scanlin->u.swtch.x4); + stmt->label = (CLabel *) scanlin->u.swtch.info; + break; + case IROLinearBeginCatch: + stmt = NewStatement(scanlin, ST_BEGINCATCH); + stmt->expr = BuildExpr(scanlin->u.ctch.linear); + break; + case IROLinearEndCatch: + stmt = NewStatement(scanlin, ST_ENDCATCH); + stmt->expr = BuildExpr(scanlin->u.monadic); + break; + case IROLinearEndCatchDtor: + stmt = NewStatement(scanlin, ST_ENDCATCHDTOR); + stmt->expr = BuildExpr(scanlin->u.monadic); + break; + case IROLinearAsm: + stmt = scanlin->u.asm_stmt; + break; + case IROLinearEnd: + stmt = NULL; + break; + default: + CError_FATAL(2685); + } + + if (stmt) { + if (LoopOptimizerRun) { + SInt32 i; + SInt32 value = 1; + for (i = 0; i < scan->loopdepth; i++) { + value = (value < 4096) ? (value * 8) : (value + 1); + } + stmt->value = value; + } + if (firstStmt) + lastStmt->next = stmt; + else + firstStmt = stmt; + lastStmt = stmt; + } + } + if (scanlin == scan->last) + break; + } + scan = scan->nextnode; + } + + return firstStmt; +} + +void IRO_RenumberInts(void) { + IROLinear *linear = IRO_FirstLinear; + IRO_NumLinear = 0; + while (linear) { + linear->index = IRO_NumLinear++; + linear = linear->next; + } +} + +static void TravExprToUpdateFlags(IROLinear *linear) { + int i; + + linear->flags &= ~(IROLF_Assigned | IROLF_8 | IROLF_Used | IROLF_Ind | IROLF_Subs | IROLF_LoopInvariant | IROLF_Ris | IROLF_Immind | IROLF_CouldError); + switch (linear->type) { + case IROLinearNop: + case IROLinearOperand: + break; + case IROLinearOp1Arg: + TravExprToUpdateFlags(linear->u.monadic); + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.monadic, 1); + if (linear->nodetype == EINDIRECT) { + MarkSubs1(linear->u.monadic); + linear->u.monadic->flags |= IROLF_Immind | IROLF_Ind; + if (IS_LINEAR_DIADIC(linear->u.monadic, EADD)) + MarkSubscript(linear->u.monadic); + } + break; + case IROLinearOp2Arg: + TravExprToUpdateFlags(linear->u.diadic.left); + TravExprToUpdateFlags(linear->u.diadic.right); + if (IRO_IsAssignOp[linear->nodetype]) + MarkAssigned(linear->u.diadic.left, IRO_IsModifyOp[linear->nodetype]); + break; + case IROLinearOp3Arg: + TravExprToUpdateFlags(linear->u.args3.a); + TravExprToUpdateFlags(linear->u.args3.b); + TravExprToUpdateFlags(linear->u.args3.c); + break; + case IROLinearFunccall: + TravExprToUpdateFlags(linear->u.funccall.linear8); + for (i = linear->u.funccall.argCount - 1; i >= 0; i--) + TravExprToUpdateFlags(linear->u.funccall.args[i]); + break; + default: + IRO_Dump("Oh, oh, bad expression type in TravExprToUpdateFlags at: %d\n", linear->index); + CError_FATAL(2853); + } +} + +void IRO_UpdateFlagsOnInts(void) { + IROLinear *linear; + IRONode *node; + + MarkAllSubExprs(IRO_FirstLinear); + + for (node = IRO_FirstNode; node; node = node->nextnode) { + for (linear = node->first; linear; linear = linear->next) { + if (!(linear->flags & IROLF_Reffed)) { + switch (linear->type) { + case IROLinearOperand: + case IROLinearOp1Arg: + case IROLinearOp2Arg: + case IROLinearOp3Arg: + case IROLinearFunccall: + TravExprToUpdateFlags(linear); + break; + case IROLinearIf: + case IROLinearIfNot: + TravExprToUpdateFlags(linear->u.label.x4); + break; + case IROLinearReturn: + if (linear->u.monadic) + TravExprToUpdateFlags(linear->u.monadic); + break; + case IROLinearSwitch: + TravExprToUpdateFlags(linear->u.swtch.x4); + break; + case IROLinearBeginCatch: + TravExprToUpdateFlags(linear->u.ctch.linear); + break; + case IROLinearEndCatch: + TravExprToUpdateFlags(linear->u.monadic); + break; + case IROLinearEndCatchDtor: + TravExprToUpdateFlags(linear->u.monadic); + break; + case IROLinearNop: + case IROLinearGoto: + case IROLinearLabel: + case IROLinearEntry: + case IROLinearExit: + case IROLinearAsm: + case IROLinearEnd: + break; + default: + CError_FATAL(2931); + } + } + if (linear == node->last) + break; + } + } +} + +void IRO_SaveLinearIR(IROLinearIRSave *save) { + save->firstLinear = IRO_FirstLinear; + save->lastLinear = IRO_LastLinear; + save->numLinear = IRO_NumLinear; + save->curStat = CurStat; + save->disableDueToAsm = DisableDueToAsm; + save->isLeafFunction = IRO_IsLeafFunction; + save->functionHasReturn = IRO_FunctionHasReturn; + save->nullCheckList = NullCheckList; + save->currStmt = CurrStmt; + save->prevStmt = PrevStmt; +} + +void IRO_RestoreLinearIR(IROLinearIRSave *save) { + IRO_FirstLinear = save->firstLinear; + IRO_LastLinear = save->lastLinear; + IRO_NumLinear = save->numLinear; + CurStat = save->curStat; + DisableDueToAsm = save->disableDueToAsm; + IRO_IsLeafFunction = save->isLeafFunction; + IRO_FunctionHasReturn = save->functionHasReturn; + NullCheckList = save->nullCheckList; + CurrStmt = save->currStmt; + PrevStmt = save->prevStmt; +} + |