cmd/compile: use NumElem instead of Type.Bound

This eliminates all direct reads of Type.Bound
outside type.go.

Change-Id: I0a9a72539f8f4c0de7f5e05e1821936bf7db5eb7
Reviewed-on: https://go-review.googlesource.com/21421
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go
index 43876d8..44898620 100644
--- a/src/cmd/compile/internal/gc/alg.go
+++ b/src/cmd/compile/internal/gc/alg.go
@@ -140,7 +140,7 @@
 			return ANOEQ, bad
 		}
 
-		switch t.Bound {
+		switch t.NumElem() {
 		case 0:
 			// We checked above that the element type is comparable.
 			return AMEM, nil
diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go
index 85376c6..b7ed9f1 100644
--- a/src/cmd/compile/internal/gc/align.go
+++ b/src/cmd/compile/internal/gc/align.go
@@ -242,12 +242,12 @@
 			dowidth(t.Elem())
 			if t.Elem().Width != 0 {
 				cap := (uint64(Thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width)
-				if uint64(t.Bound) > cap {
+				if uint64(t.NumElem()) > cap {
 					Yyerror("type %v larger than address space", Tconv(t, FmtLong))
 				}
 			}
 
-			w = t.Bound * t.Elem().Width
+			w = t.NumElem() * t.Elem().Width
 			t.Align = t.Elem().Align
 		} else if t.IsSlice() {
 			w = int64(sizeof_Array)
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index 95762ca..15b3118 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -508,7 +508,7 @@
 		}
 		if t.IsArray() {
 			p.tag(arrayTag)
-			p.int64(t.Bound)
+			p.int64(t.NumElem())
 		} else {
 			p.tag(sliceTag)
 		}
diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go
index d9c37df..b7d9d2c 100644
--- a/src/cmd/compile/internal/gc/cgen.go
+++ b/src/cmd/compile/internal/gc/cgen.go
@@ -1077,7 +1077,7 @@
 					Regalloc(&n4, Types[TUINT32], nil)
 					Thearch.Gmove(&n1, &n4)
 				} else {
-					Nodconst(&n4, Types[TUINT32], nl.Type.Bound)
+					Nodconst(&n4, Types[TUINT32], nl.Type.NumElem())
 				}
 				p1 := Thearch.Ginscmp(OLT, Types[TUINT32], &n2, &n4, +1)
 				if n4.Op == OREGISTER {
@@ -1235,7 +1235,7 @@
 					nlen.Type = t
 					nlen.Xoffset += int64(Array_nel)
 				} else {
-					Nodconst(&nlen, t, nl.Type.Bound)
+					Nodconst(&nlen, t, nl.Type.NumElem())
 				}
 
 				p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1)
@@ -1416,7 +1416,7 @@
 			} else if nl.Type.IsSlice() || nl.Type.IsString() {
 				// nlen already initialized
 			} else {
-				Nodconst(&nlen, t, nl.Type.Bound)
+				Nodconst(&nlen, t, nl.Type.NumElem())
 			}
 
 			p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1)
@@ -3025,7 +3025,7 @@
 			return
 		}
 		if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
-			Nodconst(&xlen, indexRegType, n.Left.Type.Elem().Bound)
+			Nodconst(&xlen, indexRegType, n.Left.Type.Elem().NumElem())
 			return
 		}
 		if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) {
@@ -3183,7 +3183,7 @@
 	// The func obvious below checks for out-of-order constant indexes.
 	var bound int64 = -1
 	if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
-		bound = n.Left.Type.Elem().Bound
+		bound = n.Left.Type.Elem().NumElem()
 	} else if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) {
 		bound = int64(len(n.Left.Val().U.(string)))
 	}
diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index b6136b2..b9a0a61 100644
--- a/src/cmd/compile/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -587,7 +587,7 @@
 
 	case TARRAY:
 		if t.IsArray() {
-			return fmt.Sprintf("[%d]%v", t.Bound, t.Elem())
+			return fmt.Sprintf("[%d]%v", t.NumElem(), t.Elem())
 		}
 		if t.isDDDArray() {
 			return "[...]" + t.Elem().String()
@@ -729,6 +729,12 @@
 			return "@\"unsafe\".Pointer"
 		}
 		return "unsafe.Pointer"
+
+	case TDDDFIELD:
+		if fmtmode == FExp {
+			Fatalf("cannot use TDDDFIELD with old exporter")
+		}
+		return fmt.Sprintf("%v <%v> %v", Econv(t.Etype), t.Sym, t.Wrapped())
 	}
 
 	if fmtmode == FExp {
diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go
index 1de63ae..f99e8d4 100644
--- a/src/cmd/compile/internal/gc/gen.go
+++ b/src/cmd/compile/internal/gc/gen.go
@@ -1215,7 +1215,7 @@
 			return true
 		}
 
-		for i := int64(0); i < t.Bound; i++ {
+		for i := int64(0); i < t.NumElem(); i++ {
 			if !visitComponents(t.Elem(), startOffset+i*t.Elem().Width, f) {
 				return false
 			}
diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go
index 1e66920..43f594e 100644
--- a/src/cmd/compile/internal/gc/plive.go
+++ b/src/cmd/compile/internal/gc/plive.go
@@ -926,7 +926,7 @@
 			bvset(bv, int32(*xoffset/int64(Widthptr))) // pointer in first slot (BitsPointer)
 			*xoffset += t.Width
 		} else {
-			for i := int64(0); i < t.Bound; i++ {
+			for i := int64(0); i < t.NumElem(); i++ {
 				onebitwalktype1(t.Elem(), xoffset, bv)
 			}
 		}
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index a5c85eb..7d07b4b 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -684,7 +684,7 @@
 			break
 		}
 
-		if t.Bound == 0 { // empty array
+		if t.NumElem() == 0 { // empty array
 			ret = false
 			break
 		}
@@ -747,8 +747,8 @@
 			// struct { byte *array; uintgo len; uintgo cap; }
 			return int64(Widthptr)
 		}
-		// haspointers already eliminated t.Bound == 0.
-		return (t.Bound-1)*t.Elem().Width + typeptrdata(t.Elem())
+		// haspointers already eliminated t.NumElem() == 0.
+		return (t.NumElem()-1)*t.Elem().Width + typeptrdata(t.Elem())
 
 	case TSTRUCT:
 		// Find the last field that has pointers.
@@ -1127,7 +1127,7 @@
 			ot = dcommontype(s, ot, t)
 			ot = dsymptr(s, ot, s1, 0)
 			ot = dsymptr(s, ot, s2, 0)
-			ot = duintptr(s, ot, uint64(t.Bound))
+			ot = duintptr(s, ot, uint64(t.NumElem()))
 		} else {
 			// ../../../../runtime/type.go:/sliceType
 			s1 := dtypesym(t.Elem())
@@ -1637,16 +1637,16 @@
 			p.w.Ptr(offset / int64(Widthptr))
 			return
 		}
-		if t.Bound == 0 {
+		if t.NumElem() == 0 {
 			// should have been handled by haspointers check above
 			Fatalf("GCProg.emit: empty array")
 		}
 
 		// Flatten array-of-array-of-array to just a big array by multiplying counts.
-		count := t.Bound
+		count := t.NumElem()
 		elem := t.Elem()
 		for elem.IsArray() {
-			count *= elem.Bound
+			count *= elem.NumElem()
 			elem = elem.Elem()
 		}
 
diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go
index 5144a25..7a4e68f 100644
--- a/src/cmd/compile/internal/gc/sinit.go
+++ b/src/cmd/compile/internal/gc/sinit.go
@@ -945,7 +945,7 @@
 		a.Nbody.Set1(r)
 
 		a.Ninit.Set1(Nod(OAS, index, Nodintconst(0)))
-		a.Left = Nod(OLT, index, Nodintconst(tarr.Bound))
+		a.Left = Nod(OLT, index, Nodintconst(tarr.NumElem()))
 		a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
 
 		a = typecheck(a, Etop)
@@ -1112,7 +1112,7 @@
 		}
 
 		// initialize of not completely specified
-		if var_.isSimpleName() || int64(n.List.Len()) < t.Bound {
+		if var_.isSimpleName() || int64(n.List.Len()) < t.NumElem() {
 			a := Nod(OAS, var_, nil)
 			a = typecheck(a, Etop)
 			a = walkexpr(a, init)
@@ -1399,7 +1399,7 @@
 
 			nam.Xoffset += int64(Array_nel) - int64(Array_array)
 			var nod1 Node
-			Nodconst(&nod1, Types[TINT], nr.Type.Bound)
+			Nodconst(&nod1, Types[TINT], nr.Type.NumElem())
 			gdata(&nam, &nod1, Widthint)
 
 			nam.Xoffset += int64(Array_cap) - int64(Array_nel)
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 5626feb..45e58d5 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -1973,7 +1973,7 @@
 		case n.Left.Type.IsMap(), n.Left.Type.IsChan():
 			return s.referenceTypeBuiltin(n, s.expr(n.Left))
 		default: // array
-			return s.constInt(Types[TINT], n.Left.Type.Bound)
+			return s.constInt(Types[TINT], n.Left.Type.NumElem())
 		}
 
 	case OSPTR:
@@ -2668,7 +2668,7 @@
 			a := s.addr(n.Left, bounded)
 			i := s.expr(n.Right)
 			i = s.extendIndex(i)
-			len := s.constInt(Types[TINT], n.Left.Type.Bound)
+			len := s.constInt(Types[TINT], n.Left.Type.NumElem())
 			if !n.Bounded {
 				s.boundsCheck(i, len)
 			}
@@ -3157,7 +3157,7 @@
 		ptrtype = Ptrto(elemtype)
 		s.nilCheck(v)
 		ptr = v
-		len = s.constInt(Types[TINT], t.Elem().Bound)
+		len = s.constInt(Types[TINT], t.Elem().NumElem())
 		cap = len
 	default:
 		s.Fatalf("bad type in slice %v\n", t)
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index b4acb5b..a643da8 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -739,7 +739,7 @@
 		return true
 
 	case TARRAY:
-		if t1.Bound != t2.Bound {
+		if t1.NumElem() != t2.NumElem() {
 			return false
 		}
 
@@ -2255,7 +2255,7 @@
 
 	case TARRAY:
 		// Array of 1 direct iface type can be direct.
-		return t.Bound == 1 && isdirectiface(t.Elem())
+		return t.NumElem() == 1 && isdirectiface(t.Elem())
 
 	case TSTRUCT:
 		// Struct with 1 field of direct iface type can be direct.
diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go
index c452bcf..d81ccbb 100644
--- a/src/cmd/compile/internal/gc/type.go
+++ b/src/cmd/compile/internal/gc/type.go
@@ -812,8 +812,8 @@
 		return ssa.CMPeq
 
 	case TARRAY:
-		if t.Bound != x.Bound {
-			return cmpForNe(t.Bound < x.Bound)
+		if t.NumElem() != x.NumElem() {
+			return cmpForNe(t.NumElem() < x.NumElem())
 		}
 
 	case TCHAN:
@@ -931,9 +931,7 @@
 }
 
 func (t *Type) NumElem() int64 {
-	if t.Etype != TARRAY {
-		panic("NumElem on non-TARRAY")
-	}
+	t.wantEtype(TARRAY)
 	t.checkBound()
 	return t.Bound
 }
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 68e29b6..b61d16b 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -1011,8 +1011,8 @@
 				x := n.Right.Val().U.(*Mpint).Int64()
 				if x < 0 {
 					Yyerror("invalid %s index %v (index must be non-negative)", why, n.Right)
-				} else if t.IsArray() && x >= t.Bound {
-					Yyerror("invalid array index %v (out of bounds for %d-element array)", n.Right, t.Bound)
+				} else if t.IsArray() && x >= t.NumElem() {
+					Yyerror("invalid array index %v (out of bounds for %d-element array)", n.Right, t.NumElem())
 				} else if Isconst(n.Left, CTSTR) && x >= int64(len(n.Left.Val().U.(string))) {
 					Yyerror("invalid string index %v (out of bounds for %d-byte string)", n.Right, len(n.Left.Val().U.(string)))
 				} else if n.Right.Val().U.(*Mpint).Cmp(Maxintval[TINT]) > 0 {
@@ -1418,7 +1418,7 @@
 				break
 			}
 			var r Node
-			Nodconst(&r, Types[TINT], t.Bound)
+			Nodconst(&r, Types[TINT], t.NumElem())
 			r.Orig = n
 			n = &r
 		}
@@ -2215,8 +2215,8 @@
 		if r.Val().U.(*Mpint).Int64() < 0 {
 			Yyerror("invalid slice index %v (index must be non-negative)", r)
 			return false
-		} else if tp != nil && tp.Bound > 0 && r.Val().U.(*Mpint).Int64() > tp.Bound {
-			Yyerror("invalid slice index %v (out of bounds for %d-element array)", r, tp.Bound)
+		} else if tp != nil && tp.NumElem() > 0 && r.Val().U.(*Mpint).Int64() > tp.NumElem() {
+			Yyerror("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem())
 			return false
 		} else if Isconst(l, CTSTR) && r.Val().U.(*Mpint).Int64() > int64(len(l.Val().U.(string))) {
 			Yyerror("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.Val().U.(string)))
@@ -2973,9 +2973,9 @@
 			i++
 			if int64(i) > length {
 				length = int64(i)
-				if t.IsArray() && length > t.Bound {
+				if t.IsArray() && length > t.NumElem() {
 					setlineno(l)
-					Yyerror("array index %d out of bounds [0:%d]", length-1, t.Bound)
+					Yyerror("array index %d out of bounds [0:%d]", length-1, t.NumElem())
 					// suppress any further errors out of bounds errors for the same type by pretending it is a slice
 					t.Bound = sliceBound
 				}
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 9310171..3758aa0 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -546,7 +546,7 @@
 		}
 		if t.IsArray() {
 			safeexpr(n.Left, init)
-			Nodconst(n, n.Type, t.Bound)
+			Nodconst(n, n.Type, t.NumElem())
 			n.Typecheck = 1
 		}
 
@@ -1158,7 +1158,7 @@
 			t = t.Elem()
 		}
 		if t.IsArray() {
-			n.Bounded = bounded(r, t.Bound)
+			n.Bounded = bounded(r, t.NumElem())
 			if Debug['m'] != 0 && n.Bounded && !Isconst(n.Right, CTINT) {
 				Warn("index bounds check elided")
 			}
@@ -3145,12 +3145,12 @@
 	}
 
 	var expr *Node
-	if t.Etype == TARRAY && t.Bound <= 4 && issimple[t.Elem().Etype] {
+	if t.Etype == TARRAY && t.NumElem() <= 4 && issimple[t.Elem().Etype] {
 		// Four or fewer elements of a basic type.
 		// Unroll comparisons.
 		var li *Node
 		var ri *Node
-		for i := 0; int64(i) < t.Bound; i++ {
+		for i := 0; int64(i) < t.NumElem(); i++ {
 			li = Nod(OINDEX, l, Nodintconst(int64(i)))
 			ri = Nod(OINDEX, r, Nodintconst(int64(i)))
 			a = Nod(n.Op, li, ri)
@@ -3170,7 +3170,7 @@
 
 	if t.Etype == TARRAY {
 		// Zero- or single-element array, of any type.
-		switch t.Bound {
+		switch t.NumElem() {
 		case 0:
 			n = finishcompare(n, Nodbool(n.Op == OEQ), init)
 			return n