佛山市拓洲网络科技有限公司
拓洲科技,贴近未来

软件开发语言Go的代码是怎么样编译成机器码的之三:机器码生成阶段

在之前的两篇文章中,我们大致了解了Go 1.11 的编译器,是如何地把Go的软件开发项目的源代码编译成执行文件的整个过程,以及Scanner阶段和Parser阶段的深入了解。

在这篇文章当中,我们会继续深入了解整个过程中的第三步,机器码生成阶段。

Code generation

在解析导入并检查了类型之后,我们确定程序是有效的Go代码,我们可以开始将AST转换为(伪)机器代码的过程。

此过程的第一步是将AST转换为程序的较低级别表示,特别是转换为Static Single Assignment (SSA) form。这个中间表示不是最终的机器代码,但它确实代表了最终的机器代码。SSA具有一些可以更容易地应用优化的特性,其中最重要的是变量在使用之前定义,并且每个变量只分配一次。

在生成SSA的初始版本之后,将应用许多优化过程。这些优化适用于某些代码,可以使处理器执行更简单或更快速。例如,可以消除死代码,例如if(false){fmt.Println(“test”)},因为它永远不会执行。另一个优化示例是可以删除某些nil检查,因为编译器可以证明这些检查永远不会false。

现在让我们看一下这个简单程序的SSA和一些优化过程:

如您所见,此程序只有一个功能和一个导入。它会在运行时打印2 。但是,此示例足以查看SSA。

注意:仅显示主要功能的SSA,因为这是有趣的部分。

为了显示生成的SSA,我们需要将GOSSAFUNC 环境变量设置为我们想要查看SSA的函数,在本例中为main。我们还需要将-S标志传递给编译器,因此它将打印代码并创建HTML文件。我们还将编译Linux 64位文件,以确保机器代码与您在此处看到的相同。因此,要编译文件,我们将运行:

$ GOSSAFUNC = main GOOS = linux GOARCH = amd64 go build -gcflags“-S”simple.go

它将打印所有SSA,但它也会生成一个交互式的ssa.html文件,因此我们将使用它。

当您打开ssa.html时,将显示许多通道,其中大部分都已折叠。起始传递是从AST生成的SSA; 较低的传递将非机器特定的SSA转换为机器特定的SSA,genssa是最终生成的机器代码。

开始阶段的代码如下所示:

这个简单的程序已经产生了相当多的SSA(总共35行)。然而,很多都是样板,可以消除很多(最终的SSA版本有28行,最终的机器代码版本有18行)。

每个v 都是一个新变量,可以单击以查看其使用位置。该b 的是数据块,因此在这种情况下,我们有三个大块:B1 ,B2 B3 。b1 将始终执行。b2 b3 是条件块,可以通过在b1 结尾处的If v19→b2 b3(可能)看到。我们可以点击V19 在该行查看,其中V19 定义。我们看到它定义为IsSliceInBounds <bool> v14 v15 ,通过查看Go编译器源代码我们可以看到IsSliceInBounds 检查0 <= arg0 <= arg1 。我们还可以单击v14 v15 来查看它们的定义方式,我们将看到v14 = Const64 <int> [0] ; Const64 是一个常量64位整数。v15 定义为相同但定义为。所以,我们基本上有0 <= 0 <= 1 ,这显然是正确的

编译器也能够证明这一点,当我们查看opt 阶段(“机器无关优化”)时,我们可以看到它已经重写了v19 ConstBool <bool> [true] 。这将用于opt deadcode 阶段,其中b3 被删除,因为前面显示的条件中的v19 始终为true。

我们现在将看一下在将SSA转换为机器特定的SSA之后由Go编译器进行的另一个更简单的优化,因此这将是amd64体系结构的机器代码。为此,我们来看一看下一阶段的内容:

在HTML文件中,某些行是灰色的,这意味着它们将在下一个阶段中删除或更改。例如,v15 MOVQconst <int> [1] )显示为灰色。通过点击它进一步检查v15 ,我们看到它在其他任何地方都没有使用,MOVQconst 基本上和我们之前看到的相同,Const64 ,只是amd64的机器特定。所以,我们将v15 设置为。但是,v15 在其他任何地方都没有使用,因此它是无用的代码并且可以被删除。

Go编译器应用了很多这样的优化。因此,虽然AST的第一代SSA可能不是最快的实现,但编译器将SSA优化为更快的版本。HTML文件中的每个阶段都是可能发生优化的阶段。

如果您有兴趣在Go编译器中了解有关SSA的更多信息,请查看Go编译器的SSA源代码。在这里,定义了所有操作以及优化。


邮箱:vyloy@yiqishare.com

地址:广东省佛山市顺德区容桂街道高黎村19号首层之二 邮编:528303

Copyright © 2014-2018 yiqishare.com. All rights reserved. 粤ICP备15033752号