1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 //lint:file-ignore SA1019 go/ssa's test suite is built around the deprecated go/loader. We'll leave fixing that to upstream.
7 // Incomplete source tree on Android.
13 // This file runs the IR builder in sanity-checking mode on all
14 // packages beneath $GOROOT and prints some summary information.
16 // Run with "go test -cpu=8 to" set GOMAXPROCS.
25 "honnef.co/go/tools/go/ir"
26 "honnef.co/go/tools/go/ir/irutil"
28 "golang.org/x/tools/go/packages"
31 func bytesAllocated() uint64 {
33 var stats runtime.MemStats
34 runtime.ReadMemStats(&stats)
35 return stats.TotalAlloc
38 func TestStdlib(t *testing.T) {
40 t.Skip("skipping in short mode; too slow (golang.org/issue/14113)")
55 // Load, parse and type-check the program.
57 alloc0 := bytesAllocated()
59 cfg := &packages.Config{
60 Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedTypesSizes,
62 pkgs, err := packages.Load(cfg, "std")
64 t.Fatalf("Load failed: %v", err)
66 allocLoad = bytesAllocated() - alloc0
67 dLoad = time.Since(t0)
69 alloc0 = bytesAllocated()
70 for _, pkg := range pkgs {
71 if len(pkg.Errors) != 0 {
72 t.Fatalf("Load failed: %v", pkg.Errors)
75 var mode ir.BuilderMode
76 // Comment out these lines during benchmarking. Approx IR build costs are noted.
77 mode |= ir.SanityCheckFunctions // + 2% space, + 4% time
78 mode |= ir.GlobalDebug // +30% space, +18% time
79 prog := ir.NewProgram(pkg.Fset, mode)
83 for _, pkg2 := range pkgs {
84 r := prog.CreatePackage(pkg2.Types, pkg2.Syntax, pkg2.TypesInfo, true)
89 dCreate += time.Since(t0)
93 dBuild += time.Since(t0)
95 allFuncs := irutil.AllFunctions(prog)
96 numFuncs += len(allFuncs)
98 // Check that all non-synthetic functions have distinct names.
99 // Synthetic wrappers for exported methods should be distinct too,
100 // except for unexported ones (explained at (*Function).RelString).
101 byName := make(map[string]*ir.Function)
102 for fn := range allFuncs {
103 if fn.Synthetic == 0 || ast.IsExported(fn.Name()) {
108 t.Errorf("%s: duplicate function named %s",
109 prog.Fset.Position(fn.Pos()), str)
110 t.Errorf("%s: (previously defined here)",
111 prog.Fset.Position(prev.Pos()))
116 // Dump some statistics.
118 for fn := range allFuncs {
119 for _, b := range fn.Blocks {
120 numInstrs += len(b.Instrs)
124 allocBuild = bytesAllocated() - alloc0
126 // determine line count
128 pkgs[0].Fset.Iterate(func(f *token.File) bool {
129 lineCount += f.LineCount()
133 // NB: when benchmarking, don't forget to clear the debug +
134 // sanity builder flags for better performance.
136 t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0))
137 t.Log("#Source lines: ", lineCount)
138 t.Log("Load/parse/typecheck: ", dLoad)
139 t.Log("IR create: ", dCreate)
140 t.Log("IR build: ", dBuild)
143 t.Log("#Packages: ", len(pkgs))
144 t.Log("#Functions: ", numFuncs)
145 t.Log("#Instructions: ", numInstrs)
146 t.Log("#MB AST+types: ", allocLoad/1e6)
147 t.Log("#MB IR: ", allocBuild/1e6)