2022-12-14 00:16:59 +00:00
|
|
|
#include "compiler/IroLinearForm.h"
|
|
|
|
#include "compiler/IroDump.h"
|
|
|
|
#include "compiler/IroFlowgraph.h"
|
|
|
|
#include "compiler/IroUtil.h"
|
|
|
|
#include "compiler/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)) {
|
2023-01-11 22:29:53 +00:00
|
|
|
((IROLinear *) rec->objRefs->element)->flags |= IROLF_Assigned;
|
2022-12-14 00:16:59 +00:00
|
|
|
if (flag) {
|
|
|
|
linear->flags |= IROLF_Used;
|
2023-01-11 22:29:53 +00:00
|
|
|
((IROLinear *) rec->objRefs->element)->flags |= IROLF_Used;
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)) {
|
2023-01-11 22:29:53 +00:00
|
|
|
((IROLinear *) rec->objRefs->element)->flags |= IROLF_Assigned;
|
2022-12-14 00:16:59 +00:00
|
|
|
if (flag) {
|
|
|
|
linear->flags |= IROLF_Used;
|
2023-01-11 22:29:53 +00:00
|
|
|
((IROLinear *) rec->objRefs->element)->flags |= IROLF_Used;
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
static 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:
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(368);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
2023-01-11 22:29:53 +00:00
|
|
|
((IROLinear *) rec->objRefs->element)->flags |= IROLF_Ind;
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2022-12-29 12:32:55 +00:00
|
|
|
if (!IS_TYPE_VOID(enode->rtype))
|
2022-12-14 00:16:59 +00:00
|
|
|
indnode->rtype = enode->rtype;
|
2022-12-29 12:32:55 +00:00
|
|
|
else
|
|
|
|
CError_FATAL(548);
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(580, !IS_TYPE_VOID(enode->rtype));
|
2022-12-14 00:16:59 +00:00
|
|
|
} 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);
|
|
|
|
|
2022-12-29 12:32:55 +00:00
|
|
|
if (!IS_TYPE_VOID(enode->rtype))
|
2022-12-14 00:16:59 +00:00
|
|
|
indnode->rtype = enode->rtype;
|
2022-12-29 12:32:55 +00:00
|
|
|
else
|
|
|
|
CError_FATAL(627);
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
if (!IS_TYPE_VOID(enode->rtype))
|
2022-12-14 00:16:59 +00:00
|
|
|
indnode->rtype = enode->rtype;
|
2022-12-29 12:32:55 +00:00
|
|
|
else
|
|
|
|
CError_FATAL(678);
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
if (!IS_TYPE_VOID(enode->rtype))
|
2022-12-14 00:16:59 +00:00
|
|
|
indnode->rtype = enode->rtype;
|
2022-12-29 12:32:55 +00:00
|
|
|
else
|
|
|
|
CError_FATAL(720);
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(839, n);
|
2022-12-14 00:16:59 +00:00
|
|
|
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;
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(905, !IS_TYPE_VOID(enode->rtype));
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(953, !IS_TYPE_VOID(enode->rtype));
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1003, !IS_TYPE_VOID(enode->rtype));
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
if (!IS_TYPE_VOID(enode->rtype))
|
2022-12-14 00:16:59 +00:00
|
|
|
indnode->rtype = enode->rtype;
|
2022-12-29 12:32:55 +00:00
|
|
|
else
|
|
|
|
CError_FATAL(1225);
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1276, !IS_TYPE_VOID(enode->rtype));
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
if (!IS_TYPE_VOID(enode->rtype))
|
2022-12-14 00:16:59 +00:00
|
|
|
indnode->rtype = enode->rtype;
|
2022-12-29 12:32:55 +00:00
|
|
|
else
|
|
|
|
CError_FATAL(1354);
|
2022-12-14 00:16:59 +00:00
|
|
|
|
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1405, !IS_TYPE_VOID(enode->rtype));
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void LinearizeExpr1(ENode *a, ENode *b, Boolean flag, Boolean flag2) {
|
|
|
|
switch (a->type) {
|
2022-12-29 12:32:55 +00:00
|
|
|
ENODE_CASE_MONADIC:
|
2022-12-14 00:16:59 +00:00
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1428, !IS_TYPE_VOID(a->rtype));
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
break;
|
2022-12-29 12:32:55 +00:00
|
|
|
ENODE_CASE_DIADIC_1:
|
2022-12-14 00:16:59 +00:00
|
|
|
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;
|
2022-12-29 12:32:55 +00:00
|
|
|
ENODE_CASE_ASSIGN:
|
2022-12-14 00:16:59 +00:00
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1596, !IS_TYPE_VOID(a->rtype));
|
2022-12-14 00:16:59 +00:00
|
|
|
} 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);
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1614, !IS_TYPE_VOID(a->rtype));
|
2022-12-14 00:16:59 +00:00
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_ASSERT(1639, !IS_TYPE_VOID(a->rtype));
|
2022-12-14 00:16:59 +00:00
|
|
|
} 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:
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(1723);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static IROLinear *LinearizeExpr(ENode *enode) {
|
|
|
|
IROLinear *linear = NULL;
|
|
|
|
|
|
|
|
switch (enode->type) {
|
2022-12-29 12:32:55 +00:00
|
|
|
ENODE_CASE_MONADIC:
|
2022-12-14 00:16:59 +00:00
|
|
|
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;
|
2022-12-29 12:32:55 +00:00
|
|
|
ENODE_CASE_DIADIC_1:
|
2022-12-14 00:16:59 +00:00
|
|
|
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;
|
2022-12-29 12:32:55 +00:00
|
|
|
ENODE_CASE_ASSIGN:
|
2022-12-14 00:16:59 +00:00
|
|
|
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:
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(1943);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(1989);
|
2022-12-14 00:16:59 +00:00
|
|
|
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:
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(2038);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(2143);
|
2022-12-14 00:16:59 +00:00
|
|
|
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:
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(2194);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(2390);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(2685);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(2853);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
2022-12-29 12:32:55 +00:00
|
|
|
CError_FATAL(2931);
|
2022-12-14 00:16:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|