摘要:
当把所有的源程序生成DAG表示后,就进入了编译器的最后处理阶段,LCC是把DAG生成汇编的目标代码。在这一阶段,编译器为源程序定义和使用的变量选择存储单元,并把中间指令翻译成完成相同任务的汇编代码指令序列。在代码生成里,需要处理的问题是存储管理、指令选择、寄存器分配、计算次序等等。在第一节里就已经看到了汇编代码生成,函数的名称生成如下:#001[global $main]那么在LCC是怎么样生成上面的函数名称呢?现在就跟我来分析它的代码。先从函数里funcdefn里调用代码:#203if (cfunc->sclass != STATIC)#204 (*IR->export)(cfu 阅读全文
posted @ 2007-06-22 21:42
ajuanabc
阅读(204)
评论(0)
推荐(0)
摘要:
由于INDIR树与ADDRL树的类型相同,所以已经转换为ADDRL树,直接对ADDRL树进行进访问了,下面就是在函数listnodes里处理赋值表达式的ADDRL树,它的代码如下:#412case ADDRL: #413 { #414 assert(tlab == 0 && flab == 0);#415 if (tp->u.sym->generated)#416 addlocal(tp->u.sym);#417#418 p = node(tp->op + sizeop(voidptype->size), NULL, NULL, tp->u. 阅读全文
posted @ 2007-06-21 23:08
ajuanabc
阅读(194)
评论(0)
推荐(0)
摘要:
上一次说到赋值表达式转换为有向无环图的函数listnodes,下面继续来分析这个函数代码。当赋值树处理时,就运行下面的分支来处理:#256case ASGN:#257 { #258 assert(tlab == 0 && flab == 0);#259 if (tp->kids[0]->op == FIELD) #260 {#261 Treex = tp->kids[0]->kids[0];#262 Field f = tp->kids[0]->u.field;#263 assert(generic(x->op) == INDIR);# 阅读全文
posted @ 2007-06-20 23:13
ajuanabc
阅读(209)
评论(0)
推荐(0)
摘要:
前面已经介绍怎么样把赋值表达式变换到树的中间表示,接着下来编译器要做的事情就是怎么样把树变换成有向无环图。也许你会问为什么要把树变换成有向无环图,而不是直接生成最终代码呢?其实,学习过数据结构就很清楚有向无环图的应用,编译器里就是利用有向无环图的特性来进行局部代码优化的,最主要的优化就是删除公共表达式。下面就来分析LCC从树到有向无环图的实现代码。上面函数dcllocal里调用转换函数如下:walk(root(asgn(p, e)), 0, 0);从root函数里返回一棵赋值树,然后就把它传递给函数walk,在walk函数里就会调用一系列函数实现到DAG的转换。函数walk的代码如下:#001 阅读全文
posted @ 2007-06-19 23:55
ajuanabc
阅读(255)
评论(0)
推荐(0)
摘要:
前面分析了表达式的语法,也分析了语句的语法,但它们最终的目的就是生成合适的中间表示,在LCC里是采用树作为中间表示的。现在就来分析语句生成什么样的树表示,下面的语句是来自例子里,如下:int nTest1 = 1;这个语句是声明了一个局部变量nTest1,并且给nTest1赋值为1。LCC编译器要把它变换到分析树的表示,这样才利于后面的分析和使用。它的分析树如下: 左子树=右子树 赋值树:左子树-----ID树右子树-----常量表达式树由语法分析可知,赋值语句分析过程是先生成常量表达式树,然后生成ID树,最后生成赋值树,把它变换到DAG树,然后添加到代码表。在函数dcllocal里调用下面的 阅读全文
posted @ 2007-06-18 22:26
ajuanabc
阅读(211)
评论(0)
推荐(0)
摘要:
听说STLPORT的性能不错,心动不如行动,立即就上网下载STLPORT下来使用,先到下面的网址下载源程序:http://nchc.dl.sourceforge.net/sourceforge/stlport/STLport-5.1.3.zip这个压缩包不是很大,才1.6M,很轻松地就下载完成了。接着下来就是解压,比如我解压到目录:E:/software/LIB/STLport-5.1.3由于STLPORT包括IO库和容器库文件,如果只是想使用容器库文件,就不需要编译。如果IO库也想使用的话,就需要编译它才能使用。其实我很少使用它的IO库,就不必要编译了,只要把STLPORT目录包含到工程里, 阅读全文
posted @ 2007-06-18 13:56
ajuanabc
阅读(150)
评论(0)
推荐(0)
摘要:
在现代设计的程序里,很少再用到goto语句了。虽然使用goto语句是比较高效,但它使程序也会得非常难懂,非常难维护,比较容易出错,所以很少使用goto语句的。goto语句为无条件跳转语句,它的一般形式为:goto 标号;在LCC里的是用下面的代码来处理:#001case GOTO: #002 walk(NULL, 0, 0);#003 definept(NULL);#004 t = gettok();#005 if (t == ID) #006 {#007 Symbol p = lookup(token, stmtlabs);#008#009 if (p == NULL) #010 {#011 阅读全文
posted @ 2007-06-17 11:23
ajuanabc
阅读(211)
评论(0)
推荐(0)
摘要:
在实现中,程序其实就是处理数据,然后输出处理过的结果,在C语句里最直接的方式就是函数的返回值。比如求两个数据的最大值,就可以通过函数返回值来返回最大值。而函数的返回值是通过函数中的return语句获得的。return语句后面是一个表达式,需要调用表达式函数来处理。下面来分析LCC里的代码:#001case RETURN:#002 {#003 Type rty = freturn(cfunc->type);#004 t = gettok();#005 definept(NULL);第3行取得函数返回值的类型。第4行获取下一个记号。第5行定义了执行点。#006 if (t != '; 阅读全文
posted @ 2007-06-16 20:07
ajuanabc
阅读(250)
评论(0)
推荐(0)
摘要:
default语句是使用在switch语句的复合语句里,它是所有其它分支不能处理时的分支处理。在LCC里是如下处理的:#001case DEFAULT:#002 if (swp == NULL)#003 error("illegal default label/n");#004 else if (swp->deflab)#005 error("extra default label/n");#006 else #007 {#008 swp->deflab = findlabel(swp->lab);#009 definelab(swp- 阅读全文
posted @ 2007-06-15 21:28
ajuanabc
阅读(185)
评论(0)
推荐(0)
摘要:
case语句是使用在switch语句之中,它实现了选择一个分支执行。当表达式的值与case后面的常量表达式的值相等时,就执行此case语句后面的语句。LCC处理这个语句的代码如下:#001case CASE: #002 {#003 int lab = genlabel(1);#004 if (swp == NULL)#005 error("illegal case label/n");#006#007 definelab(lab);第3行生成标号1起始值。第4行是判断是否在switch语句中,如果不在就在第5行里提示出错。第7行是生成标号1。下面开始循环处理所有case语句 阅读全文
posted @ 2007-06-14 21:35
ajuanabc
阅读(172)
评论(0)
推荐(0)