go语言编译过程概述
go语言编译过程概述
总结自《go语言设计与实现》
名词解释:
中间代码
中间代码是编译器或者虚拟机使用的语言,它可以来帮助我们分析计算机程序。在编译过程中,编译器会在将源代码转换到机器码的过程中,先把源代码转换成一种中间的表示形式,即中间代码。将编程语言到机器码的过程拆成中间代码生成和机器码生成两个简单步骤可以简化该问题,中间代码是一种更接近机器语言的表示形式,对中间代码的优化和分析相比直接分析高级编程语言更容易。
SSA
静态单赋值是中间代码的特性,如果中间代码具有静态单赋值的特性,那么每个变量就只会被赋值一次。在实践中,我们通常会用下标实现静态单赋值,这里以下面的代码举个例子:
x := 1
x := 2
y := x
经过简单的分析,我们就能够发现上述的代码第一行的赋值语句
x := 1
不会起到任何作用。下面是具有 SSA 特性的中间代码,我们可以清晰地发现变量y_1
和x_1
是没有任何关系的,所以在机器码生成时就可以省去x := 1
的赋值,通过减少需要执行的指令优化这段代码。x_1 := 1
x_2 := 2
y_1 := x_2
过程概述
词法与语法分析
编译过程其实都是从解析代码的源文件开始的,词法分析的作用就是解析源代码文件,它将文件中的字符串序列转换成 Token 序列,方便后面的处理和解析,我们一般会把执行词法分析的程序称为词法解析器。
而语法分析的输入是词法分析器输出的 Token 序列,语法分析器会按照顺序解析 Token 序列,该过程会将词法分析生成的 Token 按照编程语言定义好的文法(Grammar)自下而上或者自上而下的规约,每一个 Go 的源代码文件最终会被归纳成一个 SourceFile 结构 。
词法分析会返回一个不包含空格、换行等字符的 Token 序列,例如:package, json, import, (, io, ), …,而语法分析会把 Token 序列转换成有意义的结构体,即语法树。
类型检查
当拿到一组文件的抽象语法树之后,Go 语言的编译器会对语法树中定义和使用的类型进行检查,类型检查会按照以下的顺序分别验证和处理不同类型的节点:
- 常量、类型和函数名及类型;
- 变量的赋值和初始化;
- 函数和闭包的主体;
- 哈希键值对的类型;
- 导入函数体;
- 外部的声明;
通过对整棵抽象语法树的遍历(也会修改语法树),我们在每个节点上都会对当前子树的类型进行验证,以保证节点不存在类型错误,所有的类型错误和不匹配都会在这一个阶段被暴露出来,其中包括:结构体对接口的实现。
类型检查阶段不止会对节点的类型进行验证,还会展开和改写一些内建的函数,例如 make 关键字在这个阶段会根据子树的结构被替换成 runtime.makeslice或者 runtime.makechan等函数。
中间代码生成
当我们将源文件转换成了抽象语法树、对整棵树的语法进行解析并进行类型检查之后,就可以认为当前文件中的代码不存在语法错误和类型错误的问题了,Go 语言的编译器就会将输入的抽象语法树转换成中间代码。
在类型检查之后,编译器会通过 cmd/compile/internal/gc.compileFunctions编译整个 Go 语言项目中的全部函数,这些函数会在一个编译队列中等待几个 Goroutine 的消费,并发执行的 Goroutine 会将所有函数对应的抽象语法树转换成中间代码。由于 Go 语言编译器的中间代码使用了 SSA 的特性,所以在这一阶段我们能够分析出代码中的无用变量和片段并对代码进行优化
机器码生成
Go 语言源代码的 src/cmd/compile/internal 目录中包含了很多机器码生成相关的包,不同类型的 CPU 分别使用了不同的包生成机器码,其中包括 amd64、arm、arm64、mips、mips64、ppc64、s390x、x86 和 wasm
go语言编译过程概述的更多相关文章
- Go 语言编译过程
走进Golang之编译器原理_大愚Talk-CSDN博客 https://blog.csdn.net/hel12he/article/details/103061921 go编译器 - 知乎 http ...
- C编译过程概述
转自:http://my.oschina.net/apeng/blog/105245 C 编译过程概述 目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection), ...
- [转贴]C编译过程概述
http://my.oschina.net/apeng/blog/105245 C 编译过程概述 目前Linux下最常用的C语言编译器是GCC(GNU Compiler Collection),它是G ...
- (二)我的Makefile学习冲动&&编译过程概述
前言 一 年轻的冲动 二 学习曲线 1 Makefile基本语法 2 bash基础 3 world 三 编译过程概述 1 主机预装工具 2 编译host工具 3 编译交叉工具链 4 编译内核模块 5 ...
- C语言编译过程及数据类型
写在前面 C语言可以称得上是高级语言中的低级语言,接下来一段时间,我会写一下文章关于c语言,把它的神秘面纱一 一揭开.下面主要是c语言的C语言编译过程及数据类型 源文件编译过程 为了使计算机能执行高级 ...
- C语言编译过程以及gcc编译参数
1.1 C语言编译过程,gcc参数简介 1.1.1 C语言编译过程 一.gcc - o a a.c -o:指定文件输出名字 二.C语言编译的过程: 1.1.1 ...
- 转 C语言编译过程简介
C语言编译过程简介 C语言编译过程简介 刚开始接触编程的时候,只知道照书敲敲代码,一直都不知道为什么在windows平台下代码经过鼠标那样点击几下,程序的结果就会在那个黑色的屏幕上.现在找了个机会将C ...
- GCC 使用-C语言编译过程
任何一种高级语言,要想在机器上执行,必须翻译为机器能读懂的机器语言.编译器就相当于翻译官,将高级语言翻译为机器语言. GCC 最初只用了编译 C 语言程序,全称是 GNU C Compiler.后来扩 ...
- GCC 概述:C 语言编译过程详解
Tags: C Description: 关于 GCC 的个人笔记 GCC 概述 对于 GCC 6.1 以及之后的版本,默认使用的 C++ 标准是 C++ 14:使用 -std=c++11 来指定使用 ...
随机推荐
- Flash XSS
示例: 创建一个测试flash,代码如下,导出swf文件 //取m参数 var m=_root.m; //取showInfo参数 var showInfo=_root.showInfo; //调用ht ...
- Acwing 社交距离 分类讨论+贪心
一种新型疾病,COWVID-19,开始在全世界的奶牛之间传播. Farmer John 正在采取尽可能多的预防措施来防止他的牛群被感染. Farmer John 的牛棚是一个狭长的建筑物,有一排共 N ...
- volatile 变量和 atomic 变量有什么不同?
Volatile 变量可以确保先行关系,即写操作会发生在后续的读操作之前, 但它并不 能保证原子性.例如用 volatile 修饰 count 变量那么 count++ 操作就不是原子 性的. 而 A ...
- 如何在自定义端口上运行 Spring Boot 应用程序?
为了在自定义端口上运行 Spring Boot 应用程序,您可以在 application.properties 中指定端口. server.port = 8090
- 四种类型的数据节点 Znode?
1.PERSISTENT-持久节点 除非手动删除,否则节点一直存在于 Zookeeper 上 2.EPHEMERAL-临时节点 临时节点的生命周期与客户端会话绑定,一旦客户端会话失效(客户端与 zoo ...
- vmware 磁盘清理---还原虚拟机硬盘大小
linux host: 1.使用dd命令将客户机未使用的磁盘空间用0填满 cat /dev/zero > zero.fill;sync;sleep 1;sync;rm -f zero.fill ...
- list集合的快速筛选条件方法
List<String> list = new ArrayList<>();list.add("张无忌");list.add("周芷若" ...
- kali Linux 渗透测试 | ARP 欺骗
目录 ARP 欺骗及其原理 ARP 欺骗实施步骤 必备工具安装 nmap 工具 dsniff 工具 driftnet 工具 ettercap 工具 ARP 欺骗测试 ARP 断网攻击 ARP 欺骗(不 ...
- 12 Factor App
The Twelve-Factor App Introduction In the modern era, software is commonly delivered as a service: c ...
- CSS: 给表格的第一列和最后一列不同的样式
table td:first-child { width:160px; height:20px; border:solid 1px Black; padding:5px; text-align:cen ...