Golang 编译器代码浅析
  • 0. Golang 编译器代码浅析
  • 1. golang 编译器 - 前言
    • 1.1 编译器简介
    • 1.2 Golang 编译器
    • 1.3 Go 语言版本
    • 1.4 项目设置
    • 1.5 约定
    • 1.6 写作目的
  • 2. golang 编译器 - 词法分析
    • 2.1 简介
    • 2.2 代码结构
    • 2.3 处理字符
    • 2.4 扫描Token
    • 2.5 总结
  • 3.a 语法分析理论知识
    • 3A.1 语法分析简介
    • 3A.2 文法
    • 3A.3 语法解析
    • 3A.3.1 自顶向下(Top-Down)
    • 3A.3.2 自顶向下 - 递归下降
    • 3A.3.3 自顶向下 - LL(1)文法
    • 3A.3.4 自底向上(Bottom-Up)
    • 3A.3.5 自底向上 - LR(0)项集及SLR预测表
    • 3A.3.6 自底向上 - LR(1)、LALR
    • 3A.4 语法分析工具
    • 3A.5 总结
  • 3B. golang 编译器 - 语法分析
    • 3B.1 简介
    • 3B.2 代码结构
    • 3B.3 数据结构
    • 3B.4 构造语法树
    • 3B.5 Unit Test及AST可视化
  • 4. Golang 编译器 - 类型检查
    • 4.1 简介
    • 4.2 代码结构
    • 4.3 符号解析
    • 4.4.1 数据结构 - 作用域
    • 4.4.2 数据结构 - Package
    • 4.4.3 数据结构 - Object 对象
    • 4.4.4-1 类型数据结构 - 简介
    • 4.4.4-2 类型接口
    • 4.4.4-3 基础类型
    • 4.4.4-4 内置复合类型
    • 4.4.4-5 Struct 类型
    • 4.4.4-6 Interface 类型
    • 4.4.4-7 Named 类型
    • 4.4.4-8 Tuple 类型
    • 4.4.4-9 Sum 类型
    • 4.4.4-10 Function & Method 类型
    • 4.4.4-11 泛型类型
    • 4.4.4-12 类型的等价规则
    • 4.4.4-13 类型的比较规则
    • 4.4.4-14 总结
    • 4.4.5 类型检查器
    • 4.4.6 总结
    • 4.5.1 类型检查逻辑 - 包加载器
    • 4.5.2 类型检查逻辑 - 初始化
    • 4.5.2-1 全局作用域
    • 4.5.2-2 类型检查器
    • 4.5.3 类型检查逻辑 - 流程分析
    • 4.5.3-1.1 总体流程
    • 4.5.3-1.2 类型检查准备工作
    • 4.5.3-1.3 类型检查核心逻辑
    • 4.5.3-1.3a 总体介绍
    • 4.5.3-1.3b 类型表达式的类型检查
    • 4.5.3-1.3c 求值表达式的类型检查
    • 4.5.3-1.3d 类型兼容性检查
    • 4.5.3-1.3e 处理delayed队列
    • 4.5.3-1.4 构建初始化顺序
    • 4.5.3-1.5 总结
    • 4.5.3-2 特定问题分析
    • 4.5.3-2a 对象循环依赖检查
    • 4.5.3-2b 方法与属性查找
    • 4.5.3-2c Underlying Type
    • 4.6 如何测试
    • 4.7 总结
  • 5. Golang 编译器 - IR Tree
    • 5.1 简介
    • 5.2 代码结构
    • 5.3 数据结构
    • 5.4 处理逻辑
    • 5.5 编译日志
    • 5.6 Unit Test
    • 5.7 总结
  • 6. golang 编译器 - 初始化任务
    • 6.1 简介
    • 6.2 代码结构
    • 6.3 总体逻辑
    • 6.4 赋值语句
    • 6.5 编译日志
    • 6.6 Unit Test
    • 6.7 总结
  • 7. golang 编译器 - 清除无效代码
    • 7.1 简介
    • 7.2 处理逻辑
    • 7.3 Unit Test
  • 8. golang 编译器 - Inline
    • 8.1 简介
    • 8.2 Inline的问题
    • 8.3 代码结构
    • 8.4 处理逻辑
    • 8.4.1 遍历调用链
    • 8.4.2 内联判断
    • 8.4.3 内联操作
    • 8.4.4 编译日志
    • 8.4.5 Unit Test
    • 8.4.6 总结
  • 9. golang 编译器 - 逃逸分析
    • 9.1 什么是逃逸分析
    • 9.2 Go 的逃逸分析
    • 9.3 算法思路
    • 9.4 代码结构
    • 9.5 处理逻辑
    • 9.5.1总体逻辑
    • 9.5.2 数据结构
    • 9.5.3 构建数据流有向图
    • 9.5.4 逃逸分析
    • 9.6 编译日志
    • 9.7 Unit Test
    • 9.8 总结
  • 10. golang 编译器 - 函数编译及导出
    • 10.1 简介
    • 10.2 编译函数
    • 10.2.1 SSA
    • 10.2.2 ABI
    • 10.2.3 并发控制
    • 10.3 导出对象文件
    • 10.4 总结
  • 11. Golang 编译器 - 写在最后
由 GitBook 提供支持
在本页
  • 4.4.3.1. 接口及公用结构
  • 4.4.3.2. 具体Object类型
  • 4.4.3.3. Object对象的等价性
  • 4.4.3.4. Object的作用

这有帮助吗?

  1. 4. Golang 编译器 - 类型检查

4.4.3 数据结构 - Object 对象

Object定义了一个接口,用来表示程序中的各类命名实体,即前文一直提到的符号对象,例如函数、变量、类型等。编译器内部为不同的符号类型定义了不同的数据结构,所有定义都在文件 $GCROOT/compile/internal/types2/object.go 中。

4.4.3.1. 接口及公用结构

接口 type Object interface{...} 的声明如下:

// An Object describes a named language entity such as a package,
// constant, type, variable, function (incl. methods), or label.
// All objects implement the Object interface.
// 
type Object interface {
	Parent() *Scope  // scope in which this object is declared; nil for methods and struct fields
	Pos() syntax.Pos // position of object identifier in declaration
	Pkg() *Package   // package to which this object belongs; nil for labels and objects in the Universe scope
	Name() string    // package local object name
	Type() Type      // object type
	Exported() bool  // reports whether the name starts with a capital letter
	Id() string      // object name if exported, qualified name if not exported (see func Id)

	// String returns a human-readable string of the object.
	String() string

	// order reflects a package-level object's source order: if object
	// a is before object b in the source, then a.order() < b.order().
	// order returns a value > 0 for package-level objects; it returns
	// 0 for all other objects (including objects in file scopes).
	order() uint32

	// color returns the object's color.
	color() color

	// setType sets the type of the object.
	setType(Type)

	// setOrder sets the order number of the object. It must be > 0.
	setOrder(uint32)

	// setColor sets the object's color. It must not be white.
	setColor(color color)

	// setParent sets the parent scope of the object.
	setParent(*Scope)

	// sameId reports whether obj.Id() and Id(pkg, name) are the same.
	sameId(pkg *Package, name string) bool

	// scopePos returns the start position of the scope of this Object
	scopePos() syntax.Pos

	// setScopePos sets the start position of the scope for this Object.
	setScopePos(pos syntax.Pos)
}

该接口申明的方法比较多,但基本都是属性的 Getter 或者 Setter 方法,公用信息定义在结构type object struct{...}中,具体声明如下:

type object struct {
	parent    *Scope
	pos       syntax.Pos
	pkg       *Package
	name      string
	typ       Type
	order_    uint32
	color_    color
	scopePos_ syntax.Pos
}

4.4.3.2. 具体Object类型

编译器一共定义了 8 类 Object, 包括:

  • PagName: 包对象

  • Const: 常量对象

  • TypeName: 代表通过type关键字定义的类型,或者类型别名

  • Var: 代表一个变量声明,通过用来表示函数的参数、返回值,以及结构体的 Field

  • Func: 代表一个方法、函数声明,或者接口内的方法声明

  • Label: 代表程序内的一个 label, 用于 break, goto 等关键字;其没有 type 属性

  • Builtin: 代表一个内置函数

  • Nil: 代表 nil 值

  • dependency: 用来标识初始化表达式可能依赖的对象,只有Const, Var, 以及Func是合法的该类对象。该类对象用于构建全局变量的初始化顺序,这在后面会有详细介绍。

每种类型的自定义属性并不多,基本都只是复用了 object, 所以在这里就不一一列举代码了,详情请读者自行查阅$GCROOT/compile/internal/types2/object.go。

4.4.3.3. Object对象的等价性

4.4.3.4. Object的作用

上一页4.4.2 数据结构 - Package下一页4.4.4-1 类型数据结构 - 简介

最后更新于3年前

这有帮助吗?

object 完整地实现了Object接口。其中color_属性用于后期的,而typ属性用来保存该对象的实际类型,类型推导目的就是要为每个对象推导出该属性,一节将会详细介绍各种类型的数据结构。

每个 Object 对象都代表着程序的一个符号,所以只有指向同一个符号的两个 Object 对象才是等价的,而在不同作用域的两个符号即使在结构上完全一样,也是不同的对象,这一点与类型的等价规则不同。会在后面详细介绍。

Object 对象是类型检查的重要数据结构,准确地说,该对象的内部封装了符号对象的各方面信息:包、作用域、类型、位置信息等;每一个 Object 都与 AST 中的一个节点(Node)对应,类型检查器保存了这两类信息的映射关系( 的 objMap 属性)。

类型检查的目的,就是将所有 Object 对象的类型属性,即 object 中的 typ 属性推导出来,并检查整个类型系统的兼容性。事实上,类型检查的整个逻辑都是围绕着 Object 对象展开的,我们会在一节对其进行详细分析。在此之前,我们先来熟悉一下编译器内部的类型数据结构。

类型的等价规则
类型检查逻辑
对象循环依赖检查
Checker
类型数据结构