美文网首页
Go:编译器概述

Go:编译器概述

作者: 开心人开发世界 | 来源:发表于2019-09-16 09:48 被阅读0次
    image.png

    本文基于Go 1.13。*

    Go编译器是Go生态系统中的一个重要工具,因为它是将程序构建为可执行二进制文件的基本步骤之一。编译器的历程是漫长的,它已经用C语言编写,转移到Go,许多优化和清理将在未来继续发生。让我们发现它的高水平运作。

    Phases

    Go编译器由四个阶段组成,可分为两类:

    • 前端。此阶段从源代码运行分析,并生成源代码的抽象语法结构,称为AST
    • 后端。第二阶段将把源代码的表示转换为机器代码,以及几个优化。

    为了更好地理解每个阶段,让我们使用一个简单的程序:

    package main
    
    func main() {
        a := 1
        b := 2
        if true {
            add(a, b)
        }
    }
    
    func add(a, b int) {
        println(a + b)
    }
    

    解析

    第一阶段非常简单,并在文档中做了很好的解释:

    在编译的第一阶段,源代码被标记化(词法分析),解析(语法分析),并且为每个源文件构造语法树。

    词法分析器将是第一个为了标记源代码而运行的包。这是前一个示例标记化的输出:

    去源代码标记化

    一旦被标记化,将被解析并用于构建语法树。

    AST转换

    由于带有标志的命令,可以显示对抽象语法树的转换:go tool compile``-W


    生成AST的样本

    此阶段还将包括内联等优化。在我们的示例中,该方法add可以已经内联,因为我们没有看到CALLFUNC该方法的任何指令add。让我们使用禁用内联的标志-l运行again命令:

    AST生成后,它允许编译器使用SSA表示转到较低级别的中间表示。

    SSA

    静态单赋值形式是阶段,其中优化会发生:死代码消除,删除不使用的分支,具有恒定值等替换一些表达式

    由于GOSSAFUNC=main go tool compile main.go && open ssa.html生成HTML文档的命令将在SSA包中完成所有不同的传递,因此可以转储SSA代码:

    生成的SSA位于“开始”选项卡中:

    SSA代码

    这里的变量ab突出显示以及if条件将允许我们稍后查看这些行是如何更改的。该代码也向我们展示了编译器如何管理println是在4个步骤分解函数:printlockprintintprintnlprintunlock。编译器会自动为我们添加一个锁,并根据参数的类型调用相关方法来正确打印它。

    在我们的示例中,由于编译时已知a并且b已知,编译器可以计算最终结果并将变量标记为不再需要。通行证opt将优化此部分:

    v11这里已经被添加的结果替换,v4并且v5已被标记为死代码。该传递opt deadcode将删除该代码:

    关于if条件,opt阶段将常量标记true为死代码,然后将被删除:


    常量布尔值被删除

    然后,另一个过程将通过将不必要的块和条件标记为无效来简化控制流程。这些块稍后将被另一个专用于死代码的传递删除:


    不必要的控制流程被删除

    完成所有传递后,Go编译器现在将生成一个中间汇编代码:


    go asm代码

    下一阶段将生成机器代码到二进制文件中。

    机器代码生成

    main.o在我们的示例中,编译器的最后一步是生成目标文件。从该文件中,现在可以使用objdump执行相反过程的工具对其进行反汇编。这是Grant Seltzer Richman创建的一个很好的图表:


    go 工具编译


    go 工具objdump

    您可以在“ Dissecting Go Binaries ”中找到有关目标文件和二进制文件的更多信息

    生成目标文件后,现在可以使用该命令go tool link将其直接传递给链接器,您的二进制文件最终将准备就绪。

    翻译自:https://medium.com/a-journey-with-go/go-overview-of-the-compiler-4e5a153ca889

    相关文章

      网友评论

          本文标题:Go:编译器概述

          本文链接:https://www.haomeiwen.com/subject/odqmyctx.html