1.1 概要
目标
从头制作Cb编译器
可执行文件是怎样的文件
在Linux上,是符合ELF(Executable and Linking Format)。file命令能够查看文件时是否ELF形式。ELF代码中包含机器语言。
gcc命令是如何生成可执行文件的
一般来说,需要经过预处理->编译->(狭义的)汇编->链接。
- 预处理: 类似sed或者awk。
- 编译: .c -> .s(汇编语言)
- 汇编: .s -assembler-> 目标文件.o(机器语言)
- 没有经过链接的目标文件也是ELF文件,但是不是可执行文件,使用file文件会显示ELF 32-bit LSB relocatable。
- 链接: 目标文件.o -> 可执行文件.o
- 如果使用了动态链接,那么程序运行时才会执行链接
解释器
解释器不将程序转化为别的语言而是直接运行,编译器和解释器统称为编程语言处理器。此外,还有动态、静态类型检查之分。
1.2 编译过程
编译的4个阶段
- 语法分析
- 语义分析
- 生成中间代码
- 代码生成
语法分析
语法分析将源代码处理成语法树。
语义分析
语法树除去多余的内容,添加必要信息,生成抽象语法树(Abstract Syntax Tree)。
具体包括
- 区分变量是局部还是全局变量。
- 解析变量声明和引用
- 变量和表达式的类型检查
- 检查在引用变量之前是否进行了初始化
- 检查函数是否按照定义返回了结果
语法树和抽象语法树的区别:抽象语法树中包含了语义信息,例如:在变量的引用和定义之间有链接
生成中间代码(Intermediate Representation)
目的:支持多种编程语言或者机器语言
方法:转化为中间代码,这样对一种语言只需添加一份处理。
例子: gcc用RTL
编译器前端front-end: 解析代码,语义分析,生成中间代码
编译器后端back-end: 代码生成和优化
代码生成
关键: 填补编程语言和汇编语言之间的差易,比如弥补寄存器数目的限制。
限制:不能改变源程序语义
优化
可以在各个环节进行,对链接和运行时调用的代码都可以优化