从目标代码里,可以看到下面一行:
#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行是循环地计算所有变量的需要使用栈大小。后面再接分析怎么样计算变量占用栈的大小。