Commit cd6619d2 authored by Ian Lance Taylor's avatar Ian Lance Taylor

cmd/compile: remove remaining nodeSeqIterate calls

Mix in several other minor cleanups, including adding some new methods
to Nodes: Index, Addr, SetIndex, SetNodes.

Passes toolstash -cmp.

Update #14473.

Change-Id: I8bd4ae3fde7c5e20ba66e7dd1654fbc70c3ddeb8
Reviewed-on: https://go-review.googlesource.com/20491Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 862b9ddd
...@@ -806,24 +806,23 @@ func (p *exporter) inlinedBody(n *Node) { ...@@ -806,24 +806,23 @@ func (p *exporter) inlinedBody(n *Node) {
} }
func (p *exporter) nodeList(list Nodes) { func (p *exporter) nodeList(list Nodes) {
it := nodeSeqIterate(list)
if p.trace { if p.trace {
p.tracef("[ ") p.tracef("[ ")
} }
p.int(it.Len()) p.int(list.Len())
if p.trace { if p.trace {
if it.Len() <= 1 { if list.Len() == 0 {
p.tracef("] {}") p.tracef("] {}")
} else { } else {
p.tracef("] {>") p.tracef("] {>")
defer p.tracef("<\n}") defer p.tracef("<\n}")
} }
} }
for ; !it.Done(); it.Next() { for _, n := range list.Slice() {
if p.trace { if p.trace {
p.tracef("\n") p.tracef("\n")
} }
p.node(it.N()) p.node(n)
} }
} }
......
...@@ -1762,7 +1762,7 @@ func bvgenjump(n, res *Node, wantTrue, geninit bool) { ...@@ -1762,7 +1762,7 @@ func bvgenjump(n, res *Node, wantTrue, geninit bool) {
Bgen(n, wantTrue, 0, p2) Bgen(n, wantTrue, 0, p2)
Thearch.Gmove(Nodbool(false), res) Thearch.Gmove(Nodbool(false), res)
Patch(p3, Pc) Patch(p3, Pc)
n.Ninit.Set(init.Slice()) n.Ninit.MoveNodes(&init)
} }
// bgenx is the backend for Bgen and Bvgen. // bgenx is the backend for Bgen and Bvgen.
...@@ -2943,9 +2943,7 @@ func cgen_append(n, res *Node) { ...@@ -2943,9 +2943,7 @@ func cgen_append(n, res *Node) {
// is not going to use a write barrier. // is not going to use a write barrier.
i := 0 i := 0
var r2 Node var r2 Node
it := nodeSeqIterate(n.List) for _, n2 := range n.List.Slice()[1:] {
it.Next()
for ; !it.Done(); it.Next() {
Regalloc(&r1, Types[Tptr], nil) Regalloc(&r1, Types[Tptr], nil)
Thearch.Gmove(base, &r1) Thearch.Gmove(base, &r1)
Regalloc(&r2, Types[TUINT], nil) Regalloc(&r2, Types[TUINT], nil)
...@@ -2966,7 +2964,7 @@ func cgen_append(n, res *Node) { ...@@ -2966,7 +2964,7 @@ func cgen_append(n, res *Node) {
r1.Op = OINDREG r1.Op = OINDREG
r1.Type = res.Type.Type r1.Type = res.Type.Type
cgen_wb(it.N(), &r1, needwritebarrier(&r1, it.N())) cgen_wb(n2, &r1, needwritebarrier(&r1, n2))
Regfree(&r1) Regfree(&r1)
i++ i++
} }
......
...@@ -475,7 +475,7 @@ func colasdefn(left Nodes, defn *Node) { ...@@ -475,7 +475,7 @@ func colasdefn(left Nodes, defn *Node) {
declare(n, dclcontext) declare(n, dclcontext)
n.Name.Defn = defn n.Name.Defn = defn
defn.Ninit.Append(Nod(ODCL, n, nil)) defn.Ninit.Append(Nod(ODCL, n, nil))
left.Slice()[i2] = n left.SetIndex(i2, n)
} }
if nnew == 0 && nerr == 0 { if nnew == 0 && nerr == 0 {
...@@ -833,9 +833,9 @@ func tostruct0(t *Type, l []*Node) { ...@@ -833,9 +833,9 @@ func tostruct0(t *Type, l []*Node) {
Fatalf("struct expected") Fatalf("struct expected")
} }
for tp, it := &t.Type, nodeSeqIterate(l); !it.Done(); it.Next() { tp := &t.Type
f := structfield(it.N()) for _, n := range l {
f := structfield(n)
*tp = f *tp = f
tp = &f.Down tp = &f.Down
} }
...@@ -860,13 +860,14 @@ func tofunargs(l []*Node) *Type { ...@@ -860,13 +860,14 @@ func tofunargs(l []*Node) *Type {
t := typ(TSTRUCT) t := typ(TSTRUCT)
t.Funarg = true t.Funarg = true
for tp, it := &t.Type, nodeSeqIterate(l); !it.Done(); it.Next() { tp := &t.Type
f = structfield(it.N()) for _, n := range l {
f = structfield(n)
f.Funarg = true f.Funarg = true
// esc.go needs to find f given a PPARAM to add the tag. // esc.go needs to find f given a PPARAM to add the tag.
if it.N().Left != nil && it.N().Left.Class == PPARAM { if n.Left != nil && n.Left.Class == PPARAM {
it.N().Left.Name.Param.Field = f n.Left.Name.Param.Field = f
} }
*tp = f *tp = f
......
...@@ -722,10 +722,9 @@ func esc(e *EscState, n *Node, up *Node) { ...@@ -722,10 +722,9 @@ func esc(e *EscState, n *Node, up *Node) {
case OAS2: // x,y = a,b case OAS2: // x,y = a,b
if n.List.Len() == n.Rlist.Len() { if n.List.Len() == n.Rlist.Len() {
lrit := nodeSeqIterate(n.Rlist) rs := n.Rlist.Slice()
for _, n3 := range n.List.Slice() { for i, n := range n.List.Slice() {
escassign(e, n3, lrit.N()) escassign(e, n, rs[i])
lrit.Next()
} }
} }
...@@ -759,14 +758,14 @@ func esc(e *EscState, n *Node, up *Node) { ...@@ -759,14 +758,14 @@ func esc(e *EscState, n *Node, up *Node) {
// esccall already done on n->rlist->n. tie it's escretval to n->list // esccall already done on n->rlist->n. tie it's escretval to n->list
case OAS2FUNC: // x,y = f() case OAS2FUNC: // x,y = f()
lrit := nodeSeqIterate(e.nodeEscState(n.Rlist.First()).Escretval) rs := e.nodeEscState(n.Rlist.First()).Escretval.Slice()
for i, n := range n.List.Slice() {
var llit nodeSeqIterator if i >= len(rs) {
for llit = nodeSeqIterate(n.List); !lrit.Done() && !llit.Done(); llit.Next() { break
escassign(e, llit.N(), lrit.N()) }
lrit.Next() escassign(e, n, rs[i])
} }
if !llit.Done() || !lrit.Done() { if n.List.Len() != len(rs) {
Fatalf("esc oas2func") Fatalf("esc oas2func")
} }
...@@ -779,19 +778,19 @@ func esc(e *EscState, n *Node, up *Node) { ...@@ -779,19 +778,19 @@ func esc(e *EscState, n *Node, up *Node) {
ll = e.nodeEscState(n.List.First()).Escretval ll = e.nodeEscState(n.List.First()).Escretval
} }
llit := nodeSeqIterate(ll) i := 0
for _, lrn := range Curfn.Func.Dcl { for _, lrn := range Curfn.Func.Dcl {
if llit.Done() { if i >= ll.Len() {
break break
} }
if lrn.Op != ONAME || lrn.Class != PPARAMOUT { if lrn.Op != ONAME || lrn.Class != PPARAMOUT {
continue continue
} }
escassign(e, lrn, llit.N()) escassign(e, lrn, ll.Index(i))
llit.Next() i++
} }
if !llit.Done() { if i < ll.Len() {
Fatalf("esc return list") Fatalf("esc return list")
} }
...@@ -801,10 +800,8 @@ func esc(e *EscState, n *Node, up *Node) { ...@@ -801,10 +800,8 @@ func esc(e *EscState, n *Node, up *Node) {
case OAPPEND: case OAPPEND:
if !n.Isddd { if !n.Isddd {
llit := nodeSeqIterate(n.List) for _, n := range n.List.Slice()[1:] {
llit.Next() escassign(e, &e.theSink, n) // lose track of assign to dereference
for ; !llit.Done(); llit.Next() {
escassign(e, &e.theSink, llit.N()) // lose track of assign to dereference
} }
} else { } else {
// append(slice1, slice2...) -- slice2 itself does not escape, but contents do. // append(slice1, slice2...) -- slice2 itself does not escape, but contents do.
...@@ -1229,8 +1226,8 @@ func escassignfromtag(e *EscState, note *string, dsts Nodes, src *Node) uint16 { ...@@ -1229,8 +1226,8 @@ func escassignfromtag(e *EscState, note *string, dsts Nodes, src *Node) uint16 {
} }
em0 := em em0 := em
it := nodeSeqIterate(dsts) dstsi := 0
for em >>= EscReturnBits; em != 0 && !it.Done(); em = em >> bitsPerOutputInTag { for em >>= EscReturnBits; em != 0 && dstsi < dsts.Len(); em = em >> bitsPerOutputInTag {
// Prefer the lowest-level path to the reference (for escape purposes). // Prefer the lowest-level path to the reference (for escape purposes).
// Two-bit encoding (for example. 1, 3, and 4 bits are other options) // Two-bit encoding (for example. 1, 3, and 4 bits are other options)
// 01 = 0-level // 01 = 0-level
...@@ -1242,15 +1239,15 @@ func escassignfromtag(e *EscState, note *string, dsts Nodes, src *Node) uint16 { ...@@ -1242,15 +1239,15 @@ func escassignfromtag(e *EscState, note *string, dsts Nodes, src *Node) uint16 {
for i := uint16(0); i < embits-1; i++ { for i := uint16(0); i < embits-1; i++ {
n = e.addDereference(n) // encode level>0 as indirections n = e.addDereference(n) // encode level>0 as indirections
} }
escassign(e, it.N(), n) escassign(e, dsts.Index(dstsi), n)
} }
it.Next() dstsi++
} }
// If there are too many outputs to fit in the tag, // If there are too many outputs to fit in the tag,
// that is handled at the encoding end as EscHeap, // that is handled at the encoding end as EscHeap,
// so there is no need to check here. // so there is no need to check here.
if em != 0 && it.Done() { if em != 0 && dstsi >= dsts.Len() {
Fatalf("corrupt esc tag %q or messed up escretval list\n", note) Fatalf("corrupt esc tag %q or messed up escretval list\n", note)
} }
return em0 return em0
...@@ -1419,36 +1416,37 @@ func esccall(e *EscState, n *Node, up *Node) { ...@@ -1419,36 +1416,37 @@ func esccall(e *EscState, n *Node, up *Node) {
} }
var src *Node var src *Node
llit := nodeSeqIterate(ll) lls := ll.Slice()
for lrit := nodeSeqIterate(fn.Name.Param.Ntype.List); !llit.Done() && !lrit.Done(); llit.Next() { lrs := fn.Name.Param.Ntype.List.Slice()
src = llit.N() i := 0
if lrit.N().Isddd && !n.Isddd { for ; i < len(lls) && i < len(lrs); i++ {
src = lls[i]
if lrs[i].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) src.Type = typ(TARRAY)
src.Type.Type = lrit.N().Type.Type src.Type.Type = lrs[i].Type.Type
src.Type.Bound = int64(llit.Len()) src.Type.Bound = int64(len(lls) - i)
src.Type = Ptrto(src.Type) // make pointer so it will be tracked 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
} }
if lrit.N().Left != nil { if lrs[i].Left != nil {
escassign(e, lrit.N().Left, src) escassign(e, lrs[i].Left, src)
} }
if src != llit.N() { if src != lls[i] {
break break
} }
lrit.Next()
} }
// "..." arguments are untracked // "..." arguments are untracked
for ; !llit.Done(); llit.Next() { for ; i < len(lls); i++ {
if Debug['m'] > 2 { if Debug['m'] > 2 {
fmt.Printf("%v::esccall:: ... <- %v, untracked\n", linestr(lineno), Nconv(llit.N(), obj.FmtShort)) fmt.Printf("%v::esccall:: ... <- %v, untracked\n", linestr(lineno), Nconv(lls[i], obj.FmtShort))
} }
escassign(e, &e.theSink, llit.N()) escassign(e, &e.theSink, lls[i])
} }
return return
...@@ -1478,16 +1476,17 @@ func esccall(e *EscState, n *Node, up *Node) { ...@@ -1478,16 +1476,17 @@ func esccall(e *EscState, n *Node, up *Node) {
} }
var src *Node var src *Node
it := nodeSeqIterate(ll) i := 0
for t := fntype.Params().Type; !it.Done(); it.Next() { lls := ll.Slice()
src = it.N() for t := fntype.Params().Type; i < len(lls); i++ {
src = lls[i]
if t.Isddd && !n.Isddd { if t.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.Lineno = n.Lineno src.Lineno = n.Lineno
src.Type = typ(TARRAY) src.Type = typ(TARRAY)
src.Type.Type = t.Type.Type src.Type.Type = t.Type.Type
src.Type.Bound = int64(it.Len()) src.Type.Bound = int64(len(lls) - i)
src.Type = Ptrto(src.Type) // make pointer so it will be tracked src.Type = Ptrto(src.Type) // make pointer so it will be tracked
e.track(src) e.track(src)
n.Right = src n.Right = src
...@@ -1520,18 +1519,18 @@ func esccall(e *EscState, n *Node, up *Node) { ...@@ -1520,18 +1519,18 @@ func esccall(e *EscState, n *Node, up *Node) {
} }
} }
if src != it.N() { if src != lls[i] {
// This occurs when function parameter type Isddd and n not Isddd // This occurs when function parameter type Isddd and n not Isddd
break break
} }
t = t.Down t = t.Down
} }
for ; !it.Done(); it.Next() { for ; i < len(lls); i++ {
if Debug['m'] > 2 { if Debug['m'] > 2 {
fmt.Printf("%v::esccall:: ... <- %v\n", linestr(lineno), Nconv(it.N(), obj.FmtShort)) fmt.Printf("%v::esccall:: ... <- %v\n", linestr(lineno), Nconv(lls[i], obj.FmtShort))
} }
escassign(e, src, it.N()) // args to slice escassign(e, src, lls[i]) // args to slice
} }
} }
......
...@@ -1257,10 +1257,10 @@ func exprfmt(n *Node, prec int) string { ...@@ -1257,10 +1257,10 @@ func exprfmt(n *Node, prec int) string {
} else { } else {
f += fmt.Sprintf("(%v{", n.Type) f += fmt.Sprintf("(%v{", n.Type)
} }
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() { for i1, n1 := range n.List.Slice() {
f += fmt.Sprintf(" %v:%v", Sconv(it.N().Left.Sym, obj.FmtShort|obj.FmtByte), it.N().Right) f += fmt.Sprintf(" %v:%v", Sconv(n1.Left.Sym, obj.FmtShort|obj.FmtByte), n1.Right)
if it.Len() > 1 { if i1+1 < n.List.Len() {
f += "," f += ","
} else { } else {
f += " " f += " "
...@@ -1725,9 +1725,9 @@ func Hconv(l Nodes, flag int) string { ...@@ -1725,9 +1725,9 @@ func Hconv(l Nodes, flag int) string {
} }
var buf bytes.Buffer var buf bytes.Buffer
for it := nodeSeqIterate(l); !it.Done(); it.Next() { for i, n := range l.Slice() {
buf.WriteString(Nconv(it.N(), 0)) buf.WriteString(Nconv(n, 0))
if it.Len() > 1 { if i+1 < l.Len() {
buf.WriteString(sep) buf.WriteString(sep)
} }
} }
......
...@@ -325,8 +325,9 @@ func inlconv2list(n *Node) []*Node { ...@@ -325,8 +325,9 @@ func inlconv2list(n *Node) []*Node {
} }
func inlnodelist(l Nodes) { func inlnodelist(l Nodes) {
for i := range l.Slice() { s := l.Slice()
inlnode(&l.Slice()[i]) for i := range s {
inlnode(&s[i])
} }
} }
...@@ -411,9 +412,10 @@ func inlnode(np **Node) { ...@@ -411,9 +412,10 @@ func inlnode(np **Node) {
fallthrough fallthrough
default: default:
for i3, n3 := range n.List.Slice() { s := n.List.Slice()
if n3.Op == OINLCALL { for i1, n1 := range s {
inlconv2expr(&n.List.Slice()[i3]) if n1.Op == OINLCALL {
inlconv2expr(&s[i1])
} }
} }
} }
...@@ -431,12 +433,13 @@ func inlnode(np **Node) { ...@@ -431,12 +433,13 @@ func inlnode(np **Node) {
fallthrough fallthrough
default: default:
for i4, n4 := range n.Rlist.Slice() { s := n.Rlist.Slice()
if n4.Op == OINLCALL { for i1, n1 := range s {
if n1.Op == OINLCALL {
if n.Op == OIF { if n.Op == OIF {
inlconv2stmt(n4) inlconv2stmt(n1)
} else { } else {
inlconv2expr(&n.Rlist.Slice()[i4]) inlconv2expr(&s[i1])
} }
} }
} }
...@@ -670,7 +673,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -670,7 +673,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
as = Nod(OAS2, nil, nil) as = Nod(OAS2, nil, nil)
as.Rlist.Set(n.List.Slice()) as.Rlist.Set(n.List.Slice())
it := nodeSeqIterate(n.List) li := 0
// TODO: if len(nlist) == 1 but multiple args, check that n->list->n is a call? // TODO: if len(nlist) == 1 but multiple args, check that n->list->n is a call?
if fn.Type.Thistuple != 0 && n.Left.Op != ODOTMETH { if fn.Type.Thistuple != 0 && n.Left.Op != ODOTMETH {
...@@ -689,7 +692,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -689,7 +692,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
Fatalf("method call unknown receiver type: %v", Nconv(n, obj.FmtSign)) Fatalf("method call unknown receiver type: %v", Nconv(n, obj.FmtSign))
} }
as.List.Append(tinlvar(t)) as.List.Append(tinlvar(t))
it.Next() // track argument count. li++
} }
// append ordinary arguments to LHS. // append ordinary arguments to LHS.
...@@ -703,7 +706,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -703,7 +706,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
for t, it2 := IterFields(fn.Type.Params()); t != nil; t = it2.Next() { for t, it2 := IterFields(fn.Type.Params()); t != nil; t = it2.Next() {
if variadic && t.Isddd { if variadic && t.Isddd {
vararg = tinlvar(t) vararg = tinlvar(t)
for i = 0; i < varargcount && it.Len() != 0; i++ { for i = 0; i < varargcount && li < n.List.Len(); i++ {
m = argvar(varargtype, i) m = argvar(varargtype, i)
varargs = append(varargs, m) varargs = append(varargs, m)
as.List.Append(m) as.List.Append(m)
...@@ -718,7 +721,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -718,7 +721,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
// match arguments except final variadic (unless the call is dotted itself) // match arguments except final variadic (unless the call is dotted itself)
var t *Type var t *Type
for t = fn.Type.Params().Type; t != nil; { for t = fn.Type.Params().Type; t != nil; {
if it.Done() { if li >= n.List.Len() {
break break
} }
if variadic && t.Isddd { if variadic && t.Isddd {
...@@ -726,18 +729,18 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -726,18 +729,18 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
} }
as.List.Append(tinlvar(t)) as.List.Append(tinlvar(t))
t = t.Down t = t.Down
it.Next() li++
} }
// match varargcount arguments with variadic parameters. // match varargcount arguments with variadic parameters.
if variadic && t != nil && t.Isddd { if variadic && t != nil && t.Isddd {
vararg = tinlvar(t) vararg = tinlvar(t)
var i int var i int
for i = 0; i < varargcount && !it.Done(); i++ { for i = 0; i < varargcount && li < n.List.Len(); i++ {
m = argvar(varargtype, i) m = argvar(varargtype, i)
varargs = append(varargs, m) varargs = append(varargs, m)
as.List.Append(m) as.List.Append(m)
it.Next() li++
} }
if i == varargcount { if i == varargcount {
...@@ -745,7 +748,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -745,7 +748,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
} }
} }
if !it.Done() || t != nil { if li < n.List.Len() || t != nil {
Fatalf("arg count mismatch: %v vs %v\n", Tconv(fn.Type.Params(), obj.FmtSharp), Hconv(n.List, obj.FmtComma)) Fatalf("arg count mismatch: %v vs %v\n", Tconv(fn.Type.Params(), obj.FmtSharp), Hconv(n.List, obj.FmtComma))
} }
} }
......
...@@ -376,14 +376,17 @@ func ordercall(n *Node, order *Order) { ...@@ -376,14 +376,17 @@ func ordercall(n *Node, order *Order) {
if n.Op == OCALLFUNC { if n.Op == OCALLFUNC {
t := n.Left.Type.Params().Type t := n.Left.Type.Params().Type
for it := nodeSeqIterate(n.List); !it.Done() && t != nil; it.Next() { for i := range n.List.Slice() {
// Check for "unsafe-uintptr" tag provided by escape analysis. // Check for "unsafe-uintptr" tag provided by escape analysis.
// If present and the argument is really a pointer being converted // If present and the argument is really a pointer being converted
// to uintptr, arrange for the pointer to be kept alive until the call // to uintptr, arrange for the pointer to be kept alive until the call
// returns, by copying it into a temp and marking that temp // returns, by copying it into a temp and marking that temp
// still alive when we pop the temp stack. // still alive when we pop the temp stack.
if t == nil {
break
}
if t.Note != nil && *t.Note == unsafeUintptrTag { if t.Note != nil && *t.Note == unsafeUintptrTag {
xp := it.P() xp := n.List.Addr(i)
for (*xp).Op == OCONVNOP && !Isptr[(*xp).Type.Etype] { for (*xp).Op == OCONVNOP && !Isptr[(*xp).Type.Etype] {
xp = &(*xp).Left xp = &(*xp).Left
} }
...@@ -452,14 +455,15 @@ func ordermapassign(n *Node, order *Order) { ...@@ -452,14 +455,15 @@ func ordermapassign(n *Node, order *Order) {
if !istemp(m.Right) { if !istemp(m.Right) {
m.Right = ordercopyexpr(m.Right, m.Right.Type, order, 0) m.Right = ordercopyexpr(m.Right, m.Right.Type, order, 0)
} }
n.List.Slice()[i1] = ordertemp(m.Type, order, false) n.List.SetIndex(i1, ordertemp(m.Type, order, false))
a = Nod(OAS, m, n.List.Slice()[i1]) a = Nod(OAS, m, n.List.Index(i1))
typecheck(&a, Etop) typecheck(&a, Etop)
post = append(post, a) post = append(post, a)
} else if instrumenting && n.Op == OAS2FUNC && !isblank(n.List.Slice()[i1]) { } else if instrumenting && n.Op == OAS2FUNC && !isblank(n.List.Index(i1)) {
m = n.List.Slice()[i1] m = n.List.Index(i1)
n.List.Slice()[i1] = ordertemp(m.Type, order, false) t := ordertemp(m.Type, order, false)
a = Nod(OAS, m, n.List.Slice()[i1]) n.List.SetIndex(i1, t)
a = Nod(OAS, m, t)
typecheck(&a, Etop) typecheck(&a, Etop)
post = append(post, a) post = append(post, a)
} }
...@@ -651,9 +655,7 @@ func orderstmt(n *Node, order *Order) { ...@@ -651,9 +655,7 @@ func orderstmt(n *Node, order *Order) {
orderexprlist(n.Left.List, order) orderexprlist(n.Left.List, order)
t1 := marktemp(order) t1 := marktemp(order)
it := nodeSeqIterate(n.Left.List) np := n.Left.List.Addr(1) // map key
it.Next()
np := it.P() // map key
*np = ordercopyexpr(*np, (*np).Type, order, 0) *np = ordercopyexpr(*np, (*np).Type, order, 0)
poptemp(t1, order) poptemp(t1, order)
...@@ -666,11 +668,9 @@ func orderstmt(n *Node, order *Order) { ...@@ -666,11 +668,9 @@ func orderstmt(n *Node, order *Order) {
case ODELETE: case ODELETE:
t := marktemp(order) t := marktemp(order)
it := nodeSeqIterate(n.List) orderexpr(n.List.Addr(0), order, nil)
orderexpr(it.P(), order, nil) orderexpr(n.List.Addr(1), order, nil)
it.Next() orderaddrtemp(n.List.Addr(1), order) // map key
orderexpr(it.P(), order, nil)
orderaddrtemp(it.P(), order) // map key
order.out = append(order.out, n) order.out = append(order.out, n)
cleantemp(t, order) cleantemp(t, order)
...@@ -771,8 +771,8 @@ func orderstmt(n *Node, order *Order) { ...@@ -771,8 +771,8 @@ func orderstmt(n *Node, order *Order) {
// n->alloc is the temp for the iterator. // n->alloc is the temp for the iterator.
prealloc[n] = ordertemp(Types[TUINT8], order, true) prealloc[n] = ordertemp(Types[TUINT8], order, true)
} }
for i1 := range n.List.Slice() { for i := range n.List.Slice() {
orderexprinplace(&n.List.Slice()[i1], order) orderexprinplace(n.List.Addr(i), order)
} }
orderblockNodes(&n.Nbody) orderblockNodes(&n.Nbody)
order.out = append(order.out, n) order.out = append(order.out, n)
...@@ -815,20 +815,20 @@ func orderstmt(n *Node, order *Order) { ...@@ -815,20 +815,20 @@ func orderstmt(n *Node, order *Order) {
Yyerror("unknown op in select %v", Oconv(r.Op, 0)) Yyerror("unknown op in select %v", Oconv(r.Op, 0))
Dump("select case", r) Dump("select case", r)
// If this is case x := <-ch or case x, y := <-ch, the case has // If this is case x := <-ch or case x, y := <-ch, the case has
// the ODCL nodes to declare x and y. We want to delay that // the ODCL nodes to declare x and y. We want to delay that
// declaration (and possible allocation) until inside the case body. // declaration (and possible allocation) until inside the case body.
// Delete the ODCL nodes here and recreate them inside the body below. // Delete the ODCL nodes here and recreate them inside the body below.
case OSELRECV, OSELRECV2: case OSELRECV, OSELRECV2:
if r.Colas { if r.Colas {
itinit := nodeSeqIterate(r.Ninit) i := 0
if itinit.Len() != 0 && itinit.N().Op == ODCL && itinit.N().Left == r.Left { if r.Ninit.Len() != 0 && r.Ninit.First().Op == ODCL && r.Ninit.First().Left == r.Left {
itinit.Next() i++
} }
if itinit.Len() != 0 && itinit.N().Op == ODCL && r.List.Len() != 0 && itinit.N().Left == r.List.First() { if i < r.Ninit.Len() && r.Ninit.Index(i).Op == ODCL && r.List.Len() != 0 && r.Ninit.Index(i).Left == r.List.First() {
itinit.Next() i++
} }
if itinit.Done() { if i >= r.Ninit.Len() {
r.Ninit.Set(nil) r.Ninit.Set(nil)
} }
} }
...@@ -967,16 +967,18 @@ func orderstmt(n *Node, order *Order) { ...@@ -967,16 +967,18 @@ func orderstmt(n *Node, order *Order) {
// Orderexprlist orders the expression list l into order. // Orderexprlist orders the expression list l into order.
func orderexprlist(l Nodes, order *Order) { func orderexprlist(l Nodes, order *Order) {
for i := range l.Slice() { s := l.Slice()
orderexpr(&l.Slice()[i], order, nil) for i := range s {
orderexpr(&s[i], order, nil)
} }
} }
// Orderexprlist orders the expression list l but saves // Orderexprlist orders the expression list l but saves
// the side effects on the individual expression ninit lists. // the side effects on the individual expression ninit lists.
func orderexprlistinplace(l Nodes, order *Order) { func orderexprlistinplace(l Nodes, order *Order) {
for i := range l.Slice() { s := l.Slice()
orderexprinplace(&l.Slice()[i], order) for i := range s {
orderexprinplace(&s[i], order)
} }
} }
......
...@@ -87,11 +87,12 @@ func instrument(fn *Node) { ...@@ -87,11 +87,12 @@ func instrument(fn *Node) {
} }
func instrumentlist(l Nodes, init *Nodes) { func instrumentlist(l Nodes, init *Nodes) {
for i := range l.Slice() { s := l.Slice()
for i := range s {
var instr Nodes var instr Nodes
instrumentnode(&l.Slice()[i], &instr, 0, 0) instrumentnode(&s[i], &instr, 0, 0)
if init == nil { if init == nil {
l.Slice()[i].Ninit.AppendNodes(&instr) s[i].Ninit.AppendNodes(&instr)
} else { } else {
init.AppendNodes(&instr) init.AppendNodes(&instr)
} }
...@@ -146,25 +147,26 @@ func instrumentnode(np **Node, init *Nodes, wr int, skip int) { ...@@ -146,25 +147,26 @@ func instrumentnode(np **Node, init *Nodes, wr int, skip int) {
case OBLOCK: case OBLOCK:
var out []*Node var out []*Node
for it := nodeSeqIterate(n.List); !it.Done(); it.Next() { ls := n.List.Slice()
switch it.N().Op { for i := 0; i < len(ls); i++ {
switch ls[i].Op {
case OCALLFUNC, OCALLMETH, OCALLINTER: case OCALLFUNC, OCALLMETH, OCALLINTER:
instrumentnode(it.P(), &it.N().Ninit, 0, 0) instrumentnode(&ls[i], &ls[i].Ninit, 0, 0)
out = append(out, it.N()) out = append(out, ls[i])
// Scan past OAS nodes copying results off stack. // Scan past OAS nodes copying results off stack.
// Those must not be instrumented, because the // Those must not be instrumented, because the
// instrumentation calls will smash the results. // instrumentation calls will smash the results.
// The assignments are to temporaries, so they cannot // The assignments are to temporaries, so they cannot
// be involved in races and need not be instrumented. // be involved in races and need not be instrumented.
for it.Len() > 1 && nodeSeqSecond(it.Seq()).Op == OAS && iscallret(nodeSeqSecond(it.Seq()).Right) { for i+1 < len(ls) && ls[i+1].Op == OAS && iscallret(ls[i+1].Right) {
it.Next() i++
out = append(out, it.N()) out = append(out, ls[i])
} }
default: default:
var outn Nodes var outn Nodes
outn.Set(out) outn.Set(out)
instrumentnode(it.P(), &outn, 0, 0) instrumentnode(&ls[i], &outn, 0, 0)
out = append(outn.Slice(), it.N()) out = append(outn.Slice(), ls[i])
} }
} }
n.List.Set(out) n.List.Set(out)
......
...@@ -14,6 +14,7 @@ func typecheckrange(n *Node) { ...@@ -14,6 +14,7 @@ func typecheckrange(n *Node) {
var t2 *Type var t2 *Type
var v1 *Node var v1 *Node
var v2 *Node var v2 *Node
var ls []*Node
// Typechecking order is important here: // Typechecking order is important here:
// 0. first typecheck range expression (slice/map/chan), // 0. first typecheck range expression (slice/map/chan),
...@@ -32,9 +33,10 @@ func typecheckrange(n *Node) { ...@@ -32,9 +33,10 @@ func typecheckrange(n *Node) {
goto out goto out
} }
// delicate little dance. see typecheckas2 // delicate little dance. see typecheckas2
for i1, n1 := range n.List.Slice() { ls = n.List.Slice()
for i1, n1 := range ls {
if n1.Name == nil || n1.Name.Defn != n { if n1.Name == nil || n1.Name.Defn != n {
typecheck(&n.List.Slice()[i1], Erv|Easgn) typecheck(&ls[i1], Erv|Easgn)
} }
} }
...@@ -119,9 +121,10 @@ func typecheckrange(n *Node) { ...@@ -119,9 +121,10 @@ func typecheckrange(n *Node) {
// second half of dance // second half of dance
out: out:
n.Typecheck = 1 n.Typecheck = 1
for i2, n2 := range n.List.Slice() { ls = n.List.Slice()
if n2.Typecheck == 0 { for i1, n1 := range ls {
typecheck(&n.List.Slice()[i2], Erv|Easgn) if n1.Typecheck == 0 {
typecheck(&ls[i1], Erv|Easgn)
} }
} }
...@@ -342,10 +345,10 @@ func memclrrange(n, v1, v2, a *Node) bool { ...@@ -342,10 +345,10 @@ func memclrrange(n, v1, v2, a *Node) bool {
if v1 == nil || v2 != nil { if v1 == nil || v2 != nil {
return false return false
} }
if len(n.Nbody.Slice()) == 0 || n.Nbody.Slice()[0] == nil || len(n.Nbody.Slice()) > 1 { if n.Nbody.Len() == 0 || n.Nbody.First() == nil || n.Nbody.Len() > 1 {
return false return false
} }
stmt := n.Nbody.Slice()[0] // only stmt in body stmt := n.Nbody.First() // only stmt in body
if stmt.Op != OAS || stmt.Left.Op != OINDEX { if stmt.Op != OAS || stmt.Left.Op != OINDEX {
return false return false
} }
......
...@@ -31,8 +31,7 @@ func typecheckselect(sel *Node) { ...@@ -31,8 +31,7 @@ func typecheckselect(sel *Node) {
} else if ncase.List.Len() > 1 { } else if ncase.List.Len() > 1 {
Yyerror("select cases cannot be lists") Yyerror("select cases cannot be lists")
} else { } else {
it2 := nodeSeqIterate(ncase.List) n = typecheck(ncase.List.Addr(0), Etop)
n = typecheck(it2.P(), Etop)
ncase.Left = n ncase.Left = n
ncase.List.Set(nil) ncase.List.Set(nil)
setlineno(n) setlineno(n)
...@@ -101,7 +100,6 @@ func walkselect(sel *Node) { ...@@ -101,7 +100,6 @@ func walkselect(sel *Node) {
var n *Node var n *Node
var var_ *Node var var_ *Node
var selv *Node var selv *Node
var cas *Node
if i == 0 { if i == 0 {
sel.Nbody.Set([]*Node{mkcall("block", nil, nil)}) sel.Nbody.Set([]*Node{mkcall("block", nil, nil)})
goto out goto out
...@@ -172,8 +170,7 @@ func walkselect(sel *Node) { ...@@ -172,8 +170,7 @@ func walkselect(sel *Node) {
// convert case value arguments to addresses. // convert case value arguments to addresses.
// this rewrite is used by both the general code and the next optimization. // this rewrite is used by both the general code and the next optimization.
for it := nodeSeqIterate(sel.List); !it.Done(); it.Next() { for _, cas := range sel.List.Slice() {
cas = it.N()
setlineno(cas) setlineno(cas)
n = cas.Left n = cas.Left
if n == nil { if n == nil {
...@@ -189,9 +186,8 @@ func walkselect(sel *Node) { ...@@ -189,9 +186,8 @@ func walkselect(sel *Node) {
n.Op = OSELRECV n.Op = OSELRECV
} }
if n.Op == OSELRECV2 { if n.Op == OSELRECV2 {
it := nodeSeqIterate(n.List) n.List.SetIndex(0, Nod(OADDR, n.List.First(), nil))
*it.P() = Nod(OADDR, it.N(), nil) typecheck(n.List.Addr(0), Erv)
typecheck(it.P(), Erv)
} }
if n.Left == nil { if n.Left == nil {
...@@ -268,7 +264,7 @@ func walkselect(sel *Node) { ...@@ -268,7 +264,7 @@ func walkselect(sel *Node) {
typecheck(&r, Etop) typecheck(&r, Etop)
init = append(init, r) init = append(init, r)
// register cases // register cases
for _, cas = range sel.List.Slice() { for _, cas := range sel.List.Slice() {
setlineno(cas) setlineno(cas)
n = cas.Left n = cas.Left
r = Nod(OIF, nil, nil) r = Nod(OIF, nil, nil)
......
...@@ -2066,14 +2066,12 @@ func (s *state) expr(n *Node) *ssa.Value { ...@@ -2066,14 +2066,12 @@ func (s *state) expr(n *Node) *ssa.Value {
// Evaluate args // Evaluate args
args := make([]*ssa.Value, 0, nargs) args := make([]*ssa.Value, 0, nargs)
store := make([]bool, 0, nargs) store := make([]bool, 0, nargs)
it := nodeSeqIterate(n.List) for _, n := range n.List.Slice()[1:] {
it.Next() if canSSAType(n.Type) {
for ; !it.Done(); it.Next() { args = append(args, s.expr(n))
if canSSAType(it.N().Type) {
args = append(args, s.expr(it.N()))
store = append(store, true) store = append(store, true)
} else { } else {
args = append(args, s.addr(it.N(), false)) args = append(args, s.addr(n, false))
store = append(store, false) store = append(store, false)
} }
} }
......
...@@ -115,30 +115,33 @@ func typecheckswitch(n *Node) { ...@@ -115,30 +115,33 @@ func typecheckswitch(n *Node) {
def = ncase def = ncase
} }
} else { } else {
for i1, n1 := range ncase.List.Slice() { ls := ncase.List.Slice()
for i1, n1 := range ls {
setlineno(n1) setlineno(n1)
typecheck(&ncase.List.Slice()[i1], Erv|Etype) typecheck(&ls[i1], Erv|Etype)
if ncase.List.Slice()[i1].Type == nil || t == nil { n1 = ls[i1]
if n1.Type == nil || t == nil {
continue continue
} }
setlineno(ncase) setlineno(ncase)
switch top { switch top {
// expression switch // expression switch
case Erv: case Erv:
defaultlit(&ncase.List.Slice()[i1], t) defaultlit(&ls[i1], t)
n1 = ls[i1]
switch { switch {
case ncase.List.Slice()[i1].Op == OTYPE: case n1.Op == OTYPE:
Yyerror("type %v is not an expression", ncase.List.Slice()[i1].Type) Yyerror("type %v is not an expression", n1.Type)
case ncase.List.Slice()[i1].Type != nil && assignop(ncase.List.Slice()[i1].Type, t, nil) == 0 && assignop(t, ncase.List.Slice()[i1].Type, nil) == 0: case n1.Type != nil && assignop(n1.Type, t, nil) == 0 && assignop(t, n1.Type, nil) == 0:
if n.Left != nil { if n.Left != nil {
Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ncase.List.Slice()[i1], n.Left, ncase.List.Slice()[i1].Type, t) Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left, n1.Type, t)
} else { } else {
Yyerror("invalid case %v in switch (mismatched types %v and bool)", ncase.List.Slice()[i1], ncase.List.Slice()[i1].Type) Yyerror("invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type)
} }
case nilonly != "" && !isnil(ncase.List.Slice()[i1]): case nilonly != "" && !isnil(n1):
Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ncase.List.Slice()[i1], nilonly, n.Left) Yyerror("invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left)
case Isinter(t) && !Isinter(ncase.List.Slice()[i1].Type) && algtype1(ncase.List.Slice()[i1].Type, nil) == ANOEQ: case Isinter(t) && !Isinter(n1.Type) && algtype1(n1.Type, nil) == ANOEQ:
Yyerror("invalid case %v in switch (incomparable type)", Nconv(ncase.List.Slice()[i1], obj.FmtLong)) Yyerror("invalid case %v in switch (incomparable type)", Nconv(n1, obj.FmtLong))
} }
// type switch // type switch
...@@ -146,16 +149,17 @@ func typecheckswitch(n *Node) { ...@@ -146,16 +149,17 @@ func typecheckswitch(n *Node) {
var missing, have *Type var missing, have *Type
var ptr int var ptr int
switch { switch {
case ncase.List.Slice()[i1].Op == OLITERAL && Istype(ncase.List.Slice()[i1].Type, TNIL): case n1.Op == OLITERAL && Istype(n1.Type, TNIL):
case ncase.List.Slice()[i1].Op != OTYPE && ncase.List.Slice()[i1].Type != nil: // should this be ||? case n1.Op != OTYPE && n1.Type != nil: // should this be ||?
Yyerror("%v is not a type", Nconv(ncase.List.Slice()[i1], obj.FmtLong)) Yyerror("%v is not a type", Nconv(n1, obj.FmtLong))
// reset to original type // reset to original type
ncase.List.Slice()[i1] = n.Left.Right n1 = n.Left.Right
case ncase.List.Slice()[i1].Type.Etype != TINTER && t.Etype == TINTER && !implements(ncase.List.Slice()[i1].Type, t, &missing, &have, &ptr): ls[i1] = n1
case n1.Type.Etype != TINTER && t.Etype == TINTER && !implements(n1.Type, t, &missing, &have, &ptr):
if have != nil && !missing.Broke && !have.Broke { if have != nil && !missing.Broke && !have.Broke {
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), ncase.List.Slice()[i1].Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort)) Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), n1.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
} else if !missing.Broke { } else if !missing.Broke {
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), ncase.List.Slice()[i1].Type, missing.Sym) Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), n1.Type, missing.Sym)
} }
} }
} }
...@@ -175,8 +179,7 @@ func typecheckswitch(n *Node) { ...@@ -175,8 +179,7 @@ func typecheckswitch(n *Node) {
} }
typecheck(&nvar, Erv|Easgn) typecheck(&nvar, Erv|Easgn)
rit := nodeSeqIterate(ncase.Rlist) ncase.Rlist.SetIndex(0, nvar)
*rit.P() = nvar
} }
} }
...@@ -344,8 +347,7 @@ func casebody(sw *Node, typeswvar *Node) { ...@@ -344,8 +347,7 @@ func casebody(sw *Node, typeswvar *Node) {
var def *Node // defaults var def *Node // defaults
br := Nod(OBREAK, nil, nil) br := Nod(OBREAK, nil, nil)
for it := nodeSeqIterate(sw.List); !it.Done(); it.Next() { for i, n := range sw.List.Slice() {
n := it.N()
setlineno(n) setlineno(n)
if n.Op != OXCASE { if n.Op != OXCASE {
Fatalf("casebody %v", Oconv(n.Op, 0)) Fatalf("casebody %v", Oconv(n.Op, 0))
...@@ -395,7 +397,7 @@ func casebody(sw *Node, typeswvar *Node) { ...@@ -395,7 +397,7 @@ func casebody(sw *Node, typeswvar *Node) {
Yyerror("cannot fallthrough in type switch") Yyerror("cannot fallthrough in type switch")
} }
if it.Len() <= 1 { if i+1 >= sw.List.Len() {
setlineno(last) setlineno(last)
Yyerror("cannot fallthrough final case in switch") Yyerror("cannot fallthrough final case in switch")
} }
......
...@@ -437,14 +437,20 @@ func (n *Nodes) Len() int { ...@@ -437,14 +437,20 @@ func (n *Nodes) Len() int {
return len(*n.slice) return len(*n.slice)
} }
// First returns the first element of Nodes. // Index returns the i'th element of Nodes.
// It panics if Nodes has no elements. // It panics if n does not have at least i+1 elements.
func (n *Nodes) Index(i int) *Node {
return (*n.slice)[i]
}
// First returns the first element of Nodes (same as n.Index(0)).
// It panics if n has no elements.
func (n *Nodes) First() *Node { func (n *Nodes) First() *Node {
return (*n.slice)[0] return (*n.slice)[0]
} }
// Second returns the second element of Nodes. // Second returns the second element of Nodes (same as n.Index(1)).
// It panics if Nodes has fewer than two elements. // It panics if n has fewer than two elements.
func (n *Nodes) Second() *Node { func (n *Nodes) Second() *Node {
return (*n.slice)[1] return (*n.slice)[1]
} }
...@@ -464,7 +470,7 @@ func (n *Nodes) NodeList() *NodeList { ...@@ -464,7 +470,7 @@ func (n *Nodes) NodeList() *NodeList {
return ret return ret
} }
// Set sets Nodes to a slice. // Set sets n to a slice.
// This takes ownership of the slice. // This takes ownership of the slice.
func (n *Nodes) Set(s []*Node) { func (n *Nodes) Set(s []*Node) {
if len(s) == 0 { if len(s) == 0 {
...@@ -474,6 +480,24 @@ func (n *Nodes) Set(s []*Node) { ...@@ -474,6 +480,24 @@ func (n *Nodes) Set(s []*Node) {
} }
} }
// MoveNodes sets n to the contents of n2, then clears n2.
func (n *Nodes) MoveNodes(n2 *Nodes) {
n.slice = n2.slice
n2.slice = nil
}
// SetIndex sets the i'th element of Nodes to node.
// It panics if n does not have at least i+1 elements.
func (n *Nodes) SetIndex(i int, node *Node) {
(*n.slice)[i] = node
}
// Addr returns the address of the i'th element of Nodes.
// It panics if n does not have at least i+1 elements.
func (n *Nodes) Addr(i int) **Node {
return &(*n.slice)[i]
}
// Append appends entries to Nodes. // Append appends entries to Nodes.
// If a slice is passed in, this will take ownership of it. // If a slice is passed in, this will take ownership of it.
func (n *Nodes) Append(a ...*Node) { func (n *Nodes) Append(a ...*Node) {
...@@ -530,106 +554,6 @@ type nodesOrNodeList interface{} ...@@ -530,106 +554,6 @@ type nodesOrNodeList interface{}
// to a generic value. // to a generic value.
type nodesOrNodeListPtr interface{} type nodesOrNodeListPtr interface{}
// nodeSeqIterator is an interface used to iterate over a sequence of nodes.
// TODO(iant): Remove after conversion from NodeList to Nodes is complete.
type nodeSeqIterator interface {
// Return whether iteration is complete.
Done() bool
// Advance to the next node.
Next()
// Return the current node.
N() *Node
// Return the address of the current node.
P() **Node
// Return the number of items remaining in the iteration.
Len() int
// Return the remaining items as a sequence.
// This will have the same type as that passed to nodeSeqIterate.
Seq() nodesOrNodeList
}
// nodeListIterator is a type that implements nodeSeqIterator using a
// *NodeList.
type nodeListIterator struct {
l *NodeList
}
func (nli *nodeListIterator) Done() bool {
return nli.l == nil
}
func (nli *nodeListIterator) Next() {
nli.l = nli.l.Next
}
func (nli *nodeListIterator) N() *Node {
return nli.l.N
}
func (nli *nodeListIterator) P() **Node {
return &nli.l.N
}
func (nli *nodeListIterator) Len() int {
return count(nli.l)
}
func (nli *nodeListIterator) Seq() nodesOrNodeList {
return nli.l
}
// nodesIterator implements nodeSeqIterator using a Nodes.
type nodesIterator struct {
n Nodes
i int
}
func (ni *nodesIterator) Done() bool {
return ni.i >= len(ni.n.Slice())
}
func (ni *nodesIterator) Next() {
ni.i++
}
func (ni *nodesIterator) N() *Node {
return ni.n.Slice()[ni.i]
}
func (ni *nodesIterator) P() **Node {
return &ni.n.Slice()[ni.i]
}
func (ni *nodesIterator) Len() int {
return len(ni.n.Slice()[ni.i:])
}
func (ni *nodesIterator) Seq() nodesOrNodeList {
var r Nodes
r.Set(ni.n.Slice()[ni.i:])
return r
}
// nodeSeqIterate returns an iterator over a *NodeList, a Nodes,
// a []*Node, or nil.
func nodeSeqIterate(ns nodesOrNodeList) nodeSeqIterator {
switch ns := ns.(type) {
case *NodeList:
return &nodeListIterator{ns}
case Nodes:
return &nodesIterator{ns, 0}
case []*Node:
var r Nodes
r.Set(ns)
return &nodesIterator{r, 0}
case nil:
var r Nodes
return &nodesIterator{r, 0}
default:
panic("can't happen")
}
}
// nodeSeqLen returns the length of a *NodeList, a Nodes, a []*Node, or nil. // nodeSeqLen returns the length of a *NodeList, a Nodes, a []*Node, or nil.
func nodeSeqLen(ns nodesOrNodeList) int { func nodeSeqLen(ns nodesOrNodeList) int {
switch ns := ns.(type) { switch ns := ns.(type) {
......
...@@ -1289,8 +1289,7 @@ OpSwitch: ...@@ -1289,8 +1289,7 @@ OpSwitch:
} }
if n.List.Len() == 1 && !n.Isddd { if n.List.Len() == 1 && !n.Isddd {
it := nodeSeqIterate(n.List) typecheck(n.List.Addr(0), Erv|Efnstruct)
typecheck(it.P(), Erv|Efnstruct)
} else { } else {
typechecklist(n.List.Slice(), Erv) typechecklist(n.List.Slice(), Erv)
} }
...@@ -1576,9 +1575,7 @@ OpSwitch: ...@@ -1576,9 +1575,7 @@ OpSwitch:
return return
} }
it := nodeSeqIterate(args) args.SetIndex(1, assignconv(r, l.Type.Down, "delete"))
it.Next()
*it.P() = assignconv(r, l.Type.Down, "delete")
break OpSwitch break OpSwitch
case OAPPEND: case OAPPEND:
...@@ -1591,8 +1588,7 @@ OpSwitch: ...@@ -1591,8 +1588,7 @@ OpSwitch:
} }
if args.Len() == 1 && !n.Isddd { if args.Len() == 1 && !n.Isddd {
it := nodeSeqIterate(args) typecheck(args.Addr(0), Erv|Efnstruct)
typecheck(it.P(), Erv|Efnstruct)
} else { } else {
typechecklist(args.Slice(), Erv) typechecklist(args.Slice(), Erv)
} }
...@@ -1637,15 +1633,11 @@ OpSwitch: ...@@ -1637,15 +1633,11 @@ OpSwitch:
} }
if Istype(t.Type, TUINT8) && Istype(args.Second().Type, TSTRING) { if Istype(t.Type, TUINT8) && Istype(args.Second().Type, TSTRING) {
it := nodeSeqIterate(args) defaultlit(args.Addr(1), Types[TSTRING])
it.Next()
defaultlit(it.P(), Types[TSTRING])
break OpSwitch break OpSwitch
} }
it := nodeSeqIterate(args) args.SetIndex(1, assignconv(args.Index(1), t.Orig, "append"))
it.Next()
*it.P() = assignconv(args.Second(), t.Orig, "append")
break OpSwitch break OpSwitch
} }
...@@ -1656,13 +1648,12 @@ OpSwitch: ...@@ -1656,13 +1648,12 @@ OpSwitch:
} }
} }
} else { } else {
it := nodeSeqIterate(args) as := args.Slice()[1:]
it.Next() for i, n := range as {
for ; !it.Done(); it.Next() { if n.Type == nil {
if it.N().Type == nil {
continue continue
} }
*it.P() = assignconv(it.N(), t.Type, "append") as[i] = assignconv(n, t.Type, "append")
} }
} }
...@@ -1777,16 +1768,15 @@ OpSwitch: ...@@ -1777,16 +1768,15 @@ OpSwitch:
case OMAKE: case OMAKE:
ok |= Erv ok |= Erv
args := nodeSeqIterate(n.List) args := n.List.Slice()
if args.Len() == 0 { if len(args) == 0 {
Yyerror("missing argument to make") Yyerror("missing argument to make")
n.Type = nil n.Type = nil
return return
} }
n.List.Set(nil) n.List.Set(nil)
l := args.N() l := args[0]
args.Next()
typecheck(&l, Etype) typecheck(&l, Etype)
t := l.Type t := l.Type
if t == nil { if t == nil {
...@@ -1794,6 +1784,7 @@ OpSwitch: ...@@ -1794,6 +1784,7 @@ OpSwitch:
return return
} }
i := 1
switch t.Etype { switch t.Etype {
default: default:
Yyerror("cannot make type %v", t) Yyerror("cannot make type %v", t)
...@@ -1807,19 +1798,19 @@ OpSwitch: ...@@ -1807,19 +1798,19 @@ OpSwitch:
return return
} }
if args.Done() { if i >= len(args) {
Yyerror("missing len argument to make(%v)", t) Yyerror("missing len argument to make(%v)", t)
n.Type = nil n.Type = nil
return return
} }
l = args.N() l = args[i]
args.Next() i++
typecheck(&l, Erv) typecheck(&l, Erv)
var r *Node var r *Node
if !args.Done() { if i < len(args) {
r = args.N() r = args[i]
args.Next() i++
typecheck(&r, Erv) typecheck(&r, Erv)
} }
...@@ -1842,9 +1833,9 @@ OpSwitch: ...@@ -1842,9 +1833,9 @@ OpSwitch:
n.Op = OMAKESLICE n.Op = OMAKESLICE
case TMAP: case TMAP:
if !args.Done() { if i < len(args) {
l = args.N() l = args[i]
args.Next() i++
typecheck(&l, Erv) typecheck(&l, Erv)
defaultlit(&l, Types[TINT]) defaultlit(&l, Types[TINT])
if l.Type == nil { if l.Type == nil {
...@@ -1863,9 +1854,9 @@ OpSwitch: ...@@ -1863,9 +1854,9 @@ OpSwitch:
case TCHAN: case TCHAN:
l = nil l = nil
if !args.Done() { if i < len(args) {
l = args.N() l = args[i]
args.Next() i++
typecheck(&l, Erv) typecheck(&l, Erv)
defaultlit(&l, Types[TINT]) defaultlit(&l, Types[TINT])
if l.Type == nil { if l.Type == nil {
...@@ -1883,7 +1874,7 @@ OpSwitch: ...@@ -1883,7 +1874,7 @@ OpSwitch:
n.Op = OMAKECHAN n.Op = OMAKECHAN
} }
if !args.Done() { if i < len(args) {
Yyerror("too many arguments to make(%v)", t) Yyerror("too many arguments to make(%v)", t)
n.Op = OMAKE n.Op = OMAKE
n.Type = nil n.Type = nil
...@@ -1922,12 +1913,13 @@ OpSwitch: ...@@ -1922,12 +1913,13 @@ OpSwitch:
case OPRINT, OPRINTN: case OPRINT, OPRINTN:
ok |= Etop ok |= Etop
typechecklist(n.List.Slice(), Erv|Eindir) // Eindir: address does not escape typechecklist(n.List.Slice(), Erv|Eindir) // Eindir: address does not escape
for i1, n1 := range n.List.Slice() { ls := n.List.Slice()
for i1, n1 := range ls {
// Special case for print: int constant is int64, not int. // Special case for print: int constant is int64, not int.
if Isconst(n1, CTINT) { if Isconst(n1, CTINT) {
defaultlit(&n.List.Slice()[i1], Types[TINT64]) defaultlit(&ls[i1], Types[TINT64])
} else { } else {
defaultlit(&n.List.Slice()[i1], nil) defaultlit(&ls[i1], nil)
} }
} }
...@@ -2611,7 +2603,7 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc ...@@ -2611,7 +2603,7 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
var n *Node var n *Node
var n1 int var n1 int
var n2 int var n2 int
var it nodeSeqIterator var i int
lno := lineno lno := lineno
...@@ -2698,48 +2690,48 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc ...@@ -2698,48 +2690,48 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
} }
} }
it = nodeSeqIterate(nl) i = 0
for tl := tstruct.Type; tl != nil; tl = tl.Down { for tl := tstruct.Type; tl != nil; tl = tl.Down {
t = tl.Type t = tl.Type
if tl.Isddd { if tl.Isddd {
if isddd { if isddd {
if it.Done() { if i >= nl.Len() {
goto notenough goto notenough
} }
if it.Len() > 1 { if nl.Len()-i > 1 {
goto toomany goto toomany
} }
n = it.N() n = nl.Index(i)
setlineno(n) setlineno(n)
if n.Type != nil { if n.Type != nil {
*it.P() = assignconvfn(n, t, desc) nl.SetIndex(i, assignconvfn(n, t, desc))
} }
goto out goto out
} }
for ; !it.Done(); it.Next() { for ; i < nl.Len(); i++ {
n = it.N() n = nl.Index(i)
setlineno(it.N()) setlineno(n)
if n.Type != nil { if n.Type != nil {
*it.P() = assignconvfn(n, t.Type, desc) nl.SetIndex(i, assignconvfn(n, t.Type, desc))
} }
} }
goto out goto out
} }
if it.Done() { if i >= nl.Len() {
goto notenough goto notenough
} }
n = it.N() n = nl.Index(i)
setlineno(n) setlineno(n)
if n.Type != nil { if n.Type != nil {
*it.P() = assignconvfn(n, t, desc) nl.SetIndex(i, assignconvfn(n, t, desc))
} }
it.Next() i++
} }
if !it.Done() { if i < nl.Len() {
goto toomany goto toomany
} }
if isddd { if isddd {
...@@ -2983,7 +2975,7 @@ func typecheckcomplit(np **Node) { ...@@ -2983,7 +2975,7 @@ func typecheckcomplit(np **Node) {
l = Nod(OKEY, Nodintconst(int64(i)), l) l = Nod(OKEY, Nodintconst(int64(i)), l)
l.Left.Type = Types[TINT] l.Left.Type = Types[TINT]
l.Left.Typecheck = 1 l.Left.Typecheck = 1
n.List.Slice()[i2] = l n.List.SetIndex(i2, l)
} }
typecheck(&l.Left, Erv) typecheck(&l.Left, Erv)
...@@ -3030,7 +3022,7 @@ func typecheckcomplit(np **Node) { ...@@ -3030,7 +3022,7 @@ func typecheckcomplit(np **Node) {
l = n3 l = n3
setlineno(l) setlineno(l)
if l.Op != OKEY { if l.Op != OKEY {
typecheck(&n.List.Slice()[i3], Erv) typecheck(n.List.Addr(i3), Erv)
Yyerror("missing key in map literal") Yyerror("missing key in map literal")
continue continue
} }
...@@ -3060,9 +3052,11 @@ func typecheckcomplit(np **Node) { ...@@ -3060,9 +3052,11 @@ func typecheckcomplit(np **Node) {
f := t.Type f := t.Type
var s *Sym var s *Sym
for i4, n4 := range n.List.Slice() { ls := n.List.Slice()
setlineno(n4) for i1, n1 := range ls {
typecheck(&n.List.Slice()[i4], Erv) setlineno(n1)
typecheck(&ls[i1], Erv)
n1 = ls[i1]
if f == nil { if f == nil {
if bad == 0 { if bad == 0 {
Yyerror("too many values in struct initializer") Yyerror("too many values in struct initializer")
...@@ -3076,10 +3070,11 @@ func typecheckcomplit(np **Node) { ...@@ -3076,10 +3070,11 @@ func typecheckcomplit(np **Node) {
Yyerror("implicit assignment of unexported field '%s' in %v literal", s.Name, t) Yyerror("implicit assignment of unexported field '%s' in %v literal", s.Name, t)
} }
// No pushtype allowed here. Must name fields for that. // No pushtype allowed here. Must name fields for that.
n.List.Slice()[i4] = assignconv(n.List.Slice()[i4], f.Type, "field value") n1 = assignconv(n1, f.Type, "field value")
n.List.Slice()[i4] = Nod(OKEY, newname(f.Sym), n.List.Slice()[i4]) n1 = Nod(OKEY, newname(f.Sym), n1)
n.List.Slice()[i4].Left.Type = f n1.Left.Type = f
n.List.Slice()[i4].Left.Typecheck = 1 n1.Left.Typecheck = 1
ls[i1] = n1
f = f.Down f = f.Down
} }
...@@ -3090,23 +3085,19 @@ func typecheckcomplit(np **Node) { ...@@ -3090,23 +3085,19 @@ func typecheckcomplit(np **Node) {
hash := make(map[string]bool) hash := make(map[string]bool)
// keyed list // keyed list
var s *Sym ls := n.List.Slice()
var f *Type for i, l := range ls {
var l *Node
var s1 *Sym
for i5, n5 := range n.List.Slice() {
l = n5
setlineno(l) setlineno(l)
if l.Op != OKEY { if l.Op != OKEY {
if bad == 0 { if bad == 0 {
Yyerror("mixture of field:value and value initializers") Yyerror("mixture of field:value and value initializers")
} }
bad++ bad++
typecheck(&n.List.Slice()[i5], Erv) typecheck(&ls[i], Erv)
continue continue
} }
s = l.Left.Sym s := l.Left.Sym
if s == nil { if s == nil {
Yyerror("invalid field name %v in struct initializer", l.Left) Yyerror("invalid field name %v in struct initializer", l.Left)
typecheck(&l.Right, Erv) typecheck(&l.Right, Erv)
...@@ -3117,13 +3108,13 @@ func typecheckcomplit(np **Node) { ...@@ -3117,13 +3108,13 @@ func typecheckcomplit(np **Node) {
// package, because of import dot. Redirect to correct sym // package, because of import dot. Redirect to correct sym
// before we do the lookup. // before we do the lookup.
if s.Pkg != localpkg && exportname(s.Name) { if s.Pkg != localpkg && exportname(s.Name) {
s1 = Lookup(s.Name) s1 := Lookup(s.Name)
if s1.Origpkg == s.Pkg { if s1.Origpkg == s.Pkg {
s = s1 s = s1
} }
} }
f = lookdot1(nil, s, t, t.Type, 0) f := lookdot1(nil, s, t, t.Type, 0)
if f == nil { if f == nil {
Yyerror("unknown %v field '%v' in struct literal", t, s) Yyerror("unknown %v field '%v' in struct literal", t, s)
continue continue
...@@ -3313,20 +3304,21 @@ func checkassignto(src *Type, dst *Node) { ...@@ -3313,20 +3304,21 @@ func checkassignto(src *Type, dst *Node) {
} }
func typecheckas2(n *Node) { func typecheckas2(n *Node) {
for i1 := range n.List.Slice() { ls := n.List.Slice()
for i1, n1 := range ls {
// delicate little dance. // delicate little dance.
n.List.Slice()[i1] = resolve(n.List.Slice()[i1]) n1 = resolve(n1)
ls[i1] = n1
if n.List.Slice()[i1].Name == nil || n.List.Slice()[i1].Name.Defn != n || n.List.Slice()[i1].Name.Param.Ntype != nil { if n1.Name == nil || n1.Name.Defn != n || n1.Name.Param.Ntype != nil {
typecheck(&n.List.Slice()[i1], Erv|Easgn) typecheck(&ls[i1], Erv|Easgn)
} }
} }
cl := n.List.Len() cl := n.List.Len()
cr := n.Rlist.Len() cr := n.Rlist.Len()
if cl > 1 && cr == 1 { if cl > 1 && cr == 1 {
it := nodeSeqIterate(n.Rlist) typecheck(n.Rlist.Addr(0), Erv|Efnstruct)
typecheck(it.P(), Erv|Efnstruct)
} else { } else {
typechecklist(n.Rlist.Slice(), Erv) typechecklist(n.Rlist.Slice(), Erv)
} }
...@@ -3336,16 +3328,17 @@ func typecheckas2(n *Node) { ...@@ -3336,16 +3328,17 @@ func typecheckas2(n *Node) {
var r *Node var r *Node
if cl == cr { if cl == cr {
// easy // easy
lrit := nodeSeqIterate(n.Rlist) ls := n.List.Slice()
for _, n2 := range n.List.Slice() { rs := n.Rlist.Slice()
if n2.Type != nil && lrit.N().Type != nil { for il, nl := range ls {
*lrit.P() = assignconv(lrit.N(), n2.Type, "assignment") nr := rs[il]
if nl.Type != nil && nr.Type != nil {
rs[il] = assignconv(nr, nl.Type, "assignment")
} }
if n2.Name != nil && n2.Name.Defn == n && n2.Name.Param.Ntype == nil { if nl.Name != nil && nl.Name.Defn == n && nl.Name.Param.Ntype == nil {
defaultlit(lrit.P(), nil) defaultlit(&rs[il], nil)
n2.Type = lrit.N().Type nl.Type = rs[il].Type
} }
lrit.Next()
} }
goto out goto out
...@@ -3426,9 +3419,10 @@ mismatch: ...@@ -3426,9 +3419,10 @@ mismatch:
// second half of dance // second half of dance
out: out:
n.Typecheck = 1 n.Typecheck = 1
for i4, n4 := range n.List.Slice() { ls = n.List.Slice()
if n4.Typecheck == 0 { for i1, n1 := range ls {
typecheck(&n.List.Slice()[i4], Erv|Easgn) if n1.Typecheck == 0 {
typecheck(&ls[i1], Erv|Easgn)
} }
} }
} }
...@@ -3886,9 +3880,10 @@ func markbreak(n *Node, implicit *Node) { ...@@ -3886,9 +3880,10 @@ func markbreak(n *Node, implicit *Node) {
} }
func markbreaklist(l Nodes, implicit *Node) { func markbreaklist(l Nodes, implicit *Node) {
for it := nodeSeqIterate(l); !it.Done(); it.Next() { s := l.Slice()
n := it.N() for i := 0; i < len(s); i++ {
if n.Op == OLABEL && it.Len() > 1 && n.Name.Defn == nodeSeqSlice(it.Seq())[1] { n := s[i]
if n.Op == OLABEL && i+1 < len(s) && n.Name.Defn == s[i+1] {
switch n.Name.Defn.Op { switch n.Name.Defn.Op {
case OFOR, OSWITCH, OTYPESW, OSELECT, ORANGE: case OFOR, OSWITCH, OTYPESW, OSELECT, ORANGE:
lab := new(Label) lab := new(Label)
...@@ -3896,7 +3891,7 @@ func markbreaklist(l Nodes, implicit *Node) { ...@@ -3896,7 +3891,7 @@ func markbreaklist(l Nodes, implicit *Node) {
n.Left.Sym.Label = lab n.Left.Sym.Label = lab
markbreak(n.Name.Defn, n.Name.Defn) markbreak(n.Name.Defn, n.Name.Defn)
n.Left.Sym.Label = nil n.Left.Sym.Label = nil
it.Next() i++
continue continue
} }
} }
...@@ -3920,11 +3915,12 @@ func (l *NodeList) isterminating() bool { ...@@ -3920,11 +3915,12 @@ func (l *NodeList) isterminating() bool {
// Isterminating whether the Nodes list ends with a terminating // Isterminating whether the Nodes list ends with a terminating
// statement. // statement.
func (l Nodes) isterminating() bool { func (l Nodes) isterminating() bool {
c := len(l.Slice()) s := l.Slice()
c := len(s)
if c == 0 { if c == 0 {
return false return false
} }
return l.Slice()[c-1].isterminating() return s[c-1].isterminating()
} }
// Isterminating returns whether the node n, the last one in a // Isterminating returns whether the node n, the last one in a
......
...@@ -321,8 +321,9 @@ func walkstmt(np **Node) { ...@@ -321,8 +321,9 @@ func walkstmt(np **Node) {
ll := ascompatee(n.Op, rl, n.List.Slice(), &n.Ninit) ll := ascompatee(n.Op, rl, n.List.Slice(), &n.Ninit)
n.List.Set(reorder3(ll)) n.List.Set(reorder3(ll))
for i1 := range n.List.Slice() { ls := n.List.Slice()
n.List.Slice()[i1] = applywritebarrier(n.List.Slice()[i1]) for i, n := range ls {
ls[i] = applywritebarrier(n)
} }
break break
} }
...@@ -884,8 +885,7 @@ opswitch: ...@@ -884,8 +885,7 @@ opswitch:
if !isblank(a) { if !isblank(a) {
var_ := temp(Ptrto(t.Type)) var_ := temp(Ptrto(t.Type))
var_.Typecheck = 1 var_.Typecheck = 1
it := nodeSeqIterate(n.List) n.List.SetIndex(0, var_)
*it.P() = var_
walkexpr(&n, init) walkexpr(&n, init)
init.Append(n) init.Append(n)
n = Nod(OAS, a, Nod(OIND, var_, nil)) n = Nod(OAS, a, Nod(OIND, var_, nil))
...@@ -1661,20 +1661,20 @@ func ascompatee(op Op, nl, nr []*Node, init *Nodes) []*Node { ...@@ -1661,20 +1661,20 @@ func ascompatee(op Op, nl, nr []*Node, init *Nodes) []*Node {
} }
var nn []*Node var nn []*Node
nlit := nodeSeqIterate(nl) i := 0
nrit := nodeSeqIterate(nr) for ; i < len(nl); i++ {
for ; !nlit.Done() && !nrit.Done(); nlit.Next() { if i >= len(nr) {
break
}
// Do not generate 'x = x' during return. See issue 4014. // Do not generate 'x = x' during return. See issue 4014.
if op == ORETURN && nlit.N() == nrit.N() { if op == ORETURN && nl[i] == nr[i] {
nrit.Next()
continue continue
} }
nn = append(nn, ascompatee1(op, nlit.N(), nrit.N(), init)) nn = append(nn, ascompatee1(op, nl[i], nr[i], init))
nrit.Next()
} }
// cannot happen: caller checked that lists had same length // cannot happen: caller checked that lists had same length
if !nlit.Done() || !nrit.Done() { if i < len(nl) || i < len(nr) {
var nln, nrn Nodes var nln, nrn Nodes
nln.Set(nl) nln.Set(nl)
nrn.Set(nr) nrn.Set(nr)
...@@ -1714,12 +1714,12 @@ func ascompatet(op Op, nl Nodes, nr **Type, fp int, init *Nodes) []*Node { ...@@ -1714,12 +1714,12 @@ func ascompatet(op Op, nl Nodes, nr **Type, fp int, init *Nodes) []*Node {
var nn []*Node var nn []*Node
var mm []*Node var mm []*Node
ucount := 0 ucount := 0
it := nodeSeqIterate(nl) var i int
for ; !it.Done(); it.Next() { for i = 0; i < nl.Len(); i++ {
if r == nil { if r == nil {
break break
} }
l = it.N() l = nl.Index(i)
if isblank(l) { if isblank(l) {
r = saver.Next() r = saver.Next()
continue continue
...@@ -1749,7 +1749,7 @@ func ascompatet(op Op, nl Nodes, nr **Type, fp int, init *Nodes) []*Node { ...@@ -1749,7 +1749,7 @@ func ascompatet(op Op, nl Nodes, nr **Type, fp int, init *Nodes) []*Node {
r = saver.Next() r = saver.Next()
} }
if !it.Done() || r != nil { if i < nl.Len() || r != nil {
Yyerror("ascompatet: assignment count mismatch: %d = %d", nl.Len(), structcount(*nr)) Yyerror("ascompatet: assignment count mismatch: %d = %d", nl.Len(), structcount(*nr))
} }
...@@ -1985,7 +1985,7 @@ func walkprint(nn *Node, init *Nodes) *Node { ...@@ -1985,7 +1985,7 @@ func walkprint(nn *Node, init *Nodes) *Node {
defaultlit(&n, Types[TINT64]) defaultlit(&n, Types[TINT64])
} }
defaultlit(&n, nil) defaultlit(&n, nil)
all.Slice()[i1] = n all.SetIndex(i1, n)
if n.Type == nil || n.Type.Etype == TFORW { if n.Type == nil || n.Type.Etype == TFORW {
continue continue
} }
...@@ -2811,14 +2811,13 @@ func addstr(n *Node, init *Nodes) *Node { ...@@ -2811,14 +2811,13 @@ func addstr(n *Node, init *Nodes) *Node {
// l2 is allowed to be a string. // l2 is allowed to be a string.
func appendslice(n *Node, init *Nodes) *Node { func appendslice(n *Node, init *Nodes) *Node {
walkexprlistsafe(n.List.Slice(), init) walkexprlistsafe(n.List.Slice(), init)
for i1 := range
// walkexprlistsafe will leave OINDEX (s[n]) alone if both s // walkexprlistsafe will leave OINDEX (s[n]) alone if both s
// and n are name or literal, but those may index the slice we're // and n are name or literal, but those may index the slice we're
// modifying here. Fix explicitly. // modifying here. Fix explicitly.
n.List.Slice() { ls := n.List.Slice()
n.List.Slice()[i1] = cheapexpr(n.List.Slice()[i1], for i1, n1 := range ls {
init) ls[i1] = cheapexpr(n1, init)
} }
l1 := n.List.First() l1 := n.List.First()
...@@ -2933,9 +2932,8 @@ func appendslice(n *Node, init *Nodes) *Node { ...@@ -2933,9 +2932,8 @@ func appendslice(n *Node, init *Nodes) *Node {
// s // s
func walkappend(n *Node, init *Nodes, dst *Node) *Node { func walkappend(n *Node, init *Nodes, dst *Node) *Node {
if !samesafeexpr(dst, n.List.First()) { if !samesafeexpr(dst, n.List.First()) {
it := nodeSeqIterate(n.List) n.List.SetIndex(0, safeexpr(n.List.Index(0), init))
*it.P() = safeexpr(it.N(), init) walkexpr(n.List.Addr(0), init)
walkexpr(it.P(), init)
} }
walkexprlistsafe(n.List.Slice()[1:], init) walkexprlistsafe(n.List.Slice()[1:], init)
...@@ -2945,10 +2943,9 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node { ...@@ -2945,10 +2943,9 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
// Using cheapexpr also makes sure that the evaluation // Using cheapexpr also makes sure that the evaluation
// of all arguments (and especially any panics) happen // of all arguments (and especially any panics) happen
// before we begin to modify the slice in a visible way. // before we begin to modify the slice in a visible way.
it := nodeSeqIterate(n.List) ls := n.List.Slice()[1:]
it.Next() for i, n := range ls {
for ; !it.Done(); it.Next() { ls[i] = cheapexpr(n, init)
*it.P() = cheapexpr(it.N(), init)
} }
nsrc := n.List.First() nsrc := n.List.First()
...@@ -2991,13 +2988,12 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node { ...@@ -2991,13 +2988,12 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
nx.Etype = 1 nx.Etype = 1
l = append(l, Nod(OAS, ns, nx)) // s = s[:n+argc] l = append(l, Nod(OAS, ns, nx)) // s = s[:n+argc]
it = nodeSeqIterate(n.List) ls = n.List.Slice()[1:]
it.Next() for i, n := range ls {
for ; !it.Done(); it.Next() {
nx = Nod(OINDEX, ns, nn) // s[n] ... nx = Nod(OINDEX, ns, nn) // s[n] ...
nx.Bounded = true nx.Bounded = true
l = append(l, Nod(OAS, nx, it.N())) // s[n] = arg l = append(l, Nod(OAS, nx, n)) // s[n] = arg
if it.Len() > 1 { if i+1 < len(ls) {
l = append(l, Nod(OAS, nn, Nod(OADD, nn, Nodintconst(1)))) // n = n + 1 l = append(l, Nod(OAS, nn, Nod(OADD, nn, Nodintconst(1)))) // n = n + 1
} }
} }
......
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