GoPLS Viewer

Home|gopls/go/callgraph/callgraph.go
1// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5/*
6Package callgraph defines the call graph and various algorithms
7and utilities to operate on it.
8
9A call graph is a labelled directed graph whose nodes represent
10functions and whose edge labels represent syntactic function call
11sites.  The presence of a labelled edge (caller, site, callee)
12indicates that caller may call callee at the specified call site.
13
14A call graph is a multigraph: it may contain multiple edges (caller,
15*, callee) connecting the same pair of nodes, so long as the edges
16differ by label; this occurs when one function calls another function
17from multiple call sites.  Also, it may contain multiple edges
18(caller, site, *) that differ only by callee; this indicates a
19polymorphic call.
20
21A SOUND call graph is one that overapproximates the dynamic calling
22behaviors of the program in all possible executions.  One call graph
23is more PRECISE than another if it is a smaller overapproximation of
24the dynamic behavior.
25
26All call graphs have a synthetic root node which is responsible for
27calling main() and init().
28
29Calls to built-in functions (e.g. panic, println) are not represented
30in the call graph; they are treated like built-in operators of the
31language.
32*/
33package callgraph // import "golang.org/x/tools/go/callgraph"
34
35// TODO(adonovan): add a function to eliminate wrappers from the
36// callgraph, preserving topology.
37// More generally, we could eliminate "uninteresting" nodes such as
38// nodes from packages we don't care about.
39
40// TODO(zpavlinovic): decide how callgraphs handle calls to and from generic function bodies.
41
42import (
43    "fmt"
44    "go/token"
45
46    "golang.org/x/tools/go/ssa"
47)
48
49// A Graph represents a call graph.
50//
51// A graph may contain nodes that are not reachable from the root.
52// If the call graph is sound, such nodes indicate unreachable
53// functions.
54type Graph struct {
55    Root  *Node                   // the distinguished root node
56    Nodes map[*ssa.Function]*Node // all nodes by function
57}
58
59// New returns a new Graph with the specified root node.
60func New(root *ssa.Function) *Graph {
61    g := &Graph{Nodesmake(map[*ssa.Function]*Node)}
62    g.Root = g.CreateNode(root)
63    return g
64}
65
66// CreateNode returns the Node for fn, creating it if not present.
67func (g *GraphCreateNode(fn *ssa.Function) *Node {
68    nok := g.Nodes[fn]
69    if !ok {
70        n = &Node{FuncfnIDlen(g.Nodes)}
71        g.Nodes[fn] = n
72    }
73    return n
74}
75
76// A Node represents a node in a call graph.
77type Node struct {
78    Func *ssa.Function // the function this node represents
79    ID   int           // 0-based sequence number
80    In   []*Edge       // unordered set of incoming call edges (n.In[*].Callee == n)
81    Out  []*Edge       // unordered set of outgoing call edges (n.Out[*].Caller == n)
82}
83
84func (n *NodeString() string {
85    return fmt.Sprintf("n%d:%s"n.IDn.Func)
86}
87
88// A Edge represents an edge in the call graph.
89//
90// Site is nil for edges originating in synthetic or intrinsic
91// functions, e.g. reflect.Value.Call or the root of the call graph.
92type Edge struct {
93    Caller *Node
94    Site   ssa.CallInstruction
95    Callee *Node
96}
97
98func (e EdgeString() string {
99    return fmt.Sprintf("%s --> %s"e.Callere.Callee)
100}
101
102func (e EdgeDescription() string {
103    var prefix string
104    switch e.Site.(type) {
105    case nil:
106        return "synthetic call"
107    case *ssa.Go:
108        prefix = "concurrent "
109    case *ssa.Defer:
110        prefix = "deferred "
111    }
112    return prefix + e.Site.Common().Description()
113}
114
115func (e EdgePos() token.Pos {
116    if e.Site == nil {
117        return token.NoPos
118    }
119    return e.Site.Pos()
120}
121
122// AddEdge adds the edge (caller, site, callee) to the call graph.
123// Elimination of duplicate edges is the caller's responsibility.
124func AddEdge(caller *Nodesite ssa.CallInstructioncallee *Node) {
125    e := &Edge{callersitecallee}
126    callee.In = append(callee.Ine)
127    caller.Out = append(caller.Oute)
128}
129
MembersX
New.g
Graph.CreateNode.fn
Node.String
Edge
ssa
New.root
Edge.Description
Edge.Pos.e
AddEdge.callee
Graph
Node.ID
Edge.Site
Graph.Nodes
Edge.Caller
AddEdge.e
New
Edge.Callee
Node.Func
Edge.Description.prefix
Edge.Pos
Graph.Root
Graph.CreateNode
Node.In
Node.Out
Graph.CreateNode.g
Node.String.n
Edge.Description.e
fmt
token
Edge.String
AddEdge
AddEdge.caller
AddEdge.site
Node
Edge.String.e
Members
X