LCC编译器的源程序分析(44)函数名称的代码生成

当把所有的源程序生成DAG表示后,就进入了编译器的最后处理阶段,LCC是把DAG生成汇编的目标代码。在这一阶段,编译器为源程序定义和使用的变量选择存储单元,并把中间指令翻译成完成相同任务的汇编代码指令序列。在代码生成里,需要处理的问题是存储管理、指令选择、寄存器分配、计算次序等等。
在第一节里就已经看到了汇编代码生成,函数的名称生成如下:
#001 [global $main]
那么在LCC是怎么样生成上面的函数名称呢?现在就跟我来分析它的代码。
先从函数里funcdefn里调用代码:
#203 if (cfunc->sclass != STATIC)
#204 (*IR->export)(cfunc);
#205
#206 if (glevel && IR->stabsym)
#207 {
#208 swtoseg(CODE); (*IR->stabsym)(cfunc);
#209 }
#210
#211 swtoseg(CODE);
#212
#213 (*IR->function)(cfunc, caller, callee, cfunc->u.f.ncalls);
#214
#215 if (glevel && IR->stabfend)
#216 (*IR->stabfend)(cfunc, lineno);
#217
#218 foreach(stmtlabs, LABELS, checklab, NULL);
#219
#220 exitscope();
#221
#222 expect('}');
#223 labels = stmtlabs = NULL;
#224 retv = NULL;
#225 cfunc = NULL;
第203行就是判断函数是否静态函数,如果不是静态函数,就会调用后端的接口来生成函数的名称。
第204行的调用接口的代码如下:
#001 static void export(Symbol p)
#002 {
#003
#004 #if 0
#005 print("public %s\n", p->x.name);
#006 #else
#007 print("[global %s]\n", p->x.name);
#008 #endif
#009
#010 }
由于IR->export是一个函数指针,只要设置不同的函数指针,就可以生成不同的函数名称。这就是LCC可以生成不同机器代码的原因。
第7行里是生成函数的名称main,它是调用print函数输出到文件里。p->x.name是符号表里的函数名称。很简单吧,就这样可以生成不同的函数名称了。

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