diff --git a/call/call.go b/go/callgraph/callgraph.go similarity index 91% rename from call/call.go rename to go/callgraph/callgraph.go index 10ea9439..f97cc9cd 100644 --- a/call/call.go +++ b/go/callgraph/callgraph.go @@ -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 } diff --git a/call/util.go b/go/callgraph/util.go similarity index 82% rename from call/util.go rename to go/callgraph/util.go index 855e3701..b6875ee5 100644 --- a/call/util.go +++ b/go/callgraph/util.go @@ -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) { diff --git a/go/pointer/api.go b/go/pointer/api.go index 95c1fe6e..b9ce6b0b 100644 --- a/go/pointer/api.go +++ b/go/pointer/api.go @@ -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 } diff --git a/go/pointer/callgraph.go b/go/pointer/callgraph.go index 910affbb..be4d6015 100644 --- a/go/pointer/callgraph.go +++ b/go/pointer/callgraph.go @@ -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 diff --git a/go/pointer/example_test.go b/go/pointer/example_test.go index dd82b12e..db625783 100644 --- a/go/pointer/example_test.go +++ b/go/pointer/example_test.go @@ -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())) diff --git a/go/pointer/labels.go b/go/pointer/labels.go index 63026bfb..be7c20af 100644 --- a/go/pointer/labels.go +++ b/go/pointer/labels.go @@ -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 } diff --git a/go/pointer/pointer_test.go b/go/pointer/pointer_test.go index 4b6d70ef..daf8c184 100644 --- a/go/pointer/pointer_test.go +++ b/go/pointer/pointer_test.go @@ -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 ("") or which are not unique ("func@1.2"). diff --git a/oracle/callers.go b/oracle/callers.go index 2ce88b3a..d9415da8 100644 --- a/oracle/callers.go +++ b/oracle/callers.go @@ -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) { diff --git a/oracle/callgraph.go b/oracle/callgraph.go index 621e19ef..df597024 100644 --- a/oracle/callgraph.go +++ b/oracle/callgraph.go @@ -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) diff --git a/oracle/callstack.go b/oracle/callstack.go index 383d5607..22552386 100644 --- a/oracle/callstack.go +++ b/oracle/callstack.go @@ -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 } @@ -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) { diff --git a/oracle/oracle.go b/oracle/oracle.go index 9c41ac97..9b25ae90 100644 --- a/oracle/oracle.go +++ b/oracle/oracle.go @@ -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},