go/ssa: add Node interface: common parts of Value+Instruction, plus Operands/Referrers.

Also:
- extend Parent() to all Values and add to interface:
  (Builtin/Const/Global => nil; Function => Enclosing)
- hide Function.Enclosing since it's now redundant wrt Parent()
- make (*Function).String robust for synthetics without pkg object

LGTM=gri
R=gri
CC=golang-codereviews, khr
https://golang.org/cl/87580044
diff --git a/go/pointer/gen.go b/go/pointer/gen.go
index f0ac1ae..69eda20 100644
--- a/go/pointer/gen.go
+++ b/go/pointer/gen.go
@@ -1104,7 +1104,6 @@
 func (a *analysis) genRootCalls() *cgnode {
 	r := ssa.NewFunction("<root>", new(types.Signature), "root of callgraph")
 	r.Prog = a.prog // hack.
-	r.Enclosing = r // hack, so Function.String() doesn't crash
 	r.String()      // (asserts that it doesn't crash)
 	root := a.makeCGNode(r, 0, nil)
 
diff --git a/go/ssa/builder.go b/go/ssa/builder.go
index 9d7d9f3..be55bdb 100644
--- a/go/ssa/builder.go
+++ b/go/ssa/builder.go
@@ -472,7 +472,7 @@
 			name:      fmt.Sprintf("%s$%d", fn.Name(), 1+len(fn.AnonFuncs)),
 			Signature: fn.Pkg.typeOf(e.Type).Underlying().(*types.Signature),
 			pos:       e.Type.Func,
-			Enclosing: fn,
+			parent:    fn,
 			Pkg:       fn.Pkg,
 			Prog:      fn.Prog,
 			syntax:    e,
diff --git a/go/ssa/const.go b/go/ssa/const.go
index 36ae99e..1a4a4d0 100644
--- a/go/ssa/const.go
+++ b/go/ssa/const.go
@@ -100,6 +100,8 @@
 	return nil
 }
 
+func (c *Const) Parent() *Function { return nil }
+
 func (c *Const) Pos() token.Pos {
 	return token.NoPos
 }
diff --git a/go/ssa/doc.go b/go/ssa/doc.go
index c919823..9cb00e3 100644
--- a/go/ssa/doc.go
+++ b/go/ssa/doc.go
@@ -42,6 +42,7 @@
 //    - Member: a named member of a Go package.
 //    - Value: an expression that yields a value.
 //    - Instruction: a statement that consumes values and performs computation.
+//    - Node: a Value or Instruction (emphasizing its membership in the SSA value graph)
 //
 // A computation that yields a result implements both the Value and
 // Instruction interfaces.  The following table shows for each
diff --git a/go/ssa/func.go b/go/ssa/func.go
index 5f8d216..1bd24ec 100644
--- a/go/ssa/func.go
+++ b/go/ssa/func.go
@@ -423,10 +423,10 @@
 
 	// Definition must be in an enclosing function;
 	// plumb it through intervening closures.
-	if f.Enclosing == nil {
+	if f.parent == nil {
 		panic("no Value for type.Object " + obj.Name())
 	}
-	outer := f.Enclosing.lookup(obj, true) // escaping
+	outer := f.parent.lookup(obj, true) // escaping
 	v := &Capture{
 		name:   obj.Name(),
 		typ:    outer.Type(),
@@ -466,7 +466,7 @@
 //
 func (f *Function) RelString(from *types.Package) string {
 	// Anonymous?
-	if f.Enclosing != nil {
+	if f.parent != nil {
 		return f.name
 	}
 
@@ -544,8 +544,8 @@
 		fmt.Fprintf(buf, "# Location: %s\n", f.Prog.Fset.Position(pos))
 	}
 
-	if f.Enclosing != nil {
-		fmt.Fprintf(buf, "# Parent: %s\n", f.Enclosing.Name())
+	if f.parent != nil {
+		fmt.Fprintf(buf, "# Parent: %s\n", f.parent.Name())
 	}
 
 	if f.Recover != nil {
diff --git a/go/ssa/interp/interp.go b/go/ssa/interp/interp.go
index 53acb0d..60da061 100644
--- a/go/ssa/interp/interp.go
+++ b/go/ssa/interp/interp.go
@@ -489,7 +489,7 @@
 		caller: caller, // for panic/recover
 		fn:     fn,
 	}
-	if fn.Enclosing == nil {
+	if fn.Parent() == nil {
 		name := fn.String()
 		if ext := externals[name]; ext != nil {
 			if i.mode&EnableTracing != 0 {
diff --git a/go/ssa/sanity.go b/go/ssa/sanity.go
index dd80b5d..48e967a 100644
--- a/go/ssa/sanity.go
+++ b/go/ssa/sanity.go
@@ -357,11 +357,13 @@
 			case *Const, *Global, *Builtin:
 				continue // not local
 			case *Function:
-				if val.Enclosing == nil {
+				if val.parent == nil {
 					continue // only anon functions are local
 				}
 			}
 
+			// TODO(adonovan): check val.Parent() != nil <=> val.Referrers() is defined.
+
 			if refs := val.Referrers(); refs != nil {
 				for _, ref := range *refs {
 					if ref == instr {
@@ -442,8 +444,8 @@
 
 	s.block = nil
 	for i, anon := range fn.AnonFuncs {
-		if anon.Enclosing != fn {
-			s.errorf("AnonFuncs[%d]=%s but %s.Enclosing=%s", i, anon, anon, anon.Enclosing)
+		if anon.Parent() != fn {
+			s.errorf("AnonFuncs[%d]=%s but %s.Parent()=%s", i, anon, anon, anon.Parent())
 		}
 	}
 	s.fn = nil
diff --git a/go/ssa/ssa.go b/go/ssa/ssa.go
index 9151c97..b940255 100644
--- a/go/ssa/ssa.go
+++ b/go/ssa/ssa.go
@@ -123,6 +123,10 @@
 	// types of their operands.
 	Type() types.Type
 
+	// Parent returns the function to which this Value belongs.
+	// It returns nil for named Functions, Builtin, Const and Global.
+	Parent() *Function
+
 	// Referrers returns the list of instructions that have this
 	// value as one of their operands; it may contain duplicates
 	// if an instruction has a repeated operand.
@@ -130,9 +134,9 @@
 	// Referrers actually returns a pointer through which the
 	// caller may perform mutations to the object's state.
 	//
-	// Referrers is currently only defined for the function-local
-	// values Capture, Parameter, Functions (iff anonymous) and
-	// all value-defining instructions.
+	// Referrers is currently only defined if Parent()!=nil,
+	// i.e. for the function-local values Capture, Parameter,
+	// Functions (iff anonymous) and all value-defining instructions.
 	// It returns nil for named Functions, Builtin, Const and Global.
 	//
 	// Instruction.Operands contains the inverse of this relation.
@@ -199,9 +203,10 @@
 	// user-provided slice, and returns the resulting slice,
 	// permitting avoidance of memory allocation.
 	//
-	// The operands are appended in undefined order; the addresses
-	// are always non-nil but may point to a nil Value.  Clients
-	// may store through the pointers, e.g. to effect a value
+	// The operands are appended in undefined order, but the order
+	// is consistent for a given Instruction; the addresses are
+	// always non-nil but may point to a nil Value.  Clients may
+	// store through the pointers, e.g. to effect a value
 	// renaming.
 	//
 	// Value.Referrers is a subset of the inverse of this
@@ -229,6 +234,28 @@
 	Pos() token.Pos
 }
 
+// A Node is a node in the SSA value graph.  Every concrete type that
+// implements Node is also either a Value, an Instruction, or both.
+//
+// Node contains the methods common to Value and Instruction, plus the
+// Operands and Referrers methods generalized to return nil for
+// non-Instructions and non-Values, respectively.
+//
+// Node is provided to simplify SSA graph algorithms.  Clients should
+// use the more specific and informative Value or Instruction
+// interfaces where appropriate.
+//
+type Node interface {
+	// Common methods:
+	String() string
+	Pos() token.Pos
+	Parent() *Function
+
+	// Partial methods:
+	Operands(rands []*Value) []*Value // nil for non-Instructions
+	Referrers() *[]Instruction        // nil for non-Values
+}
+
 // Function represents the parameters, results and code of a function
 // or method.
 //
@@ -250,11 +277,11 @@
 // of the function's named return parameters followed by a return of
 // the loaded values.
 //
-// A nested function that refers to one or more lexically enclosing
-// local variables ("free variables") has Capture parameters.  Such
-// functions cannot be called directly but require a value created by
-// MakeClosure which, via its Bindings, supplies values for these
-// parameters.
+// A nested function (Parent()!=nil) that refers to one or more
+// lexically enclosing local variables ("free variables") has Capture
+// parameters.  Such functions cannot be called directly but require a
+// value created by MakeClosure which, via its Bindings, supplies
+// values for these parameters.
 //
 // If the function is a method (Signature.Recv() != nil) then the first
 // element of Params is the receiver parameter.
@@ -275,7 +302,7 @@
 
 	Synthetic string       // provenance of synthetic function; "" for true source functions
 	syntax    ast.Node     // *ast.Func{Decl,Lit}; replaced with simple ast.Node after build, unless debug mode
-	Enclosing *Function    // enclosing function if anon; nil if global
+	parent    *Function    // enclosing function if anon; nil if global
 	Pkg       *Package     // enclosing package; nil for shared funcs (wrappers and error.Error)
 	Prog      *Program     // enclosing program
 	Params    []*Parameter // function parameters; for methods, includes receiver
@@ -284,7 +311,7 @@
 	Blocks    []*BasicBlock // basic blocks of the function; nil => external
 	Recover   *BasicBlock   // optional; control transfers here after recovered panic
 	AnonFuncs []*Function   // anonymous functions directly beneath this one
-	referrers []Instruction // referring instructions (iff Enclosing != nil)
+	referrers []Instruction // referring instructions (iff Parent() != nil)
 
 	// The following fields are set transiently during building,
 	// then cleared.
@@ -1359,6 +1386,7 @@
 func (*Builtin) Referrers() *[]Instruction { return nil }
 func (v *Builtin) Pos() token.Pos          { return token.NoPos }
 func (v *Builtin) Object() types.Object    { return v.object }
+func (v *Builtin) Parent() *Function       { return nil }
 
 func (v *Capture) Type() types.Type          { return v.typ }
 func (v *Capture) Name() string              { return v.name }
@@ -1368,6 +1396,7 @@
 
 func (v *Global) Type() types.Type                     { return v.typ }
 func (v *Global) Name() string                         { return v.name }
+func (v *Global) Parent() *Function                    { return nil }
 func (v *Global) Pos() token.Pos                       { return v.pos }
 func (v *Global) Referrers() *[]Instruction            { return nil }
 func (v *Global) Token() token.Token                   { return token.VAR }
@@ -1383,8 +1412,9 @@
 func (v *Function) Object() types.Object { return v.object }
 func (v *Function) String() string       { return v.RelString(nil) }
 func (v *Function) Package() *Package    { return v.Pkg }
+func (v *Function) Parent() *Function    { return v.parent }
 func (v *Function) Referrers() *[]Instruction {
-	if v.Enclosing != nil {
+	if v.parent != nil {
 		return &v.referrers
 	}
 	return nil
@@ -1412,6 +1442,7 @@
 func (v *anInstruction) Parent() *Function          { return v.block.parent }
 func (v *anInstruction) Block() *BasicBlock         { return v.block }
 func (v *anInstruction) setBlock(block *BasicBlock) { v.block = block }
+func (v *anInstruction) Referrers() *[]Instruction  { return nil }
 
 func (t *Type) Name() string                         { return t.object.Name() }
 func (t *Type) Pos() token.Pos                       { return t.object.Pos() }
@@ -1638,3 +1669,11 @@
 func (v *UnOp) Operands(rands []*Value) []*Value {
 	return append(rands, &v.X)
 }
+
+// Non-Instruction Values:
+func (v *Builtin) Operands(rands []*Value) []*Value   { return rands }
+func (v *Capture) Operands(rands []*Value) []*Value   { return rands }
+func (v *Const) Operands(rands []*Value) []*Value     { return rands }
+func (v *Function) Operands(rands []*Value) []*Value  { return rands }
+func (v *Global) Operands(rands []*Value) []*Value    { return rands }
+func (v *Parameter) Operands(rands []*Value) []*Value { return rands }
diff --git a/go/ssa/testmain.go b/go/ssa/testmain.go
index 51c8d4e..a5d8a82 100644
--- a/go/ssa/testmain.go
+++ b/go/ssa/testmain.go
@@ -104,7 +104,7 @@
 		name:      "matcher",
 		Signature: testingMainParams.At(0).Type().(*types.Signature),
 		Synthetic: "test matcher predicate",
-		Enclosing: main,
+		parent:    main,
 		Pkg:       testmain,
 		Prog:      prog,
 	}