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

本文详细解析了寄存器分配算法中ralloc和getreg函数的工作原理,介绍了如何分配和回收寄存器资源,以及当寄存器不足时采用的溢出策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分配一个寄存器的函数是ralloc,它会调用getreg函数来获取一个寄存器。下面先来分析函数ralloc的代码,如下:
#001static void ralloc(Node p) {
#002int i;
#003unsigned mask[2];
#004
#005mask[0] = tmask[0];
#006mask[1] = tmask[1];
#007assert(p);
#008debug(fprint(stderr, "(rallocing %x)/n", p));
#009for (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}
#016if (!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}
#050p->x.registered = 1;
#051(*IR->x.clobber)(p);
#052}
14行里把已经没有用的寄存器释放掉。
33行里分配一个寄存器返回来。它是调用函数getreg分配寄存器的。
下面接着分析getreg函数,如下:
#001static Symbol getreg(Symbol s, unsigned mask[], Node p) {
#002Symbol r = askreg(s, mask);
#003if (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}
#009assert(r && r->x.regnode);
#010r->x.regnode->vbl = NULL;
#011return r;
#012}
2行里调用函数askreg来申请一个寄存器,前面已经介绍过这个函数。
如果寄存器分配不到,就需要在第4行里调用函数spillee和函数spill把前面的寄存器值保存到内存里,然后再把寄存器分配出来使用,所以第7行里调用函数askreg重新获取寄存器。下一节再分析寄存器溢出算法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值