mirror of
https://github.com/golang/go
synced 2024-11-19 10:04:56 -07:00
2a3a12930b
stdlib_test runs the builder (in sanity-checking mode) over the Go standard library. It also prints some stats about the time and memory usage. Also: - importer.LoadPackage too (not just doImport) must consult the cache to avoid creating duplicate Package instances for the same import path when called serially from a test. - importer: skip empty directories without an error. - importer: print all errors, not just the first. - visit.go: added AllFunctions utility for enumerating all Functions in a Program. - ssa.MethodSet is not safe to expose from the package since it must be accessed under an (inaccessible) lock. (!!!) This CL makes it unexported and restricts its use to the single function Program.LookupMethod(). - Program.MethodSet() has gone. Clients should instead iterate over the types.MethodSet and call LookupMethod. - Package.DumpTo(): improved efficiency of methodset printing (by not creating wrappers) and accuracy (by showing * on receiver type only when necessary). - Program.CreatePackage: documented precondition and added assertion. R=gri CC=golang-dev https://golang.org/cl/12058048
74 lines
1.7 KiB
Go
74 lines
1.7 KiB
Go
package ssa
|
|
|
|
// This file defines utilities for visiting the SSA representation of
|
|
// a Program.
|
|
//
|
|
// TODO(adonovan): improve the API:
|
|
// - permit client to supply a callback for each function,
|
|
// instruction, type with methods, etc?
|
|
// - return graph information about the traversal?
|
|
// - test coverage.
|
|
|
|
import "code.google.com/p/go.tools/go/types"
|
|
|
|
// AllFunctions returns the set of all functions (including anonymous
|
|
// functions and synthetic wrappers) in program prog.
|
|
//
|
|
// Precondition: all packages are built.
|
|
//
|
|
func AllFunctions(prog *Program) map[*Function]bool {
|
|
visit := visitor{
|
|
prog: prog,
|
|
seen: make(map[*Function]bool),
|
|
}
|
|
visit.program()
|
|
return visit.seen
|
|
}
|
|
|
|
type visitor struct {
|
|
prog *Program
|
|
seen map[*Function]bool
|
|
}
|
|
|
|
func (visit *visitor) program() {
|
|
for _, pkg := range visit.prog.PackagesByPath {
|
|
for _, mem := range pkg.Members {
|
|
switch mem := mem.(type) {
|
|
case *Function:
|
|
visit.function(mem)
|
|
case *Type:
|
|
visit.methodSet(mem.Type())
|
|
visit.methodSet(types.NewPointer(mem.Type()))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (visit *visitor) methodSet(typ types.Type) {
|
|
mset := methodSetOf(typ)
|
|
for i, n := 0, mset.Len(); i < n; i++ {
|
|
// Side-effect: creates all wrapper methods.
|
|
visit.function(visit.prog.LookupMethod(mset.At(i)))
|
|
}
|
|
}
|
|
|
|
func (visit *visitor) function(fn *Function) {
|
|
if !visit.seen[fn] {
|
|
visit.seen[fn] = true
|
|
for _, b := range fn.Blocks {
|
|
for _, instr := range b.Instrs {
|
|
switch instr := instr.(type) {
|
|
case *MakeInterface:
|
|
visit.methodSet(instr.X.Type())
|
|
}
|
|
var buf [10]*Value // avoid alloc in common case
|
|
for _, op := range instr.Operands(buf[:0]) {
|
|
if fn, ok := (*op).(*Function); ok {
|
|
visit.function(fn)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|