`
yuanjinxiu
  • 浏览: 658312 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多
上次已经说明了怎么样选择合适的指令,现在就来介绍生成最终的代码,如下:
#010mov 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),然后通过树的两子节点来选择addrrc的生成。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,代码如下:
#001unsigned emitasm(Node p, int nt) {
#002int rulenum;
#003short *nts;
#004char *fmt;
#005Node kids[10];
#006
#007p = reuse(p, nt);
#008rulenum = getrule(p, nt);
#009nts = IR->x._nts[rulenum];
#010fmt = IR->x._templates[rulenum];
#011assert(fmt);
#012if (IR->x._isinstruction[rulenum] && p->x.emitted)
#013 print("%s", p->syms[RX]->x.name);
#014else if (*fmt == '#')
#015 (*IR->x.emit2)(p);
#016else {
#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}
#036return 0;
#037}
7行处理可重用的节点。
8行就是从模式匹配里的两个值来找到相应的语句编号rulenum
9行和第10行获取语句的模板。
24行到第35行就是按照mov dword %0, %1来格式化输出代码到文件里。
这样就完成了代码的生成工作。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics