go.tools/go/callgraph: simplifications to API.
1) We remove context sensitivity from API. The pointer analysis is
not sufficiently context-sensitive for the context information to
be worth exposing. (The actual analysis precision still benefits
from being context-sensitive, though.) Since all clients would
discard the context info, we now do that for them.
2) Make the graph doubly-linked. Edges are now shared by the Nodes
at both ends of the edge so it's possible to navigate more easily
(e.g. to the callers).
3) Graph and Node are now concrete, not interfaces.
Less code in every file!
LGTM=crawshaw
R=crawshaw
CC=golang-codereviews
https://golang.org/cl/66460043
diff --git a/go/pointer/analysis.go b/go/pointer/analysis.go
index 44875e9..3b4469b 100644
--- a/go/pointer/analysis.go
+++ b/go/pointer/analysis.go
@@ -13,6 +13,7 @@
"os"
"reflect"
+ "code.google.com/p/go.tools/go/callgraph"
"code.google.com/p/go.tools/go/ssa"
"code.google.com/p/go.tools/go/types"
"code.google.com/p/go.tools/go/types/typeutil"
@@ -346,7 +347,7 @@
}
a.computeTrackBits()
- root := a.generate()
+ a.generate()
if a.log != nil {
// Show size of constraint system.
@@ -374,34 +375,37 @@
}
}
+ // Create callgraph.Nodes in deterministic order.
+ if cg := a.result.CallGraph; cg != nil {
+ for _, caller := range a.cgnodes {
+ cg.CreateNode(caller.fn)
+ }
+ }
+
// Add dynamic edges to call graph.
for _, caller := range a.cgnodes {
for _, site := range caller.sites {
for callee := range a.nodes[site.targets].pts {
- a.callEdge(site, callee)
+ a.callEdge(caller, site, callee)
}
}
}
- if a.config.BuildCallGraph {
- a.result.CallGraph = &cgraph{root, a.cgnodes}
- }
-
return a.result
}
// callEdge is called for each edge in the callgraph.
// calleeid is the callee's object node (has otFunction flag).
//
-func (a *analysis) callEdge(site *callsite, calleeid nodeid) {
+func (a *analysis) callEdge(caller *cgnode, site *callsite, calleeid nodeid) {
obj := a.nodes[calleeid].obj
if obj.flags&otFunction == 0 {
panic(fmt.Sprintf("callEdge %s -> n%d: not a function object", site, calleeid))
}
callee := obj.cgn
- if a.config.BuildCallGraph {
- site.callees = append(site.callees, callee)
+ if cg := a.result.CallGraph; cg != nil {
+ callgraph.AddEdge(cg.CreateNode(caller.fn), site.instr, cg.CreateNode(callee.fn))
}
if a.log != nil {