diff options
Diffstat (limited to 'vendor/honnef.co/go/tools/internal/passes/buildssa/buildssa.go')
-rw-r--r-- | vendor/honnef.co/go/tools/internal/passes/buildssa/buildssa.go | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/vendor/honnef.co/go/tools/internal/passes/buildssa/buildssa.go b/vendor/honnef.co/go/tools/internal/passes/buildssa/buildssa.go new file mode 100644 index 0000000..fde918d --- /dev/null +++ b/vendor/honnef.co/go/tools/internal/passes/buildssa/buildssa.go | |||
@@ -0,0 +1,116 @@ | |||
1 | // Copyright 2018 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. | ||
4 | |||
5 | // Package buildssa defines an Analyzer that constructs the SSA | ||
6 | // representation of an error-free package and returns the set of all | ||
7 | // functions within it. It does not report any diagnostics itself but | ||
8 | // may be used as an input to other analyzers. | ||
9 | // | ||
10 | // THIS INTERFACE IS EXPERIMENTAL AND MAY BE SUBJECT TO INCOMPATIBLE CHANGE. | ||
11 | package buildssa | ||
12 | |||
13 | import ( | ||
14 | "go/ast" | ||
15 | "go/types" | ||
16 | "reflect" | ||
17 | |||
18 | "golang.org/x/tools/go/analysis" | ||
19 | "honnef.co/go/tools/ssa" | ||
20 | ) | ||
21 | |||
22 | var Analyzer = &analysis.Analyzer{ | ||
23 | Name: "buildssa", | ||
24 | Doc: "build SSA-form IR for later passes", | ||
25 | Run: run, | ||
26 | ResultType: reflect.TypeOf(new(SSA)), | ||
27 | } | ||
28 | |||
29 | // SSA provides SSA-form intermediate representation for all the | ||
30 | // non-blank source functions in the current package. | ||
31 | type SSA struct { | ||
32 | Pkg *ssa.Package | ||
33 | SrcFuncs []*ssa.Function | ||
34 | } | ||
35 | |||
36 | func run(pass *analysis.Pass) (interface{}, error) { | ||
37 | // Plundered from ssautil.BuildPackage. | ||
38 | |||
39 | // We must create a new Program for each Package because the | ||
40 | // analysis API provides no place to hang a Program shared by | ||
41 | // all Packages. Consequently, SSA Packages and Functions do not | ||
42 | // have a canonical representation across an analysis session of | ||
43 | // multiple packages. This is unlikely to be a problem in | ||
44 | // practice because the analysis API essentially forces all | ||
45 | // packages to be analysed independently, so any given call to | ||
46 | // Analysis.Run on a package will see only SSA objects belonging | ||
47 | // to a single Program. | ||
48 | |||
49 | mode := ssa.GlobalDebug | ||
50 | |||
51 | prog := ssa.NewProgram(pass.Fset, mode) | ||
52 | |||
53 | // Create SSA packages for all imports. | ||
54 | // Order is not significant. | ||
55 | created := make(map[*types.Package]bool) | ||
56 | var createAll func(pkgs []*types.Package) | ||
57 | createAll = func(pkgs []*types.Package) { | ||
58 | for _, p := range pkgs { | ||
59 | if !created[p] { | ||
60 | created[p] = true | ||
61 | prog.CreatePackage(p, nil, nil, true) | ||
62 | createAll(p.Imports()) | ||
63 | } | ||
64 | } | ||
65 | } | ||
66 | createAll(pass.Pkg.Imports()) | ||
67 | |||
68 | // Create and build the primary package. | ||
69 | ssapkg := prog.CreatePackage(pass.Pkg, pass.Files, pass.TypesInfo, false) | ||
70 | ssapkg.Build() | ||
71 | |||
72 | // Compute list of source functions, including literals, | ||
73 | // in source order. | ||
74 | var funcs []*ssa.Function | ||
75 | var addAnons func(f *ssa.Function) | ||
76 | addAnons = func(f *ssa.Function) { | ||
77 | funcs = append(funcs, f) | ||
78 | for _, anon := range f.AnonFuncs { | ||
79 | addAnons(anon) | ||
80 | } | ||
81 | } | ||
82 | addAnons(ssapkg.Members["init"].(*ssa.Function)) | ||
83 | for _, f := range pass.Files { | ||
84 | for _, decl := range f.Decls { | ||
85 | if fdecl, ok := decl.(*ast.FuncDecl); ok { | ||
86 | |||
87 | // SSA will not build a Function | ||
88 | // for a FuncDecl named blank. | ||
89 | // That's arguably too strict but | ||
90 | // relaxing it would break uniqueness of | ||
91 | // names of package members. | ||
92 | if fdecl.Name.Name == "_" { | ||
93 | continue | ||
94 | } | ||
95 | |||
96 | // (init functions have distinct Func | ||
97 | // objects named "init" and distinct | ||
98 | // ssa.Functions named "init#1", ...) | ||
99 | |||
100 | fn := pass.TypesInfo.Defs[fdecl.Name].(*types.Func) | ||
101 | if fn == nil { | ||
102 | panic(fn) | ||
103 | } | ||
104 | |||
105 | f := ssapkg.Prog.FuncValue(fn) | ||
106 | if f == nil { | ||
107 | panic(fn) | ||
108 | } | ||
109 | |||
110 | addAnons(f) | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | |||
115 | return &SSA{Pkg: ssapkg, SrcFuncs: funcs}, nil | ||
116 | } | ||