[转载] 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 重新获取寄存器。下一节再分析寄存器溢出算法。
 

你可能感兴趣的:(算法,null,编译器,templates)