go.tools/call: rename package to go/callgraph
Was: Now: call.Graph callgraph.Graph call.GraphNode callgraph.Node call.Edge callgraph.Edge Though call.Graph was cute, the original naming was a mistake: 'call' is too useful a var name to waste on a package. R=gri, crawshaw CC=golang-codereviews https://golang.org/cl/53190043
This commit is contained in:
parent
3fc0fc1310
commit
b856247075
|
@ -4,7 +4,7 @@
|
|||
|
||||
/*
|
||||
|
||||
Package call defines the call graph abstraction and various algorithms
|
||||
Package callgraph defines the call graph abstraction and various algorithms
|
||||
and utilities to operate on it. It does not provide a concrete
|
||||
implementation but permits other analyses (such as pointer analyses or
|
||||
Rapid Type Analysis) to expose their own call graphs in a
|
||||
|
@ -56,7 +56,7 @@ in the call graph; they are treated like built-in operators of the
|
|||
language.
|
||||
|
||||
*/
|
||||
package call
|
||||
package callgraph
|
||||
|
||||
import "code.google.com/p/go.tools/go/ssa"
|
||||
|
||||
|
@ -67,14 +67,14 @@ import "code.google.com/p/go.tools/go/ssa"
|
|||
// functions.
|
||||
//
|
||||
type Graph interface {
|
||||
Root() GraphNode // the distinguished root node
|
||||
Nodes() []GraphNode // new unordered set of all nodes
|
||||
Root() Node // the distinguished root node
|
||||
Nodes() []Node // new unordered set of all nodes
|
||||
}
|
||||
|
||||
// A GraphNode represents a node in a call graph.
|
||||
// A Node represents a node in a call graph.
|
||||
//
|
||||
// If the call graph is context sensitive, there may be multiple
|
||||
// GraphNodes with the same Func(); the identity of the graph node
|
||||
// Nodes with the same Func(); the identity of the graph node
|
||||
// indicates the context.
|
||||
//
|
||||
// Sites returns the set of syntactic call sites within this function.
|
||||
|
@ -94,7 +94,7 @@ type Graph interface {
|
|||
//
|
||||
// Clients should not mutate the node via the results of its methods.
|
||||
//
|
||||
type GraphNode interface {
|
||||
type Node interface {
|
||||
Func() *ssa.Function // the function this node represents
|
||||
Sites() []ssa.CallInstruction // new unordered set of call sites within this function
|
||||
Edges() []Edge // new unordered set of outgoing edges
|
||||
|
@ -102,7 +102,7 @@ type GraphNode interface {
|
|||
|
||||
// A Edge represents an edge in the call graph.
|
||||
type Edge struct {
|
||||
Caller GraphNode
|
||||
Caller Node
|
||||
Site ssa.CallInstruction
|
||||
Callee GraphNode
|
||||
Callee Node
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package call
|
||||
package callgraph
|
||||
|
||||
// This file provides various representation-independent utilities
|
||||
// over call graphs, such as visitation and path search.
|
||||
|
@ -13,7 +13,7 @@ package call
|
|||
// FindSitesByPos(g Graph, lparen token.Pos) []Site
|
||||
// FindSitesByCallExpr(g Graph, expr *ast.CallExpr) []Site
|
||||
// FindSitesByInstr(g Graph, instr ssa.CallInstruction) []Site
|
||||
// FindNodesByFunc(g Graph, fn *ssa.Function) []GraphNode
|
||||
// FindNodesByFunc(g Graph, fn *ssa.Function) []Node
|
||||
// (Counterargument: they're all inefficient linear scans; if the
|
||||
// caller does it explicitly there may be opportunities to optimize.
|
||||
//
|
||||
|
@ -22,8 +22,8 @@ package call
|
|||
// CalleesOf returns a new set containing all direct callees of the
|
||||
// caller node.
|
||||
//
|
||||
func CalleesOf(caller GraphNode) map[GraphNode]bool {
|
||||
callees := make(map[GraphNode]bool)
|
||||
func CalleesOf(caller Node) map[Node]bool {
|
||||
callees := make(map[Node]bool)
|
||||
for _, e := range caller.Edges() {
|
||||
callees[e.Callee] = true
|
||||
}
|
||||
|
@ -36,9 +36,9 @@ func CalleesOf(caller GraphNode) map[GraphNode]bool {
|
|||
// value.
|
||||
//
|
||||
func GraphVisitEdges(g Graph, edge func(Edge) error) error {
|
||||
seen := make(map[GraphNode]bool)
|
||||
var visit func(n GraphNode) error
|
||||
visit = func(n GraphNode) error {
|
||||
seen := make(map[Node]bool)
|
||||
var visit func(n Node) error
|
||||
visit = func(n Node) error {
|
||||
if !seen[n] {
|
||||
seen[n] = true
|
||||
for _, e := range n.Edges() {
|
||||
|
@ -65,11 +65,11 @@ func GraphVisitEdges(g Graph, edge func(Edge) error) error {
|
|||
// PathSearch returns the path as an ordered list of edges; on
|
||||
// failure, it returns nil.
|
||||
//
|
||||
func PathSearch(start GraphNode, isEnd func(GraphNode) bool) []Edge {
|
||||
func PathSearch(start Node, isEnd func(Node) bool) []Edge {
|
||||
stack := make([]Edge, 0, 32)
|
||||
seen := make(map[GraphNode]bool)
|
||||
var search func(n GraphNode) []Edge
|
||||
search = func(n GraphNode) []Edge {
|
||||
seen := make(map[Node]bool)
|
||||
var search func(n Node) []Edge
|
||||
search = func(n Node) []Edge {
|
||||
if !seen[n] {
|
||||
seen[n] = true
|
||||
if isEnd(n) {
|
|
@ -10,7 +10,7 @@ import (
|
|||
"go/token"
|
||||
"io"
|
||||
|
||||
"code.google.com/p/go.tools/call"
|
||||
"code.google.com/p/go.tools/go/callgraph"
|
||||
"code.google.com/p/go.tools/go/ssa"
|
||||
"code.google.com/p/go.tools/go/types/typemap"
|
||||
)
|
||||
|
@ -107,7 +107,7 @@ type Warning struct {
|
|||
// See Config for how to request the various Result components.
|
||||
//
|
||||
type Result struct {
|
||||
CallGraph call.Graph // discovered call graph
|
||||
CallGraph callgraph.Graph // discovered call graph
|
||||
Queries map[ssa.Value][]Pointer // pts(v) for each v in Config.Queries.
|
||||
IndirectQueries map[ssa.Value][]Pointer // pts(*v) for each v in Config.IndirectQueries.
|
||||
Warnings []Warning // warnings of unsoundness
|
||||
|
@ -220,7 +220,7 @@ func (p Pointer) String() string {
|
|||
|
||||
// Context returns the context of this pointer,
|
||||
// if it corresponds to a local variable.
|
||||
func (p Pointer) Context() call.GraphNode {
|
||||
func (p Pointer) Context() callgraph.Node {
|
||||
return p.cgn
|
||||
}
|
||||
|
||||
|
|
|
@ -4,35 +4,35 @@
|
|||
|
||||
package pointer
|
||||
|
||||
// This file defines our implementation of the call.Graph API.
|
||||
// This file defines our implementation of the callgraph API.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
|
||||
"code.google.com/p/go.tools/call"
|
||||
"code.google.com/p/go.tools/go/callgraph"
|
||||
"code.google.com/p/go.tools/go/ssa"
|
||||
)
|
||||
|
||||
// cgraph implements call.Graph.
|
||||
// cgraph implements callgraph.Graph.
|
||||
type cgraph struct {
|
||||
root *cgnode
|
||||
nodes []*cgnode
|
||||
}
|
||||
|
||||
func (g *cgraph) Nodes() []call.GraphNode {
|
||||
nodes := make([]call.GraphNode, len(g.nodes))
|
||||
func (g *cgraph) Nodes() []callgraph.Node {
|
||||
nodes := make([]callgraph.Node, len(g.nodes))
|
||||
for i, node := range g.nodes {
|
||||
nodes[i] = node
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
func (g *cgraph) Root() call.GraphNode {
|
||||
func (g *cgraph) Root() callgraph.Node {
|
||||
return g.root
|
||||
}
|
||||
|
||||
// cgnode implements call.GraphNode.
|
||||
// cgnode implements callgraph.Node.
|
||||
type cgnode struct {
|
||||
fn *ssa.Function
|
||||
obj nodeid // start of this contour's object block
|
||||
|
@ -52,16 +52,16 @@ func (n *cgnode) Sites() []ssa.CallInstruction {
|
|||
return sites
|
||||
}
|
||||
|
||||
func (n *cgnode) Edges() []call.Edge {
|
||||
func (n *cgnode) Edges() []callgraph.Edge {
|
||||
var numEdges int
|
||||
for _, site := range n.sites {
|
||||
numEdges += len(site.callees)
|
||||
}
|
||||
edges := make([]call.Edge, 0, numEdges)
|
||||
edges := make([]callgraph.Edge, 0, numEdges)
|
||||
|
||||
for _, site := range n.sites {
|
||||
for _, callee := range site.callees {
|
||||
edges = append(edges, call.Edge{Caller: n, Site: site.instr, Callee: callee})
|
||||
edges = append(edges, callgraph.Edge{Caller: n, Site: site.instr, Callee: callee})
|
||||
}
|
||||
}
|
||||
return edges
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"fmt"
|
||||
"sort"
|
||||
|
||||
"code.google.com/p/go.tools/call"
|
||||
"code.google.com/p/go.tools/go/callgraph"
|
||||
"code.google.com/p/go.tools/go/loader"
|
||||
"code.google.com/p/go.tools/go/pointer"
|
||||
"code.google.com/p/go.tools/go/ssa"
|
||||
|
@ -75,7 +75,7 @@ func main() {
|
|||
// By converting to strings, we de-duplicate nodes
|
||||
// representing the same function due to context sensitivity.
|
||||
var edges []string
|
||||
call.GraphVisitEdges(result.CallGraph, func(edge call.Edge) error {
|
||||
callgraph.GraphVisitEdges(result.CallGraph, func(edge callgraph.Edge) error {
|
||||
caller := edge.Caller.Func()
|
||||
if caller.Pkg == mainPkg {
|
||||
edges = append(edges, fmt.Sprint(caller, " --> ", edge.Callee.Func()))
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"go/token"
|
||||
"strings"
|
||||
|
||||
"code.google.com/p/go.tools/call"
|
||||
"code.google.com/p/go.tools/go/callgraph"
|
||||
"code.google.com/p/go.tools/go/ssa"
|
||||
"code.google.com/p/go.tools/go/types"
|
||||
)
|
||||
|
@ -57,7 +57,7 @@ func (l Label) ReflectType() types.Type {
|
|||
// Context returns the analytic context in which this label's object was allocated,
|
||||
// or nil for global objects: global, const, and shared contours for functions.
|
||||
//
|
||||
func (l Label) Context() call.GraphNode {
|
||||
func (l Label) Context() callgraph.Node {
|
||||
return l.obj.cgn
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.google.com/p/go.tools/call"
|
||||
"code.google.com/p/go.tools/go/callgraph"
|
||||
"code.google.com/p/go.tools/go/loader"
|
||||
"code.google.com/p/go.tools/go/pointer"
|
||||
"code.google.com/p/go.tools/go/ssa"
|
||||
|
@ -451,9 +451,9 @@ func checkTypesExpectation(e *expectation, ptr pointer.Pointer, typ types.Type)
|
|||
|
||||
var errOK = errors.New("OK")
|
||||
|
||||
func checkCallsExpectation(prog *ssa.Program, e *expectation, callgraph call.Graph) bool {
|
||||
func checkCallsExpectation(prog *ssa.Program, e *expectation, cg callgraph.Graph) bool {
|
||||
found := make(map[string]int)
|
||||
err := call.GraphVisitEdges(callgraph, func(edge call.Edge) error {
|
||||
err := callgraph.GraphVisitEdges(cg, func(edge callgraph.Edge) error {
|
||||
// Name-based matching is inefficient but it allows us to
|
||||
// match functions whose names that would not appear in an
|
||||
// index ("<root>") or which are not unique ("func@1.2").
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"fmt"
|
||||
"go/token"
|
||||
|
||||
"code.google.com/p/go.tools/call"
|
||||
"code.google.com/p/go.tools/go/callgraph"
|
||||
"code.google.com/p/go.tools/go/ssa"
|
||||
"code.google.com/p/go.tools/oracle/serial"
|
||||
)
|
||||
|
@ -37,9 +37,9 @@ func callers(o *Oracle, qpos *QueryPos) (queryResult, error) {
|
|||
// Run the pointer analysis, recording each
|
||||
// call found to originate from target.
|
||||
o.ptaConfig.BuildCallGraph = true
|
||||
callgraph := ptrAnalysis(o).CallGraph
|
||||
var edges []call.Edge
|
||||
call.GraphVisitEdges(callgraph, func(edge call.Edge) error {
|
||||
cg := ptrAnalysis(o).CallGraph
|
||||
var edges []callgraph.Edge
|
||||
callgraph.GraphVisitEdges(cg, func(edge callgraph.Edge) error {
|
||||
if edge.Callee.Func() == target {
|
||||
edges = append(edges, edge)
|
||||
}
|
||||
|
@ -49,15 +49,15 @@ func callers(o *Oracle, qpos *QueryPos) (queryResult, error) {
|
|||
|
||||
return &callersResult{
|
||||
target: target,
|
||||
callgraph: callgraph,
|
||||
callgraph: cg,
|
||||
edges: edges,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type callersResult struct {
|
||||
target *ssa.Function
|
||||
callgraph call.Graph
|
||||
edges []call.Edge
|
||||
callgraph callgraph.Graph
|
||||
edges []callgraph.Edge
|
||||
}
|
||||
|
||||
func (r *callersResult) display(printf printfFunc) {
|
||||
|
|
|
@ -8,12 +8,12 @@ import (
|
|||
"go/token"
|
||||
"sort"
|
||||
|
||||
"code.google.com/p/go.tools/call"
|
||||
"code.google.com/p/go.tools/go/callgraph"
|
||||
"code.google.com/p/go.tools/go/ssa"
|
||||
"code.google.com/p/go.tools/oracle/serial"
|
||||
)
|
||||
|
||||
// callgraph displays the entire callgraph of the current program.
|
||||
// doCallgraph displays the entire callgraph of the current program.
|
||||
//
|
||||
// Nodes may be seem to appear multiple times due to (limited)
|
||||
// context sensitivity.
|
||||
|
@ -28,7 +28,7 @@ import (
|
|||
//
|
||||
// TODO(adonovan): elide nodes for synthetic functions?
|
||||
//
|
||||
func callgraph(o *Oracle, _ *QueryPos) (queryResult, error) {
|
||||
func doCallgraph(o *Oracle, _ *QueryPos) (queryResult, error) {
|
||||
buildSSA(o)
|
||||
|
||||
// Run the pointer analysis and build the complete callgraph.
|
||||
|
@ -41,7 +41,7 @@ func callgraph(o *Oracle, _ *QueryPos) (queryResult, error) {
|
|||
}
|
||||
|
||||
type callgraphResult struct {
|
||||
callgraph call.Graph
|
||||
callgraph callgraph.Graph
|
||||
}
|
||||
|
||||
func (r *callgraphResult) display(printf printfFunc) {
|
||||
|
@ -57,9 +57,9 @@ Non-numbered nodes indicate back- or cross-edges to the node whose
|
|||
ci := make(map[*ssa.Function]map[*ssa.Function]bool)
|
||||
|
||||
// 1. Visit the CS call graph and build the CI call graph.
|
||||
visited := make(map[call.GraphNode]bool)
|
||||
var visit func(caller call.GraphNode)
|
||||
visit = func(caller call.GraphNode) {
|
||||
visited := make(map[callgraph.Node]bool)
|
||||
var visit func(caller callgraph.Node)
|
||||
visit = func(caller callgraph.Node) {
|
||||
if !visited[caller] {
|
||||
visited[caller] = true
|
||||
|
||||
|
@ -113,7 +113,7 @@ func (s funcsByName) Less(i, j int) bool { return s[i].String() < s[j].String()
|
|||
func (r *callgraphResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||
nodes := r.callgraph.Nodes()
|
||||
|
||||
numbering := make(map[call.GraphNode]int)
|
||||
numbering := make(map[callgraph.Node]int)
|
||||
for i, n := range nodes {
|
||||
numbering[n] = i
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ func (r *callgraphResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
|||
fn := n.Func()
|
||||
j.Name = fn.String()
|
||||
j.Pos = fset.Position(fn.Pos()).String()
|
||||
for callee := range call.CalleesOf(n) {
|
||||
for callee := range callgraph.CalleesOf(n) {
|
||||
j.Children = append(j.Children, numbering[callee])
|
||||
}
|
||||
sort.Ints(j.Children)
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"fmt"
|
||||
"go/token"
|
||||
|
||||
"code.google.com/p/go.tools/call"
|
||||
"code.google.com/p/go.tools/go/callgraph"
|
||||
"code.google.com/p/go.tools/go/ssa"
|
||||
"code.google.com/p/go.tools/oracle/serial"
|
||||
)
|
||||
|
@ -42,11 +42,11 @@ func callstack(o *Oracle, qpos *QueryPos) (queryResult, error) {
|
|||
|
||||
// Run the pointer analysis and build the complete call graph.
|
||||
o.ptaConfig.BuildCallGraph = true
|
||||
callgraph := ptrAnalysis(o).CallGraph
|
||||
cg := ptrAnalysis(o).CallGraph
|
||||
|
||||
// Search for an arbitrary path from a root to the target function.
|
||||
isEnd := func(n call.GraphNode) bool { return n.Func() == target }
|
||||
callpath := call.PathSearch(callgraph.Root(), isEnd)
|
||||
isEnd := func(n callgraph.Node) bool { return n.Func() == target }
|
||||
callpath := callgraph.PathSearch(cg.Root(), isEnd)
|
||||
if callpath != nil {
|
||||
callpath = callpath[1:] // remove synthetic edge from <root>
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ func callstack(o *Oracle, qpos *QueryPos) (queryResult, error) {
|
|||
type callstackResult struct {
|
||||
qpos *QueryPos
|
||||
target *ssa.Function
|
||||
callpath []call.Edge
|
||||
callpath []callgraph.Edge
|
||||
}
|
||||
|
||||
func (r *callstackResult) display(printf printfFunc) {
|
||||
|
|
|
@ -97,7 +97,7 @@ var modes = []*modeInfo{
|
|||
// Pointer analyses, whole program:
|
||||
{"callees", needPTA | needExactPos, callees},
|
||||
{"callers", needPTA | needPos, callers},
|
||||
{"callgraph", needPTA, callgraph},
|
||||
{"callgraph", needPTA, doCallgraph},
|
||||
{"callstack", needPTA | needPos, callstack},
|
||||
{"peers", needPTA | needSSADebug | needPos, peers},
|
||||
{"pointsto", needPTA | needSSADebug | needExactPos, pointsto},
|
||||
|
|
Loading…
Reference in New Issue