Commit eb98e515 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile: add typArray, typSlice, and typDDDArray

These are the first of several convenience
constructors for types.

They are part of type field encapsulation.
This removes most external writes to TARRAY Type and Bound fields.

substAny still directly fiddles with the .Type field.
substAny generally needs access to Type internals.
It will be moved to type.go in a future CL.

bimport still directly writes the .Type field.
This is hard to change.

Also of note:

* inl.go contains an (apparently irrelevant) bug fix:
  as.Right was given the wrong type.
  vararrtype was previously unused.
* I believe that aindex (subr.go) never creates slices,
  but it is safer to keep existing behavior.
  The removal of -1 as a constant there is part
  of hiding that implementation detail.
  Future CLs will finish that job.

Passes toolstash -cmp.

Change-Id: If09bf001a874d7dba08e9ad0bcd6722860af4b91
Reviewed-on: https://go-review.googlesource.com/21249Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent f32161da
...@@ -1494,10 +1494,8 @@ func esccall(e *EscState, n *Node, up *Node) { ...@@ -1494,10 +1494,8 @@ func esccall(e *EscState, n *Node, up *Node) {
if n2.Isddd && !n.Isddd { if n2.Isddd && !n.Isddd {
// Introduce ODDDARG node to represent ... allocation. // Introduce ODDDARG node to represent ... allocation.
src = Nod(ODDDARG, nil, nil) src = Nod(ODDDARG, nil, nil)
src.Type = typ(TARRAY) arr := typArray(n2.Type.Type, int64(len(lls)))
src.Type.Type = n2.Type.Type src.Type = Ptrto(arr) // make pointer so it will be tracked
src.Type.Bound = int64(len(lls))
src.Type = Ptrto(src.Type) // make pointer so it will be tracked
src.Lineno = n.Lineno src.Lineno = n.Lineno
e.track(src) e.track(src)
n.Right = src n.Right = src
...@@ -1556,10 +1554,8 @@ func esccall(e *EscState, n *Node, up *Node) { ...@@ -1556,10 +1554,8 @@ func esccall(e *EscState, n *Node, up *Node) {
// Introduce ODDDARG node to represent ... allocation. // Introduce ODDDARG node to represent ... allocation.
src = Nod(ODDDARG, nil, nil) src = Nod(ODDDARG, nil, nil)
src.Lineno = n.Lineno src.Lineno = n.Lineno
src.Type = typ(TARRAY) arr := typArray(t.Type.Type, int64(len(lls)-i))
src.Type.Type = t.Type.Type src.Type = Ptrto(arr) // make pointer so it will be tracked
src.Type.Bound = int64(len(lls) - i)
src.Type = Ptrto(src.Type) // make pointer so it will be tracked
e.track(src) e.track(src)
n.Right = src n.Right = src
} }
......
...@@ -747,11 +747,8 @@ func mkinlcall1(n *Node, fn *Node, isddd bool) *Node { ...@@ -747,11 +747,8 @@ func mkinlcall1(n *Node, fn *Node, isddd bool) *Node {
as.Right = nodnil() as.Right = nodnil()
as.Right.Type = varargtype as.Right.Type = varargtype
} else { } else {
vararrtype := typ(TARRAY) vararrtype := typArray(varargtype.Type, int64(varargcount))
vararrtype.Type = varargtype.Type as.Right = Nod(OCOMPLIT, nil, typenod(vararrtype))
vararrtype.Bound = int64(varargcount)
as.Right = Nod(OCOMPLIT, nil, typenod(varargtype))
as.Right.List.Set(varargs) as.Right.List.Set(varargs)
as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil)) as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil))
} }
......
...@@ -1005,9 +1005,7 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node { ...@@ -1005,9 +1005,7 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
orderexprlist(n.List, order) orderexprlist(n.List, order)
if n.List.Len() > 5 { if n.List.Len() > 5 {
t := typ(TARRAY) t := typArray(Types[TSTRING], int64(n.List.Len()))
t.Bound = int64(n.List.Len())
t.Type = Types[TSTRING]
prealloc[n] = ordertemp(t, order, false) prealloc[n] = ordertemp(t, order, false)
} }
......
...@@ -3133,9 +3133,7 @@ func (p *parser) hidden_funarg() *Node { ...@@ -3133,9 +3133,7 @@ func (p *parser) hidden_funarg() *Node {
s3 := p.hidden_type() s3 := p.hidden_type()
s4 := p.oliteral() s4 := p.oliteral()
t := typ(TARRAY) t := typSlice(s3)
t.Bound = -1
t.Type = s3
ss := Nod(ODCLFIELD, nil, typenod(t)) ss := Nod(ODCLFIELD, nil, typenod(t))
if s1 != nil { if s1 != nil {
......
...@@ -93,19 +93,12 @@ func mapbucket(t *Type) *Type { ...@@ -93,19 +93,12 @@ func mapbucket(t *Type) *Type {
} }
// The first field is: uint8 topbits[BUCKETSIZE]. // The first field is: uint8 topbits[BUCKETSIZE].
arr := typ(TARRAY) arr := typArray(Types[TUINT8], BUCKETSIZE)
arr.Type = Types[TUINT8]
arr.Bound = BUCKETSIZE
field := make([]*Field, 0, 5) field := make([]*Field, 0, 5)
field = append(field, makefield("topbits", arr)) field = append(field, makefield("topbits", arr))
arr = typ(TARRAY) arr = typArray(keytype, BUCKETSIZE)
arr.Type = keytype
arr.Bound = BUCKETSIZE
field = append(field, makefield("keys", arr)) field = append(field, makefield("keys", arr))
arr = typ(TARRAY) arr = typArray(valtype, BUCKETSIZE)
arr.Type = valtype
arr.Bound = BUCKETSIZE
field = append(field, makefield("values", arr)) field = append(field, makefield("values", arr))
// Make sure the overflow pointer is the last memory in the struct, // Make sure the overflow pointer is the last memory in the struct,
...@@ -1124,10 +1117,7 @@ ok: ...@@ -1124,10 +1117,7 @@ ok:
if t.Bound >= 0 { if t.Bound >= 0 {
// ../../../../runtime/type.go:/arrayType // ../../../../runtime/type.go:/arrayType
s1 := dtypesym(t.Type) s1 := dtypesym(t.Type)
t2 := typSlice(t.Type)
t2 := typ(TARRAY)
t2.Type = t.Type
t2.Bound = -1 // slice
s2 := dtypesym(t2) s2 := dtypesym(t2)
ot = dcommontype(s, ot, t) ot = dcommontype(s, ot, t)
ot = dsymptr(s, ot, s1, 0) ot = dsymptr(s, ot, s1, 0)
......
...@@ -433,10 +433,8 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool { ...@@ -433,10 +433,8 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
initplan(r) initplan(r)
if Isslice(r.Type) { if Isslice(r.Type) {
// Init slice. // Init slice.
ta := typ(TARRAY) bound := r.Right.Val().U.(*Mpint).Int64()
ta := typArray(r.Type.Type, bound)
ta.Type = r.Type.Type
ta.Bound = r.Right.Val().U.(*Mpint).Int64()
a := staticname(ta, 1) a := staticname(ta, 1)
inittemps[r] = a inittemps[r] = a
n := *l n := *l
...@@ -876,9 +874,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -876,9 +874,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
tstruct := typ(TSTRUCT) tstruct := typ(TSTRUCT)
tstruct.SetFields(fields[:]) tstruct.SetFields(fields[:])
tarr := typ(TARRAY) tarr := typArray(tstruct, int64(b))
tarr.Bound = int64(b)
tarr.Type = tstruct
// TODO(josharian): suppress alg generation for these types? // TODO(josharian): suppress alg generation for these types?
dowidth(tarr) dowidth(tarr)
......
...@@ -483,7 +483,8 @@ func Nodbool(b bool) *Node { ...@@ -483,7 +483,8 @@ func Nodbool(b bool) *Node {
} }
func aindex(b *Node, t *Type) *Type { func aindex(b *Node, t *Type) *Type {
bound := int64(-1) // open bound hasbound := false
var bound int64
b = typecheck(b, Erv) b = typecheck(b, Erv)
if b != nil { if b != nil {
switch consttype(b) { switch consttype(b) {
...@@ -491,6 +492,7 @@ func aindex(b *Node, t *Type) *Type { ...@@ -491,6 +492,7 @@ func aindex(b *Node, t *Type) *Type {
Yyerror("array bound must be an integer expression") Yyerror("array bound must be an integer expression")
case CTINT, CTRUNE: case CTINT, CTRUNE:
hasbound = true
bound = b.Val().U.(*Mpint).Int64() bound = b.Val().U.(*Mpint).Int64()
if bound < 0 { if bound < 0 {
Yyerror("array bound must be non negative") Yyerror("array bound must be non negative")
...@@ -498,12 +500,10 @@ func aindex(b *Node, t *Type) *Type { ...@@ -498,12 +500,10 @@ func aindex(b *Node, t *Type) *Type {
} }
} }
// fixed array if !hasbound {
r := typ(TARRAY) return typSlice(t)
}
r.Type = t return typArray(t, bound)
r.Bound = bound
return r
} }
// treecopy recursively copies n, with the exception of // treecopy recursively copies n, with the exception of
...@@ -1904,10 +1904,7 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) { ...@@ -1904,10 +1904,7 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
// that the interface call will pass in. // that the interface call will pass in.
// Add a dummy padding argument after the // Add a dummy padding argument after the
// receiver to make up the difference. // receiver to make up the difference.
tpad := typ(TARRAY) tpad := typArray(Types[TUINT8], Types[Tptr].Width-rcvr.Width)
tpad.Type = Types[TUINT8]
tpad.Bound = Types[Tptr].Width - rcvr.Width
pad := Nod(ODCLFIELD, newname(Lookup(".pad")), typenod(tpad)) pad := Nod(ODCLFIELD, newname(Lookup(".pad")), typenod(tpad))
l = append(l, pad) l = append(l, pad)
} }
......
...@@ -235,6 +235,30 @@ func typ(et EType) *Type { ...@@ -235,6 +235,30 @@ func typ(et EType) *Type {
return t return t
} }
// typArray returns a new fixed-length array Type.
func typArray(elem *Type, bound int64) *Type {
t := typ(TARRAY)
t.Type = elem
t.Bound = bound
return t
}
// typSlice returns a new slice Type.
func typSlice(elem *Type) *Type {
t := typ(TARRAY)
t.Type = elem
t.Bound = -1
return t
}
// typeDDDArray returns a new [...]T array Type.
func typeDDDArray(elem *Type) *Type {
t := typ(TARRAY)
t.Type = elem
t.Bound = dddBound
return t
}
func newField() *Field { func newField() *Field {
return &Field{ return &Field{
Offset: BADWIDTH, Offset: BADWIDTH,
......
...@@ -330,13 +330,19 @@ OpSwitch: ...@@ -330,13 +330,19 @@ OpSwitch:
case OTARRAY: case OTARRAY:
ok |= Etype ok |= Etype
t := typ(TARRAY) var t *Type
l := n.Left l := n.Left
r := n.Right r := n.Right
r = typecheck(r, Etype)
if r.Type == nil {
n.Type = nil
return n
}
if l == nil { if l == nil {
t.Bound = -1 // slice t = typSlice(r.Type)
} else if l.Op == ODDD { } else if l.Op == ODDD {
t.Bound = dddBound // to be filled in t = typeDDDArray(r.Type)
if top&Ecomplit == 0 && n.Diag == 0 { if top&Ecomplit == 0 && n.Diag == 0 {
t.Broke = true t.Broke = true
n.Diag = 1 n.Diag = 1
...@@ -363,7 +369,8 @@ OpSwitch: ...@@ -363,7 +369,8 @@ OpSwitch:
return n return n
} }
t.Bound = v.U.(*Mpint).Int64() t = typArray(r.Type, v.U.(*Mpint).Int64())
if doesoverflow(v, Types[TINT]) { if doesoverflow(v, Types[TINT]) {
Yyerror("array bound is too large") Yyerror("array bound is too large")
n.Type = nil n.Type = nil
...@@ -375,12 +382,6 @@ OpSwitch: ...@@ -375,12 +382,6 @@ OpSwitch:
} }
} }
r = typecheck(r, Etype)
if r.Type == nil {
n.Type = nil
return n
}
t.Type = r.Type
n.Op = OTYPE n.Op = OTYPE
n.Type = t n.Type = t
n.Left = nil n.Left = nil
...@@ -1128,9 +1129,7 @@ OpSwitch: ...@@ -1128,9 +1129,7 @@ OpSwitch:
n.Op = OSLICESTR n.Op = OSLICESTR
} else if Isptr[t.Etype] && Isfixedarray(t.Type) { } else if Isptr[t.Etype] && Isfixedarray(t.Type) {
tp = t.Type tp = t.Type
n.Type = typ(TARRAY) n.Type = typSlice(tp.Type)
n.Type.Type = tp.Type
n.Type.Bound = -1
dowidth(n.Type) dowidth(n.Type)
n.Op = OSLICEARR n.Op = OSLICEARR
} else if Isslice(t) { } else if Isslice(t) {
...@@ -1195,9 +1194,7 @@ OpSwitch: ...@@ -1195,9 +1194,7 @@ OpSwitch:
var tp *Type var tp *Type
if Isptr[t.Etype] && Isfixedarray(t.Type) { if Isptr[t.Etype] && Isfixedarray(t.Type) {
tp = t.Type tp = t.Type
n.Type = typ(TARRAY) n.Type = typSlice(tp.Type)
n.Type.Type = tp.Type
n.Type.Bound = -1
dowidth(n.Type) dowidth(n.Type)
n.Op = OSLICE3ARR n.Op = OSLICE3ARR
} else if Isslice(t) { } else if Isslice(t) {
......
...@@ -1715,9 +1715,7 @@ func mkdotargslice(lr0, nn []*Node, l *Field, fp int, init *Nodes, ddd *Node) [] ...@@ -1715,9 +1715,7 @@ func mkdotargslice(lr0, nn []*Node, l *Field, fp int, init *Nodes, ddd *Node) []
esc = ddd.Esc esc = ddd.Esc
} }
tslice := typ(TARRAY) tslice := typSlice(l.Type.Type)
tslice.Type = l.Type.Type
tslice.Bound = -1
var n *Node var n *Node
if len(lr0) == 0 { if len(lr0) == 0 {
...@@ -2707,9 +2705,7 @@ func addstr(n *Node, init *Nodes) *Node { ...@@ -2707,9 +2705,7 @@ func addstr(n *Node, init *Nodes) *Node {
// large numbers of strings are passed to the runtime as a slice. // large numbers of strings are passed to the runtime as a slice.
fn = "concatstrings" fn = "concatstrings"
t := typ(TARRAY) t := typSlice(Types[TSTRING])
t.Type = Types[TSTRING]
t.Bound = -1
slice := Nod(OCOMPLIT, nil, typenod(t)) slice := Nod(OCOMPLIT, nil, typenod(t))
if prealloc[n] != nil { if prealloc[n] != nil {
prealloc[slice] = prealloc[n] prealloc[slice] = prealloc[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