在代码生成的函数gencode里,需要产生寄存器给临时变量使用。下面就来分析这段代码,如下:
#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;
当代码表里的代码类型是
Gen
时就会运行上面的代码。寄存器分配是在函数 IR->gen里调用的,接着来分析这个函数的代码,如下:
#001 Node gen(Node forest) {
#002 int i;
#003 struct node sentinel;
#004 Node dummy, p;
#005
#006 head = forest;
#007 for (p = forest; p; p = p->link) {
#008 assert(p->count == 0);
#009 if (generic(p->op) == CALL)
#010 docall(p);
#011 else if ( generic(p->op) == ASGN
#012 && generic(p->kids[1]->op) == CALL)
#013 docall(p->kids[1]);
#014 else if (generic(p->op) == ARG)
#015 (*IR->x.doarg)(p);
#016 rewrite(p);
#017 p->x.listed = 1;
#018 }
#019 for (p = forest; p; p = p->link)
#020 prune(p, &dummy);
#021 relink(&sentinel, &sentinel);
#022 for (p = forest; p; p = p->link)
#023 linearize(p, &sentinel);
#024 forest = sentinel.x.next;
#025 assert(forest);
#026 sentinel.x.next->x.prev = NULL;
#027 sentinel.x.prev->x.next = NULL;
#028 for (p = forest; p; p = p->x.next)
#029 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
#030 assert(p->x.kids[i]->syms[RX]);
#031 if (p->x.kids[i]->syms[RX]->temporary) {
#032 p->x.kids[i]->x.prevuse =
#033 p->x.kids[i]->syms[RX]->x.lastuse;
#034 p->x.kids[i]->syms[RX]->x.lastuse = p->x.kids[i];
#035 }
#036 }
#037 for (p = forest; p; p = p->x.next) {
#038 ralloc(p);
#039 if (p->x.listed && NeedsReg[opindex(p->op)]
#040 && (*IR->x.rmap)(opkind(p->op))) {
#041 assert(generic(p->op) == CALL || generic(p->op) == LOAD);
#042 putreg(p->syms[RX]);
#043 }
#044 }
#045 return forest;
#046 }
其它的代码后面再分析,现在只关心寄存器分配的函数
ralloc
,它是在第
38
行里调用的。在那个函数里计算着怎么样分配一个寄存器。下次再接着分析。