📄 gstmt386.c
字号:
{
if (retlab != - 1)
gen_label(retlab);
if (flag &2)
{
return ap;
}
if (currentfunc->value.classdata.eofdest)
{
if (returndreg)
{
if (currentfunc->tp->btp->type == bt_longlong || currentfunc
->tp->btp->type == bt_unsignedlonglong)
gen_codes(op_push, BESZ_DWORD , makedreg(2), 0);
gen_codes(op_push, BESZ_DWORD , makedreg(0), 0);
}
gen_expr(currentfunc->value.classdata.eofdest, TRUE, FALSE, 0);
if (returndreg)
{
gen_codes(op_pop, BESZ_DWORD , makedreg(0), 0);
if (currentfunc->tp->btp->type == bt_longlong || currentfunc
->tp->btp->type == bt_unsignedlonglong)
gen_codes(op_pop, BESZ_DWORD , makedreg(2), 0);
}
}
if ((conscount || try_block_list || currentfunc
->value.classdata.throwlist && currentfunc
->value.classdata.throwlist->data) && prm_xcept)
call_library("__RundownExceptBlock");
if (fsave_mask != 0)
diag("Float restore in return");
if (currentfunc->loadds && !currentfunc->intflag)
gen_code(op_pop, makesegreg(DS), 0);
if (save_mask != 0)
popregs(save_mask);
if (prm_cplusplus && prm_xcept || (funcfloat || lc_maxauto ||
currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM*) -
1)
|| (currentfunc->value.classdata.cppflags &PF_MEMBER) && !
(currentfunc->value.classdata.cppflags &PF_STATIC)
|| !prm_smartframes)
{
/* LEAVE is a little faster in simple tests, but since this version
* can be paired with other instructions on later processors we
* do it this way. Also don't reload ESP if no local vars...
*/
if (funcfloat || lc_maxauto)
gen_code(op_mov, makedreg(ESP), makedreg(EBP));
else
initstack();
if (!currentfunc->intflag)
gen_code(op_pop, makedreg(EBP), 0);
}
if (currentfunc->intflag || currentfunc->faultflag)
{
gen_codes(op_popad, 0, 0, 0);
if (prm_farkeyword)
{
gen_pop(GS + 24, am_dreg, 0);
gen_pop(FS + 24, am_dreg, 0);
gen_pop(ES + 24, am_dreg, 0);
}
}
if (currentfunc->loadds && currentfunc->intflag)
gen_code(op_pop, makesegreg(DS), 0);
if (currentfunc->faultflag)
{
gen_codes(op_add, BESZ_DWORD , makedreg(ESP), make_immed(4));
gen_codes(op_iretd, 0, 0, 0);
}
if (currentfunc->intflag)
{
gen_codes(op_iretd, 0, 0, 0);
}
else
{
int retop = op_ret;
if (currentfunc->farproc)
retop = op_retf;
if (currentfunc->pascaldefn || currentfunc->isstdcall)
{
long retsize = 0;
if (currentfunc->tp->lst.head && currentfunc->tp->lst.head !=
(SYM*) - 1)
{
retsize = currentfunc->paramsize - 8;
}
if (currentfunc->tp->btp && isstructured(currentfunc->tp->btp))
retsize += 4;
if (currentfunc->farproc)
retsize -= 4;
if (retsize)
{
gen_codes(retop, 0, make_immed(retsize), 0);
return 0;
}
}
gen_codes(retop, 0, 0, 0);
}
}
else
{
gen_codes(op_jmp, 0, make_label(retlab), 0);
}
return 0;
}
//-------------------------------------------------------------------------
void gen_tryblock(void *val)
{
AMODE *ap1 = xalloc(sizeof(AMODE));
ap1->mode = am_indisp;
ap1->preg = EBP;
ap1->offset = makeintnode(en_icon, - xceptoffs + 12); // ESP
switch ((int)val)
{
case 0:
// begin try
gen_codes(op_push, BESZ_DWORD , makedreg(EBX), 0);
gen_codes(op_push, BESZ_DWORD , makedreg(ESI), 0);
gen_codes(op_push, BESZ_DWORD , makedreg(EDI), 0);
gen_codes(op_push, BESZ_DWORD , ap1, 0);
gen_codes(op_mov, BESZ_DWORD , ap1, makedreg(ESP));
break;
case 1:
// begin catch
gen_codes(op_mov, BESZ_DWORD , makedreg(ESP), ap1);
gen_codes(op_pop, BESZ_DWORD , ap1, 0);
gen_codes(op_pop, BESZ_DWORD , makedreg(EDI), 0);
gen_codes(op_pop, BESZ_DWORD , makedreg(ESI), 0);
gen_codes(op_pop, BESZ_DWORD , makedreg(EBX), 0);
break;
case 2:
// end try
gen_codes(op_mov, BESZ_DWORD , makedreg(ESP), ap1);
gen_codes(op_pop, BESZ_DWORD , ap1, 0);
gen_codes(op_add, BESZ_DWORD , makedreg(ESP), make_immed(3 *4));
break;
}
}
//-------------------------------------------------------------------------
void genstmt(SNODE *stmt)
/*
* genstmt will generate a statement and follow the next pointer
* until the block is generated.
*/
{
while (stmt != 0)
{
OCODE *result;
switch (stmt->stype)
{
case st_case:
if ((int)stmt->label >= 0)
gen_label((int)stmt->label);
break;
case st_block:
result = gen_codes(op_blockstart, 0, 0, 0);
result->blocknum = (int)stmt->label;
genstmt(stmt->exp);
result = gen_codes(op_blockend, 0, 0, 0);
result->blocknum = (int)stmt->label;
break;
case st_label:
gen_label((int)stmt->label);
break;
case st_goto:
gen_codes(op_jmp, 0, make_label((int)stmt->label), 0);
break;
case st_tryblock:
initstack(); // important!!!
gen_tryblock(stmt->label);
break;
case st_expr:
gen_void(stmt->exp);
initstack();
break;
case st_return:
genreturn(stmt, 0);
break;
case st_if:
genif(stmt);
break;
case st_while:
genwhile(stmt);
break;
case st_do:
gendo(stmt);
break;
case st_for:
gen_for(stmt);
break;
case st_continue:
gen_codes(op_jmp, 0, make_label(contlab), 0);
break;
case st_break:
gen_codes(op_jmp, 0, make_label(breaklab), 0);
break;
case st_switch:
genxswitch(stmt);
break;
case st_line:
gen_line(stmt);
break;
case st_asm:
if (stmt->exp)
add_peep(stmt->exp);
break;
case st__genword:
gen_codes(op_genword, 0, make_immed((int)stmt->exp), 0);
break;
default:
DIAG("unknown statement.");
break;
}
stmt = stmt->next;
}
}
//-------------------------------------------------------------------------
void scppinit(void)
/*
* code in MAIN to execute C++ startup routines
* it is safe to do it in MAIN since you cannot call main or take its address
*
*/
{
#ifdef OLD
if (!strcmp(currentfunc->name, "_main"))
{
AMODE *ap1, *ap2, *ap3, *ap4;
int lbl = nextlabel++;
initstack();
ap1 = makedreg(ESI);
ap4 = makedreg(EAX);
ap2 = set_symbol("cppistart", 0);
ap3 = set_symbol("cppiend", 0);
gen_code(op_push, ap1, 0);
gen_code(op_mov, ap1, ap2);
gen_label(lbl);
gen_code(op_lodsd, 0, 0);
gen_code(op_call, ap4, 0);
gen_codes(op_cmp, BESZ_DWORD , ap1, ap3);
gen_code(op_jb, make_label(lbl), 0);
gen_code(op_pop, ap1, 0);
freeop(ap1);
}
#endif
}
SYM *gen_mp_virtual_thunk(SYM *vsp)
{
LIST *v = mpthunklist;
SYM *sp;
AMODE *ap1, *ap2;
char buf[256];
while (v)
{
sp = (SYM*)v->data;
if (sp->value.i == vsp->value.classdata.vtabindex)
if (isstructured(vsp->tp->btp) == isstructured(sp->tp->btp))
return sp;
v = v->link;
}
global_flag++;
sp = makesym(sc_static);
sp->tp = vsp->tp;
sp->value.i = vsp->value.classdata.vtabindex;
sprintf(buf, "@$mpt$%d$%d", sp->value.i, isstructured(sp->tp->btp));
sp->name = litlate(buf);
sp->staticlabel = FALSE;
v = xalloc(sizeof(LIST));
v->data = sp;
v->link = mpthunklist;
mpthunklist = v;
global_flag--;
// gen_codelab(sp) ;
gen_virtual(sp, FALSE);
ap1 = makedreg(ESP);
ap1->mode = am_indisp;
ap1->offset = makeintnode(en_icon, isstructured(sp->tp->btp) ? 8 : 4);
gen_codes(op_mov, BESZ_DWORD , makedreg(EAX), ap1);
ap1->preg = 0;
if (sp->value.classdata.vtaboffs)
ap1->offset = makeintnode(en_icon, sp->value.classdata.vtaboffs);
else
ap1->offset = makeintnode(en_icon, 0);
gen_codes(op_mov, BESZ_DWORD , makedreg(EAX), ap1);
ap1->offset = makeintnode(en_icon, sp->value.i);
gen_codes(op_jmp, BESZ_DWORD , ap1, 0);
flush_peep();
gen_endvirtual(sp);
return sp;
}
SYM *gen_vsn_virtual_thunk(SYM *func, int ofs)
{
SYM *sp;
AMODE *ap1, *ap2;
char buf[256];
global_flag++;
sp = makesym(sc_static);
sp->value.i = ofs;
sprintf(buf, "@$vsn%s$%d", func->name, sp->value.i);
sp->name = litlate(buf);
sp->staticlabel = FALSE;
sp->tp = func->mainsym; // strange use of the TP field here
global_flag--;
gen_virtual(sp, FALSE);
ap1 = makedreg(ESP);
ap1->mode = am_indisp;
ap1->offset = makeintnode(en_icon, BESZ_DWORD );
gen_codes(op_add, BESZ_DWORD , ap1, make_immed( - ofs));
ap2 = xalloc(sizeof(AMODE));
ap2->offset = makenode(en_napccon, (void*)func, 0);
ap2->mode = am_immed;
gen_codes(op_jmp, BESZ_DWORD , ap2, 0);
flush_peep();
gen_endvirtual(sp);
return sp;
}
void genfunc(SNODE *stmt)
/*
* generate a function body.
*/
{
//int isconst = FALSE;
cseg();
currentfunc->gennedvirtfunc = (virtualfuncs || (currentfunc
->value.classdata.cppflags &(PF_HEADERFUNC | PF_INSTANTIATED)));
if (currentfunc->storage_class == sc_global && !(currentfunc
->value.classdata.cppflags &PF_INLINE))
if (!currentfunc->gennedvirtfunc)
globaldef(currentfunc);
returndreg = FALSE;
retsize = 0;
contlab = breaklab = - 1;
retlab = nextlabel++;
startlab = nextlabel++;
funcfloat = 0;
if (funcstmt)
gen_line(funcstmt);
funcstmt = 0;
if (currentfunc->gennedvirtfunc)
gen_virtual(templateSP ? templateSP : currentfunc, FALSE);
else
gen_codelab(currentfunc);
/* name of function */
opt1(stmt); /* push args & also subtracts SP */
#ifdef XXXXX
if (isconst)
{
SYM *psp = currentfunc->parentclass;
if (currentfunc->value.classdata.basecons)
gen_void(currentfunc->value.classdata.basecons);
if (psp->value.classdata.baseclass->vtabsp)
{
CLASSLIST *l = psp->value.classdata.baseclass;
ENODE *thisn = copynode(thisenode);
ENODE *ts = makenode(en_nacon, psp
->value.classdata.baseclass->vtabsp, 0);
ENODE *exp1, *exp2;
thisn = makenode(en_a_ref, thisn, 0);
while (l)
{
if (l->flags &CL_VTAB)
{
exp1 = makenode(en_addstruc, ts, makeintnode
(en_icon, l->vtaboffs));
exp2 = makenode(en_addstruc, thisn, makeintnode
(en_icon, l->offset));
exp2 = makenode(en_a_ref, exp2, 0);
exp2 = makenode(en_assign, exp2, exp1);
initstack();
gen_expr(exp2, FALSE, TRUE, BESZ_DWORD );
}
l = l->link;
}
}
}
#endif
if (prm_cplusplus)
scppinit();
initstack();
genstmt(stmt);
if (block_rundown)
if (retsize)
if (retsize > 4)
{
gen_code(op_fstp, floatconvpos(), 0);
gen_void(block_rundown);
gen_code(op_fld, floatconvpos(), 0);
}
else
{
gen_code(op_push, makedreg(EAX), 0);
gen_void(block_rundown);
gen_code(op_pop, makedreg(EAX), 0);
}
else
gen_void(block_rundown);
if (funcendstmt)
gen_line(funcendstmt);
funcendstmt = 0;
genreturn(0, 1);
thissp->inreg = FALSE;
thissp->value.i = 8;
flush_peep();
if (currentfunc->gennedvirtfunc)
gen_endvirtual(templateSP ? templateSP : currentfunc);
if ((conscount || try_block_list || currentfunc
->value.classdata.throwlist && currentfunc
->value.classdata.throwlist->data) && prm_xcept)
dumpXceptBlock(currentfunc);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -