go.tools/pointer: more reflection.

Support for:
        (*reflect.rtype).Field
        (*reflect.rtype).FieldByName
        reflect.MakeSlice
        runtime.SetFinalizer

Details:
- analysis locates ssa.Functions for (reflect.Value).Call
  and runtime.SetFinalizer during startup to that it can
  special-case them during genCall.  ('Call' is forthcoming.)
- The callsite.targets mechanism is only used for dynamic
  calls now.  For static calls we call callEdge during constraint
  generation; this is a minor optimisation.
- Static calls to SetFinalizer are inlined so that the call
  appears to go direct to the finalizer.  (We'll use the same
  trick for (reflect.Value).Call.)
- runtime.FuncForPC: treat as a no-op.
- Fixed pointer_test to properly deal with expectations
  that are multi-sets.
- Inlined rtypeMethodByNameConstraint.addMethod.
- More tests.

R=crawshaw
CC=golang-dev
https://golang.org/cl/14682045
diff --git a/pointer/gen.go b/pointer/gen.go
index 72e7e66..7b7ca60 100644
--- a/pointer/gen.go
+++ b/pointer/gen.go
@@ -578,18 +578,31 @@
 
 // genStaticCall generates constraints for a statically dispatched function call.
 func (a *analysis) genStaticCall(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
-	// Ascertain the context (contour/CGNode) for a particular call.
-	var obj nodeid
 	fn := call.StaticCallee()
+
+	// Special cases for inlined intrinsics.
+	switch fn {
+	case a.runtimeSetFinalizer:
+		// Inline SetFinalizer so the call appears direct.
+		site.targets = a.addOneNode(tInvalid, "SetFinalizer.targets", nil)
+		a.addConstraint(&runtimeSetFinalizerConstraint{
+			targets: site.targets,
+			x:       a.valueNode(call.Args[0]),
+			f:       a.valueNode(call.Args[1]),
+		})
+		return
+	}
+
+	// Ascertain the context (contour/cgnode) for a particular call.
+	var obj nodeid
 	if a.shouldUseContext(fn) {
 		obj = a.makeFunctionObject(fn, site) // new contour
 	} else {
 		obj = a.objectNode(nil, fn) // shared contour
 	}
+	a.callEdge(site, obj)
 
 	sig := call.Signature()
-	targets := a.addOneNode(sig, "call.targets", nil)
-	a.addressOf(targets, obj) // (a singleton)
 
 	// Copy receiver, if any.
 	params := a.funcParams(obj)
@@ -613,20 +626,18 @@
 	if result != 0 {
 		a.copy(result, a.funcResults(obj), a.sizeof(sig.Results()))
 	}
-
-	// pts(targets) will be the (singleton) set of possible call targets.
-	site.targets = targets
 }
 
 // genDynamicCall generates constraints for a dynamic function call.
 func (a *analysis) genDynamicCall(caller *cgnode, site *callsite, call *ssa.CallCommon, result nodeid) {
-	fn := a.valueNode(call.Value)
-	sig := call.Signature()
+	// 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(fn).
+	// discovered in pts(targets).
 
+	sig := call.Signature()
 	var offset uint32 = 1 // P/R block starts at offset 1
 	for i, arg := range call.Args {
 		sz := a.sizeof(sig.Params().At(i).Type())
@@ -636,9 +647,6 @@
 	if result != 0 {
 		a.genLoad(caller, result, call.Value, offset, a.sizeof(sig.Results()))
 	}
-
-	// pts(targets) will be the (singleton) set of possible call targets.
-	site.targets = fn
 }
 
 // genInvoke generates constraints for a dynamic method invocation.
@@ -699,9 +707,7 @@
 	fn := a.prog.Method(meth)
 
 	obj := a.makeFunctionObject(fn, site) // new contour for this call
-
-	// pts(targets) will be the (singleton) set of possible call targets.
-	site.targets = obj
+	a.callEdge(site, obj)
 
 	// From now on, it's essentially a static call, but little is
 	// gained by factoring together the code for both cases.
@@ -745,13 +751,11 @@
 	}
 
 	site := &callsite{instr: instr}
-
-	switch {
-	case call.StaticCallee() != nil:
+	if call.StaticCallee() != nil {
 		a.genStaticCall(caller, site, call, result)
-	case call.IsInvoke():
+	} else if call.IsInvoke() {
 		a.genInvoke(caller, site, call, result)
-	default:
+	} else {
 		a.genDynamicCall(caller, site, call, result)
 	}