1
0
mirror of https://github.com/golang/go synced 2024-10-01 13:08:32 -06:00
go/call/call.go
Alan Donovan 39779f52c3 go.tools/call: a callgraph API.
This package provides a simple abstraction of a call graph,
capable of representing context sensitive and insensitive
graphs.  It also provides some basic utilities and algorithms.

This simplifies clients such as the oracle, and makes similar
clients (e.g. an offline version of the oracle) easier to write.

R=crawshaw, gri
CC=golang-dev
https://golang.org/cl/13901044
2013-09-25 14:16:35 -04:00

109 lines
4.1 KiB
Go

// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package call 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
representation-independent manner.
A call graph is a labelled directed graph whose nodes represent
functions and whose edge labels represent syntactic function call
sites. The presence of a labelled edge (caller, site, callee)
indicates that caller may call callee at the specified call site.
A call graph is a multigraph: it may contain multiple edges (caller,
*, callee) connecting the same pair of nodes, so long as the edges
differ by label; this occurs when one function calls another function
from multiple call sites. Also, it may contain multiple edges
(caller, site, *) that differ only by callee; this indicates a
polymorphic call.
A call graph is called CONTEXT INSENSITIVE if no two nodes in N
represent the same syntactic function declaration, i.e. the set of
nodes and the set of syntactic functions are in one-to-one
correspondence.
A context-sensitive call graph may have multiple nodes corresponding
to the same function; this may yield a more precise approximation to
the calling behavior of the program. Consider this program:
func Apply(fn func(V), value V) { fn(value) }
Apply(F, v1)
...
Apply(G, v2)
A context-insensitive call graph would represent all calls to Apply by
the same node, so that node would have successors F and G. A
context-sensitive call graph might represent the first and second
calls to Apply by distinct nodes, so that the first would have
successor F and the second would have successor G. This is a more
precise representation of the possible behaviors of the program.
A SOUND call graph is one that overapproximates the dynamic calling
behaviors of the program in all possible executions. One call graph
is more PRECISE than another if it is a smaller overapproximation of
the dynamic behavior.
All call graphs have a synthetic root node which is responsible for
calling main() and init().
Calls to built-in functions (e.g. panic, println) are not represented
in the call graph; they are treated like built-in operators of the
language.
*/
package call
import "code.google.com/p/go.tools/ssa"
// A Graph represents a call graph.
//
// A graph may contain nodes that are not reachable from the root.
// If the call graph is sound, such nodes indicate unreachable
// functions.
//
type Graph interface {
Root() GraphNode // the distinguished root node
Nodes() []GraphNode // new unordered set of all nodes
}
// A GraphNode 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
// indicates the context.
//
// Sites returns the set of syntactic call sites within this function.
//
// For nodes representing synthetic or intrinsic functions
// (e.g. reflect.Call, or the root of the call graph), Sites() returns
// a slice containing a single nil value to indicate the synthetic
// call site, and each edge in Edges() has a nil Site.
//
// All nodes "belong" to a single graph and must not be mixed with
// nodes belonging to another graph.
//
// A site may appear in Sites() but not in {e.Site | e ∈ Edges()}.
// This indicates that that caller node was unreachable, or that the
// call was dynamic yet no func or interface values flow to the call
// site.
//
// Clients should not mutate the node via the results of its methods.
//
type GraphNode 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
}
// A Edge represents an edge in the call graph.
type Edge struct {
Caller GraphNode
Site ssa.CallInstruction
Callee GraphNode
}