下面详细地注释了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
这里是公用的生成代码,其实还有不同目标的指令模块,这里没有列出来。