5.5 编译日志

如果查看 irgen.generate() 的完整代码,可以发现如下代码片段:

if base.Flag.W > 1 {
    for _, n := range g.target.Decls {
        s := fmt.Sprintf("\nafter noder2 %v", n)
        ir.Dump(s, n)
    }
}

可见 IR Tree 并没有完全隐藏在编译器内部,而是可以通过编译参数 -W 来查看,并且编译器不仅会 dump 出 IR Tree 的结构,还会 dump 出泛型函数实例化时所做的改变。我们通过一个例子来查看一下。

将下列代码保存为 main.go:

package main

import "fmt"

func genericFun[T any](i, j T)  {
    fmt.Printf("i: %v, j: %v\n",i, j)
}

func main() {
    genericFun(5,6)
    genericFun[float32](10.5, 11.8)
}

通过命令 go tool compile -G=2 -W=2 main.go 进行编译即可看到如下结果:

前两个以 after noder2 开头的结构分别对应两个函数申明,这是 Step 3 完成之后 IR Tree 的总体结构,可以看到其中还包括泛型信息;而随后的信息是泛型函数实例化的 dump 信息,以 stenciled 开头的两个函数 genericFun[int]genericFun[float32] 便是生成的实例化函数,最后 modified main 是修改之后的 main 函数,可以发现此时 main 函数内部直接调用的是实例化函数,已经抹掉了有关泛型的所有信息。

编译参数加上 -G=2 是为了启用泛型支持以便调用新的类型检查逻辑,并且在创建 IR Tree 完成之后退出编译,否则会 dump 出非常多的信息。可以在 irgen.go 的函数 check2() 中查看该 flag 的使用方式。

最后更新于

这有帮助吗?