2、go语言编译基础
文章基于:go1.14.2
1、go编译简介
1.1、编译相关概念
编译器
:将一种语言(通常为高级语言)翻译为另一种语言(通常为低级语言)的程序
高级语言
:便于人编写,阅读,交流,维护
机器语言
:计算机能直接解读,运行的
反编译器
:从低级语言到高级语言的编译器。这类编译器用来把从高级语言生成的低级语言代码重新生成高级语言的代码。
1.2、go编译器编译流程简介
一般可以把编译器的编译流程分为两个部分:编译器前端、编译器后端
下方流程是简化过的
2、go编译详解
2.1、词法分析
词法分析结果主要是为了获取token流(下图中的右边列表)
将一个go源码文件翻译成一个token列表
2.2、语法分析
通过词法分析获得token流后,通过词法分析,一个个读入token生成树结构
下方站点可以实现这一过程
https://astexplorer.net/
2.3、语义分析
语义分析主要是做遍历语法树的工作如下图
同时在抽象语法树AST上做类型检查,比如不能给一个int类型变量赋string类型的值
2.4、中间代码SSA生成与优化
当获得AST抽象语法树
要转化成最终的汇编,还需要经过两三步,此处先跳过。
静态单赋值语句SSA(Single Static Assignment)的两大特点:
Static
:每个变量只能赋值一次(因此应该叫常量更合适)Single
:每个表达式只能做一个简单运算,对于复杂的表达式a*b+c*d
要拆分成:t0=a*b; t1=c*d; t2=t0+t1;
三个简单表达式
在线看go生成汇编指令:https://godbolt.org/
本地生成ssa.html
本地使用下方命令生成ssa.html来查看
设置go ssa方法名set GOSSAFUNC=main
执行构建:go build -gcflags -S main.go
最终生成的ssa.html结果如下
2.5、编译工具
2.5.1、go tool compile -S
go tool compile命令是把go文件编译成.o文件
.o文件需要通过链接再生成可执行文件
下方只需要看懂go源码编译为汇编代码后调用的函数即可,也就是下图中的CALL那一行
命令例子:go tool compile -S ./hello.go | grep "hello.go:5"
grep "hello.go:5"表示的是查看go源码中第5行代码对应生成的汇编内容
该命令会生成.o目标文件,并把目标的汇编内容输出
2.5.2、go tool objdump
go tool objdump是把可执行文件反编译成汇编
例子:使用go tool objdump来找make的实现方法
make.go
执行命令:
go build make.go && go tool objdump ./make | grep -E "make.go:6|make.go:10|make.go:14"
查看make调用了哪些方法: