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.
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.
10 // THIS INTERFACE IS EXPERIMENTAL AND MAY BE SUBJECT TO INCOMPATIBLE CHANGE.
18 "golang.org/x/tools/go/analysis"
19 "golang.org/x/tools/go/ssa"
22 var Analyzer = &analysis.Analyzer{
24 Doc: "build SSA-form IR for later passes",
26 ResultType: reflect.TypeOf(new(SSA)),
29 // SSA provides SSA-form intermediate representation for all the
30 // non-blank source functions in the current package.
33 SrcFuncs []*ssa.Function
36 func run(pass *analysis.Pass) (interface{}, error) {
37 // Plundered from ssautil.BuildPackage.
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.
49 // Some Analyzers may need GlobalDebug, in which case we'll have
50 // to set it globally, but let's wait till we need it.
51 mode := ssa.BuilderMode(0)
53 prog := ssa.NewProgram(pass.Fset, mode)
55 // Create SSA packages for all imports.
56 // Order is not significant.
57 created := make(map[*types.Package]bool)
58 var createAll func(pkgs []*types.Package)
59 createAll = func(pkgs []*types.Package) {
60 for _, p := range pkgs {
63 prog.CreatePackage(p, nil, nil, true)
64 createAll(p.Imports())
68 createAll(pass.Pkg.Imports())
70 // Create and build the primary package.
71 ssapkg := prog.CreatePackage(pass.Pkg, pass.Files, pass.TypesInfo, false)
74 // Compute list of source functions, including literals,
76 var funcs []*ssa.Function
77 for _, f := range pass.Files {
78 for _, decl := range f.Decls {
79 if fdecl, ok := decl.(*ast.FuncDecl); ok {
81 // SSA will not build a Function
82 // for a FuncDecl named blank.
83 // That's arguably too strict but
84 // relaxing it would break uniqueness of
85 // names of package members.
86 if fdecl.Name.Name == "_" {
90 // (init functions have distinct Func
91 // objects named "init" and distinct
92 // ssa.Functions named "init#1", ...)
94 fn := pass.TypesInfo.Defs[fdecl.Name].(*types.Func)
99 f := ssapkg.Prog.FuncValue(fn)
104 var addAnons func(f *ssa.Function)
105 addAnons = func(f *ssa.Function) {
106 funcs = append(funcs, f)
107 for _, anon := range f.AnonFuncs {
116 return &SSA{Pkg: ssapkg, SrcFuncs: funcs}, nil