📄 analyze.c
字号:
}
//-------------------------------------------------------------------------
void repcse(SNODE *block)
/*
* repcse will scan through a block of statements replacing the
* optimized expressions with their temporary references.
*/
{
while (block != 0)
{
switch (block->stype)
{
case st_tryblock:
break;
case st_throw:
if (block->exp)
repexpr(block->exp, 0);
break;
case st_return:
case st_expr:
case st_while:
case st_do:
repexpr(block->exp, 0);
repcse(block->s1);
break;
case st_for:
repexpr(block->label, 0);
repexpr(block->exp, 0);
repcse(block->s1);
repexpr(block->s2, 0);
break;
case st_if:
repexpr(block->exp, 0);
repcse(block->s1);
repcse(block->s2);
break;
case st_switch:
repexpr(block->exp, 0);
repcse(block->s1);
break;
case st_case:
repcse(block->s1);
break;
case st_block:
repcse(block->exp);
break;
case st_asm:
if (block->exp)
asm_repcse(block->exp);
break;
}
block = block->next;
}
}
//-------------------------------------------------------------------------
void repvoidassign(ENODE *node, int size)
/*
* repvoidassign will replace all allocated references within an expression
* with tempref nodes.
*/
{
CSE *csp;
if (node == 0)
return ;
if (size == 0)
size = natural_size(node);
switch (node->nodetype)
{
case en_structret:
break;
case en_conslabel:
case en_destlabel:
case en_movebyref:
repvoidassign(node->v.p[0], size);
break;
case en_rcomplexcon:
case en_lrcomplexcon:
case en_fcomplexcon:
case en_rimaginarycon:
case en_lrimaginarycon:
case en_fimaginarycon:
case en_rcon:
case en_lrcon:
case en_fcon:
case en_icon:
case en_lcon:
case en_iucon:
case en_lucon:
case en_llcon:
case en_llucon:
case en_boolcon:
case en_ccon:
case en_cucon:
case en_nacon:
case en_napccon:
case en_absacon:
case en_autocon:
case en_autoreg:
break;
case en_fp_ref:
repvoidassign(node->v.p[0], 0);
break;
case en_fcomplexref:
case en_rcomplexref:
case en_lrcomplexref:
repvoidassign(node->v.p[0], 0);
break;
case en_floatref:
case en_doubleref:
case en_longdoubleref:
case en_fimaginaryref:
case en_rimaginaryref:
case en_lrimaginaryref:
case en_ub_ref:
case en_uw_ref:
case en_b_ref:
case en_bool_ref:
case en_w_ref:
case en_l_ref:
case en_ul_ref:
case en_i_ref:
case en_ui_ref:
case en_a_ref: case en_ua_ref:
repvoidassign(node->v.p[0], 0);
break;
case en_ll_ref:
case en_ull_ref:
case en_cl_reg:
repvoidassign(node->v.p[0], 0);
break;
case en_uminus:
case en_bits:
case en_asuminus:
case en_ascompl:
case en_not:
case en_compl:
repvoidassign(node->v.p[0], 0);
break;
case en_cfc:
case en_cfi:
case en_crc:
case en_cri:
case en_clrc:
case en_clri:
case en_cb:
case en_cub:
case en_cbool:
case en_cw:
case en_cuw:
case en_cl:
case en_cul:
case en_ci:
case en_cui:
case en_cll:
case en_cull:
case en_csp:
case en_cf:
case en_cd:
case en_cp:
case en_cld:
case en_cfp:
repvoidassign(node->v.p[0], natural_size(node->v.p[0]));
break;
case en_pfcall:
case en_pfcallb:
case en_sfcall:
case en_sfcallb:
case en_fcallb:
case en_fcall:
{
SYM *sp;
ENODE *node2 = node->v.p[1]->v.p[0]->v.p[0];
if (node2->nodetype == en_nacon || node2->nodetype ==
en_napccon)
{
sp = node2->v.sp;
if (sp && (sp->value.classdata.cppflags &PF_INLINE))
voidAssign(sp->value.classdata.inlinefunc->stmt, 0);
}
}
case en_stackblock:
case en_callblock:
case en_pcallblock:
case en_scallblock:
case en_intcall:
case en_ainc:
case en_adec:
case en_add:
case en_sub:
case en_addstruc:
en_addcast: case en_umul:
case en_udiv:
case en_umod:
case en_mul:
case en_div:
case en_mod:
case en_lsh:
case en_asalsh:
case en_asarsh:
case en_alsh:
case en_arsh:
case en_arshd:
case en_asarshd:
case en_rsh:
case en_and:
case en_or:
case en_xor:
case en_land:
case en_lor:
case en_eq:
case en_ne:
case en_lt:
case en_le:
case en_ugt:
case en_uge:
case en_ult:
case en_ule:
case en_gt:
case en_ge:
case en_cond:
case en_void:
case en_voidnz:
case en_dvoid:
case en_pdiv:
case en_pmul:
case en_arrayindex:
case en_moveblock:
case en_thiscall:
case en_repcons:
case en_array:
repvoidassign(node->v.p[1], 0);
case en_trapcall:
case en_substack:
case en_clearblock:
repvoidassign(node->v.p[0], 0);
break;
case en_asadd:
case en_assub:
case en_asmul:
case en_asdiv:
case en_asor:
case en_asand:
case en_asxor:
case en_asmod:
case en_aslsh:
case en_asumod:
case en_asudiv:
case en_asumul:
case en_asrsh:
case en_assign:
case en_refassign:
en_lassign: voidlref(node->v.p[0]);
repvoidassign(node->v.p[1], 0);
repvoidassign(node->v.p[0], 0);
break;
}
}
//-------------------------------------------------------------------------
void voidAssign(SNODE *block, int state)
/*
* voidAssign will scan through a block of statements replacing the
* optimized expressions with their temporary references.
*/
{
int istate = state;
while (block != 0)
{
switch (block->stype)
{
case st_tryblock:
if (!state)
{
if ((int)block->label == 0)
// begin try
istate++;
else if ((int)block->label == 2)
// end try
istate--;
}
break;
case st_throw:
if (istate && block->exp)
repvoidassign(block->exp, 0);
break;
case st_return:
case st_expr:
case st_while:
case st_do:
if (istate)
repvoidassign(block->exp, 0);
voidAssign(block->s1, istate);
break;
case st_for:
if (istate)
{
repvoidassign(block->label, 0);
repvoidassign(block->exp, 0);
repvoidassign(block->s2, 0);
}
voidAssign(block->s1, istate);
break;
case st_if:
if (istate)
repvoidassign(block->exp, 0);
voidAssign(block->s1, istate);
voidAssign(block->s2, istate);
break;
case st_switch:
if (istate)
repvoidassign(block->exp, 0);
voidAssign(block->s1, istate);
break;
case st_case:
voidAssign(block->s1, istate);
break;
case st_block:
voidAssign(block->exp, istate);
break;
case st_asm:
// if (block->exp)
// asm_voidAssign(block->exp);
break;
}
block = block->next;
}
}
//-------------------------------------------------------------------------
void allocstack(void)
/*
* This allocates space for local variables
* we do this AFTER the register optimization so that we can
* avoid allocating space on the stack twice
*/
{
int lvl = - 1;
// base assignments are at level 0, function body starts at level 1
int again = TRUE;
int oldauto, max;
lc_maxauto = max = 0;
while (again)
{
LIST *t = varlisthead;
int align;
lvl++;
oldauto = max;
again = FALSE;
while (t)
{
SYM *sp = t->data;
while (sp && (sp->inreg || sp->funcparm || sp->storage_class ==
sc_static || sp->storage_class == sc_label || sp->storage_class
== sc_ulabel))
sp = sp->next;
if (!sp)
{
t = t->link;
continue;
}
if (sp->value.i >= lvl)
again = TRUE;
if (sp->value.i == lvl)
{
lc_maxauto = oldauto;
while (sp)
{
if (!sp->inreg && !sp->funcparm && sp->storage_class !=
sc_static)
{
int val;
if (sp->tp->size >= stdaddrsize)
align = stdaddrsize;
else
align = getalign(sc_auto, sp->tp);
lc_maxauto += sp->tp->size;
val = lc_maxauto % align;
if (val != 0)
lc_maxauto += align - val;
sp->value.i = - lc_maxauto;
}
sp = sp->next;
}
}
if (lc_maxauto > max)
max = lc_maxauto;
t = t->link;
}
}
lc_maxauto = max;
lc_maxauto += stackadd;
lc_maxauto &= stackmod;
}
//-------------------------------------------------------------------------
void opt1(SNODE *block)
/*
* opt1 is the externally callable optimization routine. it will
* collect and allocate common subexpressions and substitute the
* tempref for all occurrances of the expression within the block.
*
*/
{
int datareg = cf_freedata;
int addreg = 16+cf_freeaddress;
int floatreg = 32+cf_freefloat;
olist = 0;
scan(block); /* collect expressions */
voidall(); /* Disallow regs whose address is taken */
voidfloat(block); /* disallow optimizing things which are assigned values
derived from floats */
if ((try_block_list || currentfunc->value.classdata.throwlist &&
currentfunc->value.classdata.throwlist->data) && prm_xcept)
voidAssign(block, FALSE);
/* void having assignment targets in registers for exception handling */
reserveregs(&datareg, &addreg, &floatreg); /* Allocate register vars */
allocate(datareg, addreg, floatreg, block); /* allocate registers for opt*/
repcse(block); /* replace allocated expressions */
loadregs(); /* Initialize allocated regs */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -