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
|
and utilities to operate on it. It does not provide a concrete
|
||||||
implementation but permits other analyses (such as pointer analyses or
|
implementation but permits other analyses (such as pointer analyses or
|
||||||
Rapid Type Analysis) to expose their own call graphs in a
|
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.
|
language.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package call
|
package callgraph
|
||||||
|
|
||||||
import "code.google.com/p/go.tools/go/ssa"
|
import "code.google.com/p/go.tools/go/ssa"
|
||||||
|
|
||||||
|
@ -67,14 +67,14 @@ import "code.google.com/p/go.tools/go/ssa"
|
||||||
// functions.
|
// functions.
|
||||||
//
|
//
|
||||||
type Graph interface {
|
type Graph interface {
|
||||||
Root() GraphNode // the distinguished root node
|
Root() Node // the distinguished root node
|
||||||
Nodes() []GraphNode // new unordered set of all nodes
|
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
|
// 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.
|
// indicates the context.
|
||||||
//
|
//
|
||||||
// Sites returns the set of syntactic call sites within this function.
|
// 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.
|
// 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
|
Func() *ssa.Function // the function this node represents
|
||||||
Sites() []ssa.CallInstruction // new unordered set of call sites within this function
|
Sites() []ssa.CallInstruction // new unordered set of call sites within this function
|
||||||
Edges() []Edge // new unordered set of outgoing edges
|
Edges() []Edge // new unordered set of outgoing edges
|
||||||
|
@ -102,7 +102,7 @@ type GraphNode interface {
|
||||||
|
|
||||||
// A Edge represents an edge in the call graph.
|
// A Edge represents an edge in the call graph.
|
||||||
type Edge struct {
|
type Edge struct {
|
||||||
Caller GraphNode
|
Caller Node
|
||||||
Site ssa.CallInstruction
|
Site ssa.CallInstruction
|
||||||
Callee GraphNode
|
Callee Node
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package call
|
package callgraph
|
||||||
|
|
||||||
// This file provides various representation-independent utilities
|
// This file provides various representation-independent utilities
|
||||||
// over call graphs, such as visitation and path search.
|
// over call graphs, such as visitation and path search.
|
||||||
|
@ -13,7 +13,7 @@ package call
|
||||||
// FindSitesByPos(g Graph, lparen token.Pos) []Site
|
// FindSitesByPos(g Graph, lparen token.Pos) []Site
|
||||||
// FindSitesByCallExpr(g Graph, expr *ast.CallExpr) []Site
|
// FindSitesByCallExpr(g Graph, expr *ast.CallExpr) []Site
|
||||||
// FindSitesByInstr(g Graph, instr ssa.CallInstruction) []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
|
// (Counterargument: they're all inefficient linear scans; if the
|
||||||
// caller does it explicitly there may be opportunities to optimize.
|
// 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
|
// CalleesOf returns a new set containing all direct callees of the
|
||||||
// caller node.
|
// caller node.
|
||||||
//
|
//
|
||||||
func CalleesOf(caller GraphNode) map[GraphNode]bool {
|
func CalleesOf(caller Node) map[Node]bool {
|
||||||
callees := make(map[GraphNode]bool)
|
callees := make(map[Node]bool)
|
||||||
for _, e := range caller.Edges() {
|
for _, e := range caller.Edges() {
|
||||||
callees[e.Callee] = true
|
callees[e.Callee] = true
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,9 @@ func CalleesOf(caller GraphNode) map[GraphNode]bool {
|
||||||
// value.
|
// value.
|
||||||
//
|
//
|
||||||
func GraphVisitEdges(g Graph, edge func(Edge) error) error {
|
func GraphVisitEdges(g Graph, edge func(Edge) error) error {
|
||||||
seen := make(map[GraphNode]bool)
|
seen := make(map[Node]bool)
|
||||||
var visit func(n GraphNode) error
|
var visit func(n Node) error
|
||||||
visit = func(n GraphNode) error {
|
visit = func(n Node) error {
|
||||||
if !seen[n] {
|
if !seen[n] {
|
||||||
seen[n] = true
|
seen[n] = true
|
||||||
for _, e := range n.Edges() {
|
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
|
// PathSearch returns the path as an ordered list of edges; on
|
||||||
// failure, it returns nil.
|
// 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)
|
stack := make([]Edge, 0, 32)
|
||||||
seen := make(map[GraphNode]bool)
|
seen := make(map[Node]bool)
|
||||||
var search func(n GraphNode) []Edge
|
var search func(n Node) []Edge
|
||||||
search = func(n GraphNode) []Edge {
|
search = func(n Node) []Edge {
|
||||||
if !seen[n] {
|
if !seen[n] {
|
||||||
seen[n] = true
|
seen[n] = true
|
||||||
if isEnd(n) {
|
if isEnd(n) {
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"go/token"
|
"go/token"
|
||||||
"io"
|
"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/ssa"
|
||||||
"code.google.com/p/go.tools/go/types/typemap"
|
"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.
|
// See Config for how to request the various Result components.
|
||||||
//
|
//
|
||||||
type Result struct {
|
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.
|
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.
|
IndirectQueries map[ssa.Value][]Pointer // pts(*v) for each v in Config.IndirectQueries.
|
||||||
Warnings []Warning // warnings of unsoundness
|
Warnings []Warning // warnings of unsoundness
|
||||||
|
@ -220,7 +220,7 @@ func (p Pointer) String() string {
|
||||||
|
|
||||||
// Context returns the context of this pointer,
|
// Context returns the context of this pointer,
|
||||||
// if it corresponds to a local variable.
|
// if it corresponds to a local variable.
|
||||||
func (p Pointer) Context() call.GraphNode {
|
func (p Pointer) Context() callgraph.Node {
|
||||||
return p.cgn
|
return p.cgn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,35 +4,35 @@
|
||||||
|
|
||||||
package pointer
|
package pointer
|
||||||
|
|
||||||
// This file defines our implementation of the call.Graph API.
|
// This file defines our implementation of the callgraph API.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"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/go/ssa"
|
||||||
)
|
)
|
||||||
|
|
||||||
// cgraph implements call.Graph.
|
// cgraph implements callgraph.Graph.
|
||||||
type cgraph struct {
|
type cgraph struct {
|
||||||
root *cgnode
|
root *cgnode
|
||||||
nodes []*cgnode
|
nodes []*cgnode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *cgraph) Nodes() []call.GraphNode {
|
func (g *cgraph) Nodes() []callgraph.Node {
|
||||||
nodes := make([]call.GraphNode, len(g.nodes))
|
nodes := make([]callgraph.Node, len(g.nodes))
|
||||||
for i, node := range g.nodes {
|
for i, node := range g.nodes {
|
||||||
nodes[i] = node
|
nodes[i] = node
|
||||||
}
|
}
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *cgraph) Root() call.GraphNode {
|
func (g *cgraph) Root() callgraph.Node {
|
||||||
return g.root
|
return g.root
|
||||||
}
|
}
|
||||||
|
|
||||||
// cgnode implements call.GraphNode.
|
// cgnode implements callgraph.Node.
|
||||||
type cgnode struct {
|
type cgnode struct {
|
||||||
fn *ssa.Function
|
fn *ssa.Function
|
||||||
obj nodeid // start of this contour's object block
|
obj nodeid // start of this contour's object block
|
||||||
|
@ -52,16 +52,16 @@ func (n *cgnode) Sites() []ssa.CallInstruction {
|
||||||
return sites
|
return sites
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *cgnode) Edges() []call.Edge {
|
func (n *cgnode) Edges() []callgraph.Edge {
|
||||||
var numEdges int
|
var numEdges int
|
||||||
for _, site := range n.sites {
|
for _, site := range n.sites {
|
||||||
numEdges += len(site.callees)
|
numEdges += len(site.callees)
|
||||||
}
|
}
|
||||||
edges := make([]call.Edge, 0, numEdges)
|
edges := make([]callgraph.Edge, 0, numEdges)
|
||||||
|
|
||||||
for _, site := range n.sites {
|
for _, site := range n.sites {
|
||||||
for _, callee := range site.callees {
|
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
|
return edges
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"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/loader"
|
||||||
"code.google.com/p/go.tools/go/pointer"
|
"code.google.com/p/go.tools/go/pointer"
|
||||||
"code.google.com/p/go.tools/go/ssa"
|
"code.google.com/p/go.tools/go/ssa"
|
||||||
|
@ -75,7 +75,7 @@ func main() {
|
||||||
// By converting to strings, we de-duplicate nodes
|
// By converting to strings, we de-duplicate nodes
|
||||||
// representing the same function due to context sensitivity.
|
// representing the same function due to context sensitivity.
|
||||||
var edges []string
|
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()
|
caller := edge.Caller.Func()
|
||||||
if caller.Pkg == mainPkg {
|
if caller.Pkg == mainPkg {
|
||||||
edges = append(edges, fmt.Sprint(caller, " --> ", edge.Callee.Func()))
|
edges = append(edges, fmt.Sprint(caller, " --> ", edge.Callee.Func()))
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"go/token"
|
"go/token"
|
||||||
"strings"
|
"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/ssa"
|
||||||
"code.google.com/p/go.tools/go/types"
|
"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,
|
// 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.
|
// 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
|
return l.obj.cgn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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/loader"
|
||||||
"code.google.com/p/go.tools/go/pointer"
|
"code.google.com/p/go.tools/go/pointer"
|
||||||
"code.google.com/p/go.tools/go/ssa"
|
"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")
|
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)
|
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
|
// Name-based matching is inefficient but it allows us to
|
||||||
// match functions whose names that would not appear in an
|
// match functions whose names that would not appear in an
|
||||||
// index ("<root>") or which are not unique ("func@1.2").
|
// index ("<root>") or which are not unique ("func@1.2").
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"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/go/ssa"
|
||||||
"code.google.com/p/go.tools/oracle/serial"
|
"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
|
// Run the pointer analysis, recording each
|
||||||
// call found to originate from target.
|
// call found to originate from target.
|
||||||
o.ptaConfig.BuildCallGraph = true
|
o.ptaConfig.BuildCallGraph = true
|
||||||
callgraph := ptrAnalysis(o).CallGraph
|
cg := ptrAnalysis(o).CallGraph
|
||||||
var edges []call.Edge
|
var edges []callgraph.Edge
|
||||||
call.GraphVisitEdges(callgraph, func(edge call.Edge) error {
|
callgraph.GraphVisitEdges(cg, func(edge callgraph.Edge) error {
|
||||||
if edge.Callee.Func() == target {
|
if edge.Callee.Func() == target {
|
||||||
edges = append(edges, edge)
|
edges = append(edges, edge)
|
||||||
}
|
}
|
||||||
|
@ -49,15 +49,15 @@ func callers(o *Oracle, qpos *QueryPos) (queryResult, error) {
|
||||||
|
|
||||||
return &callersResult{
|
return &callersResult{
|
||||||
target: target,
|
target: target,
|
||||||
callgraph: callgraph,
|
callgraph: cg,
|
||||||
edges: edges,
|
edges: edges,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type callersResult struct {
|
type callersResult struct {
|
||||||
target *ssa.Function
|
target *ssa.Function
|
||||||
callgraph call.Graph
|
callgraph callgraph.Graph
|
||||||
edges []call.Edge
|
edges []callgraph.Edge
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *callersResult) display(printf printfFunc) {
|
func (r *callersResult) display(printf printfFunc) {
|
||||||
|
|
|
@ -8,12 +8,12 @@ import (
|
||||||
"go/token"
|
"go/token"
|
||||||
"sort"
|
"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/go/ssa"
|
||||||
"code.google.com/p/go.tools/oracle/serial"
|
"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)
|
// Nodes may be seem to appear multiple times due to (limited)
|
||||||
// context sensitivity.
|
// context sensitivity.
|
||||||
|
@ -28,7 +28,7 @@ import (
|
||||||
//
|
//
|
||||||
// TODO(adonovan): elide nodes for synthetic functions?
|
// TODO(adonovan): elide nodes for synthetic functions?
|
||||||
//
|
//
|
||||||
func callgraph(o *Oracle, _ *QueryPos) (queryResult, error) {
|
func doCallgraph(o *Oracle, _ *QueryPos) (queryResult, error) {
|
||||||
buildSSA(o)
|
buildSSA(o)
|
||||||
|
|
||||||
// Run the pointer analysis and build the complete callgraph.
|
// Run the pointer analysis and build the complete callgraph.
|
||||||
|
@ -41,7 +41,7 @@ func callgraph(o *Oracle, _ *QueryPos) (queryResult, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type callgraphResult struct {
|
type callgraphResult struct {
|
||||||
callgraph call.Graph
|
callgraph callgraph.Graph
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *callgraphResult) display(printf printfFunc) {
|
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)
|
ci := make(map[*ssa.Function]map[*ssa.Function]bool)
|
||||||
|
|
||||||
// 1. Visit the CS call graph and build the CI call graph.
|
// 1. Visit the CS call graph and build the CI call graph.
|
||||||
visited := make(map[call.GraphNode]bool)
|
visited := make(map[callgraph.Node]bool)
|
||||||
var visit func(caller call.GraphNode)
|
var visit func(caller callgraph.Node)
|
||||||
visit = func(caller call.GraphNode) {
|
visit = func(caller callgraph.Node) {
|
||||||
if !visited[caller] {
|
if !visited[caller] {
|
||||||
visited[caller] = true
|
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) {
|
func (r *callgraphResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
nodes := r.callgraph.Nodes()
|
nodes := r.callgraph.Nodes()
|
||||||
|
|
||||||
numbering := make(map[call.GraphNode]int)
|
numbering := make(map[callgraph.Node]int)
|
||||||
for i, n := range nodes {
|
for i, n := range nodes {
|
||||||
numbering[n] = i
|
numbering[n] = i
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ func (r *callgraphResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
fn := n.Func()
|
fn := n.Func()
|
||||||
j.Name = fn.String()
|
j.Name = fn.String()
|
||||||
j.Pos = fset.Position(fn.Pos()).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])
|
j.Children = append(j.Children, numbering[callee])
|
||||||
}
|
}
|
||||||
sort.Ints(j.Children)
|
sort.Ints(j.Children)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"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/go/ssa"
|
||||||
"code.google.com/p/go.tools/oracle/serial"
|
"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.
|
// Run the pointer analysis and build the complete call graph.
|
||||||
o.ptaConfig.BuildCallGraph = true
|
o.ptaConfig.BuildCallGraph = true
|
||||||
callgraph := ptrAnalysis(o).CallGraph
|
cg := ptrAnalysis(o).CallGraph
|
||||||
|
|
||||||
// Search for an arbitrary path from a root to the target function.
|
// Search for an arbitrary path from a root to the target function.
|
||||||
isEnd := func(n call.GraphNode) bool { return n.Func() == target }
|
isEnd := func(n callgraph.Node) bool { return n.Func() == target }
|
||||||
callpath := call.PathSearch(callgraph.Root(), isEnd)
|
callpath := callgraph.PathSearch(cg.Root(), isEnd)
|
||||||
if callpath != nil {
|
if callpath != nil {
|
||||||
callpath = callpath[1:] // remove synthetic edge from <root>
|
callpath = callpath[1:] // remove synthetic edge from <root>
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ func callstack(o *Oracle, qpos *QueryPos) (queryResult, error) {
|
||||||
type callstackResult struct {
|
type callstackResult struct {
|
||||||
qpos *QueryPos
|
qpos *QueryPos
|
||||||
target *ssa.Function
|
target *ssa.Function
|
||||||
callpath []call.Edge
|
callpath []callgraph.Edge
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *callstackResult) display(printf printfFunc) {
|
func (r *callstackResult) display(printf printfFunc) {
|
||||||
|
|
|
@ -97,7 +97,7 @@ var modes = []*modeInfo{
|
||||||
// Pointer analyses, whole program:
|
// Pointer analyses, whole program:
|
||||||
{"callees", needPTA | needExactPos, callees},
|
{"callees", needPTA | needExactPos, callees},
|
||||||
{"callers", needPTA | needPos, callers},
|
{"callers", needPTA | needPos, callers},
|
||||||
{"callgraph", needPTA, callgraph},
|
{"callgraph", needPTA, doCallgraph},
|
||||||
{"callstack", needPTA | needPos, callstack},
|
{"callstack", needPTA | needPos, callstack},
|
||||||
{"peers", needPTA | needSSADebug | needPos, peers},
|
{"peers", needPTA | needSSADebug | needPos, peers},
|
||||||
{"pointsto", needPTA | needSSADebug | needExactPos, pointsto},
|
{"pointsto", needPTA | needSSADebug | needExactPos, pointsto},
|
||||||
|
|
Loading…
Reference in New Issue