📄 iexpr.c
字号:
//-------------------------------------------------------------------------
IMODE *gen_asunary( ENODE *node, int flags, int size, int op)
{
IMODE *ap;
int nsize = natural_size(node->v.p[0]);
ap = gen_expr( node->v.p[0], 0, nsize);
gen_icode(op, ap, ap, 0);
return ap;
}
//-------------------------------------------------------------------------
IMODE *gen_asbin( ENODE *node, int flags, int size, int op)
/*
* generate a plus equal or a minus equal node.
*/
{
IMODE *ap, *ap1, *ap2;
int ssize, rsize;
ssize = natural_size(node->v.p[0]);
rsize = natural_size(node->v.p[1]);
ap1 = gen_expr( node->v.p[0], 0, ssize);
ap2 = gen_expr( node->v.p[1], 0, rsize);
#ifdef XXXXX
if ((ap1->mode != i_direct || ap1->offset->nodetype != en_tempref) && (ap2->mode != i_direct || ap2->offset->nodetype != en_tempref)) {
IMODE *ap3 ;
gen_icode(op,ap3 = genasn(0,ssize), ap1, ap2);
gen_icode(i_assn,ap1,ap3,0);
if (ap1->size == ap3->size && !ap1->bits)
return ap3;
} else
#endif
gen_icode(op, ap1, ap2, 0);
return ap1 ;
#ifdef XXXXX
ap = xalloc(sizeof(IMODE));
ap->bits = ap1->bits;
ap->startbit = ap1->startbit;
ap->offset = ap1->offset;
ap->mode = ap1->mode;
ap->size = ap1->size;
return (ap);
#endif
}
//-------------------------------------------------------------------------
IMODE *gen_moveblock(ENODE *node, int flags, int size)
/*
* Generate code to copy one structure to another
*/
{
IMODE *ap1, *ap2;
if (!node->size)
return (0);
ap1 = gen_expr( node->v.p[0], F_VOL, ISZ_UINT);
ap2 = gen_expr( node->v.p[1], F_VOL, ISZ_UINT);
gen_icode(i_assnblock, ap1, ap2, make_immed(node->size));
return (ap1);
}
IMODE *gen_clearblock(ENODE *node, int flags, int size)
/*
* Generate code to copy one structure to another
*/
{
IMODE *ap1, *ap2;
if (!node->size)
return (0);
ap1 = gen_expr( node->v.p[0], F_VOL, ISZ_UINT);
gen_icode(i_clrblock, 0, ap1, make_immed(node->size));
return (ap1);
}
//-------------------------------------------------------------------------
IMODE *gen_assign( ENODE *node, int flags, int size, int ref)
/*
* generate code for an assignment node. if the size of the
* assignment destination is larger than the size passed then
* everything below this node will be evaluated with the
* assignment size.
*/
{
IMODE *ap1, *ap2;
ENODE *enode;
if (ref)
{
enode = makenode(node->v.p[0]->nodetype, makenode(en_cp, node->v.p[0]
->v.p[0], 0), 0);
}
else
enode = node->v.p[0];
ap1 = gen_expr(enode, 0, natural_size(node->v.p[0]));
ap2 = gen_expr(node->v.p[1], 0, natural_size(node->v.p[1]));
#ifdef XXXXX
if ((ap1->mode != i_direct || ap1->offset->nodetype != en_tempref) && (ap2->mode != i_direct || ap2->offset->nodetype != en_tempref)) {
IMODE *ap3 = ap2;
gen_icode(i_assn,ap2 = genasn(0,ap2->size), ap2, 0);
}
#endif
gen_icode(i_assn, ap1, ap2, 0);
if (ap1->size == ap2->size && !ap1->bits)
return ap2;
return ap1;
}
//-------------------------------------------------------------------------
IMODE *gen_aincdec( ENODE *node, int flags, int size, int op)
/*
* generate an auto increment or decrement node. op should be
* either op_add (for increment) or op_sub (for decrement).
*/
{
IMODE *ap1, *ap2,*ap3;
int siz1;
siz1 = natural_size(node->v.p[0]);
ap2 = gen_expr(node->v.p[1], 0, siz1);
if (flags &F_NOVALUE)
/* dont need result */
{
ap1 = gen_expr( node->v.p[0], F_ADDR, siz1);
gen_icode(op, ap1, ap1, ap2);
return ap1;
}
ap1 = gen_expr( node->v.p[0], F_ADDR, siz1);
ap3 = tempreg(siz1,0);
gen_icode(i_assn, ap3, ap1, 0);
gen_icode(op, ap1, ap1, ap2);
return ap3;
}
//-------------------------------------------------------------------------
int push_param(ENODE *ep, int size)
/*
* push the operand expression onto the stack.
*/
{
IMODE *ap;
int rv;
switch (ep->nodetype)
{
case en_imode:
ap = ep->v.p[0];
gen_nodag(i_parm, 0, ap, 0);
rv = ap->size;
break;
default:
rv = natural_size(ep);
ap = gen_expr( ep, F_ADDR, rv);
gen_nodag(i_parm, 0, ap, 0);
rv = ap->size;
break;
}
return (rv < 0 ? - rv: rv);
}
//-------------------------------------------------------------------------
int push_stackblock(ENODE *ep)
/*
* Push a structure on the stack
*/
{
IMODE *ap;
int sz = ep->size;
if (!sz)
return (0);
switch (ep->nodetype)
{
case en_imode:
ap = ep->v.p[0];
break;
default:
ap = gen_expr( ep, F_ADDR, sz);
break;
}
gen_icode(i_parmblock, 0, ap, (IMODE*)sz);
sz = sz < 0 ? - sz: sz;
sz += ISZ_UINT - ISZ_UCHAR;
sz /= ISZ_UINT;
sz *= ISZ_UINT;
return sz;
}
//-------------------------------------------------------------------------
int gen_parms(ENODE *plist, int size)
/*
* push a list of parameters onto the stack and return the
* size of parameters pushed.
*/
{
int i;
i = 0;
while (plist != 0)
{
if (plist->nodetype == en_stackblock)
i += push_stackblock(plist->v.p[0]);
else
i += push_param(plist->v.p[0], size);
plist = plist->v.p[1];
}
return i;
}
//-------------------------------------------------------------------------
IMODE *gen_tcall(ENODE *node, int flags)
/*
* generate a trap call node and return the address mode
* of the result.
*/
{
IMODE *ap, *result;
int i, siz1 = ISZ_UINT;
ap = make_offset(node->v.p[0]->v.p[0]);
ap->mode = i_immed;
gen_igosub(i_int, ap);
if (!(flags &F_NOVALUE)) {
ap = xalloc(sizeof(IMODE));
*ap = rret;
ap->size = siz1;
}
return ap;
}
//-------------------------------------------------------------------------
IMODE *inlinecall(ENODE *node, int flags)
{
ENODE *nameref = node, *thisn = 0;
SYM *sp;
IMODE *ap = 0;
int size;
if (nameref->nodetype == en_thiscall)
{
thisn = nameref->v.p[0];
nameref = nameref->v.p[1];
}
if (nameref->nodetype == en_callblock || nameref->nodetype == en_scallblock)
{
size = ISZ_UINT;
nameref = nameref->v.p[1];
}
else
size = nameref->v.p[0]->v.i;
nameref = nameref->v.p[1]->v.p[0]->v.p[0];
if (nameref->nodetype == en_nacon || nameref->nodetype == en_napccon)
{
sp = nameref->v.sp;
if (sp && (sp->value.classdata.cppflags &PF_INLINE))
{
int oldretlab = retlab;
IMODE *ap;
SYM *oldcurfunc = currentfunc;
currentfunc = sp;
retlab = nextlabel++;
#ifdef XXXXX
if (sp->value.classdata.cppflags &PF_CONSTRUCTOR)
{
SYM *psp = sp->parentclass;
if (psp && psp->value.classdata.baseclass->vtabsp)
{
ENODE *ts = makenode(en_nacon, psp
->value.classdata.baseclass->vtabsp, 0);
thisn = makenode(en_a_ref, thisn, 0);
ts = makenode(en_assign, thisn, ts);
gen_expr(ts, FALSE, TRUE, ISZ_UINT);
}
}
#endif
genstmt(sp->value.classdata.inlinefunc->stmt);
if (!(flags &F_NOVALUE)) {
ap = xalloc(sizeof(IMODE));
*ap = rret;
ap->size = size;
}
}
}
return ap;
}
//-------------------------------------------------------------------------
IMODE *gen_fcall( ENODE *node, int flags, int size)
/*
* generate a function call node and return the address mode
* of the result.
*/
{
IMODE *ap;
int i, siz1;
ENODE *pushthis = 0;
/* if it returns a structure */
if (ap = inlinecall(node, flags))
return ap;
if (node->nodetype != en_callblock && node->nodetype != en_scallblock)
if (ap = HandleIntrins(node, flags &F_NOVALUE))
return ap;
if (node->nodetype == en_thiscall)
{
pushthis = node->v.p[0];
node = node->v.p[1];
i = ISZ_UINT;
}
if (node->nodetype == en_callblock || node->nodetype == en_scallblock)
{
siz1 = ISZ_ADDR;
}
else
{
siz1 = node->v.p[0]->v.i;
}
if (node->nodetype == en_callblock)
{
i += gen_parms(node->v.p[1]->v.p[1]->v.p[1]->v.p[0], size);
ap = gen_expr( node->v.p[0], F_ADDR, ISZ_ADDR);
gen_icode(i_parm, 0, ap, 0);
i += ISZ_ADDR;
node = node->v.p[1];
siz1 = ISZ_UINT;
}
else
{
i += gen_parms(node->v.p[1]->v.p[1]->v.p[0], size); /* generate
parameters */
}
if (node->nodetype == en_trapcall)
{
/* trap call */
gen_igosub(i_trap, make_immed(node->v.p[1]->v.p[0]->v.i));
}
else if (node->nodetype == en_intcall)
{
/* int call */
ap = make_offset(node->v.p[0]);
ap->mode = i_immed;
gen_igosub(i_int, ap);
}
else if (pushthis)
{
// IMODE *ap2 = gen_expr(pushthis, FALSE, TRUE, ISZ_UINT);
// gen_icode(i_parm, 0, ap2, 0);
}
/* named function */
if (node->v.p[1]->v.p[0]->nodetype == en_imode)
{
ap = node->v.p[1]->v.p[0]->v.p[0]->v.p[0]->v.sp;
gen_igosub(i_gosub, ap);
}
else
/* pointer to function */
{
ap = gen_expr( node->v.p[1]->v.p[0]->v.p[0], 0, ISZ_UINT);
gen_igosub(i_gosub, ap);
}
/* undo pars and make a temp for the result */
if (node->nodetype != en_fcallb && node->nodetype != en_fcall && node
->nodetype != en_callblock)
if (i != 0)
{
// gen_nodag(i_parmadj, 0, make_parmadj(i), 0);
}
if (!(flags &F_NOVALUE)) {
ap = xalloc(sizeof(IMODE));
*ap = rret;
ap->size = siz1;
}
return ap;
}
//-------------------------------------------------------------------------
IMODE *gen_repcons(ENODE *node)
/*
* generate a function call node and return the address mode
* of the result.
*/
{
IMODE *ax, *cx, *ap, *ap1, *ap2, *ap3, *ap4;
ENODE *pushthis = 0, *onode = node;
int i = 0, siz1;
int lab;
int regax, regdx, regcx;
node = node->v.p[1];
if (node->nodetype == en_thiscall)
{
pushthis = node->v.p[0];
node = node->v.p[1];
i = ISZ_UINT;
}
ap1 = gen_expr( onode->v.p[0]->v.p[0], 0, ISZ_UINT);
ap3 = genasn(onode->v.p[0]->v.p[0], ISZ_UINT);
if (pushthis)
{
ap2 = genasn(pushthis, ISZ_UINT);
}
gen_label(lab = nextlabel++);
/* named function */
if (node->v.p[1]->v.p[0]->nodetype == en_imode)
{
ap = node->v.p[1]->v.p[0]->v.p[0]->v.p[0]->v.sp;
gen_igosub(i_gosub, ap);
}
else
/* pointer to function */
{
ap = gen_expr( node->v.p[1]->v.p[0]->v.p[0], 0, ISZ_UINT);
gen_igosub(i_gosub, ap);
}
gen_icode(i_add, ap3, ap3, make_immed((int)node->v.p[0]->v.p[1]->v.p[0]));
gen_icode(i_sub, ap1, ap1, make_immed(1));
gen_icgoto(i_jg, lab, ap1, make_immed(0));
}
//-------------------------------------------------------------------------
IMODE *gen_pfcall( ENODE *node, int flags, int size)
/*
* generate a function call node and return the address mode
* of the result.
*/
{
IMODE *ap;
ENODE *pushthis = 0;
int i, siz1;
ENODE *invnode = 0, *anode, *node2;
if (ap = inlinecall(node, flags))
return ap;
/* invert the parameter list */
if (node->nodetype == en_pcallblock || node->nodetype == en_scallblock)
anode = node->v.p[1]->v.p[1]->v.p[1]->v.p[0];
else
anode = node->v.p[1]->v.p[1]->v.p[0];
while (anode)
{
invnode = makenode(anode->nodetype, anode->v.p[0], invnode);
anode = anode->v.p[1];
}
/* if it returns a structure */
if (node->nodetype == en_thiscall)
{
pushthis = node->v.p[0];
node = node->v.p[1];
i = ISZ_UINT;
}
if (node->nodetype == en_pcallblock || node->nodetype == en_scallblock)
{
siz1 = ISZ_UINT;
}
else
{
siz1 = node->v.p[0]->v.i;
}
if (pushthis)
{
// IMODE *ap2 = gen_expr(pushthis, FALSE, TRUE, ISZ_UINT);
// gen_icode(i_parm, 0, ap2, 0);
}
if (node->nodetype == en_callblock || node->nodetype == en_scallblock)
{
i = gen_parms(invnode, size);
ap = gen_expr( node->v.p[0], F_ADDR, ISZ_ADDR);
gen_icode(i_parm, 0, ap, 0);
i += ISZ_ADDR;
node = node->v.p[1];
siz1 = ISZ_UINT;
}
else
{
i = gen_parms(invnode, size); /* generate parameters */
siz1 = natural_size(node->v.p[1]);
}
if (node->nodetype == en_trapcall)
{
/* trap call */
gen_igosub(i_trap, make_immed(node->v.p[1]->v.p[0]->v.i));
}
else if (node->nodetype == en_intcall)
{
/* int call */
ap = make_offset(node->v.p[0]);
ap->mode = i_immed;
gen_igosub(i_int, ap);
}
else if (pushthis)
{
IMODE *ap2 = gen_expr( pushthis, 0, ISZ_UINT);
gen_icode(i_parm, 0, ap2, 0);
}
/* named function */
if (node->v.p[1]->v.p[0]->nodetype == en_imode)
{
ap = node->v.p[1]->v.p[0]->v.p[0]->v.p[0];
gen_igosub(i_gosub, ap);
}
else
/* pointer to function */
{
ap = gen_expr( node->v.p[1]->v.p[0]->v.p[0], 0, ISZ_UINT);
gen_igosub(i_gosub, ap);
}
if (!(flags &F_NOVALUE)) {
ap = xalloc(sizeof(IMODE));
*ap = rret;
ap->size = size;
}
return ap;
}
//-------------------------------------------------------------------------
IMODE *gen_expr( ENODE *node, int flags, int size)
/*
* general expression evaluation. returns the addressing mode
* of the result.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -