龙书-编译器基础知识
编译器作用
一个程序语言从源代码到可执行程序需要经过下面的过程,从过程中可以了解到编译器在其中所处的地位和作用
- 预处理:把源代码进行初步处理,例如宏展开
- 编译:把初步处理后的源代码,通过编译器,编译成汇编程序
- 汇编:汇编器把汇编程序转化成可重定位的目标机器代码
- 链接:链接器把可重定位的目标机器代码转化为目标机器上的可执行程序
编译器处理的几个阶段
词法分析: 把字符流(源代码)转化成 token 序列:
pos = init + rate * 60
=><id, 1> <=> <id, 2> <+> <id,3> <*> <60>
,同时 生成一个符号表,符号表里存放着源代码中相关符号的信息,例如符号表中第一项,名字为pos
,还有一些其它信息,例如类型等等。符号 表会被编译器处理的各个阶段使用,修改。语法分析: 把词法分析后的结果根据语言的语法要求,转化成语法树。语法树帮助后面的阶段分析源代码,并生成目标代码
语义分析:根据语法树和符号表的信息,分析程序语义,例如作类型检查
中间代码生成:把语法树转化成一种中间代码表示方式,例如三地址表示法,便于产生汇编代码
机器无关的代码优化
代码生成:把中间代码生成汇编代码
机器相关的代码优化
创建编译器的科学
编译器设计是一个使用数学方法抽象现实世界的复杂问题,再使用数学工具去解决问题的绝佳案例。
编译器优化需要符合下面的设计目标:
- 优化必须是正确的,即优化不能改变程序执行的结果
- 优化必须能提高大部分程序的性能
- 编译时间是可以接受的
- 工程实现上的成本是可以接受的
仔细思考上面的目标,说的就是你要做一件事,这件事是有用的,合理的,同时成本可控
影响编译技术发展的有两个主要内容,一是新的高级程序语言的实现,二是计算机体系结构的发展。
新的高级语言带来的新特性需要编译器支持,而要确保编译出的目标代码在新的体系结构上高效运行,就必须针对新的体系结构来做优化。