mirror of
https://github.com/golang/go
synced 2024-11-19 01:34:40 -07:00
39779f52c3
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
109 lines
4.1 KiB
Go
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
|
|
}
|