自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(29)
  • 收藏
  • 关注

LCC编译器的源程序分析(47)计算需要使用栈大小

计算栈的大小,是通过后端接口的代码来完成计算的。栈的大小,主要就是局部变量、临时变量、调用参数和返回值等使用的字节大小,如果变量可以放到寄存器,就不需加到栈的大小里。上面已经看了下面的代码: #044 case Blockbeg: #045 { #046 Symbol *p = cp->u.block.locals; #047 (*IR->blockbeg)(&cp...

2007-06-28 22:55:00 111

LCC编译器的源程序分析(46)计算需要使用栈大小

从目标代码里,可以看到下面一行: #009sub esp, 16 在这行里是保留栈的大小,值为16。但16个字节是怎么样计算出来的呢?下面就来分析LCC的代码,看它是怎么样计算的。它是在函数gencode里进行计算的,它的代码如下: #001void gencode(Symbol caller[], Symbol callee[]) #002{ #003 Code cp; #00...

2007-06-27 21:56:00 84

LCC编译器的源程序分析(45)函数代码入口和出口的代码生成

由于C语言可以动态地分配局部变量,因此它的运行环境都是基于栈式的分配来实现的,所以在函数的入口就会生成一段分配栈的代码,如下: #002[section .text] #003$main: #004push ebx #005push esi #006push edi #007 push ebp #008mov ebp, esp #009sub esp, 16 第2行是NAS...

2007-06-23 21:17:00 93

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

当把所有的源程序生成DAG表示后,就进入了编译器的最后处理阶段,LCC是把DAG生成汇编的目标代码。在这一阶段,编译器为源程序定义和使用的变量选择存储单元,并把中间指令翻译成完成相同任务的汇编代码指令序列。在代码生成里,需要处理的问题是存储管理、指令选择、寄存器分配、计算次序等等。 在第一节里就已经看到了汇编代码生成,函数的名称生成如下: #001[global $main] 那么在L...

2007-06-22 21:42:00 85

LCC编译器的源程序分析(43)赋值表达式的有向无环图

由于INDIR树与ADDRL树的类型相同,所以已经转换为ADDRL树,直接对ADDRL树进行进访问了,下面就是在函数listnodes里处理赋值表达式的ADDRL树,它的代码如下: #412case ADDRL: #413 { #414 assert(tlab == 0 && flab == 0); #415 if (tp->u.sym->generat...

2007-06-21 23:08:00 79

LCC编译器的源程序分析(42)赋值表达式的有向无环图

上一次说到赋值表达式转换为有向无环图的函数listnodes,下面继续来分析这个函数代码。 当赋值树处理时,就运行下面的分支来处理: #256case ASGN: #257 { #258 assert(tlab == 0 && flab == 0); #259 if (tp->kids[0]->op == FIELD) #260 { #261 Tr...

2007-06-20 23:13:00 83

LCC编译器的源程序分析(41)赋值表达式的有向无环图

前面已经介绍怎么样把赋值表达式变换到树的中间表示,接着下来编译器要做的事情就是怎么样把树变换成有向无环图。也许你会问为什么要把树变换成有向无环图,而不是直接生成最终代码呢?其实,学习过数据结构就很清楚有向无环图的应用,编译器里就是利用有向无环图的特性来进行局部代码优化的,最主要的优化就是删除公共表达式。下面就来分析LCC从树到有向无环图的实现代码。 上面函数dcllocal里调用转换函数如...

2007-06-19 23:55:00 83

LCC编译器的源程序分析(40)赋值表达式树

前面分析了表达式的语法,也分析了语句的语法,但它们最终的目的就是生成合适的中间表示,在LCC里是采用树作为中间表示的。 现在就来分析语句生成什么样的树表示,下面的语句是来自例子里,如下: int nTest1 = 1; 这个语句是声明了一个局部变量nTest1,并且给nTest1赋值为1。LCC编译器要把它变换到分析树的表示,这样才利于后面的分析和使用。它的分析树如下: 左子树...

2007-06-18 22:26:00 75

在VC2005里使用STLPORT

听说STLPORT的性能不错,心动不如行动,立即就上网下载STLPORT下来使用,先到下面的网址下载源程序: http://nchc.dl.sourceforge.net/sourceforge/stlport/STLport-5.1.3.zip 这个压缩包不是很大,才1.6M,很轻松地就下载完成了。 接着下来就是解压,比如我解压到目录: E:/software/LIB/STLport...

2007-06-18 13:56:00 62

LCC编译器的源程序分析(39)goto语句

在现代设计的程序里,很少再用到goto语句了。虽然使用goto语句是比较高效,但它使程序也会得非常难懂,非常难维护,比较容易出错,所以很少使用goto语句的。goto语句为无条件跳转语句,它的一般形式为: goto 标号; 在LCC里的是用下面的代码来处理: #001case GOTO: #002 walk(NULL, 0, 0); #003 definept(NULL);...

2007-06-17 11:23:00 65

LCC编译器的源程序分析(38)return语句

在实现中,程序其实就是处理数据,然后输出处理过的结果,在C语句里最直接的方式就是函数的返回值。比如求两个数据的最大值,就可以通过函数返回值来返回最大值。而函数的返回值是通过函数中的return语句获得的。return语句后面是一个表达式,需要调用表达式函数来处理。 下面来分析LCC里的代码: #001case RETURN: #002 { #003 Type rty = fretu...

2007-06-16 20:07:00 103

LCC编译器的源程序分析(37)default语句

default语句是使用在switch语句的复合语句里,它是所有其它分支不能处理时的分支处理。在LCC里是如下处理的: #001case DEFAULT: #002 if (swp == NULL) #003 error("illegal default label/n"); #004 else if (swp->deflab) #005 error("extra defa...

2007-06-15 21:28:00 55

LCC编译器的源程序分析(36)case语句

case语句是使用在switch语句之中,它实现了选择一个分支执行。当表达式的值与case后面的常量表达式的值相等时,就执行此case语句后面的语句。LCC处理这个语句的代码如下: #001case CASE: #002 { #003 int lab = genlabel(1); #004 if (swp == NULL) #005 error("illegal case lab...

2007-06-14 21:35:00 98

LCC编译器的源程序分析(35)switch语句

switch语句是多分支选择语句,主要方便多个选择的情况使用,当然也可以使用if语句来实现,但嵌套的if语句过多会使用程序的可读性降低。 switch(表达式) { case 常量表达式1: 语句1; case 常量表达式2: 语句2; … case 常量表达式n: 语句n; default: 语句n+1 } 上面就是swit...

2007-06-13 19:04:00 82

LCC编译器的源程序分析(34)continue语句

continue语句的作用是跳过循环体中后面尚未执行的语句,接着进行下一次是否执行循环的判断。比如下面的例子: while(表达式1) { … if(表达式2) continue; … } 下面就来仔细地分析LCC里处理continue语句的源程序: #001case CONTINUE: #002 walk(NULL, 0, 0); #003 defi...

2007-06-12 21:20:00 70

LCC编译器的源程序分析(33)break语句

break语句可以使用流程跳出switch语句的分支选择,当然它还可以用来从循环体内跳出循环体,即提前结束循环,接着执行循环下面的语句。但它不能用于循环语句和switch语句之外的其它语句中。 比如下面的例子: for(;;) { if( a++ > 100) break; } 现在就来分析一下面处理break的代码: #001case BREAK: #00...

2007-06-11 21:55:00 74

LCC编译器的源程序分析(32)for循环语句

C语言中的for语句使用最为灵活,不仅可以用于循环次数已经确定的情况,而且可以用于循环次数不确定而只给出循环结束条件的情况。因此,这个语句的使用频率是最高的,当然它的处理情况比上面两种循环要复杂一些。它的形式如下: for(表达式1;表达式2;表达式3) 语句1 它的执行过程是先求解表达式1的值,然后再计算表达式2的值。如果其值为真,就执行语句1,然后再执行表达式3。如果其值...

2007-06-10 14:12:00 98

LCC编译器的源程序分析(31)do while循环语句

do—while语句是实现“直到型”循环结构。一般形式如下: do { 语句1 }while(表达式) 上面的语句是这样的执行的,先执行一次语句1,然后判断表达式的值,如果表达式的值为真,也就是非零时,返回重新执行语句1,如此反复,直到表达式的值等于0为止。这个表达式与前面一个while语句的区别,就是表达式值的判断和语句1执行先后的问题。前面while语句先判断后执...

2007-06-09 23:43:00 72

LCC编译器的源程序分析(30)while循环语句

while语句的语义是这样定义的: while(表达式) 语句1 当表达式为非0值时执行while语句中的内嵌语句1。其特点就是先判断表达式的值,然后再执行语句。LCC是通过下面的代码来处理这个语句的: #015case WHILE: #016 whilestmt(genlabel(3), swp, lev + 1); #017 break; 上面第16行语句里,第一...

2007-06-08 22:08:00 78

LCC编译器的源程序分析(29)if条件语句

if语句是用来判定所给定的条件是否满足,根据判定的结果决定执行给出来的两种操作之一。if语句有下面三种形式: 1. if(表达式)语句 2. if(表达式)语句1 else 语句2 3. if(表达式1)语句1 else if(表达式2)语句2 else if(表达式3)语句3 else 语句4 那么LCC又是怎么样处理if语句的呢?LCC在函数sta...

2007-06-07 21:39:00 94

LCC编译器的源程序分析(28)函数表达式语句

前面已经介绍了很多表达式,但还没有介绍函数表达式语句,那么在LCC里是怎么样处理函数调用,也就是函数表达式的呢?现在就来分析函数表达式的代码,函数调用是使用非常多的,因此分析这里的代码,需要非常仔细地查看。 从hello.i例子里,就可看到下面的函数表达式语句: printf("nTest3 = %d/r/n",nTest3); 它是由ID名称printf、表达式("nTest3 = %d...

2007-06-06 21:45:00 95

LCC编译器的源程序分析(27)基本语句

由前面的例子可以知道,C函数里包含数据定义部分和执行部分,执行部分就是由语句组成。计算机最基本的动作就是具备条件判断,这也是计算机具有这么大魔力的原因。而这些条件判断是通过语句来实现的。基本的语句有下面几种: 1. 控制语句: ifelse for while do while continue break switch goto return 2. 函数调用...

2007-06-05 21:25:00 149

LCC编译器的源程序分析(26)逗号表达式

逗号表达式是优先级最低的表达式。像下面的例子: 1+2,2+3; a = (a,b,c); 还有在for语句中的使用: for(int a=3,b=4; a < 10; a++,b++) { } 要处理上面这些逗号表达式,在LCC里就需调用表达式处理函数expr,它的代码如下: #001Tree expr(int tok) #002{ #003static ch...

2007-06-04 21:18:00 100

LCC编译器的源程序分析(25)赋值表达式

C语言是非常强大的,可以连续赋值的操作。将赋值表达式作为表达式的一种,使赋值操作不仅可以出现在赋值语句中,而且可以以表达式的形式出现在其它语句中,这是C语言灵活性的一种表现。 变量 赋值运算符 表达式 上面就是赋值表达式的组成,如下面的例子: x = y = 2+8; 这样的赋值表达式在LCC里是通过函数expr1来实现的。 #001Tree expr1(int tok) #00...

2007-06-03 18:11:00 76

LCC编译器的源程序分析(24)条件表达式

C语言里条件表达式语句如下: 表达式1 ?表达式2 :表达式3 条件运算符要求有三个操作对象,称为三元运算符,它是C语言中唯一的一个三目运算符。比如计算两个值的最大值,就可以写成下面这样: int nMax = a > b ? a:b; 下面就来看LCC是怎么样处理条件表达式的,它的代码如下: #001static Tree expr2(void) #002{ #003 ...

2007-06-03 18:10:00 65

LCC编译器的源程序分析(23)一元运算表达式

前面分析了基本表达式,主要由常量和变量ID组成。接着下来,就需要分析优先级比较高的一元运算表达式了,主要由第1级和第2级运算符组成的运算,一般只需要一个操作数就可以运算的表达式。 在LCC里处理一元运算表达式的代码如下: #001static Tree unary(void) #002{ #003Tree p; #004 #005switch (t) #006{ #00...

2007-06-03 18:09:00 98

LCC编译器的源程序分析(22)基本表达式

表达式是C编译器里最重要的一部份,由于表达式的使用是无所不在,任何的计算都需要使用到表达式运算。这次就带你去分析一下LCC编译器处理表达式的代码。 比如在例子里: int nTest1 = 1; int nTest2 = 2; 赋值语句的右边是一个表达式,这个表达式可以简单的也可以复杂的。像下面语句的右边也是表达式: nTest3 = nTest1 + nTest2; 还有很多地方都...

2007-06-02 20:57:00 79

LCC编译器的源程序分析(21)局部变量的声明

局部变量的处理是比较特别,它是复杂语句里面声明,作用域也只限于复合语句里。如下面的例子: { int a = 2; } 上面的a就是局部变量的声明。 现在再来仔细地分析compound里处理局部变量的代码。如下: #031//局部变量声明处理. #032while (kind[t] == CHAR || kind[t] == STATIC #033 || istypen...

2007-06-02 20:55:00 102

LCC编译器的源程序分析(20)复合语句

在C语言里,有一种语句叫做复合语句。它是由{ }把一些语句括起来的,如下面的例子: { y = x + 1; z = y + 2; } 在LCC里处理这样的复合语句的函数是compound,它在上面函数定义函数funcdefn是这样调用的: #150labels = table(NULL, LABELS); #151stmtlabs = table(NULL, LABELS)...

2007-06-01 00:11:00 109

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除