GoPLS Viewer

Home|gopls/go/ssa/ssautil/visit.go
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.
4
5package ssautil // import "golang.org/x/tools/go/ssa/ssautil"
6
7import "golang.org/x/tools/go/ssa"
8
9// This file defines utilities for visiting the SSA representation of
10// a Program.
11//
12// TODO(adonovan): test coverage.
13
14// AllFunctions finds and returns the set of functions potentially
15// needed by program prog, as determined by a simple linker-style
16// reachability algorithm starting from the members and method-sets of
17// each package.  The result may include anonymous functions and
18// synthetic wrappers.
19//
20// Precondition: all packages are built.
21func AllFunctions(prog *ssa.Program) map[*ssa.Function]bool {
22    visit := visitor{
23        progprog,
24        seenmake(map[*ssa.Function]bool),
25    }
26    visit.program()
27    return visit.seen
28}
29
30type visitor struct {
31    prog *ssa.Program
32    seen map[*ssa.Function]bool
33}
34
35func (visit *visitorprogram() {
36    for _pkg := range visit.prog.AllPackages() {
37        for _mem := range pkg.Members {
38            if fnok := mem.(*ssa.Function); ok {
39                visit.function(fn)
40            }
41        }
42    }
43    for _T := range visit.prog.RuntimeTypes() {
44        mset := visit.prog.MethodSets.MethodSet(T)
45        for in := 0mset.Len(); i < ni++ {
46            visit.function(visit.prog.MethodValue(mset.At(i)))
47        }
48    }
49}
50
51func (visit *visitorfunction(fn *ssa.Function) {
52    if !visit.seen[fn] {
53        visit.seen[fn] = true
54        var buf [10]*ssa.Value // avoid alloc in common case
55        for _b := range fn.Blocks {
56            for _instr := range b.Instrs {
57                for _op := range instr.Operands(buf[:0]) {
58                    if fnok := (*op).(*ssa.Function); ok {
59                        visit.function(fn)
60                    }
61                }
62            }
63        }
64    }
65}
66
67// MainPackages returns the subset of the specified packages
68// named "main" that define a main function.
69// The result may include synthetic "testmain" packages.
70func MainPackages(pkgs []*ssa.Package) []*ssa.Package {
71    var mains []*ssa.Package
72    for _pkg := range pkgs {
73        if pkg.Pkg.Name() == "main" && pkg.Func("main") != nil {
74            mains = append(mainspkg)
75        }
76    }
77    return mains
78}
79
MembersX
AllFunctions.prog
visitor.seen
visitor.program
visitor.program.RangeStmt_1001.BlockStmt.RangeStmt_1050.mem
visitor.function.BlockStmt.RangeStmt_1513.b
visitor.function.BlockStmt.RangeStmt_1513.BlockStmt.RangeStmt_1546.BlockStmt.RangeStmt_1583.op
MainPackages.pkgs
AllFunctions
MainPackages.RangeStmt_1973.pkg
MainPackages.mains
visitor.prog
visitor.program.RangeStmt_1162.BlockStmt.mset
visitor.program.RangeStmt_1162.BlockStmt.n
visitor.function
visitor.function.fn
visitor.function.BlockStmt.RangeStmt_1513.BlockStmt.RangeStmt_1546.instr
AllFunctions.visit
visitor.program.visit
visitor.program.RangeStmt_1162.BlockStmt.i
MainPackages
visitor
visitor.program.RangeStmt_1162.T
visitor.function.visit
visitor.function.BlockStmt.buf
visitor.program.RangeStmt_1001.pkg
Members
X