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