LCC编译器的源程序分析(59)代码生成的源程序注释

下面详细地注释了gen.c的源程序,这样看起来就比较容易理解,希望对你有所帮助。
#001 #include "c.h"
#002
#003 static char rcsid[] = "$Id: gen.c 355 2007-02-18 22:08:49Z drh $";
#004
#005 #define readsreg(p) #006 (generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P)
#007 #define setsrc(d) ((d) && (d)->x.regnode && #008 (d)->x.regnode->set == src->x.regnode->set && #009 (d)->x.regnode->mask&src->x.regnode->mask)
#010
#011 #define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))
#012
#013 static Symbol askfixedreg(Symbol);
#014 static Symbol askreg(Symbol, unsigned*);
#015 static void blkunroll(int, int, int, int, int, int, int[]);
#016 static void docall(Node);
#017 static void dumpcover(Node, int, int);
#018 static void dumpregs(char *, char *, char *);
#019 static void dumprule(int);
#020 static void dumptree(Node);
#021 static void genreload(Node, Symbol, int);
#022 static void genspill(Symbol, Node, Symbol);
#023 static Symbol getreg(Symbol, unsigned*, Node);
#024 static int getrule(Node, int);
#025 static void linearize(Node, Node);
#026 static int moveself(Node);
#027 static void prelabel(Node);
#028 static Node* prune(Node, Node*);
#029 static void putreg(Symbol);
#030 static void ralloc(Node);
#031 static void reduce(Node, int);
#032 static int reprune(Node*, int, int, Node);
#033 static int requate(Node);
#034 static Node reuse(Node, int);
#035 static void rewrite(Node);
#036 static Symbol spillee(Symbol, unsigned mask[], Node);
#037 static void spillr(Symbol, Node);
#038 static int uses(Node, Regnode);
#039
#040
#041 保存栈分配的偏移位置。
#042 int offset;
#043
#044 //所有代码块使用栈的最大值。
#045 int maxoffset;
#046
#047 //大于或者等于maxoffset,由于作内存对齐的处理。
#048 //用来输出栈的使用大小。
#049 int framesize;
#050
#051 //保存下一块参数使用内存开始。
#052 int argoffset;
#053
#054 //保存参数使用最大值。
#055 int maxargoffset;
#056
#057 int dalign, salign;
#058 int bflag = 0; /* omit */
#059 int dflag = 0;
#060
#061 int swap;
#062
#063 //设置后面输出汇编代码的函数.
#064 unsigned (*emitter)(Node, int) = emitasm;
#065
#066 //定义需要寄存器的中间代码类型。
#067 static char NeedsReg[] =
#068 {
#069 0, /* unused */
#070 1, /* CNST */
#071 0, 0, /* ARG ASGN */
#072 1, /* INDIR */
#073 0, 0, 1, 1, /* - - CVF CVI */
#074 1, 0, 1, 1, /* CVP - CVU NEG */
#075 1, /* CALL */
#076 1, /* LOAD */
#077 0, /* RET */
#078 1, 1, 1, /* ADDRG ADDRF ADDRL */
#079 1, 1, 1, 1, 1, /* ADD SUB LSH MOD RSH */
#080 1, 1, 1, 1, /* BAND BCOM BOR BXOR */
#081 1, 1, /* DIV MUL */
#082 0, 0, 0, 0, 0, 0, /* EQ GE GT LE LT NE */
#083 0, 0 /* JUMP LABEL */
#084 };
#085 Node head;
#086
#087 //保存空闲的寄存器
#088 unsigned freemask[2];
#089
#090 //保存已经使用的寄存器。
#091 unsigned usedmask[2];
#092
#093 //临时变量使用的寄存器
#094 unsigned tmask[2];
#095
#096 //变量使用的寄存器.
#097 unsigned vmask[2];
#098
#099 //创建并初始化寄存器。
#100 Symbol mkreg(char *fmt, int n, int mask, int set)
#101 {
#102 Symbol p;
#103
#104 NEW0(p, PERM);
#105 p->name = p->x.name = stringf(fmt, n);
#106 NEW0(p->x.regnode, PERM);
#107 p->x.regnode->number = n;
#108 p->x.regnode->mask = mask«n;
#109 p->x.regnode->set = set;
#110 return p;
#111 }
#112
#113 //创建寄存器链表。
#114 Symbol mkwildcard(Symbol *syms)
#115 {
#116 Symbol p;
#117
#118 NEW0(p, PERM);
#119 p->name = p->x.name = "wildcard";
#120 //保存寄存器列表。
#121 p->x.wildcard = syms;
#122 return p;
#123 }
#124
#125 //保持栈分配对齐。
#126 //
#127 //蔡军生 2007/07/21
#128 //
#129 void mkauto(Symbol p)
#130 {
#131 assert(p->sclass == AUTO);
#132 offset = roundup(offset + p->type->size, p->type->align);
#133 p->x.offset = -offset;
#134 p->x.name = stringd(-offset);
#135 }
#136
#137 //每块代码开始都需要保存栈位置和寄存器状态。
#138 void blockbeg(Env *e)
#139 {
#140 e->offset = offset;
#141 e->freemask[IREG] = freemask[IREG];
#142 e->freemask[FREG] = freemask[FREG];
#143 }
#144
#145 //每块代码结束都需要查看栈使用的最大值,
#146 //恢复寄存器的使用情况。
#147 void blockend(Env *e)
#148 {
#149 //查看使用栈的最大位置。
#150 if (offset > maxoffset)
#151 {
#152 maxoffset = offset;
#153 }
#154
#155 //恢复栈的大小。
#156 offset = e->offset;
#157
#158 //恢复寄存器状态。
#159 freemask[IREG] = e->freemask[IREG];
#160 freemask[FREG] = e->freemask[FREG];
#161 }
#162
#163 //
#164 //计算参数块下一块的开始位置。
#165 //
#166 //蔡军生 2007/07/21 QQ: 9073204
#167 //
#168 //
#169 int mkactual(int align, int size)
#170 {
#171 int n = roundup(argoffset, align);
#172
#173 //保存一块参数块的开始位置。
#174 argoffset = n + size;
#175 return n;
#176 }
#177
#178 //准备下一次调用的参数块。
#179 static void docall(Node p)
#180 {
#181 //保存参数偏移地址。
#182 p->syms[1] = p->syms[0];
#183 p->syms[0] = intconst(argoffset);
#184 if (argoffset > maxargoffset)
#185 {
#186 maxargoffset = argoffset;
#187 }
#188
#189 argoffset = 0;
#190 }
#191
#192 //块复制代码。
#193 //
#194 //蔡军生 2007/07/22 QQ: 9073204
#195 //
#196 void blkcopy(int dreg, int doff, int sreg, int soff, int size, int tmp[])
#197 {
#198 assert(size >= 0);
#199 if (size == 0)
#200 {
#201 //没有字节复制。
#202 return;
#203 }
#204 else if (size <= 2)
#205 {
#206 //两个或者一个字节复制。
#207 blkunroll(size, dreg, doff, sreg, soff, size, tmp);
#208 }
#209 else if (size == 3)
#210 {
#211 blkunroll(2, dreg, doff, sreg, soff, 2, tmp);
#212 blkunroll(1, dreg, doff+2, sreg, soff+2, 1, tmp);
#213 }
#214 else if (size <= 16)
#215 {
#216 //每次拷贝4个字节。
#217 blkunroll(4, dreg, doff, sreg, soff, size&~3, tmp);
#218 //递归处理
#219 blkcopy(dreg, doff+(size&~3),
#220 sreg, soff+(size&~3), size&3, tmp);
#221 }
#222 else
#223 {
#224 (*IR->x.blkloop)(dreg, doff, sreg, soff, size, tmp);
#225 }
#226 }
#227
#228 //小块复制。
#229 static void blkunroll(int k, int dreg, int doff, int sreg, int soff, int size, int tmp[])
#230 {
#231 int i;
#232
#233 assert(IR->x.max_unaligned_load);
#234 if (k > IR->x.max_unaligned_load &&
#235 (k > salign || k > dalign))
#236 {
#237 k = IR->x.max_unaligned_load;
#238 }
#239
#240 for (i = 0; i+k < size; i += 2*k)
#241 {
#242 //取回数据。
#243 (*IR->x.blkfetch)(k, soff+i, sreg, tmp[0]);
#244 (*IR->x.blkfetch)(k, soff+i+k, sreg, tmp[1]);
#245
#246 //保存数据。
#247 (*IR->x.blkstore)(k, doff+i, dreg, tmp[0]);
#248 (*IR->x.blkstore)(k, doff+i+k, dreg, tmp[1]);
#249 }
#250
#251 if (i < size)
#252 {
#253 (*IR->x.blkfetch)(k, i+soff, sreg, tmp[0]);
#254 (*IR->x.blkstore)(k, i+doff, dreg, tmp[0]);
#255 }
#256 }
#257
#258 //分析输入给后端的参数。
#259 void parseflags(int argc, char *argv[])
#260 {
#261 int i;
#262
#263 for (i = 0; i < argc; i++)
#264 {
#265 if (strcmp(argv[i], "-d") == 0)
#266 {
#267 //调试标志。
#268 dflag = 1;
#269 }
#270 else if (strcmp(argv[i], "-b") == 0) /* omit */
#271 {
#272 bflag = 1; /* omit */
#273 }
#274 }
#275 }
#276
#277 //获取指令编码。
#278 static int getrule(Node p, int nt)
#279 {
#280 int rulenum;
#281
#282 assert(p);
#283
#284 //返回指令编码。
#285 rulenum = (*IR->x._rule)(p->x.state, nt);
#286 if (!rulenum)
#287 {
#288 fprint(stderr, "(%x->op=%s at %w is corrupt.)\n", p, opname(p->op), &src);
#289 assert(0);
#290 }
#291
#292 return rulenum;
#293 }
#294
#295 //选择代价最小的实现。
#296 static void reduce(Node p, int nt)
#297 {
#298 int rulenum, i;
#299 short *nts;
#300 Node kids[10];
#301
#302 p = reuse(p, nt);
#303
#304 //获取指令编码。
#305 rulenum = getrule(p, nt);
#306
#307 //获取非终结符数组。
#308 nts = IR->x._nts[rulenum];
#309
#310 //根据指令模板保存子节点到kids中
#311 (*IR->x._kids)(p, rulenum, kids);
#312
#313 //遍历所有非终结符。
#314 for (i = 0; nts[i]; i++)
#315 {
#316 //递归处理子节点。
#317 reduce(kids[i], nts[i]);
#318 }
#319
#320 //是否是指令。
#321 if (IR->x._isinstruction[rulenum])
#322 {
#323 assert(p->x.inst == 0 || p->x.inst == nt);
#324 //保存指令类型。
#325 p->x.inst = nt;
#326 if (p->syms[RX] && p->syms[RX]->temporary)
#327 {
#328 //计算临时变量使用的次数。
#329 debug(fprint(stderr, "(using %s)\n", p->syms[RX]->name));
#330 p->syms[RX]->x.usecount++;
#331 }
#332 }
#333 }
#334
#335 //
#336 //化简函数。
#337 //
#338 static Node reuse(Node p, int nt)
#339 {
#340 struct _state
#341 {
#342 short cost[1];
#343 };
#344
#345 Symbol r = p->syms[RX];
#346
#347 if (generic(p->op) == INDIR &&
#348 p->kids[0]->op == VREG+P &&
#349 r->u.t.cse && p->x.mayrecalc &&
#350 ((struct _state*)r->u.t.cse->x.state)->cost[nt] == 0)
#351 {
#352 //返回公共表达式。
#353 return r->u.t.cse;
#354 }
#355 else
#356 {
#357 return p;
#358 }
#359 }
#360
#361 //判断公共表达式可以重新计算
#362 int mayrecalc(Node p)
#363 {
#364 int nOperater;
#365
#366 assert(p && p->syms[RX]);
#367 if (p->syms[RX]->u.t.cse == NULL)
#368 {
#369 //不是公共表达式返回。
#370 return 0;
#371 }
#372
#373 nOperater = generic(p->syms[RX]->u.t.cse->op);
#374 if (nOperater == CNST || nOperater == ADDRF ||
#375 nOperater == ADDRG || nOperater == ADDRL)
#376 {
#377 //公共表达式可以重新计算。
#378 p->x.mayrecalc = 1;
#379 return 1;
#380 }
#381 else
#382 {
#383 //公共表达式不可以重新计算。
#384 return 0;
#385 }
#386 }
#387
#388 //删除某些子指令。
#389 static Node *prune(Node p, Node pp[])
#390 {
#391 if (p == NULL)
#392 {
#393 return pp;
#394 }
#395
#396 p->x.kids[0] = p->x.kids[1] = p->x.kids[2] = NULL;
#397 if (p->x.inst == 0)
#398 {
#399 //如果节点不是指令,就递归到下一个节点。
#400 return prune(p->kids[1], prune(p->kids[0], pp));
#401 }
#402 else if (p->syms[RX] && p->syms[RX]->temporary &&
#403 p->syms[RX]->x.usecount < 2)
#404 {
#405 //删除没有用的临时变量的指令。
#406 p->x.inst = 0;
#407 debug(fprint(stderr, "(clobbering %s)\n", p->syms[RX]->name));
#408
#409 return prune(p->kids[1], prune(p->kids[0], pp));
#410 }
#411 else
#412 {
#413 prune(p->kids[1], prune(p->kids[0], &p->x.kids[0]));
#414 *pp = p;
#415 return pp + 1;
#416 }
#417 }
#418
#419 #define ck(i) return (i) ? 0 : LBURG_MAX
#420
#421 //代价值计算.
#422 int range(Node p, int lo, int hi)
#423 {
#424 Symbol s = p->syms[0];
#425
#426 switch (specific(p->op))
#427 {
#428 case ADDRF+P:
#429 case ADDRL+P: ck(s->x.offset >= lo && s->x.offset <= hi);
#430 case CNST+I: ck(s->u.c.v.i >= lo && s->u.c.v.i <= hi);
#431 case CNST+U: ck(s->u.c.v.u >= lo && s->u.c.v.u <= hi);
#432 case CNST+P: ck(s->u.c.v.p == 0 && lo <= 0 && hi >= 0);
#433 }
#434 return LBURG_MAX;
#435 }
#436
#437 //调试输出指令树
#438 static void dumptree(Node p)
#439 {
#440 if (p->op == VREG+P && p->syms[0])
#441 {
#442 fprint(stderr, "VREGP(%s)", p->syms[0]->name);
#443 return;
#444 }
#445 else if (generic(p->op) == LOAD)
#446 {
#447 fprint(stderr, "LOAD(");
#448 dumptree(p->kids[0]);
#449 fprint(stderr, ")");
#450 return;
#451 }
#452
#453 fprint(stderr, "%s(", opname(p->op));
#454 switch (generic(p->op)) {
#455 case CNST: case LABEL:
#456 case ADDRG: case ADDRF: case ADDRL:
#457 if (p->syms[0])
#458 fprint(stderr, "%s", p->syms[0]->name);
#459 break;
#460 case RET:
#461 if (p->kids[0])
#462 dumptree(p->kids[0]);
#463 break;
#464 case CVF: case CVI: case CVP: case CVU: case JUMP:
#465 case ARG: case BCOM: case NEG: case INDIR:
#466 dumptree(p->kids[0]);
#467 break;
#468 case CALL:
#469 if (optype(p->op) != B) {
#470 dumptree(p->kids[0]);
#471 break;
#472 }
#473 /* else fall thru */
#474 case EQ: case NE: case GT: case GE: case LE: case LT:
#475 case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH:
#476 case ADD: case SUB: case DIV: case MUL: case MOD:
#477 dumptree(p->kids[0]);
#478 fprint(stderr, ", ");
#479 dumptree(p->kids[1]);
#480 break;
#481 default: assert(0);
#482 }
#483 fprint(stderr, ")");
#484 }
#485
#486 static void dumpcover(Node p, int nt, int in)
#487 {
#488 int rulenum, i;
#489 short *nts;
#490 Node kids[10];
#491
#492 p = reuse(p, nt);
#493 rulenum = getrule(p, nt);
#494 nts = IR->x._nts[rulenum];
#495 fprint(stderr, "dumpcover(%x) = ", p);
#496 for (i = 0; i < in; i++)
#497 fprint(stderr, " ");
#498 dumprule(rulenum);
#499 (*IR->x._kids)(p, rulenum, kids);
#500 for (i = 0; nts[i]; i++)
#501 dumpcover(kids[i], nts[i], in+1);
#502 }
#503
#504 //调试输出指令的规则.
#505 static void dumprule(int rulenum)
#506 {
#507 assert(rulenum);
#508 fprint(stderr, "%s / %s", IR->x._string[rulenum],
#509 IR->x._templates[rulenum]);
#510 if (!IR->x._isinstruction[rulenum])
#511 fprint(stderr, "\n");
#512 }
#513
#514 //输出一个节点的汇编代码。
#515 //
#516 // 格式如下:
#517 // %% 输出 %
#518 // %F 输出 framesize
#519 // %数字 输出对应 非终结符的第几个子树。
#520 // %字母 输出变量所在的地址
#521 // #开头 调用emit2函数输出.
#522 // ?开头 如果源寄存器和目标寄存器一样,就忽略第一条指令。
#523 //
#524 unsigned emitasm(Node p, int nt)
#525 {
#526 int rulenum;
#527 short *nts;
#528 char *fmt;
#529
#530 //保存子节点。
#531 Node kids[10];
#532
#533
#534 p = reuse(p, nt);
#535
#536 //取得指令编码。
#537 rulenum = getrule(p, nt);
#538
#539 nts = IR->x._nts[rulenum];
#540
#541 //获取指令模板。
#542 fmt = IR->x._templates[rulenum];
#543
#544 assert(fmt);
#545 if (IR->x._isinstruction[rulenum] && p->x.emitted)
#546 {
#547 //已经输出过代码。
#548 print("%s", p->syms[RX]->x.name);
#549 }
#550 else if (*fmt == '#')
#551 {
#552 //复杂的指令输出。
#553 (*IR->x.emit2)(p);
#554 }
#555 else
#556 {
#557 //如果源寄存器和目标寄存器一样,就忽略第一条指令。
#558 if (*fmt == '?')
#559 {
#560 fmt++;
#561 assert(p->kids[0]);
#562 if (p->syms[RX] == p->x.kids[0]->syms[RX])
#563 {
#564 while (*fmt++ != '\n');
#565 }
#566 }
#567
#568 //先根据模板保存两子节点到kids中。
#569 for ((*IR->x._kids)(p, rulenum, kids); *fmt; fmt++)
#570 {
#571 if (*fmt != '%')
#572 {
#573 //输出指令字符。
#574 (void)putchar(*fmt);
#575 }
#576 else
#577 {
#578 //跳过%号。
#579 ++fmt;
#580
#581 //
#582 if (*fmt == 'F')
#583 {
#584 //输出帧内存的大小。
#585 print("%d", framesize);
#586 }
#587 else if (*fmt >= '0' && *fmt <= '9')
#588 {
#589 //递归地输出子节点的指令代码。
#590 emitasm(kids[*fmt - '0'], nts[*fmt - '0']);
#591 }
#592 else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms))
#593 {
#594 //输出变量所在的地址。
#595 fputs(p->syms[*fmt - 'a']->x.name, stdout);
#596 }
#597 else
#598 {
#599 (void)putchar(*fmt);
#600 }
#601 }
#602 }
#603 }
#604
#605 return 0;
#606 }
#607
#608 //
#609 //把中间代码输出汇编代码。
#610 //
#611 void emit(Node p)
#612 {
#613 //遍历代码表节点。
#614 for (; p; p = p->x.next)
#615 {
#616 assert(p->x.registered);
#617 if (p->x.equatable && requate(p) || moveself(p))
#618 {
#619 //跳过这些不需要生成指的节点。
#620 ;
#621 }
#622 else
#623 {
#624 //调用输出汇编代码函数。
#625 (*emitter)(p, p->x.inst);
#626 }
#627
#628 //标识已经输出指令
#629 p->x.emitted = 1;
#630 }
#631 }
#632
#633 //检查是否自己复制自己的寄存器。
#634 static int moveself(Node p)
#635 {
#636 return p->x.copy
#637 && p->syms[RX]->x.name == p->x.kids[0]->syms[RX]->x.name;
#638 }
#639
#640 //设置寄存器到寄存器的拷贝。
#641 int move(Node p)
#642 {
#643 p->x.copy = 1;
#644 return 1;
#645 }
#646
#647 //寄存器是否相等判断。
#648 static int requate(Node q)
#649 {
#650 Symbol src = q->x.kids[0]->syms[RX];
#651 Symbol tmp = q->syms[RX];
#652 Node p;
#653 int n = 0;
#654
#655 debug(fprint(stderr, "(requate(%x): tmp=%s src=%s)\n", q, tmp->x.name, src->x.name));
#656 for (p = q->x.next; p; p = p->x.next)
#657 {
#658 if (p->x.copy && p->syms[RX] == src &&
#659 p->x.kids[0]->syms[RX] == tmp)
#660 {
#661 debug(fprint(stderr, "(requate arm 0 at %x)\n", p)),
#662 p->syms[RX] = tmp;
#663 }
#664 else if (setsrc(p->syms[RX]) && !moveself(p) && !readsreg(p))
#665 {
#666 return 0;
#667 }
#668 else if (p->x.spills)
#669 {
#670 return 0;
#671 }
#672 else if (generic(p->op) == CALL && p->x.next)
#673 {
#674 return 0;
#675 }
#676 else if (p->op == LABEL+V && p->x.next)
#677 {
#678 return 0;
#679 }
#680 else if (p->syms[RX] == tmp && readsreg(p))
#681 {
#682 debug(fprint(stderr, "(requate arm 5 at %x)\n", p)),
#683 n++;
#684 }
#685 else if (p->syms[RX] == tmp)
#686 {
#687 break;
#688 }
#689 }
#690
#691 debug(fprint(stderr, "(requate arm 7 at %x)\n", p));
#692 assert(n > 0);
#693 for (p = q->x.next; p; p = p->x.next)
#694 {
#695 if (p->syms[RX] == tmp && readsreg(p))
#696 {
#697 p->syms[RX] = src;
#698 if (n <= 0)
#699 break;
#700 }
#701 }
#702
#703 return 1;
#704 }
#705
#706 //后序遍历代码树,根据不同类型设置寄存器。
#707 //
#708 static void prelabel(Node p)
#709 {
#710 //树节点为空就返回。
#711 if (p == NULL)
#712 return;
#713
#714 //递归遍历
#715 prelabel(p->kids[0]);
#716 prelabel(p->kids[1]);
#717
#718 //查找是否需要寄存器。
#719 if (NeedsReg[opindex(p->op)])
#720 {
#721 //设置需要寄存器的类型。
#722 setreg(p, (*IR->x.rmap)(opkind(p->op)));
#723 }
#724
#725 //
#726 switch (generic(p->op))
#727 {
#728 case ADDRF:
#729 case ADDRL:
#730 if (p->syms[0]->sclass == REGISTER)
#731 {
#732 //如果引用是寄存器变量,就修改操作码。
#733 p->op = VREG+P;
#734 }
#735 break;
#736 case INDIR:
#737 if (p->kids[0]->op == VREG+P)
#738 {
#739 setreg(p, p->kids[0]->syms[0]);
#740 }
#741 break;
#742 case ASGN:
#743 if (p->kids[0]->op == VREG+P)
#744 {
#745 rtarget(p, 1, p->kids[0]->syms[0]);
#746 }
#747 break;
#748 case CVI:
#749 case CVU:
#750 case CVP:
#751 if (optype(p->op) != F &&
#752 opsize(p->op) <= p->syms[0]->u.c.v.i)
#753 {
#754 p->op = LOAD + opkind(p->op);
#755 }
#756 break;
#757 }
#758
#759 //调整寄存器的类型。
#760 (IR->x.target)(p);
#761 }
#762
#763 //保存寄存器类型指针。
#764 void setreg(Node p, Symbol r)
#765 {
#766 p->syms[RX] = r;
#767 }
#768
#769 //计算那些需要放到特定寄存器的树节点。
#770 void rtarget(Node p, int n, Symbol r)
#771 {
#772 Node q = p->kids[n];
#773
#774 assert(q);
#775 assert(r);
#776 assert(r->sclass == REGISTER || !r->x.wildcard);
#777 assert(q->syms[RX]);
#778
#779 if (r != q->syms[RX] && !q->syms[RX]->x.wildcard)
#780 {
#781 //当子节点与父节点的寄存器不相同时要产生寄存器复制。
#782 q = newnode(LOAD + opkind(q->op),
#783 q, NULL, q->syms[0]);
#784
#785 if (r->u.t.cse == p->kids[n])
#786 {
#787 r->u.t.cse = q;
#788 }
#789
#790 p->kids[n] = p->x.kids[n] = q;
#791 q->x.kids[0] = q->kids[0];
#792 }
#793
#794 //设置寄存器类型.
#795 setreg(q, r);
#796
#797 debug(fprint(stderr, "(targeting %x->x.kids[%d]=%x to %s)\n", p, n, p->kids[n], r->x.name));
#798 }
#799
#800 //完成单棵树的寄存器定位和指令选择。
#801 static void rewrite(Node p)
#802 {
#803 assert(p->x.inst == 0);
#804 //设置寄存器类型和重定位目标。
#805 prelabel(p);
#806
#807 debug(dumptree(p));
#808 debug(fprint(stderr, "\n"));
#809
#810 //设置每个节点的指令选择。
#811 (*IR->x._label)(p);
#812
#813 debug(dumpcover(p, 1, 0));
#814
#815 //
#816 reduce(p, 1);
#817 }
#818
#819 //生成代码。
#820 Node gen(Node forest)
#821 {
#822 int i;
#823 struct node sentinel;
#824 Node dummy, p;
#825
#826 head = forest;
#827
#828 //为整个森林选择指令。
#829 for (p = forest; p; p = p->link)
#830 {
#831 assert(p->count == 0);
#832 //调用参数块分配。
#833 if (generic(p->op) == CALL)
#834 {
#835 docall(p);
#836 }
#837 else if ( generic(p->op) == ASGN &&
#838 generic(p->kids[1]->op) == CALL)
#839 {
#840 docall(p->kids[1]);
#841 }
#842 else if (generic(p->op) == ARG)
#843 {
#844 (*IR->x.doarg)(p);
#845 }
#846
#847 //为一个节点选择指令。
#848 rewrite(p);
#849
#850 /
标记已经遍历过。
#851 p->x.listed = 1;
#852 }
#853
#854 构造指令树,并从指令树中删除一些子指令。
#855 for (p = forest; p; p = p->link)
#856 {
#857 prune(p, &dummy);
#858 }
#859
#860 //为指令树进行线性化处理.
#861 relink(&sentinel, &sentinel);
#862 for (p = forest; p; p = p->link)
#863 {
#864 //输出指令排序。
#865 linearize(p, &sentinel);
#866 }
#867
#868 forest = sentinel.x.next;
#869 assert(forest);
#870 sentinel.x.next->x.prev = NULL;
#871 sentinel.x.prev->x.next = NULL;
#872
#873 //为所有临时变量建立一个列表.
#874 for (p = forest; p; p = p->x.next)
#875 {
#876 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
#877 {
#878 assert(p->x.kids[i]->syms[RX]);
#879 if (p->x.kids[i]->syms[RX]->temporary)
#880 {
#881 p->x.kids[i]->x.prevuse =
#882 p->x.kids[i]->syms[RX]->x.lastuse;
#883 p->x.kids[i]->syms[RX]->x.lastuse = p->x.kids[i];
#884 }
#885 }
#886 }
#887
#888 //为每个节点分配一个寄存器.
#889 for (p = forest; p; p = p->x.next)
#890 {
#891 //分配寄存器。
#892 ralloc(p);
#893
#894 if (p->x.listed && NeedsReg[opindex(p->op)] &&
#895 (*IR->x.rmap)(opkind(p->op)))
#896 {
#897 assert(generic(p->op) == CALL || generic(p->op) == LOAD);
#898 putreg(p->syms[RX]);
#899 }
#900 }
#901 return forest;
#902 }
#903
#904 int notarget(Node p)
#905 {
#906 return p->syms[RX]->x.wildcard ? 0 : LBURG_MAX;
#907 }
#908
#909 //释放一个寄存器。
#910 static void putreg(Symbol r)
#911 {
#912 assert(r && r->x.regnode);
#913 freemask[r->x.regnode->set] |= r->x.regnode->mask;
#914 debug(dumpregs("(freeing %s)\n", r->x.name, NULL));
#915 }
#916
#917 //
#918 //请求分配一个固定的寄存器。
#919 //蔡军生 2007/07/17
#920 //
#921 static Symbol askfixedreg(Symbol s)
#922 {
#923 Regnode r = s->x.regnode;
#924 int n = r->set;
#925
#926 //判断请求这个寄存器是否有空,
#927 //如果没有空的寄存器就返回NULL。
#928 if (r->mask&~freemask[n])
#929 {
#930 return NULL;
#931 }
#932 else
#933 {
#934 //保存已经使用的寄存器。
#935 freemask[n] &= ~r->mask;
#936 usedmask[n] |= r->mask;
#937 return s;
#938 }
#939 }
#940
#941 //请求分配一个寄存器。
#942 static Symbol askreg(Symbol rs, unsigned rmask[])
#943 {
#944 int i;
#945
#946 if (rs->x.wildcard == NULL)
#947 {
#948 return askfixedreg(rs);
#949 }
#950
#951 for (i = 31; i >= 0; i
)
#952 {
#953 Symbol r = rs->x.wildcard[i];
#954 if (r != NULL &&
#955 !(r->x.regnode->mask&~rmask[r->x.regnode->set]) &&
#956 askfixedreg(r))
#957 {
#958 return r;
#959 }
#960 }
#961
#962 return NULL;
#963 }
#964
#965 //获取一个寄存器。
#966 static Symbol getreg(Symbol s, unsigned mask[], Node p)
#967 {
#968 //尝试请求一个寄存器。
#969 Symbol r = askreg(s, mask);
#970 if (r == NULL)
#971 {
#972 //请求寄存器不成功,接着把寄存器空出来。
#973 //下面先找到最近不使用的寄存器r.
#974 r = spillee(s, mask, p);
#975 assert(r && r->x.regnode);
#976
#977 //溢出这个寄存器。
#978 spill(r->x.regnode->mask, r->x.regnode->set, p);
#979 r = askreg(s, mask);
#980 }
#981
#982 assert(r && r->x.regnode);
#983 r->x.regnode->vbl = NULL;
#984
#985 return r;
#986 }
#987
#988 //为一个局部变量或者参数分配一个寄存器.
#989 int askregvar(Symbol p, Symbol regs)
#990 {
#991 Symbol r;
#992
#993 assert(p);
#994 if (p->sclass != REGISTER)
#995 {
#996 //非寄存器类型,不分配寄存器.
#997 return 0;
#998 }
#999 else if (!isscalar(p->type))
#1000 {
#1001 //聚合类型不分配寄存器.
#1002 p->sclass = AUTO;
#1003 return 0;
#1004 }
#1005 else if (p->temporary)
#1006 {
#1007 //如果变量是一个临时变量,延时分配.
#1008 p->x.name = "?";
#1009 return 1;
#1010 }
#1011 else if ((r = askreg(regs, vmask)) != NULL)
#1012 {
#1013 p->x.regnode = r->x.regnode;
#1014 p->x.regnode->vbl = p;
#1015 p->x.name = r->x.name;
#1016 debug(dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name));
#1017 return 1;
#1018 }
#1019 else
#1020 {
#1021 //如果分配不成功,就强制地放到栈空间里.
#1022 p->sclass = AUTO;
#1023 return 0;
#1024 }
#1025 }
#1026
#1027 //把指令树线性化.
#1028 static void linearize(Node p, Node next)
#1029 {
#1030 int i;
#1031
#1032 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
#1033 {
#1034 linearize(p->x.kids[i], next);
#1035 }
#1036
#1037 relink(next->x.prev, p);
#1038 relink(p, next);
#1039
#1040 debug(fprint(stderr, "(listing %x)\n", p));
#1041 }
#1042
#1043 //为一条指令分配一个寄存器或者释放一个寄存器。
#1044 static void ralloc(Node p)
#1045 {
#1046 int i;
#1047 unsigned mask[2];
#1048
#1049 //获取所有可能使用的寄存器。
#1050 mask[0] = tmask[0];
#1051 mask[1] = tmask[1];
#1052
#1053 assert(p);
#1054 debug(fprint(stderr, "(rallocing %x)\n", p));
#1055
#1056 //释放最近不使用的寄存器。
#1057 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
#1058 {
#1059 Node kid = p->x.kids[i];
#1060 Symbol r = kid->syms[RX];
#1061 assert(r && kid->x.registered);
#1062 if (r->sclass != REGISTER && r->x.lastuse == kid)
#1063 {
#1064 putreg(r);
#1065 }
#1066 }
#1067
#1068 if (!p->x.registered && NeedsReg[opindex(p->op)] &&
#1069 (*IR->x.rmap)(opkind(p->op)))
#1070 {
#1071 Symbol sym = p->syms[RX], set = sym;
#1072 assert(sym);
#1073
#1074 if (sym->temporary)
#1075 set = (*IR->x.rmap)(opkind(p->op));
#1076
#1077 assert(set);
#1078 if (set->sclass != REGISTER)
#1079 {
#1080 Symbol r;
#1081 //是否需要两条指令完成的模板代码.
#1082 if (*IR->x._templates[getrule(p, p->x.inst)] == '?')
#1083 {
#1084 //如果是就需要从第一个寄存器开始.
#1085 for (i = 1; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
#1086 {
#1087 Symbol r = p->x.kids[i]->syms[RX];
#1088 assert(p->x.kids[i]->x.registered);
#1089 assert(r && r->x.regnode);
#1090 assert(sym->x.wildcard || sym != r);
#1091 mask[r->x.regnode->set] &= ~r->x.regnode->mask;
#1092 }
#1093 }
#1094
#1095 //获取一个寄存器。
#1096 r = getreg(set, mask, p);
#1097
#1098 //临时变量的处理。
#1099 if (sym->temporary)
#1100 {
#1101 Node q;
#1102 r->x.lastuse = sym->x.lastuse;
#1103 for (q = sym->x.lastuse; q; q = q->x.prevuse)
#1104 {
#1105 q->syms[RX] = r;
#1106 q->x.registered = 1;
#1107
#1108 if (sym->u.t.cse && q->x.copy)
#1109 {
#1110 q->x.equatable = 1;
#1111 }
#1112 }
#1113 }
#1114 else
#1115 {
#1116 p->syms[RX] = r;
#1117 r->x.lastuse = p;
#1118 }
#1119 debug(dumpregs("(allocating %s to node %x)\n", r->x.name, (char *) p));
#1120 }
#1121 }
#1122
#1123 //标记已经做过寄存器分配。
#1124 p->x.registered = 1;
#1125
#1126 //寄存器溢出后,重新加载内存单元数据到寄存器。
#1127 (*IR->x.clobber)(p);
#1128 }
#1129
#1130 //标记一个寄存器溢出。
#1131 static Symbol spillee(Symbol set, unsigned mask[], Node here)
#1132 {
#1133 Symbol bestreg = NULL;
#1134 int bestdist = -1, i;
#1135
#1136 assert(set);
#1137 if (!set->x.wildcard)
#1138 bestreg = set;
#1139 else
#1140 {
#1141 //寻找最近不使用的寄存器来溢出。
#1142 for (i = 31; i >= 0; i—)
#1143 {
#1144 Symbol ri = set->x.wildcard[i];
#1145 if (
#1146 ri != NULL &&
#1147 ri->x.lastuse &&
#1148 (ri->x.regnode->mask&tmask[ri->x.regnode->set]&mask[ri->x.regnode->set])
#1149 )
#1150 {
#1151 Regnode rn = ri->x.regnode;
#1152 Node q = here;
#1153 int dist = 0;
#1154
#1155 for (; q && !uses(q, rn); q = q->x.next)
#1156 dist++;
#1157
#1158 if (q && dist > bestdist)
#1159 {
#1160 bestdist = dist;
#1161 bestreg = ri;
#1162 }
#1163 }
#1164 }
#1165 }
#1166
#1167 assert(bestreg); /* Must be able to spill something. Reconfigure the register allocator
#1168 to ensure that we can allocate a register for all nodes without spilling
#1169 the node's necessary input regs. */
#1170 assert(bestreg->x.regnode->vbl == NULL); /* Can't spill register variables because
#1171 the reload site might be in other blocks. Reconfigure the register allocator
#1172 to ensure that this register is never allocated to a variable. */
#1173 return bestreg;
#1174 }
#1175
#1176 //判断节点p是否使用rn的寄存器.
#1177 static int uses(Node p, Regnode rn)
#1178 {
#1179 int i;
#1180
#1181 for (i = 0; i < NELEMS(p->x.kids); i++)
#1182 if (
#1183 p->x.kids[i] &&
#1184 p->x.kids[i]->x.registered &&
#1185 rn->set == p->x.kids[i]->syms[RX]->x.regnode->set &&
#1186 (rn->mask&p->x.kids[i]->syms[RX]->x.regnode->mask)
#1187 )
#1188 return 1;
#1189
#1190 return 0;
#1191 }
#1192
#1193 //溢出一个寄存器。
#1194 static void spillr(Symbol r, Node here)
#1195 {
#1196 int i;
#1197 Symbol tmp;
#1198 Node p = r->x.lastuse;
#1199 assert(p);
#1200
#1201 while (p->x.prevuse)
#1202 {
#1203 assert(r == p->syms[RX]),
#1204 p = p->x.prevuse;
#1205 }
#1206
#1207 assert(p->x.registered && !readsreg(p));
#1208
#1209 tmp = newtemp(AUTO, optype(p->op), opsize(p->op));
#1210
#1211 //生成溢出代码.
#1212 genspill(r, p, tmp);
#1213
#1214 for (p = here->x.next; p; p = p->x.next)
#1215 {
#1216 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
#1217 {
#1218 Node k = p->x.kids[i];
#1219 if (k->x.registered && k->syms[RX] == r)
#1220 {
#1221 //生成重新加载代码.
#1222 genreload(p, tmp, i);
#1223 }
#1224 }
#1225 }
#1226
#1227 //释放这个寄存器可以使用.
#1228 putreg(r);
#1229 }
#1230
#1231 //生成保存寄存器到储存器的代码.
#1232 static void genspill(Symbol r, Node last, Symbol tmp)
#1233 {
#1234 Node p, q;
#1235 Symbol s;
#1236 unsigned ty;
#1237
#1238 debug(fprint(stderr, "(spilling %s to local %s)\n", r->x.name, tmp->x.name));
#1239 debug(fprint(stderr, "(genspill: "));
#1240 debug(dumptree(last));
#1241 debug(fprint(stderr, ")\n"));
#1242
#1243 ty = opkind(last->op);
#1244 NEW0(s, FUNC);
#1245 s->sclass = REGISTER;
#1246 s->name = s->x.name = r->x.name;
#1247 s->x.regnode = r->x.regnode;
#1248 q = newnode(ADDRL+P + sizeop(IR->ptrmetric.size), NULL, NULL, s);
#1249 q = newnode(INDIR + ty, q, NULL, NULL);
#1250 p = newnode(ADDRL+P + sizeop(IR->ptrmetric.size), NULL, NULL, tmp);
#1251 p = newnode(ASGN + ty, p, q, NULL);
#1252
#1253 //寄存器溢出标志
#1254 p->x.spills = 1;
#1255
#1256 rewrite(p);
#1257 prune(p, &q);
#1258 q = last->x.next;
#1259 linearize(p, q);
#1260 for (p = last->x.next; p != q; p = p->x.next)
#1261 {
#1262 ralloc(p);
#1263 assert(!p->x.listed || !NeedsReg[opindex(p->op)] || !(*IR->x.rmap)(opkind(p->op)));
#1264 }
#1265 }
#1266
#1267 //产生代码重新加载被溢出的寄存器值。
#1268 static void genreload(Node p, Symbol tmp, int i)
#1269 {
#1270 Node q;
#1271 int ty;
#1272
#1273 debug(fprint(stderr, "(replacing %x with a reload from %s)\n", p->x.kids[i], tmp->x.name));
#1274 debug(fprint(stderr, "(genreload: "));
#1275 debug(dumptree(p->x.kids[i]));
#1276 debug(fprint(stderr, ")\n"));
#1277
#1278 ty = opkind(p->x.kids[i]->op);
#1279 q = newnode(ADDRL+P + sizeop(IR->ptrmetric.size), NULL, NULL, tmp);
#1280 p->x.kids[i] = newnode(INDIR + ty, q, NULL, NULL);
#1281
#1282 rewrite(p->x.kids[i]);
#1283
#1284 prune(p->x.kids[i], &q);
#1285
#1286 reprune(&p->kids[1], reprune(&p->kids[0], 0, i, p), i, p);
#1287
#1288 prune(p, &q);
#1289
#1290 linearize(p->x.kids[i], p);
#1291 }
#1292
#1293 //寄存器溢出后,重新调整x.kids的节点关系.
#1294 static int reprune(Node *pp, int k, int n, Node p)
#1295 {
#1296 struct node x, *q = *pp;
#1297
#1298 if (q == NULL || k > n)
#1299 {
#1300 return k;
#1301 }
#1302 else if (q->x.inst == 0)
#1303 {
#1304 return reprune(&q->kids[1], reprune(&q->kids[0], k, n, p), n, p);
#1305 }
#1306
#1307 if (k == n)
#1308 {
#1309 debug(fprint(stderr, "(reprune changes %x from %x to %x)\n", pp, *pp, p->x.kids[n]));
#1310 *pp = p->x.kids[n];
#1311 x = *p;
#1312
#1313 (IR->x.target)(&x);
#1314 }
#1315
#1316 return k + 1;
#1317 }
#1318
#1319 //溢出一个寄存器。
#1320 void spill(unsigned mask, int n, Node here)
#1321 {
#1322 int i;
#1323 Node p;
#1324
#1325 //设置这个寄存器被溢出。
#1326 here->x.spills = 1;
#1327 usedmask[n] |= mask;
#1328
#1329 if (mask&~freemask[n])
#1330 {
#1331
#1332 assert( /* It makes no sense for a node to clobber() its target. */
#1333 here->x.registered == 0 || /* call isn't coming through clobber() */
#1334 here->syms[RX] == NULL ||
#1335 here->syms[RX]->x.regnode == NULL ||
#1336 here->syms[RX]->x.regnode->set != n ||
#1337 (here->syms[RX]->x.regnode->mask&mask) == 0
#1338 );
#1339
#1340 for (p = here; p; p = p->x.next)
#1341 {
#1342 for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
#1343 {
#1344 Symbol r = p->x.kids[i]->syms[RX];
#1345 assert(r);
#1346 if (p->x.kids[i]->x.registered &&
#1347 r->x.regnode->set == n &&
#1348 r->x.regnode->mask&mask)
#1349 {
#1350 spillr(r, here);
#1351 }
#1352 }
#1353 }
#1354 }

#1355 }
#1356
#1357 //输出空闲的寄存器.
#1358 static void dumpregs(char *msg, char *a, char *b)
#1359 {
#1360 fprint(stderr, msg, a, b);
#1361 fprint(stderr, "(free[0]=%x)\n", freemask[0]);
#1362 fprint(stderr, "(free[1]=%x)\n", freemask[1]);
#1363 }
#1364
#1365 //获取节点的寄存器号.
#1366 int getregnum(Node p)
#1367 {
#1368 assert(p && p->syms[RX] && p->syms[RX]->x.regnode);
#1369 return p->syms[RX]->x.regnode->number;
#1370 }
#1371
#1372
#1373 unsigned regloc(Symbol p)
#1374 {
#1375 assert(p && p->sclass == REGISTER && p->sclass == REGISTER && p->x.regnode);
#1376 return p->x.regnode->set«8 | p->x.regnode->number;
#1377 }
#1378
#1379

这里是公用的生成代码,其实还有不同目标的指令模块,这里没有列出来。

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