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 "golang.org/x/tools/go/packages"
26 "honnef.co/go/tools/ir"
27 "honnef.co/go/tools/ir/irutil"
30 func bytesAllocated() uint64 {
32 var stats runtime.MemStats
33 runtime.ReadMemStats(&stats)
34 return stats.TotalAlloc
37 func TestStdlib(t *testing.T) {
39 t.Skip("skipping in short mode; too slow (golang.org/issue/14113)")
54 // Load, parse and type-check the program.
56 alloc0 := bytesAllocated()
58 cfg := &packages.Config{
59 Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedTypesSizes,
61 pkgs, err := packages.Load(cfg, "std")
63 t.Fatalf("Load failed: %v", err)
65 allocLoad = bytesAllocated() - alloc0
66 dLoad = time.Since(t0)
68 alloc0 = bytesAllocated()
69 for _, pkg := range pkgs {
70 if len(pkg.Errors) != 0 {
71 t.Fatalf("Load failed: %v", pkg.Errors)
74 var mode ir.BuilderMode
75 // Comment out these lines during benchmarking. Approx IR build costs are noted.
76 mode |= ir.SanityCheckFunctions // + 2% space, + 4% time
77 mode |= ir.GlobalDebug // +30% space, +18% time
78 prog := ir.NewProgram(pkg.Fset, mode)
82 for _, pkg2 := range pkgs {
83 r := prog.CreatePackage(pkg2.Types, pkg2.Syntax, pkg2.TypesInfo, true)
88 dCreate += time.Since(t0)
92 dBuild += time.Since(t0)
94 allFuncs := irutil.AllFunctions(prog)
95 numFuncs += len(allFuncs)
97 // Check that all non-synthetic functions have distinct names.
98 // Synthetic wrappers for exported methods should be distinct too,
99 // except for unexported ones (explained at (*Function).RelString).
100 byName := make(map[string]*ir.Function)
101 for fn := range allFuncs {
102 if fn.Synthetic == "" || ast.IsExported(fn.Name()) {
107 t.Errorf("%s: duplicate function named %s",
108 prog.Fset.Position(fn.Pos()), str)
109 t.Errorf("%s: (previously defined here)",
110 prog.Fset.Position(prev.Pos()))
115 // Dump some statistics.
117 for fn := range allFuncs {
118 for _, b := range fn.Blocks {
119 numInstrs += len(b.Instrs)
123 allocBuild = bytesAllocated() - alloc0
125 // determine line count
127 pkgs[0].Fset.Iterate(func(f *token.File) bool {
128 lineCount += f.LineCount()
132 // NB: when benchmarking, don't forget to clear the debug +
133 // sanity builder flags for better performance.
135 t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0))
136 t.Log("#Source lines: ", lineCount)
137 t.Log("Load/parse/typecheck: ", dLoad)
138 t.Log("IR create: ", dCreate)
139 t.Log("IR build: ", dBuild)
142 t.Log("#Packages: ", len(pkgs))
143 t.Log("#Functions: ", numFuncs)
144 t.Log("#Instructions: ", numInstrs)
145 t.Log("#MB AST+types: ", allocLoad/1e6)
146 t.Log("#MB IR: ", allocBuild/1e6)