Commit 3a0783c5 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

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: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 077902d1
...@@ -140,7 +140,7 @@ func algtype1(t *Type) (AlgKind, *Type) { ...@@ -140,7 +140,7 @@ func algtype1(t *Type) (AlgKind, *Type) {
return ANOEQ, bad return ANOEQ, bad
} }
switch t.Bound { switch t.NumElem() {
case 0: case 0:
// We checked above that the element type is comparable. // We checked above that the element type is comparable.
return AMEM, nil return AMEM, nil
......
...@@ -242,12 +242,12 @@ func dowidth(t *Type) { ...@@ -242,12 +242,12 @@ func dowidth(t *Type) {
dowidth(t.Elem()) dowidth(t.Elem())
if t.Elem().Width != 0 { if t.Elem().Width != 0 {
cap := (uint64(Thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width) 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)) 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 t.Align = t.Elem().Align
} else if t.IsSlice() { } else if t.IsSlice() {
w = int64(sizeof_Array) w = int64(sizeof_Array)
......
...@@ -508,7 +508,7 @@ func (p *exporter) typ(t *Type) { ...@@ -508,7 +508,7 @@ func (p *exporter) typ(t *Type) {
} }
if t.IsArray() { if t.IsArray() {
p.tag(arrayTag) p.tag(arrayTag)
p.int64(t.Bound) p.int64(t.NumElem())
} else { } else {
p.tag(sliceTag) p.tag(sliceTag)
} }
......
...@@ -1077,7 +1077,7 @@ func Agenr(n *Node, a *Node, res *Node) { ...@@ -1077,7 +1077,7 @@ func Agenr(n *Node, a *Node, res *Node) {
Regalloc(&n4, Types[TUINT32], nil) Regalloc(&n4, Types[TUINT32], nil)
Thearch.Gmove(&n1, &n4) Thearch.Gmove(&n1, &n4)
} else { } else {
Nodconst(&n4, Types[TUINT32], nl.Type.Bound) Nodconst(&n4, Types[TUINT32], nl.Type.NumElem())
} }
p1 := Thearch.Ginscmp(OLT, Types[TUINT32], &n2, &n4, +1) p1 := Thearch.Ginscmp(OLT, Types[TUINT32], &n2, &n4, +1)
if n4.Op == OREGISTER { if n4.Op == OREGISTER {
...@@ -1235,7 +1235,7 @@ func Agenr(n *Node, a *Node, res *Node) { ...@@ -1235,7 +1235,7 @@ func Agenr(n *Node, a *Node, res *Node) {
nlen.Type = t nlen.Type = t
nlen.Xoffset += int64(Array_nel) nlen.Xoffset += int64(Array_nel)
} else { } else {
Nodconst(&nlen, t, nl.Type.Bound) Nodconst(&nlen, t, nl.Type.NumElem())
} }
p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1) p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1)
...@@ -1416,7 +1416,7 @@ func Agenr(n *Node, a *Node, res *Node) { ...@@ -1416,7 +1416,7 @@ func Agenr(n *Node, a *Node, res *Node) {
} else if nl.Type.IsSlice() || nl.Type.IsString() { } else if nl.Type.IsSlice() || nl.Type.IsString() {
// nlen already initialized // nlen already initialized
} else { } else {
Nodconst(&nlen, t, nl.Type.Bound) Nodconst(&nlen, t, nl.Type.NumElem())
} }
p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1) p1 := Thearch.Ginscmp(OLT, t, &n2, &nlen, +1)
...@@ -3025,7 +3025,7 @@ func cgen_slice(n, res *Node, wb bool) { ...@@ -3025,7 +3025,7 @@ func cgen_slice(n, res *Node, wb bool) {
return return
} }
if n.Op == OSLICEARR || n.Op == OSLICE3ARR { if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
Nodconst(&xlen, indexRegType, n.Left.Type.Elem().Bound) Nodconst(&xlen, indexRegType, n.Left.Type.Elem().NumElem())
return return
} }
if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) { if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) {
...@@ -3183,7 +3183,7 @@ func cgen_slice(n, res *Node, wb bool) { ...@@ -3183,7 +3183,7 @@ func cgen_slice(n, res *Node, wb bool) {
// The func obvious below checks for out-of-order constant indexes. // The func obvious below checks for out-of-order constant indexes.
var bound int64 = -1 var bound int64 = -1
if n.Op == OSLICEARR || n.Op == OSLICE3ARR { 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) { } else if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) {
bound = int64(len(n.Left.Val().U.(string))) bound = int64(len(n.Left.Val().U.(string)))
} }
......
...@@ -587,7 +587,7 @@ func typefmt(t *Type, flag FmtFlag) string { ...@@ -587,7 +587,7 @@ func typefmt(t *Type, flag FmtFlag) string {
case TARRAY: case TARRAY:
if t.IsArray() { if t.IsArray() {
return fmt.Sprintf("[%d]%v", t.Bound, t.Elem()) return fmt.Sprintf("[%d]%v", t.NumElem(), t.Elem())
} }
if t.isDDDArray() { if t.isDDDArray() {
return "[...]" + t.Elem().String() return "[...]" + t.Elem().String()
...@@ -729,6 +729,12 @@ func typefmt(t *Type, flag FmtFlag) string { ...@@ -729,6 +729,12 @@ func typefmt(t *Type, flag FmtFlag) string {
return "@\"unsafe\".Pointer" return "@\"unsafe\".Pointer"
} }
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 { if fmtmode == FExp {
......
...@@ -1215,7 +1215,7 @@ func visitComponents(t *Type, startOffset int64, f func(elem *Type, elemOffset i ...@@ -1215,7 +1215,7 @@ func visitComponents(t *Type, startOffset int64, f func(elem *Type, elemOffset i
return true 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) { if !visitComponents(t.Elem(), startOffset+i*t.Elem().Width, f) {
return false return false
} }
......
...@@ -926,7 +926,7 @@ func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) { ...@@ -926,7 +926,7 @@ func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) {
bvset(bv, int32(*xoffset/int64(Widthptr))) // pointer in first slot (BitsPointer) bvset(bv, int32(*xoffset/int64(Widthptr))) // pointer in first slot (BitsPointer)
*xoffset += t.Width *xoffset += t.Width
} else { } else {
for i := int64(0); i < t.Bound; i++ { for i := int64(0); i < t.NumElem(); i++ {
onebitwalktype1(t.Elem(), xoffset, bv) onebitwalktype1(t.Elem(), xoffset, bv)
} }
} }
......
...@@ -684,7 +684,7 @@ func haspointers(t *Type) bool { ...@@ -684,7 +684,7 @@ func haspointers(t *Type) bool {
break break
} }
if t.Bound == 0 { // empty array if t.NumElem() == 0 { // empty array
ret = false ret = false
break break
} }
...@@ -747,8 +747,8 @@ func typeptrdata(t *Type) int64 { ...@@ -747,8 +747,8 @@ func typeptrdata(t *Type) int64 {
// struct { byte *array; uintgo len; uintgo cap; } // struct { byte *array; uintgo len; uintgo cap; }
return int64(Widthptr) return int64(Widthptr)
} }
// haspointers already eliminated t.Bound == 0. // haspointers already eliminated t.NumElem() == 0.
return (t.Bound-1)*t.Elem().Width + typeptrdata(t.Elem()) return (t.NumElem()-1)*t.Elem().Width + typeptrdata(t.Elem())
case TSTRUCT: case TSTRUCT:
// Find the last field that has pointers. // Find the last field that has pointers.
...@@ -1127,7 +1127,7 @@ ok: ...@@ -1127,7 +1127,7 @@ ok:
ot = dcommontype(s, ot, t) ot = dcommontype(s, ot, t)
ot = dsymptr(s, ot, s1, 0) ot = dsymptr(s, ot, s1, 0)
ot = dsymptr(s, ot, s2, 0) ot = dsymptr(s, ot, s2, 0)
ot = duintptr(s, ot, uint64(t.Bound)) ot = duintptr(s, ot, uint64(t.NumElem()))
} else { } else {
// ../../../../runtime/type.go:/sliceType // ../../../../runtime/type.go:/sliceType
s1 := dtypesym(t.Elem()) s1 := dtypesym(t.Elem())
...@@ -1637,16 +1637,16 @@ func (p *GCProg) emit(t *Type, offset int64) { ...@@ -1637,16 +1637,16 @@ func (p *GCProg) emit(t *Type, offset int64) {
p.w.Ptr(offset / int64(Widthptr)) p.w.Ptr(offset / int64(Widthptr))
return return
} }
if t.Bound == 0 { if t.NumElem() == 0 {
// should have been handled by haspointers check above // should have been handled by haspointers check above
Fatalf("GCProg.emit: empty array") Fatalf("GCProg.emit: empty array")
} }
// Flatten array-of-array-of-array to just a big array by multiplying counts. // Flatten array-of-array-of-array to just a big array by multiplying counts.
count := t.Bound count := t.NumElem()
elem := t.Elem() elem := t.Elem()
for elem.IsArray() { for elem.IsArray() {
count *= elem.Bound count *= elem.NumElem()
elem = elem.Elem() elem = elem.Elem()
} }
......
...@@ -945,7 +945,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -945,7 +945,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
a.Nbody.Set1(r) a.Nbody.Set1(r)
a.Ninit.Set1(Nod(OAS, index, Nodintconst(0))) 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.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
a = typecheck(a, Etop) a = typecheck(a, Etop)
...@@ -1112,7 +1112,7 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -1112,7 +1112,7 @@ func anylit(ctxt int, n *Node, var_ *Node, init *Nodes) {
} }
// initialize of not completely specified // 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 := Nod(OAS, var_, nil)
a = typecheck(a, Etop) a = typecheck(a, Etop)
a = walkexpr(a, init) a = walkexpr(a, init)
...@@ -1399,7 +1399,7 @@ func genAsInitNoCheck(n *Node, reportOnly bool) bool { ...@@ -1399,7 +1399,7 @@ func genAsInitNoCheck(n *Node, reportOnly bool) bool {
nam.Xoffset += int64(Array_nel) - int64(Array_array) nam.Xoffset += int64(Array_nel) - int64(Array_array)
var nod1 Node var nod1 Node
Nodconst(&nod1, Types[TINT], nr.Type.Bound) Nodconst(&nod1, Types[TINT], nr.Type.NumElem())
gdata(&nam, &nod1, Widthint) gdata(&nam, &nod1, Widthint)
nam.Xoffset += int64(Array_cap) - int64(Array_nel) nam.Xoffset += int64(Array_cap) - int64(Array_nel)
......
...@@ -1973,7 +1973,7 @@ func (s *state) expr(n *Node) *ssa.Value { ...@@ -1973,7 +1973,7 @@ func (s *state) expr(n *Node) *ssa.Value {
case n.Left.Type.IsMap(), n.Left.Type.IsChan(): case n.Left.Type.IsMap(), n.Left.Type.IsChan():
return s.referenceTypeBuiltin(n, s.expr(n.Left)) return s.referenceTypeBuiltin(n, s.expr(n.Left))
default: // array default: // array
return s.constInt(Types[TINT], n.Left.Type.Bound) return s.constInt(Types[TINT], n.Left.Type.NumElem())
} }
case OSPTR: case OSPTR:
...@@ -2668,7 +2668,7 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value { ...@@ -2668,7 +2668,7 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value {
a := s.addr(n.Left, bounded) a := s.addr(n.Left, bounded)
i := s.expr(n.Right) i := s.expr(n.Right)
i = s.extendIndex(i) 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 { if !n.Bounded {
s.boundsCheck(i, len) s.boundsCheck(i, len)
} }
...@@ -3157,7 +3157,7 @@ func (s *state) slice(t *Type, v, i, j, k *ssa.Value) (p, l, c *ssa.Value) { ...@@ -3157,7 +3157,7 @@ func (s *state) slice(t *Type, v, i, j, k *ssa.Value) (p, l, c *ssa.Value) {
ptrtype = Ptrto(elemtype) ptrtype = Ptrto(elemtype)
s.nilCheck(v) s.nilCheck(v)
ptr = v ptr = v
len = s.constInt(Types[TINT], t.Elem().Bound) len = s.constInt(Types[TINT], t.Elem().NumElem())
cap = len cap = len
default: default:
s.Fatalf("bad type in slice %v\n", t) s.Fatalf("bad type in slice %v\n", t)
......
...@@ -739,7 +739,7 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool { ...@@ -739,7 +739,7 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool {
return true return true
case TARRAY: case TARRAY:
if t1.Bound != t2.Bound { if t1.NumElem() != t2.NumElem() {
return false return false
} }
...@@ -2255,7 +2255,7 @@ func isdirectiface(t *Type) bool { ...@@ -2255,7 +2255,7 @@ func isdirectiface(t *Type) bool {
case TARRAY: case TARRAY:
// Array of 1 direct iface type can be direct. // 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: case TSTRUCT:
// Struct with 1 field of direct iface type can be direct. // Struct with 1 field of direct iface type can be direct.
......
...@@ -812,8 +812,8 @@ func (t *Type) cmp(x *Type) ssa.Cmp { ...@@ -812,8 +812,8 @@ func (t *Type) cmp(x *Type) ssa.Cmp {
return ssa.CMPeq return ssa.CMPeq
case TARRAY: case TARRAY:
if t.Bound != x.Bound { if t.NumElem() != x.NumElem() {
return cmpForNe(t.Bound < x.Bound) return cmpForNe(t.NumElem() < x.NumElem())
} }
case TCHAN: case TCHAN:
...@@ -931,9 +931,7 @@ func (t *Type) FieldOff(i int) int64 { ...@@ -931,9 +931,7 @@ func (t *Type) FieldOff(i int) int64 {
} }
func (t *Type) NumElem() int64 { func (t *Type) NumElem() int64 {
if t.Etype != TARRAY { t.wantEtype(TARRAY)
panic("NumElem on non-TARRAY")
}
t.checkBound() t.checkBound()
return t.Bound return t.Bound
} }
......
...@@ -1011,8 +1011,8 @@ OpSwitch: ...@@ -1011,8 +1011,8 @@ OpSwitch:
x := n.Right.Val().U.(*Mpint).Int64() x := n.Right.Val().U.(*Mpint).Int64()
if x < 0 { if x < 0 {
Yyerror("invalid %s index %v (index must be non-negative)", why, n.Right) Yyerror("invalid %s index %v (index must be non-negative)", why, n.Right)
} else if t.IsArray() && x >= t.Bound { } else if t.IsArray() && x >= t.NumElem() {
Yyerror("invalid array index %v (out of bounds for %d-element array)", n.Right, t.Bound) 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))) { } 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))) 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 { } else if n.Right.Val().U.(*Mpint).Cmp(Maxintval[TINT]) > 0 {
...@@ -1418,7 +1418,7 @@ OpSwitch: ...@@ -1418,7 +1418,7 @@ OpSwitch:
break break
} }
var r Node var r Node
Nodconst(&r, Types[TINT], t.Bound) Nodconst(&r, Types[TINT], t.NumElem())
r.Orig = n r.Orig = n
n = &r n = &r
} }
...@@ -2215,8 +2215,8 @@ func checksliceindex(l *Node, r *Node, tp *Type) bool { ...@@ -2215,8 +2215,8 @@ func checksliceindex(l *Node, r *Node, tp *Type) bool {
if r.Val().U.(*Mpint).Int64() < 0 { if r.Val().U.(*Mpint).Int64() < 0 {
Yyerror("invalid slice index %v (index must be non-negative)", r) Yyerror("invalid slice index %v (index must be non-negative)", r)
return false return false
} else if tp != nil && tp.Bound > 0 && r.Val().U.(*Mpint).Int64() > 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.Bound) Yyerror("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem())
return false return false
} else if Isconst(l, CTSTR) && r.Val().U.(*Mpint).Int64() > int64(len(l.Val().U.(string))) { } 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))) Yyerror("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.Val().U.(string)))
...@@ -2973,9 +2973,9 @@ func typecheckcomplit(n *Node) *Node { ...@@ -2973,9 +2973,9 @@ func typecheckcomplit(n *Node) *Node {
i++ i++
if int64(i) > length { if int64(i) > length {
length = int64(i) length = int64(i)
if t.IsArray() && length > t.Bound { if t.IsArray() && length > t.NumElem() {
setlineno(l) 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 // suppress any further errors out of bounds errors for the same type by pretending it is a slice
t.Bound = sliceBound t.Bound = sliceBound
} }
......
...@@ -546,7 +546,7 @@ opswitch: ...@@ -546,7 +546,7 @@ opswitch:
} }
if t.IsArray() { if t.IsArray() {
safeexpr(n.Left, init) safeexpr(n.Left, init)
Nodconst(n, n.Type, t.Bound) Nodconst(n, n.Type, t.NumElem())
n.Typecheck = 1 n.Typecheck = 1
} }
...@@ -1158,7 +1158,7 @@ opswitch: ...@@ -1158,7 +1158,7 @@ opswitch:
t = t.Elem() t = t.Elem()
} }
if t.IsArray() { 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) { if Debug['m'] != 0 && n.Bounded && !Isconst(n.Right, CTINT) {
Warn("index bounds check elided") Warn("index bounds check elided")
} }
...@@ -3145,12 +3145,12 @@ func walkcompare(n *Node, init *Nodes) *Node { ...@@ -3145,12 +3145,12 @@ func walkcompare(n *Node, init *Nodes) *Node {
} }
var expr *Node 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. // Four or fewer elements of a basic type.
// Unroll comparisons. // Unroll comparisons.
var li *Node var li *Node
var ri *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))) li = Nod(OINDEX, l, Nodintconst(int64(i)))
ri = Nod(OINDEX, r, Nodintconst(int64(i))) ri = Nod(OINDEX, r, Nodintconst(int64(i)))
a = Nod(n.Op, li, ri) a = Nod(n.Op, li, ri)
...@@ -3170,7 +3170,7 @@ func walkcompare(n *Node, init *Nodes) *Node { ...@@ -3170,7 +3170,7 @@ func walkcompare(n *Node, init *Nodes) *Node {
if t.Etype == TARRAY { if t.Etype == TARRAY {
// Zero- or single-element array, of any type. // Zero- or single-element array, of any type.
switch t.Bound { switch t.NumElem() {
case 0: case 0:
n = finishcompare(n, Nodbool(n.Op == OEQ), init) n = finishcompare(n, Nodbool(n.Op == OEQ), init)
return n return n
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment