MWCC/compiler_and_linker/FrontEnd/Optimizer/IroLinearForm.c

1798 lines
58 KiB
C

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