go.tools/pointer: make os.Args point to something.

Since the Go runtime treats it specially, so must the pointer analysis.

Details:
- Combine object.{val,typ} fields into 'data interface{}'.
  It may now hold a string, describing an instrinsically
  allocated object such as the command-line args.
- extend Label accordingly; add Label.ReflectType() accessor.

Also: document pointer analysis algorithm classification.

R=crawshaw
CC=golang-dev
https://golang.org/cl/14156043
diff --git a/pointer/gen.go b/pointer/gen.go
index 8dd5218..b4c19e2 100644
--- a/pointer/gen.go
+++ b/pointer/gen.go
@@ -95,9 +95,9 @@
 // a single object allocation.
 //
 // obj is the start node of the object, from a prior call to nextNode.
-// Its size, flags and (optionally) data will be updated.
+// Its size, flags and optional data will be updated.
 //
-func (a *analysis) endObject(obj nodeid, cgn *cgnode, val ssa.Value) *object {
+func (a *analysis) endObject(obj nodeid, cgn *cgnode, data interface{}) *object {
 	// Ensure object is non-empty by padding;
 	// the pad will be the object node.
 	size := uint32(a.nextNode() - obj)
@@ -108,12 +108,9 @@
 	o := &object{
 		size: size, // excludes padding
 		cgn:  cgn,
-		val:  val,
+		data: data,
 	}
 	objNode.obj = o
-	if val != nil && a.log != nil {
-		fmt.Fprintf(a.log, "\tobj[%s] = n%d\n", val, obj)
-	}
 
 	return o
 }
@@ -150,10 +147,10 @@
 }
 
 // makeTagged creates a tagged object of type typ.
-func (a *analysis) makeTagged(typ types.Type, cgn *cgnode, val ssa.Value) nodeid {
+func (a *analysis) makeTagged(typ types.Type, cgn *cgnode, data interface{}) nodeid {
 	obj := a.addOneNode(typ, "tagged.T", nil) // NB: type may be non-scalar!
 	a.addNodes(typ, "tagged.v")
-	a.endObject(obj, cgn, val).flags |= otTagged
+	a.endObject(obj, cgn, data).flags |= otTagged
 	return obj
 }
 
@@ -168,10 +165,9 @@
 	// ordinarily a large struct but here a single node will do.
 	obj := a.nextNode()
 	a.addOneNode(T, "reflect.rtype", nil)
-	a.endObject(obj, nil, nil).rtype = T
+	a.endObject(obj, nil, T)
 
-	id := a.makeTagged(a.reflectRtypePtr, nil, nil)
-	a.nodes[id].obj.rtype = T
+	id := a.makeTagged(a.reflectRtypePtr, nil, T)
 	a.nodes[id+1].typ = T // trick (each *rtype tagged object is a singleton)
 	a.addressOf(id+1, obj)
 
@@ -809,6 +805,10 @@
 				// For now, Captures have the same cardinality as globals.
 				// TODO(adonovan): treat captures context-sensitively.
 			}
+
+			if a.log != nil {
+				fmt.Fprintf(a.log, "\tglobalobj[%s] = n%d\n", a.nodes[obj].obj, obj)
+			}
 			a.globalobj[v] = obj
 		}
 		return obj
@@ -874,6 +874,10 @@
 			// - unsafe.Pointer->*T conversion acts like Alloc
 			// - string->[]byte/[]rune conversion acts like MakeSlice
 		}
+
+		if a.log != nil {
+			fmt.Fprintf(a.log, "\tlocalobj[%s] = n%d\n", a.nodes[obj].obj, obj)
+		}
 		a.localobj[v] = obj
 	}
 	return obj
@@ -1222,5 +1226,13 @@
 		a.genFunc(cgn)
 	}
 
+	// The runtime magically allocates os.Args; so should we.
+	if os := a.prog.ImportedPackage("os"); os != nil {
+		// In effect:  os.Args = new([1]string)[:]
+		obj := a.addNodes(types.NewArray(types.Typ[types.String], 1), "<command-line args>")
+		a.endObject(obj, nil, "<command-line args>")
+		a.addressOf(a.objectNode(nil, os.Var("Args")), obj)
+	}
+
 	return root
 }