summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
committerAsh Wolf <ninji@wuffs.org>2023-01-26 11:30:47 +0000
commit094b96ca1df4a035b5f93c351f773306c0241f3f (patch)
tree95ce05e3ebe816c7ee7996206bb37ea17d8ca33c /compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c
parentfc0c4c0df7b583b55a08317cf1ef6a71d27c0440 (diff)
downloadMWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.tar.gz
MWCC-094b96ca1df4a035b5f93c351f773306c0241f3f.zip
move lots of source files around to match their actual placement in the original treemain
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c')
-rw-r--r--compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c1797
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;
+}
+