编译过程:
-----编译前端------
- 词法分析与语法分析
- 类型检查(别的语言中的语义分析,这时候有语法错误才会被找出来)
-----编译后端------
- 中间代码生成
- 机器码生成
我们一一来看各个过程都做了什么事
1. 词法分析与语法分析
词法分析
将源代码翻译成token
语法分析
将token序列变成抽象语法树(AST)
所谓的语法分析就是将 Token 转化为可识别的程序语法结构,而 AST 就是这个语法的抽象表示。构造这颗树有两种方法。
- 自上而下
这种方式会首先构造根节点,然后就开始扫描 Token,遇到 STRING 或者其它类型就知道这是在进行类型申明,func 就表示是函数申明。就这样一直扫描直到程序结束。
- 自下而上
这种是与上一种方式相反的,它先构造子树,然后再组装成一颗完整的树。
go 语言进行语法分析使用的是自下而上的方式来构造 AST
2. 类型检查(语义分析)(传说中的逃逸分析就是在这个阶段做的)
Golang 文档中提到的会进行类型检查,还有类型推断,查看类型是否匹配,是否进行隐式转化(go 没有隐式转化)
名称检查和类型推断,签定每个对象所属的标识符,以及每个表达式具有什么类型。类型检查也还有一些其它的检查要做,像“声明未使用”以及确定函数是否中止。
AST 也会进行转换,有些节点根据类型信息进行精简,比如从算术加法节点类型中拆分出字符串加法。其它一些例子像 dead code 的消除,函数调用内联和逃逸分析。
3. 中间代码生成
在进行各个平台的兼容之前,我们还需要替换一些底层函数,比如我们使用 make 来初始化 slice,此时会根据传入的类型替换为:makeslice64
或者 makeslice
中间码存在的另外一个价值是提升后端编译的重用,比如我们定义好了一套中间码应该是长什么样子,那么后端机器码生成就是相对固定的。每一种语言只需要完成自己的编译器前端工作即可。这也是大家可以看到现在开发一门新语言速度比较快的原因。编译是绝大部分都可以重复使用的。
中间码也是有多种格式的,像 Golang
使用的就是 SSA 特性的中间码(IR),这种形式的中间码,最重要的一个特性就是最在使用变量之前总是定义变量,并且每个变量只分配一次。
4. 机器码生成
经过优化后的中间代码,首先会在这个阶段被转化为汇编代码(Plan9),而汇编语言仅仅是机器码的文本表示,机器还不能真的去执行它。所以这个阶段会调用汇编器,汇编器会根据我们在执行编译时设置的架构,调用对应代码来生成目标机器码。
标签:机器码,语法分析,AST,中间,golang,编译,类型,过程 From: https://www.cnblogs.com/JujunWang/p/16909197.html