aboutsummaryrefslogtreecommitdiff
path: root/vendor/honnef.co/go/tools/internal/passes/buildssa/buildssa.go
diff options
context:
space:
mode:
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.go116
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.
11package buildssa
12
13import (
14 "go/ast"
15 "go/types"
16 "reflect"
17
18 "golang.org/x/tools/go/analysis"
19 "honnef.co/go/tools/ssa"
20)
21
22var 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.
31type SSA struct {
32 Pkg *ssa.Package
33 SrcFuncs []*ssa.Function
34}
35
36func 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}