go/pointer: implement pointer equivalence via hash-value numbering, a pre-solver optimization.

This reduces solver time by about 40%.
See hvn.go for detailed description.

Also in this CL:
- Update package docs.
- Added various global opt/debug options for maintainer convenience.
- Added logging of phase timing.
- Added stdlib_test, disabled by default, that runs the analysis
  on all tests in $GOROOT.
- include types when dumping solution

LGTM=crawshaw
R=crawshaw, dannyb
CC=golang-codereviews
https://golang.org/cl/96650048
diff --git a/go/pointer/gen.go b/go/pointer/gen.go
index bcb7448..65988fb 100644
--- a/go/pointer/gen.go
+++ b/go/pointer/gen.go
@@ -59,7 +59,7 @@
 //
 func (a *analysis) addOneNode(typ types.Type, comment string, subelement *fieldInfo) nodeid {
 	id := a.nextNode()
-	a.nodes = append(a.nodes, &node{typ: typ, subelement: subelement})
+	a.nodes = append(a.nodes, &node{typ: typ, subelement: subelement, solve: new(solverState)})
 	if a.log != nil {
 		fmt.Fprintf(a.log, "\tcreate n%d %s for %s%s\n",
 			id, typ, comment, subelement.path())
@@ -178,6 +178,9 @@
 
 // makeRtype returns the canonical tagged object of type *rtype whose
 // payload points to the sole rtype object for T.
+//
+// TODO(adonovan): move to reflect.go; it's part of the solver really.
+//
 func (a *analysis) makeRtype(T types.Type) nodeid {
 	if v := a.rtypes.At(T); v != nil {
 		return v.(nodeid)
@@ -261,7 +264,7 @@
 	return n.typ, obj + 1, flags&otIndirect != 0
 }
 
-// funcParams returns the first node of the params block of the
+// funcParams returns the first node of the params (P) block of the
 // function whose object node (obj.flags&otFunction) is id.
 //
 func (a *analysis) funcParams(id nodeid) nodeid {
@@ -272,7 +275,7 @@
 	return id + 1
 }
 
-// funcResults returns the first node of the results block of the
+// funcResults returns the first node of the results (R) block of the
 // function whose object node (obj.flags&otFunction) is id.
 //
 func (a *analysis) funcResults(id nodeid) nodeid {
@@ -662,9 +665,9 @@
 	// pts(targets) will be the set of possible call targets.
 	site.targets = a.valueNode(call.Value)
 
-	// We add dynamic closure rules that store the arguments into,
-	// and load the results from, the P/R block of each function
-	// discovered in pts(targets).
+	// We add dynamic closure rules that store the arguments into
+	// the P-block and load the results from the R-block of each
+	// function discovered in pts(targets).
 
 	sig := call.Signature()
 	var offset uint32 = 1 // P/R block starts at offset 1
@@ -705,9 +708,9 @@
 		a.copy(result, r, a.sizeof(sig.Results()))
 	}
 
-	// We add a dynamic invoke constraint that will add
-	// edges from the caller's P/R block to the callee's
-	// P/R block for each discovered call target.
+	// We add a dynamic invoke constraint that will connect the
+	// caller's and the callee's P/R blocks for each discovered
+	// call target.
 	a.addConstraint(&invokeConstraint{call.Method, a.valueNode(call.Value), block})
 }
 
@@ -749,7 +752,7 @@
 	a.copy(params, rtype, 1)
 	params++
 
-	// Copy actual parameters into formal params block.
+	// Copy actual parameters into formal P-block.
 	// Must loop, since the actuals aren't contiguous.
 	for i, arg := range call.Args {
 		sz := a.sizeof(sig.Params().At(i).Type())
@@ -757,7 +760,7 @@
 		params += nodeid(sz)
 	}
 
-	// Copy formal results block to actual result.
+	// Copy formal R-block to actual R-block.
 	if result != 0 {
 		a.copy(result, a.funcResults(obj), a.sizeof(sig.Results()))
 	}
@@ -790,6 +793,7 @@
 	caller.sites = append(caller.sites, site)
 
 	if a.log != nil {
+		// TODO(adonovan): debug: improve log message.
 		fmt.Fprintf(a.log, "\t%s to targets %s from %s\n", site, site.targets, caller)
 	}
 }
@@ -863,7 +867,15 @@
 			obj = a.nextNode()
 			tmap := v.Type().Underlying().(*types.Map)
 			a.addNodes(tmap.Key(), "makemap.key")
-			a.addNodes(tmap.Elem(), "makemap.value")
+			elem := a.addNodes(tmap.Elem(), "makemap.value")
+
+			// To update the value field, MapUpdate
+			// generates store-with-offset constraints which
+			// the presolver can't model, so we must mark
+			// those nodes indirect.
+			for id, end := elem, elem+nodeid(a.sizeof(tmap.Elem())); id < end; id++ {
+				a.mapValues = append(a.mapValues, id)
+			}
 			a.endObject(obj, cgn, v)
 
 		case *ssa.MakeInterface:
@@ -1140,8 +1152,7 @@
 	impl := a.findIntrinsic(fn)
 
 	if a.log != nil {
-		fmt.Fprintln(a.log)
-		fmt.Fprintln(a.log)
+		fmt.Fprintf(a.log, "\n\n==== Generating constraints for %s, %s\n", cgn, cgn.contour())
 
 		// Hack: don't display body if intrinsic.
 		if impl != nil {
@@ -1187,6 +1198,7 @@
 
 	// Create value nodes for all value instructions
 	// since SSA may contain forward references.
+	var space [10]*ssa.Value
 	for _, b := range fn.Blocks {
 		for _, instr := range b.Instrs {
 			switch instr := instr.(type) {
@@ -1202,6 +1214,19 @@
 				id := a.addNodes(instr.Type(), comment)
 				a.setValueNode(instr, id, cgn)
 			}
+
+			// Record all address-taken functions (for presolver).
+			rands := instr.Operands(space[:0])
+			if call, ok := instr.(ssa.CallInstruction); ok && !call.Common().IsInvoke() {
+				// Skip CallCommon.Value in "call" mode.
+				// TODO(adonovan): fix: relies on unspecified ordering.  Specify it.
+				rands = rands[1:]
+			}
+			for _, rand := range rands {
+				if atf, ok := (*rand).(*ssa.Function); ok {
+					a.atFuncs[atf] = true
+				}
+			}
 		}
 	}
 
@@ -1218,14 +1243,29 @@
 
 // genMethodsOf generates nodes and constraints for all methods of type T.
 func (a *analysis) genMethodsOf(T types.Type) {
+	itf := isInterface(T)
+
+	// TODO(adonovan): can we skip this entirely if itf is true?
+	// I think so, but the answer may depend on reflection.
 	mset := a.prog.MethodSets.MethodSet(T)
 	for i, n := 0, mset.Len(); i < n; i++ {
-		a.valueNode(a.prog.Method(mset.At(i)))
+		m := a.prog.Method(mset.At(i))
+		a.valueNode(m)
+
+		if !itf {
+			// Methods of concrete types are address-taken functions.
+			a.atFuncs[m] = true
+		}
 	}
 }
 
 // generate generates offline constraints for the entire program.
 func (a *analysis) generate() {
+	start("Constraint generation")
+	if a.log != nil {
+		fmt.Fprintln(a.log, "==== Generating constraints")
+	}
+
 	// Create a dummy node since we use the nodeid 0 for
 	// non-pointerlike variables.
 	a.addNodes(tInvalid, "(zero)")
@@ -1273,4 +1313,6 @@
 	a.globalval = nil
 	a.localval = nil
 	a.localobj = nil
+
+	stop("Constraint generation")
 }