...
1
2
3
4
5
6
7
8
9 package buildssa
10
11 import (
12 "go/ast"
13 "go/types"
14 "reflect"
15
16 "golang.org/x/tools/go/analysis"
17 "golang.org/x/tools/go/ssa"
18 )
19
20 var Analyzer = &analysis.Analyzer{
21 Name: "buildssa",
22 Doc: "build SSA-form IR for later passes",
23 URL: "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/buildssa",
24 Run: run,
25 ResultType: reflect.TypeOf(new(SSA)),
26 }
27
28
29
30 type SSA struct {
31 Pkg *ssa.Package
32 SrcFuncs []*ssa.Function
33 }
34
35 func run(pass *analysis.Pass) (interface{}, error) {
36
37
38
39
40
41
42
43
44
45
46
47
48 mode := ssa.BuilderMode(0)
49
50 prog := ssa.NewProgram(pass.Fset, mode)
51
52
53 for _, p := range pass.Pkg.Imports() {
54 prog.CreatePackage(p, nil, nil, true)
55 }
56
57
58 ssapkg := prog.CreatePackage(pass.Pkg, pass.Files, pass.TypesInfo, false)
59 ssapkg.Build()
60
61
62
63 var funcs []*ssa.Function
64 for _, f := range pass.Files {
65 for _, decl := range f.Decls {
66 if fdecl, ok := decl.(*ast.FuncDecl); ok {
67
68
69
70
71 fn := pass.TypesInfo.Defs[fdecl.Name].(*types.Func)
72 if fn == nil {
73 panic(fn)
74 }
75
76 f := ssapkg.Prog.FuncValue(fn)
77 if f == nil {
78 panic(fn)
79 }
80
81 var addAnons func(f *ssa.Function)
82 addAnons = func(f *ssa.Function) {
83 funcs = append(funcs, f)
84 for _, anon := range f.AnonFuncs {
85 addAnons(anon)
86 }
87 }
88 addAnons(f)
89 }
90 }
91 }
92
93 return &SSA{Pkg: ssapkg, SrcFuncs: funcs}, nil
94 }
95
View as plain text