从目标代码里,可以看到下面一行:
#009 sub esp, 16
在这行里是保留栈的大小,值为16。但16个字节是怎么样计算出来的呢?下面就来分析LCC的代码,看它是怎么样计算的。它是在函数
gencode 里进行计算的,它的代码如下:
#001 void gencode(Symbol caller[], Symbol callee[])
#002 {
#003
Code cp;
#004
Coordinate save;
#005
#006
if (prunetemps == -1)
#007
prunetemps = !IR->wants_dag;
#008
save = src;
#009
if (assignargs)
#010
{
#011
int i;
#012
Symbol p, q;
#013
cp = codehead.next->next;
#014
codelist = codehead.next;
#015
for (i = 0; (p = callee[i]) != NULL
#016
&& (q = caller[i]) != NULL; i++)
#017
if (p->sclass != q->sclass || p->type != q->type)
#018
walk(asgn(p, idtree(q)), 0, 0);
#019
codelist->next = cp;
#020
cp->prev = codelist;
#021
}
#022
#023
if (glevel && IR->stabsym)
#024
{
#025
int i;
#026
Symbol p, q;
#027
for (i = 0; (p = callee[i]) != NULL
#028
&& (q = caller[i]) != NULL; i++)
#029
{
#030
(*IR->stabsym)(p);
#031
if (p->sclass != q->sclass || p->type != q->type)
#032
(*IR->stabsym)(q);
#033
}
#034
swtoseg(CODE);
#035
}
#036
#037
cp = codehead.next;
#038
for ( ; errcnt <= 0 && cp; cp = cp->next)
#039
switch (cp->kind)
#040
{
#041
case Address: assert(IR->address);
#042
(*IR->address)(cp->u.addr.sym, cp->u.addr.base,
#043
cp->u.addr.offset); break;
#044
case Blockbeg:
#045
{
#046
Symbol *p = cp->u.block.locals;
#047
(*IR->blockbeg)(&cp->u.block.x);
#048
for ( ; *p; p++)
#049
if ((*p)->ref != 0.0)
#050
(*IR->local)(*p);
#051
else if (glevel) (*IR->local)(*p);
#052
}
#053
break;
#054
case Blockend: (*IR->blockend)(&cp->u.begin->u.block.x); break;
#055
case Defpoint: src = cp->u.point.src; break;
#056
case Gen: case Jump:
#057
case Label:
#058
if (prunetemps)
#059
cp->u.forest = prune(cp->u.forest);
#060
fixup(cp->u.forest);
#061
cp->u.forest = (*IR->gen)(cp->u.forest); break;
#062
case Local:
#063
(*IR->local)(cp->u.var); break;
#064
case Switch: break;
#065
default: assert(0);
#066
}
#067
src = save;
#068 }
#069
计算栈大小的代码是从44行开始到第53行为止。第44行是处理块代码的开始类型。
第46行是获取当前代码块的符号表。
第47行是清空环境变量。
第48行到第51行是循环地计算所有变量的需要使用栈大小。后面再接分析怎么样计算变量占用栈的大小。