[转载]LCC编译器的源程序分析(55)最终代码的生成

上次已经说明了怎么样选择合适的指令,现在就来介绍生成最终的代码,如下:
#010 mov dword [ebp + -12], 1
其实生成上面的代码是通过后面的语句来构造出来的,它的过程如下:
ASGNI4(ADDRLP4(nTest1), CNSTI4(1))
stmt: ASGNI4(addr,rc) / mov dword %0, %1
addr: base / [%0]
base: ADDRLP4 / ebp + %a
rc: con / %0
con: CNSTI4 / %a
在中间表示里,通过指令模式匹配到语句( stmt: ASGNI4(addr,rc) / mov dword %0, %1 ),然后通过树的两子节点来选择 addr rc 的生成。 addr 又通过模式匹配选择到 addr: base / [%0] ,接着再进一下就选择 base: ADDRLP4 / ebp + %a ,这样就可以生成 [ebp + -12] 代码了。右节点选择 rc: con / %0 ,接着选择 con: CNSTI4 / %a ,这样就可以生成下面的代码:
mov dword [ebp + %a], %a
最后通过格式化把这个变量分配的栈位置 -12 输出,再把常量的值 1 输出,就生成最终的代码:
mov dword [ebp + -12], 1
这样就完成了语句( int nTest1 = 1; )编译过程。
 
在函数 emitcode 里调用函数 emitasm ,代码如下:
#001 unsigned emitasm(Node p, int nt) {
#002  int rulenum;
#003  short *nts;
#004  char *fmt;
#005  Node kids[10];
#006 
#007  p = reuse(p, nt);
#008  rulenum = getrule(p, nt);
#009  nts = IR->x._nts[rulenum];
#010  fmt = IR->x._templates[rulenum];
#011  assert(fmt);
#012  if (IR->x._isinstruction[rulenum] && p->x.emitted)
#013         print("%s", p->syms[RX]->x.name);
#014  else if (*fmt == '#')
#015         (*IR->x.emit2)(p);
#016  else {
#017         if (*fmt == '?') {
#018               fmt++;
#019               assert(p->kids[0]);
#020               if (p->syms[RX] == p->x.kids[0]->syms[RX])
#021                    while (*fmt++ != '/n')
#022                          ;
#023         }
#024         for ((*IR->x._kids)(p, rulenum, kids); *fmt; fmt++)
#025               if (*fmt != '%')
#026                    (void)putchar(*fmt);
#027               else if (*++fmt == 'F')
#028                    print("%d", framesize);
#029               else if (*fmt >= '0' && *fmt <= '9')
#030                    emitasm(kids[*fmt - '0'], nts[*fmt - '0']);
#031               else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms))
#032                    fputs(p->syms[*fmt - 'a']->x.name, stdout);
#033               else
#034                    (void)putchar(*fmt);
#035  }
#036  return 0;
#037 }
7 行处理可重用的节点。
8 行就是从模式匹配里的两个值来找到相应的语句编号 rulenum
9 行和第 10 行获取语句的模板。
24 行到第 35 行就是按照 mov dword %0, %1 来格式化输出代码到文件里。
 
这样就完成了代码的生成工作。
 
 

你可能感兴趣的:([转载]LCC编译器的源程序分析(55)最终代码的生成)