E-COM-NET
首页
在线工具
Layui镜像站
SUI文档
联系我们
推荐频道
Java
PHP
C++
C
C#
Python
Ruby
go语言
Scala
Servlet
Vue
MySQL
NoSQL
Redis
CSS
Oracle
SQL Server
DB2
HBase
Http
HTML5
Spring
Ajax
Jquery
JavaScript
Json
XML
NodeJs
mybatis
Hibernate
算法
设计模式
shell
数据结构
大数据
JS
消息中间件
正则表达式
Tomcat
SQL
Nginx
Shiro
Maven
Linux
lcc
LCC
编译器的源程序分析(62)生成常量树节点的流程
在
LCC
里分析下面的语句 : #005 int nTest1 = 1; 就需要把 1 生成一个常量树节点,那么在
LCC
里用怎么样的流程来创建这个树节点的呢?
·
2015-11-13 19:37
编译器
LCC
编译器的源程序分析(63)创建DAG森林的源程序
#001 // #002 void walk(Tree tp, int tlab, int flab) #003 { #004 // 创建 DAG 森林 . #005 listnodes(tp, tlab, flab); #006 #007 // 如果 DAG 森林
·
2015-11-13 19:36
编译器
LCC
编译器的源程序分析(64)符号表的结构注释
符号表是用来保存每个符号信息的,因为编译器分析源程序的过程会生成很多符号的属性,后端根据这些属性来生成合适的指令和代码的格式。 #001 // 符号表结构 . #002 // #003 // 蔡军生 2007/08/10 QQ:9073204 #004 // #005 struct symbol
·
2015-11-13 19:36
编译器
LCC
编译器的源程序分析(65)后端接口的结构注释
因为
LCC
后端可以生成不同机器结构的代码,所以需要定义后端的接口结构,当不同的模块实现这些接口时,就可以实现不同的机器代码生成。下面就是这个接口的结构定义注释。
·
2015-11-13 19:35
编译器
LCC
编译器的源程序分析(66)DAG树分析例子
前面已经介绍创建分析树,下面就来详细地说明一个例子,看看到底生成什么样的分析树, C 源程序如下: #005 int nTest1 = 1; #006 int nTest2 = 2; #007 int nTest3; #008 int i; #009 #010&n
·
2015-11-13 19:34
编译器
LCC
编译器的源程序分析(67)删除内存链表
LCC
的内存分配是使用先分配大块内存,然后再从大块内存里分配出来小块内存,这样减少调用 malloc 的次数,当然也就减少调用函数 free 释放内存的次数,以便提高
LCC
的内存管理的性能。
·
2015-11-13 19:33
编译器
LCC
编译器的源程序分析(68)内存分配链表
LCC
采用大块内存的方法,那它分配内存也是比较特殊的,它的源程序如下: #001 //大块内存结构。
·
2015-11-13 19:30
内存分配
LCC
编译器的源程序分析(69)全局变量的初始化
前面已经介绍了全局函数和全局变量的声明处理,但全局变量的初始化,还没有详细地分析,现在就来干这件事情。比如编写 C 的程序,有如下的代码: #001 #002 int g_nTest = 100; #003 #004 int main(void) #005 { #006 int nTest1 = 1
·
2015-11-13 19:28
全局变量
LCC
编译器的源程序分析(69)全局变量的初始化
前面已经介绍了全局函数和全局变量的声明处理,但全局变量的初始化,还没有详细地分析,现在就来干这件事情。比如编写 C 的程序,有如下的代码: #001 #002 int g_nTest = 100; #003 #004 int main(void) #005 { #006 int nTest1 = 1
·
2015-11-13 17:55
全局变量
LCC
编译器的源程序分析(68)内存分配链表
LCC
采用大块内存的方法,那它分配内存也是比较特殊的,它的源程序如下: #001 //大块内存结构。
·
2015-11-13 16:38
内存分配
LCC
编译器的源程序分析(67)删除内存链表
LCC
的内存分配是使用先分配大块内存,然后再从大块内存里分配出来小块内存,这样减少调用 malloc 的次数,当然也就减少调用函数 free 释放内存的次数,以便提高
LCC
的内存管理的性能。
·
2015-11-13 16:36
编译器
LCC
编译器的源程序分析(66)DAG树分析例子
前面已经介绍创建分析树,下面就来详细地说明一个例子,看看到底生成什么样的分析树, C 源程序如下: #005 int nTest1 = 1; #006 int nTest2 = 2; #007 int nTest3; #008 int i; #009 #010&n
·
2015-11-13 16:33
编译器
LCC
编译器的源程序分析(65)后端接口的结构注释
因为
LCC
后端可以生成不同机器结构的代码,所以需要定义后端的接口结构,当不同的模块实现这些接口时,就可以实现不同的机器代码生成。下面就是这个接口的结构定义注释。
·
2015-11-13 16:32
编译器
LCC
编译器的源程序分析(64)符号表的结构注释
符号表是用来保存每个符号信息的,因为编译器分析源程序的过程会生成很多符号的属性,后端根据这些属性来生成合适的指令和代码的格式。 #001 // 符号表结构 . #002 // #003 // 蔡军生 2007/08/10 QQ:9073204 #004 // #005 struct symbol
·
2015-11-13 16:31
编译器
LCC
编译器的源程序分析(63)创建DAG森林的源程序
#001 // #002 void walk(Tree tp, int tlab, int flab) #003 { #004 // 创建 DAG 森林 . #005 listnodes(tp, tlab, flab); #006 #007 // 如果 DAG 森林
·
2015-11-13 16:30
编译器
LCC
编译器的源程序分析(62)生成常量树节点的流程
在
LCC
里分析下面的语句 : #005 int nTest1 = 1; 就需要把 1 生成一个常量树节点,那么在
LCC
里用怎么样的流程来创建这个树节点的呢?
·
2015-11-13 16:28
编译器
LCC
编译器的源程序分析(61)复合语句的代码块流程
LCC
编译器要分析下面的程序,大体流程是这样的。
·
2015-11-13 16:26
编译器
LCC
编译器的源程序分析(60)代码表的结构
在
LCC
里使用代码表来表示代码块,前端把所有代码属性放到代码表里,后端根据代码表来生成代码,它的结构如下: #001 //代码表结构定义.
·
2015-11-13 16:23
编译器
LCC
编译器的源程序分析(59)代码生成的源程序注释
下面详细地注释了gen.c的源程序,这样看起来就比较容易理解,希望对你有所帮助。 #001 #include "c.h" #002 #003 static char rcsid[] = "$Id: gen.c 355 2007-02-18 22:08:49Z drh $"; #004 #005&
·
2015-11-13 16:18
代码生成
LCC
编译器的源程序分析(58)后端使用的节点结构
在
LCC
编译器后端,主要使用下面的节点结构来标识代码属性。 #001 #002 //节点注释的扩展,主要是代码生成使用。
·
2015-11-13 16:16
编译器
LCC
编译器的源程序分析(57)不同目标代码生成的接口结构
LCC
为了生成不同机器的目标代码,它提供了一个接口给后端的代码生成,以便可以只修改后端,就可以达到生成不同的机器代码。
·
2015-11-13 16:13
代码生成
LCC
编译器的源程序分析(56)寄存器分配的属性结构
现在详细地分析寄存器分配的属性结构,它的定义如下: #001 typedef struct { #002 Symbol vbl; //保存变量符号,而不是临时变量. #003 short set; //寄存器类型,比如整数,或者浮点数。 #004 &nbs
·
2015-11-13 16:12
编译器
LCC
编译器的源程序分析(47)计算需要使用栈大小
计算栈的大小,是通过后端接口的代码来完成计算的。栈的大小,主要就是局部变量、临时变量、调用参数和返回值等使用的字节大小,如果变量可以放到寄存器,就不需加到栈的大小里。上面已经看了下面的代码: #044 case Blockbeg: #045 &nb
·
2015-11-13 16:55
编译器
LCC
编译器的源程序分析(45)函数代码入口和出口的代码生成
由于 C 语言可以动态地分配局部变量,因此它的运行环境都是基于栈式的分配来实现的,所以在函数的入口就会生成一段分配栈的代码,如下: #002 [section .text] #003 $main: #004 push ebx #005 push esi #006 push edi #007 push ebp
·
2015-11-13 16:54
代码生成
LCC
编译器的源程序分析(46)计算需要使用栈大小
下面就来分析
LCC
的代码,看它是怎么样计算的。
·
2015-11-13 16:54
编译器
LCC
编译器的源程序分析(44)函数名称的代码生成
当把所有的源程序生成 DAG 表示后,就进入了编译器的最后处理阶段,
LCC
是把 DAG 生成汇编的目标代码。
·
2015-11-13 16:53
代码生成
LCC
编译器的源程序分析(42)赋值表达式的有向无环图
上一次说到赋值表达式转换为有向无环图的函数 listnodes ,下面继续来分析这个函数代码。 当赋值树处理时,就运行下面的分支来处理: #256 case ASGN: #257 { #258 &nbs
·
2015-11-13 16:52
表达式
LCC
编译器的源程序分析(43)赋值表达式的有向无环图
由于 INDIR 树与 ADDRL 树的类型相同,所以已经转换为 ADDRL 树,直接对 ADDRL 树进行进访问了,下面就是在函数 listnodes 里处理赋值表达式的 ADDRL 树,它的代码如下: #412 case ADDRL: #413 { #414&n
·
2015-11-13 16:52
表达式
LCC
编译器的源程序分析(41)赋值表达式的有向无环图
下面就来分析
LCC
从树到有向无环图的实现代码。 上面函数 dcllocal 里调用转换函
·
2015-11-13 16:51
表达式
LCC
编译器的源程序分析(40)赋值表达式树
前面分析了表达式的语法,也分析了语句的语法,但它们最终的目的就是生成合适的中间表示,在
LCC
里是采用树作为中间表示的。
·
2015-11-13 16:49
表达式
LCC
编译器的源程序分析(39)goto语句
goto 语句为无条件跳转语句,它的一般形式为: goto 标号 ; 在
LCC
里的是用下面的代码来处理: #001 case GOTO: &
·
2015-11-13 16:49
编译器
LCC
编译器的源程序分析(38)return语句
下面来分析
LCC
里的代码: #001 case RETURN: #002
·
2015-11-13 16:48
return
LCC
编译器的源程序分析(37)default语句
在
LCC
里是如下处理的: #001 case DEFAULT: #002  
·
2015-11-13 16:47
编译器
LCC
编译器的源程序分析(36)case语句
LCC
处理这个语句的代码如下: #001 case CASE: #002
·
2015-11-13 16:46
case
LCC
编译器的源程序分析(35)switch语句
switch 语句是多分支选择语句,主要方便多个选择的情况使用,当然也可以使用 if 语句来实现,但嵌套的 if 语句过多会使用程序的可读性降低。 switch( 表达式 ) { case 常量表达式 1 : 语句 1; case 常量表达式 2 : &nbs
·
2015-11-13 16:45
switch
LCC
编译器的源程序分析(34)continue语句
continue 语句的作用是跳过循环体中后面尚未执行的语句,接着进行下一次是否执行循环的判断。比如下面的例子: while( 表达式 1) { … if( 表达式 2) continue;
·
2015-11-13 16:44
continue
LCC
编译器的源程序分析(19)全局函数的定义
函数定义 funcdefn 处理里,已经准备好调用参数和参数返回,接着就是调用全局函数声明来处理。如下面的代码: #132 // 声明函数。 #133 cfunc = dclglobal(sclass, id, ty, &pt); #134 上面的代码是处理函数全局定义。 现在就去就分析 dclglobal 函数的
·
2015-11-13 16:35
编译器
LCC
编译器的源程序分析(17)参数变量的声明
函数里的参数变量个数不固定,因此也需要检查这些参数的名称是否相同,还需要检查类型的合法性。现在就来分析上次提到的函数 dclparam ,它的代码如下: #001 // 参数类型声明处理 #002 static Symbol dclparam(int sclass, char *id, Type ty, Coordinate *pos) #003&
·
2015-11-13 16:34
编译器
LCC
编译器的源程序分析(18)函数定义
激动人心的时刻就要开始了,从这节开始,就进入处理实际的代码了。由于 C 语言是函数式的语言,也就是每个程序都是有一个一个的函数组成的,一个 C 源程序至少包含一个函数( main 函数),也可以包含一个 main 函数和若干个其它函数。因此,函数是 C 程序的基本单位。仔细地查看一下第一节里的例子代码,它是如下: #001 #include <stdio.h&g
·
2015-11-13 16:34
编译器
LCC
编译器的源程序分析(16)函数的声明
因此就需要了解什么是函数的声明,在
LCC
里又是怎么样处理函数的声明的。在 hello.i 文件里,有
·
2015-11-13 16:33
编译器
LCC
编译器的源程序分析(15)结构类型成员的声明
上次只介绍到开始分析结构类型的定义开始部分,接着就要去分析它的成员类型定义了。它调用函数来处理结构的成员,如下代码: #001 static void fields(Type ty) #002 { #003 { #004 int n = 0;
·
2015-11-13 16:32
编译器
LCC
编译器的源程序分析(14)结构类型的声明
以前都是简单类型的识别和语法分析,现在来分析结构的声明,它是比较复杂的一种数据类型,但结构在编写程序中使用是非常多的。由于程序的方程式就是: 数据结构 + 算法 = 程序 现在面向对象的方程式是: 数据结构 + 算法 = 对象 对象 + 对象 = 程序 由上面的公式,就可以看出程序中的数据结构是非常重要的,无论是面向对象的编程,还是面向过程的编程,有什么样的数据结构,就需要有什
·
2015-11-13 16:31
编译器
LCC
编译器的源程序分析(13)指针类型的声明
下面就来看例子里的指针语句,如下: typedef char * va_list; 上面这句声明了 va_list 为 char 的指针类型的别名,那么在
LCC
里又是
·
2015-11-13 16:30
编译器
LCC
编译器的源程序分析(12)自定义类型的声明
语法分析是比较复杂的处理,下面再来分析一个例子,它的代码如下: typedef unsigned short wchar_t; typedef wchar_t wint_t; 第一句语句在
LCC
·
2015-11-13 16:28
自定义
LCC
编译器的源程序分析(11)声明与符号表
前一次已经分析了声明的函数,但还有一个声明函数没有分析的,它就是 dclr 函数,这个函数是大内总管,分别调用前面两个声明函数来处理所有的声明语句,接着又会保存声明的 ID 和属性到符号表,当然它需要调用处理函数定义的函数,接着在那里把函数生成汇编代码并写到输出文件里。 现在就来看代码: #001 static void decl(Symbol (*dcl)(int, char
·
2015-11-13 16:11
编译器
LCC
编译器的源程序分析(9)声明分析
在语法分析里,最主要的组成部份是声明分析,并且这是 C 语言编译器最复杂的组成部分。由于任何变量都需要声明,那么怎么样知道这个变量声明是合法的呢?现在带着这个问题去分下面的代码。 为了理解代码的工作,先来看前面的例子里的第一行有效代码: typedef unsigned int size_t; 在这句语句里,使用类型定义关键字来声明了一个无符号整数的类型 size_t
·
2015-11-13 16:10
编译器
LCC
编译器的源程序分析(10)声明类型
上一次把声明的说明符已经分析得很清楚,也就是把 C 的变量和函数声明都已经了解了。最后还剩下一个问题没有解决,这个问题就是声明后面的 ID 是变量呢?还是函数?或者是指针?为了识别后面的 ID ,下面来看一个例子。如下的语句: typedef unsigned int size_t; 这是第一行处理的代码,它通过函数 specifier 处理后,已经就把 typedef 、 unsigne
·
2015-11-13 16:10
编译器
LCC
编译器的源程序分析(8)语法分析的开始
下面就来仔细地分析
LCC
编译器是怎么样处理这两个问题的。
·
2015-11-13 16:09
编译器
LCC
编译器的源程序分析(7)词法分析
下面开始关键字、 ID 等识别,采用这种词法分析,是最高效的,由于在识别的过程里,就已经区分它是什么关键字,而不像其它的词法分析程序,需要查找才能决定是否是关键字。 #074 case 'i': #075 &nbs
·
2015-11-13 16:08
编译器
LCC
编译器的源程序分析(5)行号同步与类型初始化
上面已经介绍打开文件输入,并且分析了读取到缓冲区里的代码,接着下来就是分析行号同步的处理,还有类型初始化。 先来看看生成中间文件 hello.i 中的源程序,在它的第 1 行和第 2 行如下: #001 #line 1 "hello.c" #002 #line 1 "include/stdio.h" #0
·
2015-11-13 16:07
初始化
上一页
1
2
3
4
5
6
7
8
下一页
按字母分类:
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
其他