LCC编译器的源程序分析(51) 分配一个寄存器

分配一个寄存器的函数是ralloc,它会调用getreg函数来获取一个寄存器。下面先来分析函数ralloc的代码,如下:
#001 static void ralloc(Node p) {
#002 int i;
#003 unsigned mask[2];
#004
#005 mask[0] = tmask[0];
#006 mask[1] = tmask[1];
#007 assert(p);
#008 debug(fprint(stderr, "(rallocing %x)\n", p));
#009 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
#010 Node kid = p->x.kids[i];
#011 Symbol r = kid->syms[RX];
#012 assert(r && kid->x.registered);
#013 if (r->sclass != REGISTER && r->x.lastuse == kid)
#014 putreg(r);
#015 }
#016 if (!p->x.registered && NeedsReg[opindex(p->op)]
#017 && (*IR->x.rmap)(opkind(p->op))) {
#018 Symbol sym = p->syms[RX], set = sym;
#019 assert(sym);
#020 if (sym->temporary)
#021 set = (*IR->x.rmap)(opkind(p->op));
#022 assert(set);
#023 if (set->sclass != REGISTER) {
#024 Symbol r;
#025 if (*IR->x._templates[getrule(p, p->x.inst)] == '?')
#026 for (i = 1; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
#027 Symbol r = p->x.kids[i]->syms[RX];
#028 assert(p->x.kids[i]->x.registered);
#029 assert(r && r->x.regnode);
#030 assert(sym->x.wildcard || sym != r);
#031 mask[r->x.regnode->set] &= ~r->x.regnode->mask;
#032 }
#033 r = getreg(set, mask, p);
#034 if (sym->temporary) {
#035 Node q;
#036 r->x.lastuse = sym->x.lastuse;
#037 for (q = sym->x.lastuse; q; q = q->x.prevuse) {
#038 q->syms[RX] = r;
#039 q->x.registered = 1;
#040 if (sym->u.t.cse && q->x.copy)
#041 q->x.equatable = 1;
#042 }
#043 } else {
#044 p->syms[RX] = r;
#045 r->x.lastuse = p;
#046 }
#047 debug(dumpregs("(allocating %s to node %x)\n", r->x.name, (char *) p));
#048 }
#049 }
#050 p->x.registered = 1;
#051 (*IR->x.clobber)(p);
#052 }
第14行里把已经没有用的寄存器释放掉。
第33行里分配一个寄存器返回来。它是调用函数getreg分配寄存器的。

下面接着分析getreg函数,如下:
#001 static Symbol getreg(Symbol s, unsigned mask[], Node p) {
#002 Symbol r = askreg(s, mask);
#003 if (r == NULL) {
#004 r = spillee(s, mask, p);
#005 assert(r && r->x.regnode);
#006 spill(r->x.regnode->mask, r->x.regnode->set, p);
#007 r = askreg(s, mask);
#008 }
#009 assert(r && r->x.regnode);
#010 r->x.regnode->vbl = NULL;
#011 return r;
#012 }
第2行里调用函数askreg来申请一个寄存器,前面已经介绍过这个函数。
如果寄存器分配不到,就需要在第4行里调用函数spillee和函数spill把前面的寄存器值保存到内存里,然后再把寄存器分配出来使用,所以第7行里调用函数askreg重新获取寄存器。下一节再分析寄存器溢出算法。

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License