Go编译原理过程图
词法和语法分析
词法分析是将字符序列转换为标记(token)序列的过程
- Go 语言的词法解析是通过 src/cmd/compile/internal/syntax/scanner.go 文件中的 cmd/compile/internal/syntax.scanner 结构体实现的
- 词法分析主要是由 cmd/compile/internal/syntax.scanner 这个结构体中的 cmd/compile/internal/syntax.scanner.next 方法驱动,这个 250 行函数的主体是一个 switch/case 结构
语法分析是根据某种特定的形式文法(Grammar)对 Token 序列构成的输入文本进行分析并确定其语法结构的过程
- Go 语言的解析器使用了 LALR(1) 的文法来解析词法分析过程中输出的 Token 序列,最右推导加向前查看构成了 Go 语言解析器的最基本原理,也是大多数编程语言的选择
- 解析过程会调用协程
- 语法分析器cmd/compile/internal/syntax.parser
- cmd/compile/internal/syntax.parser.fileOrNil 是一个核心解析方法
产物:文件对应的抽象语法树
类型检查
类型检查是 Go 语言编译的第二个阶段,在词法和语法分析之后我们得到了每个文件对应的抽象语法树,随后的类型检查会遍历抽象语法树中的节点,对每个节点的类型进行检验,找出其中存在的语法错误,在这个过程中也可能会对抽象语法树进行改写,这不仅能够去除一些不会被执行的代码、对代码进行优化以提高执行效率,而且也会修改 make、new 等关键字对应节点的操作类型
中间代码生成
中间代码是指一种应用于抽象机器的编程语言,它设计的目的,是用来帮助我们分析计算机程序。在编译的过程中,编译器会在将源代码转换成目标机器上机器码的过程中,先把源代码转换成一种中间的表述形式
Go 语言编译器的中间代码具有静态单赋值(SSA)的特性
中间代码的生成过程其实就是从 AST 抽象语法树到 SSA 中间代码的转换过程,在这期间会对语法树中的关键字在进行一次改写,改写后的语法树会经过多轮处理转变成最后的 SSA 中间代码,这里的代码大都是巨型的 switch 语句、复杂的函数以及调用栈,阅读和分析起来也非常困难
机器码生成
Go 语言编译的最后一个阶段就是根据 SSA 中间代码生成机器码了,这里谈的机器码就是在目标 CPU 架构上能够运行的二进制代码,中间代码生成一节简单介绍的从抽象语法树到 SSA 中间代码的生成过程,将近 50 个生成中间代码的步骤中有一些过程严格上说是属于机器码生成阶段的。
机器码的生成过程其实就是对 SSA 中间代码的降级(lower)过程,在 SSA 中间代码降级的过程中,编译器将一些值重写成了目标 CPU 架构的特定值,降级的过程处理了所有机器特定的重写规则并对代码进行了一定程度的优化;在 SSA 中间代码生成阶段的最后,Go 函数体的代码会被转换成一系列的 obj.Prog 结构体