编译器的工作
编译器是将高级语言翻译成机器语言的一个工具,编译过程是对预处理完的文件进行一系列词法分析,语法分析,语义分析及优化后生成相应的汇编代码文件,编译流程如下图所示。
以C语言语句 array[index] = (index+4) * (2 + 6)为例进行分析。
1 词法分析
首先源代码程序被输入到扫描器(Scanner),扫描器进行词法分析,运用类似于有限状态机的算法将源代码的字符序列分割成一系列的记号(Tokens)。
如上述的语句将被分割成:array [ index ] = ( index + 4 ) * ( 2 + 4 )等记号,词法分析产生的记号一般包括关键字,标识符,字面量(数字,字符串等)和特殊符号(如加号,等号),在识别记号的同时,扫描器将标识符存放到符号表,将数字,字符串常量存放到文字表,当程序中出现未声明的变量时,在该阶段编译器即发现错误。
2 语法分析
接下来语法分析器(Parser)将对由扫描器产生的记号进行语法分析,从而产生语法树。如下图所示,当表达式出现逻辑错误时(如a =+ b等),在该阶段编译器即发现错误。
3 语义分析
语法分析仅仅完成了对表达式的语法层面的分析,但其并不了解这个语句是否真正有意义,如C语言里两个指针做乘法运算时没有意义的,但其在语法上是合法的。编译器所能分析的语义是静态语义,即在编译器可以确定的语义,静态语义通常包括声明和类型的匹配,类型的转换等,不符合语义的表达式将在该阶段由编译器提示警告或者错误信息。
经过语义分析阶段以后,整个语法树的表达式都被标识了类型,如果有些类型需要做隐式转换,语义分析程序会在语法树中插入相应的转换节点,如下图所示:
4 中间语言生成
现代的编译器有着很多层次的优化,往往在源代码级别会有一个优化过程,如上述表达式中的2+6这个表达式可以被优化,即直接求出其值8。由于直接在语法树上做优化比较困难,所以源代码优化器往往将整个语法树转换成中间代码(Intermediate Code),它是语法树的顺序表示,非常接近目标码。常见的中间代码包括三地址码,P-代码。
上述语法树翻译成三地址码表示为:
t1 = 2 + 6
t2 = index + 4
t3 = t2 * t1
array[index] = t3
通过优化计算2+6的值,可表示为:
t2 = index + 4
t2 = t2 * 8
array[index] = t2
5 目标代码的生成与优化
代码生成器将中间代码转换成目标机器代码,该过程依赖于目标机器,因为不同机器有着不同的字长,寄存器,,整型数据类型和浮点数数据类型等,该过程将生成汇编代码,并由汇编器(如