]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: convert subr, swt, typecheck to nodeSeq
authorIan Lance Taylor <iant@golang.org>
Sat, 5 Mar 2016 01:28:07 +0000 (17:28 -0800)
committerIan Lance Taylor <iant@golang.org>
Sat, 5 Mar 2016 02:26:11 +0000 (02:26 +0000)
Passes toolstash -cmp.

Update #14473.

Change-Id: I836197810405cde72cbb49fef7e163a517601f9c
Reviewed-on: https://go-review.googlesource.com/20242
Reviewed-by: David Crawshaw <crawshaw@golang.org>
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/swt.go
src/cmd/compile/internal/gc/syntax.go
src/cmd/compile/internal/gc/typecheck.go

index 5cb5e8b77bf3b828af194d0436e6b6e81203cc83..94c4bebec107635fd76668369a26ab6a67675163 100644 (file)
@@ -297,19 +297,19 @@ func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
                lastconst = cl
                lasttype = t
        }
-       cl = listtreecopy(cl, lno)
+       clcopy := listtreecopy(cl, lno)
 
        var v *Node
        var c *Node
        var vv *NodeList
        for ; vl != nil; vl = vl.Next {
-               if cl == nil {
+               if len(clcopy) == 0 {
                        Yyerror("missing value in const declaration")
                        break
                }
 
-               c = cl.N
-               cl = cl.Next
+               c = clcopy[0]
+               clcopy = clcopy[1:]
 
                v = vl.N
                v.Op = OLITERAL
@@ -321,7 +321,7 @@ func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
                vv = list(vv, Nod(ODCLCONST, v, nil))
        }
 
-       if cl != nil {
+       if len(clcopy) != 0 {
                Yyerror("extra expression in const declaration")
        }
        iota_ += 1
index f828bd268e56d520cff0b13e5ad10298da6c26dc..24ee47bbc43a067695225998b030f867f4034f75 100644 (file)
@@ -536,7 +536,7 @@ func treecopy(n *Node, lineno int32) *Node {
                m.Orig = m
                m.Left = treecopy(n.Left, lineno)
                m.Right = treecopy(n.Right, lineno)
-               m.List = listtreecopy(n.List, lineno)
+               setNodeSeq(&m.List, listtreecopy(n.List, lineno))
                if lineno != 0 {
                        m.Lineno = lineno
                }
@@ -1393,7 +1393,7 @@ func ullmancalc(n *Node) {
 
        var ul int
        var ur int
-       if n.Ninit != nil {
+       if nodeSeqLen(n.Ninit) != 0 {
                ul = UINF
                goto out
        }
@@ -2014,13 +2014,13 @@ func expandmeth(t *Type) {
 }
 
 // Given funarg struct list, return list of ODCLFIELD Node fn args.
-func structargs(tl **Type, mustname int) *NodeList {
+func structargs(tl **Type, mustname int) []*Node {
        var savet Iter
        var a *Node
        var n *Node
        var buf string
 
-       var args *NodeList
+       var args []*Node
        gen := 0
        for t := Structfirst(&savet, tl); t != nil; t = structnext(&savet) {
                n = nil
@@ -2038,7 +2038,7 @@ func structargs(tl **Type, mustname int) *NodeList {
                if n != nil {
                        n.Isddd = t.Isddd
                }
-               args = list(args, a)
+               args = append(args, a)
        }
 
        return args
@@ -2091,7 +2091,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
        out := structargs(Getoutarg(method.Type), 0)
 
        t := Nod(OTFUNC, nil, nil)
-       l := list1(this)
+       l := []*Node{this}
        if iface != 0 && rcvr.Width < Types[Tptr].Width {
                // Building method for interface table and receiver
                // is smaller than the single pointer-sized word
@@ -2103,11 +2103,11 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
                tpad.Type = Types[TUINT8]
                tpad.Bound = Types[Tptr].Width - rcvr.Width
                pad := Nod(ODCLFIELD, newname(Lookup(".pad")), typenod(tpad))
-               l = list(l, pad)
+               l = append(l, pad)
        }
 
-       t.List = concat(l, in)
-       t.Rlist = out
+       setNodeSeq(&t.List, append(l, in...))
+       setNodeSeq(&t.Rlist, out)
 
        fn := Nod(ODCLFUNC, nil, nil)
        fn.Func.Nname = newname(newnam)
@@ -2117,12 +2117,12 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
        funchdr(fn)
 
        // arg list
-       var args *NodeList
+       var args []*Node
 
        isddd := false
-       for l := in; l != nil; l = l.Next {
-               args = list(args, l.N.Left)
-               isddd = l.N.Left.Isddd
+       for _, n := range in {
+               args = append(args, n.Left)
+               isddd = n.Left.Isddd
        }
 
        methodrcvr := getthisx(method.Type).Type.Type
@@ -2136,17 +2136,17 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
 
                // these strings are already in the reflect tables,
                // so no space cost to use them here.
-               var l *NodeList
+               var l []*Node
 
                var v Val
                v.U = rcvr.Type.Sym.Pkg.Name // package name
-               l = list(l, nodlit(v))
+               l = append(l, nodlit(v))
                v.U = rcvr.Type.Sym.Name // type name
-               l = list(l, nodlit(v))
+               l = append(l, nodlit(v))
                v.U = method.Sym.Name
-               l = list(l, nodlit(v)) // method name
+               l = append(l, nodlit(v)) // method name
                call := Nod(OCALL, syslook("panicwrap"), nil)
-               call.List = l
+               setNodeSeq(&call.List, l)
                n.Nbody.Set([]*Node{call})
                fn.Nbody.Append(n)
        }
@@ -2169,11 +2169,11 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
        } else {
                fn.Func.Wrapper = true // ignore frame for panic+recover matching
                call := Nod(OCALL, dot, nil)
-               call.List = args
+               setNodeSeq(&call.List, args)
                call.Isddd = isddd
                if method.Type.Outtuple > 0 {
                        n := Nod(ORETURN, nil, nil)
-                       n.List = list1(call)
+                       setNodeSeq(&n.List, []*Node{call})
                        call = n
                }
 
@@ -2207,10 +2207,10 @@ func hashmem(t *Type) *Node {
        n := newname(sym)
        n.Class = PFUNC
        tfn := Nod(OTFUNC, nil, nil)
-       tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
-       tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
-       tfn.List = list(tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
-       tfn.Rlist = list(tfn.Rlist, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
+       appendNodeSeqNode(&tfn.List, Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
+       appendNodeSeqNode(&tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
+       appendNodeSeqNode(&tfn.List, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
+       appendNodeSeqNode(&tfn.Rlist, Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
        typecheck(&tfn, Etype)
        n.Type = tfn.Type
        return n
@@ -2354,10 +2354,10 @@ func Simsimtype(t *Type) EType {
        return et
 }
 
-func listtreecopy(l *NodeList, lineno int32) *NodeList {
-       var out *NodeList
-       for ; l != nil; l = l.Next {
-               out = list(out, treecopy(l.N, lineno))
+func listtreecopy(l nodesOrNodeList, lineno int32) []*Node {
+       var out []*Node
+       for it := nodeSeqIterate(l); !it.Done(); it.Next() {
+               out = append(out, treecopy(it.N(), lineno))
        }
        return out
 }
index 4f3d3dde49c934b4dd062af96dbc94f201fd7988..9870614f72d7af7ebabce9f573ac81359a089a2c 100644 (file)
@@ -105,11 +105,10 @@ func typecheckswitch(n *Node) {
        n.Type = t
 
        var def *Node
-       var ll *NodeList
-       for l := n.List; l != nil; l = l.Next {
-               ncase := l.N
+       for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
+               ncase := it.N()
                setlineno(n)
-               if ncase.List == nil {
+               if nodeSeqLen(ncase.List) == 0 {
                        // default
                        if def != nil {
                                Yyerror("multiple defaults in switch (first at %v)", def.Line())
@@ -117,30 +116,30 @@ func typecheckswitch(n *Node) {
                                def = ncase
                        }
                } else {
-                       for ll = ncase.List; ll != nil; ll = ll.Next {
-                               setlineno(ll.N)
-                               typecheck(&ll.N, Erv|Etype)
-                               if ll.N.Type == nil || t == nil {
+                       for it2 := nodeSeqIterate(ncase.List); !it2.Done(); it2.Next() {
+                               setlineno(it2.N())
+                               typecheck(it2.P(), Erv|Etype)
+                               if it2.N().Type == nil || t == nil {
                                        continue
                                }
                                setlineno(ncase)
                                switch top {
                                // expression switch
                                case Erv:
-                                       defaultlit(&ll.N, t)
+                                       defaultlit(it2.P(), t)
                                        switch {
-                                       case ll.N.Op == OTYPE:
-                                               Yyerror("type %v is not an expression", ll.N.Type)
-                                       case ll.N.Type != nil && assignop(ll.N.Type, t, nil) == 0 && assignop(t, ll.N.Type, nil) == 0:
+                                       case it2.N().Op == OTYPE:
+                                               Yyerror("type %v is not an expression", it2.N().Type)
+                                       case it2.N().Type != nil && assignop(it2.N().Type, t, nil) == 0 && assignop(t, it2.N().Type, nil) == 0:
                                                if n.Left != nil {
-                                                       Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ll.N, n.Left, ll.N.Type, t)
+                                                       Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", it2.N(), n.Left, it2.N().Type, t)
                                                } else {
-                                                       Yyerror("invalid case %v in switch (mismatched types %v and bool)", ll.N, ll.N.Type)
+                                                       Yyerror("invalid case %v in switch (mismatched types %v and bool)", it2.N(), it2.N().Type)
                                                }
-                                       case nilonly != "" && !isnil(ll.N):
-                                               Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ll.N, nilonly, n.Left)
-                                       case Isinter(t) && !Isinter(ll.N.Type) && algtype1(ll.N.Type, nil) == ANOEQ:
-                                               Yyerror("invalid case %v in switch (incomparable type)", Nconv(ll.N, obj.FmtLong))
+                                       case nilonly != "" && !isnil(it2.N()):
+                                               Yyerror("invalid case %v in switch (can only compare %s %v to nil)", it2.N(), nilonly, n.Left)
+                                       case Isinter(t) && !Isinter(it2.N().Type) && algtype1(it2.N().Type, nil) == ANOEQ:
+                                               Yyerror("invalid case %v in switch (incomparable type)", Nconv(it2.N(), obj.FmtLong))
                                        }
 
                                // type switch
@@ -148,16 +147,16 @@ func typecheckswitch(n *Node) {
                                        var missing, have *Type
                                        var ptr int
                                        switch {
-                                       case ll.N.Op == OLITERAL && Istype(ll.N.Type, TNIL):
-                                       case ll.N.Op != OTYPE && ll.N.Type != nil: // should this be ||?
-                                               Yyerror("%v is not a type", Nconv(ll.N, obj.FmtLong))
+                                       case it2.N().Op == OLITERAL && Istype(it2.N().Type, TNIL):
+                                       case it2.N().Op != OTYPE && it2.N().Type != nil: // should this be ||?
+                                               Yyerror("%v is not a type", Nconv(it2.N(), obj.FmtLong))
                                                // reset to original type
-                                               ll.N = n.Left.Right
-                                       case ll.N.Type.Etype != TINTER && t.Etype == TINTER && !implements(ll.N.Type, t, &missing, &have, &ptr):
+                                               *it2.P() = n.Left.Right
+                                       case it2.N().Type.Etype != TINTER && t.Etype == TINTER && !implements(it2.N().Type, t, &missing, &have, &ptr):
                                                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), ll.N.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), it2.N().Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
                                                } else if !missing.Broke {
-                                                       Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym)
+                                                       Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), it2.N().Type, missing.Sym)
                                                }
                                        }
                                }
@@ -165,19 +164,20 @@ func typecheckswitch(n *Node) {
                }
 
                if top == Etype && n.Type != nil {
-                       ll = ncase.List
-                       if ncase.Rlist != nil {
-                               nvar := ncase.Rlist.N
-                               if ll != nil && ll.Next == nil && ll.N.Type != nil && !Istype(ll.N.Type, TNIL) {
+                       ll := ncase.List
+                       if nodeSeqLen(ncase.Rlist) != 0 {
+                               nvar := nodeSeqFirst(ncase.Rlist)
+                               if nodeSeqLen(ll) == 1 && nodeSeqFirst(ll).Type != nil && !Istype(nodeSeqFirst(ll).Type, TNIL) {
                                        // single entry type switch
-                                       nvar.Name.Param.Ntype = typenod(ll.N.Type)
+                                       nvar.Name.Param.Ntype = typenod(nodeSeqFirst(ll).Type)
                                } else {
                                        // multiple entry type switch or default
                                        nvar.Name.Param.Ntype = typenod(n.Type)
                                }
 
                                typecheck(&nvar, Erv|Easgn)
-                               ncase.Rlist.N = nvar
+                               rit := nodeSeqIterate(ncase.Rlist)
+                               *rit.P() = nvar
                        }
                }
 
@@ -244,7 +244,7 @@ func (s *exprSwitch) walk(sw *Node) {
 
        // enumerate the cases, and lop off the default case
        cc := caseClauses(sw, s.kind)
-       sw.List = nil
+       setNodeSeq(&sw.List, nil)
        var def *Node
        if len(cc) > 0 && cc[0].typ == caseKindDefault {
                def = cc[0].node.Right
@@ -326,7 +326,7 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
        }
        typecheck(&a.Left, Erv)
        a.Nbody.Set([]*Node{s.walkCases(cc[:half])})
-       a.Rlist = list1(s.walkCases(cc[half:]))
+       setNodeSeq(&a.Rlist, []*Node{s.walkCases(cc[half:])})
        return a
 }
 
@@ -334,28 +334,28 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
 // It makes labels between cases and statements
 // and deals with fallthrough, break, and unreachable statements.
 func casebody(sw *Node, typeswvar *Node) {
-       if sw.List == nil {
+       if nodeSeqLen(sw.List) == 0 {
                return
        }
 
        lno := setlineno(sw)
 
-       var cas *NodeList // cases
-       var stat []*Node  // statements
-       var def *Node     // defaults
+       var cas []*Node  // cases
+       var stat []*Node // statements
+       var def *Node    // defaults
        br := Nod(OBREAK, nil, nil)
 
-       for l := sw.List; l != nil; l = l.Next {
-               n := l.N
+       for it := nodeSeqIterate(sw.List); !it.Done(); it.Next() {
+               n := it.N()
                setlineno(n)
                if n.Op != OXCASE {
                        Fatalf("casebody %v", Oconv(int(n.Op), 0))
                }
                n.Op = OCASE
-               needvar := count(n.List) != 1 || n.List.N.Op == OLITERAL
+               needvar := nodeSeqLen(n.List) != 1 || nodeSeqFirst(n.List).Op == OLITERAL
 
                jmp := Nod(OGOTO, newCaseLabel(), nil)
-               if n.List == nil {
+               if nodeSeqLen(n.List) == 0 {
                        if def != nil {
                                Yyerror("more than one default case")
                        }
@@ -364,24 +364,24 @@ func casebody(sw *Node, typeswvar *Node) {
                        def = n
                }
 
-               if n.List != nil && n.List.Next == nil {
+               if nodeSeqLen(n.List) == 1 {
                        // one case -- reuse OCASE node
-                       n.Left = n.List.N
+                       n.Left = nodeSeqFirst(n.List)
                        n.Right = jmp
-                       n.List = nil
-                       cas = list(cas, n)
+                       setNodeSeq(&n.List, nil)
+                       cas = append(cas, n)
                } else {
                        // expand multi-valued cases
-                       for lc := n.List; lc != nil; lc = lc.Next {
-                               cas = list(cas, Nod(OCASE, lc.N, jmp))
+                       for lcit := nodeSeqIterate(n.List); !lcit.Done(); lcit.Next() {
+                               cas = append(cas, Nod(OCASE, lcit.N(), jmp))
                        }
                }
 
                stat = append(stat, Nod(OLABEL, jmp.Left, nil))
-               if typeswvar != nil && needvar && n.Rlist != nil {
+               if typeswvar != nil && needvar && nodeSeqLen(n.Rlist) != 0 {
                        l := []*Node{
-                               Nod(ODCL, n.Rlist.N, nil),
-                               Nod(OAS, n.Rlist.N, typeswvar),
+                               Nod(ODCL, nodeSeqFirst(n.Rlist), nil),
+                               Nod(OAS, nodeSeqFirst(n.Rlist), typeswvar),
                        }
                        typecheckslice(l, Etop)
                        stat = append(stat, l...)
@@ -396,7 +396,7 @@ func casebody(sw *Node, typeswvar *Node) {
                                Yyerror("cannot fallthrough in type switch")
                        }
 
-                       if l.Next == nil {
+                       if it.Len() <= 1 {
                                setlineno(last)
                                Yyerror("cannot fallthrough final case in switch")
                        }
@@ -409,10 +409,10 @@ func casebody(sw *Node, typeswvar *Node) {
 
        stat = append(stat, br)
        if def != nil {
-               cas = list(cas, def)
+               cas = append(cas, def)
        }
 
-       sw.List = cas
+       setNodeSeq(&sw.List, cas)
        sw.Nbody.Set(stat)
        lineno = lno
 }
@@ -432,8 +432,8 @@ func newCaseLabel() *Node {
 // Kind is the kind of switch statement.
 func caseClauses(sw *Node, kind int) []*caseClause {
        var cc []*caseClause
-       for l := sw.List; l != nil; l = l.Next {
-               n := l.N
+       for it := nodeSeqIterate(sw.List); !it.Done(); it.Next() {
+               n := it.N()
                c := new(caseClause)
                cc = append(cc, c)
                c.ordinal = len(cc)
@@ -518,7 +518,7 @@ func (s *typeSwitch) walk(sw *Node) {
        sw.Left = nil
 
        if cond == nil {
-               sw.List = nil
+               setNodeSeq(&sw.List, nil)
                return
        }
        if cond.Right == nil {
@@ -552,7 +552,7 @@ func (s *typeSwitch) walk(sw *Node) {
        casebody(sw, s.facename)
 
        cc := caseClauses(sw, switchKindType)
-       sw.List = nil
+       setNodeSeq(&sw.List, nil)
        var def *Node
        if len(cc) > 0 && cc[0].typ == caseKindDefault {
                def = cc[0].node.Right
@@ -588,7 +588,7 @@ func (s *typeSwitch) walk(sw *Node) {
                i.Nbody.Set([]*Node{Nod(OGOTO, lbl, nil)})
                // Wrap default case with label.
                blk := Nod(OBLOCK, nil, nil)
-               blk.List = list(list1(Nod(OLABEL, lbl, nil)), def)
+               setNodeSeq(&blk.List, []*Node{Nod(OLABEL, lbl, nil), def})
                def = blk
        }
        typecheck(&i.Left, Erv)
@@ -669,7 +669,7 @@ func (s *typeSwitch) walk(sw *Node) {
        if nerrors == 0 {
                cas = append(cas, def)
                sw.Nbody.Set(append(cas, sw.Nbody.Slice()...))
-               sw.List = nil
+               setNodeSeq(&sw.List, nil)
                walkstmtlist(sw.Nbody)
        }
 }
@@ -679,11 +679,11 @@ func (s *typeSwitch) walk(sw *Node) {
 func (s *typeSwitch) typeone(t *Node) *Node {
        var name *Node
        var init *NodeList
-       if t.Rlist == nil {
+       if nodeSeqLen(t.Rlist) == 0 {
                name = nblank
                typecheck(&nblank, Erv|Easgn)
        } else {
-               name = t.Rlist.N
+               name = nodeSeqFirst(t.Rlist)
                init = list1(Nod(ODCL, name, nil))
                a := Nod(OAS, name, nil)
                typecheck(&a, Etop)
@@ -691,10 +691,10 @@ func (s *typeSwitch) typeone(t *Node) *Node {
        }
 
        a := Nod(OAS2, nil, nil)
-       a.List = list(list1(name), s.okname) // name, ok =
+       setNodeSeq(&a.List, []*Node{name, s.okname}) // name, ok =
        b := Nod(ODOTTYPE, s.facename, nil)
        b.Type = t.Left.Type // interface.(type)
-       a.Rlist = list1(b)
+       setNodeSeq(&a.Rlist, []*Node{b})
        typecheck(&a, Etop)
        init = list(init, a)
 
@@ -729,7 +729,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
        a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
        typecheck(&a.Left, Erv)
        a.Nbody.Set([]*Node{s.walkCases(cc[:half])})
-       a.Rlist = list1(s.walkCases(cc[half:]))
+       setNodeSeq(&a.Rlist, []*Node{s.walkCases(cc[half:])})
        return a
 }
 
index 3cc01717ad667e752dfb681c76a791c5f9ced0db..4c058e139faba8efb84a3c86f8b654942141140a 100644 (file)
@@ -391,12 +391,12 @@ func list1(n *Node) *NodeList {
        if n == nil {
                return nil
        }
-       if n.Op == OBLOCK && n.Ninit == nil {
+       if n.Op == OBLOCK && nodeSeqLen(n.Ninit) == 0 {
                // Flatten list and steal storage.
                // Poison pointer to catch errant uses.
                l := n.List
 
-               n.List = nil
+               setNodeSeq(&n.List, nil)
                return l
        }
 
index ec3229400bc18d6e2336932196744d3a47900417..50b5698b7467c0401a97df3b75b05dc328ddf376 100644 (file)
@@ -217,21 +217,12 @@ func callrecv(n *Node) bool {
                return true
        }
 
-       return callrecv(n.Left) || callrecv(n.Right) || callrecvlist(n.Ninit) || callrecvslice(n.Nbody.Slice()) || callrecvlist(n.List) || callrecvlist(n.Rlist)
+       return callrecv(n.Left) || callrecv(n.Right) || callrecvlist(n.Ninit) || callrecvlist(n.Nbody) || callrecvlist(n.List) || callrecvlist(n.Rlist)
 }
 
-func callrecvlist(l *NodeList) bool {
-       for ; l != nil; l = l.Next {
-               if callrecv(l.N) {
-                       return true
-               }
-       }
-       return false
-}
-
-func callrecvslice(l []*Node) bool {
-       for _, n := range l {
-               if callrecv(n) {
+func callrecvlist(l nodesOrNodeList) bool {
+       for it := nodeSeqIterate(l); !it.Done(); it.Next() {
+               if callrecv(it.N()) {
                        return true
                }
        }
@@ -440,7 +431,7 @@ OpSwitch:
                        n.Type = nil
                        return
                }
-               n.List = nil
+               setNodeSeq(&n.List, nil)
 
        case OTINTER:
                ok |= Etype
@@ -714,14 +705,14 @@ OpSwitch:
                                n.Op = OADDSTR
 
                                if l.Op == OADDSTR {
-                                       n.List = l.List
+                                       setNodeSeq(&n.List, l.List)
                                } else {
-                                       n.List = list1(l)
+                                       setNodeSeq(&n.List, []*Node{l})
                                }
                                if r.Op == OADDSTR {
-                                       n.List = concat(n.List, r.List)
+                                       appendNodeSeq(&n.List, r.List)
                                } else {
-                                       n.List = list(n.List, r)
+                                       appendNodeSeqNode(&n.List, r)
                                }
                                n.Left = nil
                                n.Right = nil
@@ -1298,8 +1289,9 @@ OpSwitch:
                        return
                }
 
-               if count(n.List) == 1 && !n.Isddd {
-                       typecheck(&n.List.N, Erv|Efnstruct)
+               if nodeSeqLen(n.List) == 1 && !n.Isddd {
+                       it := nodeSeqIterate(n.List)
+                       typecheck(it.P(), Erv|Efnstruct)
                } else {
                        typechecklist(n.List, Erv)
                }
@@ -1455,22 +1447,22 @@ OpSwitch:
                ok |= Erv
                var r *Node
                var l *Node
-               if count(n.List) == 1 {
+               if nodeSeqLen(n.List) == 1 {
                        typechecklist(n.List, Efnstruct)
-                       if n.List.N.Op != OCALLFUNC && n.List.N.Op != OCALLMETH {
+                       if nodeSeqFirst(n.List).Op != OCALLFUNC && nodeSeqFirst(n.List).Op != OCALLMETH {
                                Yyerror("invalid operation: complex expects two arguments")
                                n.Type = nil
                                return
                        }
 
-                       t := n.List.N.Left.Type
+                       t := nodeSeqFirst(n.List).Left.Type
                        if t.Outtuple != 2 {
-                               Yyerror("invalid operation: complex expects two arguments, %v returns %d results", n.List.N, t.Outtuple)
+                               Yyerror("invalid operation: complex expects two arguments, %v returns %d results", nodeSeqFirst(n.List), t.Outtuple)
                                n.Type = nil
                                return
                        }
 
-                       t = n.List.N.Type.Type
+                       t = nodeSeqFirst(n.List).Type.Type
                        l = t.Nname
                        r = t.Down.Nname
                } else {
@@ -1557,19 +1549,19 @@ OpSwitch:
 
        case ODELETE:
                args := n.List
-               if args == nil {
+               if nodeSeqLen(args) == 0 {
                        Yyerror("missing arguments to delete")
                        n.Type = nil
                        return
                }
 
-               if args.Next == nil {
+               if nodeSeqLen(args) == 1 {
                        Yyerror("missing second (key) argument to delete")
                        n.Type = nil
                        return
                }
 
-               if args.Next.Next != nil {
+               if nodeSeqLen(args) != 2 {
                        Yyerror("too many arguments to delete")
                        n.Type = nil
                        return
@@ -1577,33 +1569,36 @@ OpSwitch:
 
                ok |= Etop
                typechecklist(args, Erv)
-               l := args.N
-               r := args.Next.N
+               l := nodeSeqFirst(args)
+               r := nodeSeqSecond(args)
                if l.Type != nil && l.Type.Etype != TMAP {
                        Yyerror("first argument to delete must be map; have %v", Tconv(l.Type, obj.FmtLong))
                        n.Type = nil
                        return
                }
 
-               args.Next.N = assignconv(r, l.Type.Down, "delete")
+               it := nodeSeqIterate(args)
+               it.Next()
+               *it.P() = assignconv(r, l.Type.Down, "delete")
                break OpSwitch
 
        case OAPPEND:
                ok |= Erv
                args := n.List
-               if args == nil {
+               if nodeSeqLen(args) == 0 {
                        Yyerror("missing arguments to append")
                        n.Type = nil
                        return
                }
 
-               if count(args) == 1 && !n.Isddd {
-                       typecheck(&args.N, Erv|Efnstruct)
+               if nodeSeqLen(args) == 1 && !n.Isddd {
+                       it := nodeSeqIterate(args)
+                       typecheck(it.P(), Erv|Efnstruct)
                } else {
                        typechecklist(args, Erv)
                }
 
-               t := args.N.Type
+               t := nodeSeqFirst(args).Type
                if t == nil {
                        n.Type = nil
                        return
@@ -1618,7 +1613,7 @@ OpSwitch:
 
                n.Type = t
                if !Isslice(t) {
-                       if Isconst(args.N, CTNIL) {
+                       if Isconst(nodeSeqFirst(args), CTNIL) {
                                Yyerror("first argument to append must be typed slice; have untyped nil")
                                n.Type = nil
                                return
@@ -1630,24 +1625,28 @@ OpSwitch:
                }
 
                if n.Isddd {
-                       if args.Next == nil {
+                       if nodeSeqLen(args) == 1 {
                                Yyerror("cannot use ... on first argument to append")
                                n.Type = nil
                                return
                        }
 
-                       if args.Next.Next != nil {
+                       if nodeSeqLen(args) != 2 {
                                Yyerror("too many arguments to append")
                                n.Type = nil
                                return
                        }
 
-                       if Istype(t.Type, TUINT8) && Istype(args.Next.N.Type, TSTRING) {
-                               defaultlit(&args.Next.N, Types[TSTRING])
+                       if Istype(t.Type, TUINT8) && Istype(nodeSeqSecond(args).Type, TSTRING) {
+                               it := nodeSeqIterate(args)
+                               it.Next()
+                               defaultlit(it.P(), Types[TSTRING])
                                break OpSwitch
                        }
 
-                       args.Next.N = assignconv(args.Next.N, t.Orig, "append")
+                       it := nodeSeqIterate(args)
+                       it.Next()
+                       *it.P() = assignconv(nodeSeqSecond(args), t.Orig, "append")
                        break OpSwitch
                }
 
@@ -1658,11 +1657,13 @@ OpSwitch:
                                }
                        }
                } else {
-                       for args = args.Next; args != nil; args = args.Next {
-                               if args.N.Type == nil {
+                       it := nodeSeqIterate(args)
+                       it.Next()
+                       for ; !it.Done(); it.Next() {
+                               if it.N().Type == nil {
                                        continue
                                }
-                               args.N = assignconv(args.N, t.Type, "append")
+                               *it.P() = assignconv(it.N(), t.Type, "append")
                        }
                }
 
@@ -1671,21 +1672,21 @@ OpSwitch:
        case OCOPY:
                ok |= Etop | Erv
                args := n.List
-               if args == nil || args.Next == nil {
+               if nodeSeqLen(args) == 0 || args.Next == nil {
                        Yyerror("missing arguments to copy")
                        n.Type = nil
                        return
                }
 
-               if args.Next.Next != nil {
+               if nodeSeqLen(args) > 2 {
                        Yyerror("too many arguments to copy")
                        n.Type = nil
                        return
                }
 
-               n.Left = args.N
-               n.Right = args.Next.N
-               n.List = nil
+               n.Left = nodeSeqFirst(args)
+               n.Right = nodeSeqSecond(args)
+               setNodeSeq(&n.List, nil)
                n.Type = Types[TINT]
                typecheck(&n.Left, Erv)
                typecheck(&n.Right, Erv)
@@ -1777,16 +1778,16 @@ OpSwitch:
 
        case OMAKE:
                ok |= Erv
-               args := n.List
-               if args == nil {
+               args := nodeSeqIterate(n.List)
+               if args.Len() == 0 {
                        Yyerror("missing argument to make")
                        n.Type = nil
                        return
                }
 
-               n.List = nil
-               l := args.N
-               args = args.Next
+               setNodeSeq(&n.List, nil)
+               l := args.N()
+               args.Next()
                typecheck(&l, Etype)
                t := l.Type
                if t == nil {
@@ -1807,19 +1808,19 @@ OpSwitch:
                                return
                        }
 
-                       if args == nil {
+                       if args.Done() {
                                Yyerror("missing len argument to make(%v)", t)
                                n.Type = nil
                                return
                        }
 
-                       l = args.N
-                       args = args.Next
+                       l = args.N()
+                       args.Next()
                        typecheck(&l, Erv)
                        var r *Node
-                       if args != nil {
-                               r = args.N
-                               args = args.Next
+                       if !args.Done() {
+                               r = args.N()
+                               args.Next()
                                typecheck(&r, Erv)
                        }
 
@@ -1842,9 +1843,9 @@ OpSwitch:
                        n.Op = OMAKESLICE
 
                case TMAP:
-                       if args != nil {
-                               l = args.N
-                               args = args.Next
+                       if !args.Done() {
+                               l = args.N()
+                               args.Next()
                                typecheck(&l, Erv)
                                defaultlit(&l, Types[TINT])
                                if l.Type == nil {
@@ -1863,9 +1864,9 @@ OpSwitch:
 
                case TCHAN:
                        l = nil
-                       if args != nil {
-                               l = args.N
-                               args = args.Next
+                       if !args.Done() {
+                               l = args.N()
+                               args.Next()
                                typecheck(&l, Erv)
                                defaultlit(&l, Types[TINT])
                                if l.Type == nil {
@@ -1883,7 +1884,7 @@ OpSwitch:
                        n.Op = OMAKECHAN
                }
 
-               if args != nil {
+               if !args.Done() {
                        Yyerror("too many arguments to make(%v)", t)
                        n.Op = OMAKE
                        n.Type = nil
@@ -1896,20 +1897,20 @@ OpSwitch:
        case ONEW:
                ok |= Erv
                args := n.List
-               if args == nil {
+               if nodeSeqLen(args) == 0 {
                        Yyerror("missing argument to new")
                        n.Type = nil
                        return
                }
 
-               l := args.N
+               l := nodeSeqFirst(args)
                typecheck(&l, Etype)
                t := l.Type
                if t == nil {
                        n.Type = nil
                        return
                }
-               if args.Next != nil {
+               if nodeSeqLen(args) > 1 {
                        Yyerror("too many arguments to new(%v)", t)
                        n.Type = nil
                        return
@@ -1922,12 +1923,12 @@ OpSwitch:
        case OPRINT, OPRINTN:
                ok |= Etop
                typechecklist(n.List, Erv|Eindir) // Eindir: address does not escape
-               for args := n.List; args != nil; args = args.Next {
+               for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
                        // Special case for print: int constant is int64, not int.
-                       if Isconst(args.N, CTINT) {
-                               defaultlit(&args.N, Types[TINT64])
+                       if Isconst(it.N(), CTINT) {
+                               defaultlit(it.P(), Types[TINT64])
                        } else {
-                               defaultlit(&args.N, nil)
+                               defaultlit(it.P(), nil)
                        }
                }
 
@@ -1949,7 +1950,7 @@ OpSwitch:
 
        case ORECOVER:
                ok |= Erv | Etop
-               if n.List != nil {
+               if nodeSeqLen(n.List) != 0 {
                        Yyerror("too many arguments to recover")
                        n.Type = nil
                        return
@@ -2093,7 +2094,7 @@ OpSwitch:
 
        case ORETURN:
                ok |= Etop
-               if count(n.List) == 1 {
+               if nodeSeqLen(n.List) == 1 {
                        typechecklist(n.List, Erv|Efnstruct)
                } else {
                        typechecklist(n.List, Erv)
@@ -2104,7 +2105,7 @@ OpSwitch:
                        return
                }
 
-               if Curfn.Type.Outnamed && n.List == nil {
+               if Curfn.Type.Outnamed && nodeSeqLen(n.List) == 0 {
                        break OpSwitch
                }
                typecheckaste(ORETURN, nil, false, getoutargx(Curfn.Type), n.List, func() string { return "return argument" })
@@ -2332,22 +2333,22 @@ func onearg(n *Node, f string, args ...interface{}) bool {
        if n.Left != nil {
                return true
        }
-       if n.List == nil {
+       if nodeSeqLen(n.List) == 0 {
                p := fmt.Sprintf(f, args...)
                Yyerror("missing argument to %s: %v", p, n)
                return false
        }
 
-       if n.List.Next != nil {
+       if nodeSeqLen(n.List) > 1 {
                p := fmt.Sprintf(f, args...)
                Yyerror("too many arguments to %s: %v", p, n)
-               n.Left = n.List.N
-               n.List = nil
+               n.Left = nodeSeqFirst(n.List)
+               setNodeSeq(&n.List, nil)
                return false
        }
 
-       n.Left = n.List.N
-       n.List = nil
+       n.Left = nodeSeqFirst(n.List)
+       setNodeSeq(&n.List, nil)
        return true
 }
 
@@ -2355,26 +2356,26 @@ func twoarg(n *Node) bool {
        if n.Left != nil {
                return true
        }
-       if n.List == nil {
+       if nodeSeqLen(n.List) == 0 {
                Yyerror("missing argument to %v - %v", Oconv(int(n.Op), 0), n)
                return false
        }
 
-       n.Left = n.List.N
-       if n.List.Next == nil {
+       n.Left = nodeSeqFirst(n.List)
+       if nodeSeqLen(n.List) == 1 {
                Yyerror("missing argument to %v - %v", Oconv(int(n.Op), 0), n)
-               n.List = nil
+               setNodeSeq(&n.List, nil)
                return false
        }
 
-       if n.List.Next.Next != nil {
+       if nodeSeqLen(n.List) > 2 {
                Yyerror("too many arguments to %v - %v", Oconv(int(n.Op), 0), n)
-               n.List = nil
+               setNodeSeq(&n.List, nil)
                return false
        }
 
-       n.Right = n.List.Next.N
-       n.List = nil
+       n.Right = nodeSeqSecond(n.List)
+       setNodeSeq(&n.List, nil)
        return true
 }
 
@@ -2915,8 +2916,8 @@ func typecheckcomplit(np **Node) {
        }()
 
        if n.Right == nil {
-               if n.List != nil {
-                       setlineno(n.List.N)
+               if nodeSeqLen(n.List) != 0 {
+                       setlineno(nodeSeqFirst(n.List))
                }
                Yyerror("missing type in composite literal")
                n.Type = nil
@@ -2966,22 +2967,22 @@ func typecheckcomplit(np **Node) {
        case TARRAY:
                // Only allocate hash if there are some key/value pairs.
                var hash map[int64]*Node
-               for ll := n.List; ll != nil; ll = ll.Next {
-                       if ll.N.Op == OKEY {
+               for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
+                       if it.N().Op == OKEY {
                                hash = make(map[int64]*Node)
                                break
                        }
                }
                length := int64(0)
                i := 0
-               for ll := n.List; ll != nil; ll = ll.Next {
-                       l := ll.N
+               for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
+                       l := it.N()
                        setlineno(l)
                        if l.Op != OKEY {
                                l = Nod(OKEY, Nodintconst(int64(i)), l)
                                l.Left.Type = Types[TINT]
                                l.Left.Typecheck = 1
-                               ll.N = l
+                               *it.P() = l
                        }
 
                        typecheck(&l.Left, Erv)
@@ -3024,11 +3025,11 @@ func typecheckcomplit(np **Node) {
        case TMAP:
                hash := make(map[uint32][]*Node)
                var l *Node
-               for ll := n.List; ll != nil; ll = ll.Next {
-                       l = ll.N
+               for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
+                       l = it.N()
                        setlineno(l)
                        if l.Op != OKEY {
-                               typecheck(&ll.N, Erv)
+                               typecheck(it.P(), Erv)
                                Yyerror("missing key in map literal")
                                continue
                        }
@@ -3053,14 +3054,14 @@ func typecheckcomplit(np **Node) {
 
        case TSTRUCT:
                bad := 0
-               if n.List != nil && nokeys(n.List) {
+               if nodeSeqLen(n.List) != 0 && nokeys(n.List) {
                        // simple list of variables
                        f := t.Type
 
                        var s *Sym
-                       for ll := n.List; ll != nil; ll = ll.Next {
-                               setlineno(ll.N)
-                               typecheck(&ll.N, Erv)
+                       for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
+                               setlineno(it.N())
+                               typecheck(it.P(), Erv)
                                if f == nil {
                                        if bad == 0 {
                                                Yyerror("too many values in struct initializer")
@@ -3075,11 +3076,11 @@ func typecheckcomplit(np **Node) {
                                }
 
                                // No pushtype allowed here. Must name fields for that.
-                               ll.N = assignconv(ll.N, f.Type, "field value")
+                               *it.P() = assignconv(it.N(), f.Type, "field value")
 
-                               ll.N = Nod(OKEY, newname(f.Sym), ll.N)
-                               ll.N.Left.Type = f
-                               ll.N.Left.Typecheck = 1
+                               *it.P() = Nod(OKEY, newname(f.Sym), it.N())
+                               it.N().Left.Type = f
+                               it.N().Left.Typecheck = 1
                                f = f.Down
                        }
 
@@ -3094,15 +3095,15 @@ func typecheckcomplit(np **Node) {
                        var f *Type
                        var l *Node
                        var s1 *Sym
-                       for ll := n.List; ll != nil; ll = ll.Next {
-                               l = ll.N
+                       for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
+                               l = it.N()
                                setlineno(l)
                                if l.Op != OKEY {
                                        if bad == 0 {
                                                Yyerror("mixture of field:value and value initializers")
                                        }
                                        bad++
-                                       typecheck(&ll.N, Erv)
+                                       typecheck(it.P(), Erv)
                                        continue
                                }
 
@@ -3313,19 +3314,20 @@ func checkassignto(src *Type, dst *Node) {
 }
 
 func typecheckas2(n *Node) {
-       for ll := n.List; ll != nil; ll = ll.Next {
+       for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
                // delicate little dance.
-               ll.N = resolve(ll.N)
+               *it.P() = resolve(it.N())
 
-               if ll.N.Name == nil || ll.N.Name.Defn != n || ll.N.Name.Param.Ntype != nil {
-                       typecheck(&ll.N, Erv|Easgn)
+               if it.N().Name == nil || it.N().Name.Defn != n || it.N().Name.Param.Ntype != nil {
+                       typecheck(it.P(), Erv|Easgn)
                }
        }
 
-       cl := count(n.List)
-       cr := count(n.Rlist)
+       cl := nodeSeqLen(n.List)
+       cr := nodeSeqLen(n.Rlist)
        if cl > 1 && cr == 1 {
-               typecheck(&n.Rlist.N, Erv|Efnstruct)
+               it := nodeSeqIterate(n.Rlist)
+               typecheck(it.P(), Erv|Efnstruct)
        } else {
                typechecklist(n.Rlist, Erv)
        }
@@ -3335,23 +3337,24 @@ func typecheckas2(n *Node) {
        var r *Node
        if cl == cr {
                // easy
-               ll := n.List
-               lr := n.Rlist
-               for ; ll != nil; ll, lr = ll.Next, lr.Next {
-                       if ll.N.Type != nil && lr.N.Type != nil {
-                               lr.N = assignconv(lr.N, ll.N.Type, "assignment")
+               llit := nodeSeqIterate(n.List)
+               lrit := nodeSeqIterate(n.Rlist)
+               for llit = nodeSeqIterate(n.List); !llit.Done(); llit.Next() {
+                       if llit.N().Type != nil && lrit.N().Type != nil {
+                               *lrit.P() = assignconv(lrit.N(), llit.N().Type, "assignment")
                        }
-                       if ll.N.Name != nil && ll.N.Name.Defn == n && ll.N.Name.Param.Ntype == nil {
-                               defaultlit(&lr.N, nil)
-                               ll.N.Type = lr.N.Type
+                       if llit.N().Name != nil && llit.N().Name.Defn == n && llit.N().Name.Param.Ntype == nil {
+                               defaultlit(lrit.P(), nil)
+                               llit.N().Type = lrit.N().Type
                        }
+                       lrit.Next()
                }
 
                goto out
        }
 
-       l = n.List.N
-       r = n.Rlist.N
+       l = nodeSeqFirst(n.List)
+       r = nodeSeqFirst(n.Rlist)
 
        // x,y,z = f()
        if cr == 1 {
@@ -3370,12 +3373,12 @@ func typecheckas2(n *Node) {
                        n.Op = OAS2FUNC
                        var s Iter
                        t := Structfirst(&s, &r.Type)
-                       for ll := n.List; ll != nil; ll = ll.Next {
-                               if t.Type != nil && ll.N.Type != nil {
-                                       checkassignto(t.Type, ll.N)
+                       for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
+                               if t.Type != nil && it.N().Type != nil {
+                                       checkassignto(t.Type, it.N())
                                }
-                               if ll.N.Name != nil && ll.N.Name.Defn == n && ll.N.Name.Param.Ntype == nil {
-                                       ll.N.Type = t.Type
+                               if it.N().Name != nil && it.N().Name.Defn == n && it.N().Name.Param.Ntype == nil {
+                                       it.N().Type = t.Type
                                }
                                t = structnext(&s)
                        }
@@ -3409,7 +3412,7 @@ func typecheckas2(n *Node) {
                        if l.Name != nil && l.Name.Defn == n {
                                l.Type = r.Type
                        }
-                       l := n.List.Next.N
+                       l := nodeSeqSecond(n.List)
                        if l.Type != nil && l.Type.Etype != TBOOL {
                                checkassignto(Types[TBOOL], l)
                        }
@@ -3427,9 +3430,9 @@ mismatch:
 out:
        n.Typecheck = 1
 
-       for ll := n.List; ll != nil; ll = ll.Next {
-               if ll.N.Typecheck == 0 {
-                       typecheck(&ll.N, Erv|Easgn)
+       for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
+               if it.N().Typecheck == 0 {
+                       typecheck(it.P(), Erv|Easgn)
                }
        }
 }
@@ -3462,23 +3465,23 @@ func stringtoarraylit(np **Node) {
        }
 
        s := n.Left.Val().U.(string)
-       var l *NodeList
+       var l []*Node
        if n.Type.Type.Etype == TUINT8 {
                // []byte
                for i := 0; i < len(s); i++ {
-                       l = list(l, Nod(OKEY, Nodintconst(int64(i)), Nodintconst(int64(s[0]))))
+                       l = append(l, Nod(OKEY, Nodintconst(int64(i)), Nodintconst(int64(s[0]))))
                }
        } else {
                // []rune
                i := 0
                for _, r := range s {
-                       l = list(l, Nod(OKEY, Nodintconst(int64(i)), Nodintconst(int64(r))))
+                       l = append(l, Nod(OKEY, Nodintconst(int64(i)), Nodintconst(int64(r))))
                        i++
                }
        }
 
        nn := Nod(OCOMPLIT, nil, typenod(n.Type))
-       nn.List = l
+       setNodeSeq(&nn.List, l)
        typecheck(&nn, Erv)
        *np = nn
 }
@@ -3880,43 +3883,16 @@ func markbreak(n *Node, implicit *Node) {
 
                markbreak(n.Right, implicit)
                markbreaklist(n.Ninit, implicit)
-               markbreakslice(n.Nbody.Slice(), implicit)
+               markbreaklist(n.Nbody, implicit)
                markbreaklist(n.List, implicit)
                markbreaklist(n.Rlist, implicit)
        }
 }
 
-func markbreaklist(l *NodeList, implicit *Node) {
-       var n *Node
-       var lab *Label
-
-       for ; l != nil; l = l.Next {
-               n = l.N
-               if n.Op == OLABEL && l.Next != nil && n.Name.Defn == l.Next.N {
-                       switch n.Name.Defn.Op {
-                       case OFOR,
-                               OSWITCH,
-                               OTYPESW,
-                               OSELECT,
-                               ORANGE:
-                               lab = new(Label)
-                               lab.Def = n.Name.Defn
-                               n.Left.Sym.Label = lab
-                               markbreak(n.Name.Defn, n.Name.Defn)
-                               n.Left.Sym.Label = nil
-                               l = l.Next
-                               continue
-                       }
-               }
-
-               markbreak(n, implicit)
-       }
-}
-
-func markbreakslice(l []*Node, implicit *Node) {
-       for i := 0; i < len(l); i++ {
-               n := l[i]
-               if n.Op == OLABEL && i+1 < len(l) && n.Name.Defn == l[i+1] {
+func markbreaklist(l nodesOrNodeList, implicit *Node) {
+       for it := nodeSeqIterate(l); !it.Done(); it.Next() {
+               n := it.N()
+               if n.Op == OLABEL && it.Len() > 1 && n.Name.Defn == nodeSeqSlice(it.Seq())[1] {
                        switch n.Name.Defn.Op {
                        case OFOR, OSWITCH, OTYPESW, OSELECT, ORANGE:
                                lab := new(Label)
@@ -3924,7 +3900,7 @@ func markbreakslice(l []*Node, implicit *Node) {
                                n.Left.Sym.Label = lab
                                markbreak(n.Name.Defn, n.Name.Defn)
                                n.Left.Sym.Label = nil
-                               i++
+                               it.Next()
                                continue
                        }
                }
@@ -3991,11 +3967,11 @@ func (n *Node) isterminating() bool {
                        return false
                }
                def := 0
-               for l := n.List; l != nil; l = l.Next {
-                       if !l.N.Nbody.isterminating() {
+               for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
+                       if !it.N().Nbody.isterminating() {
                                return false
                        }
-                       if l.N.List == nil { // default
+                       if nodeSeqLen(it.N().List) == 0 { // default
                                def = 1
                        }
                }
@@ -4011,7 +3987,7 @@ func (n *Node) isterminating() bool {
 
 func checkreturn(fn *Node) {
        if fn.Type.Outtuple != 0 && len(fn.Nbody.Slice()) != 0 {
-               markbreakslice(fn.Nbody.Slice(), nil)
+               markbreaklist(fn.Nbody, nil)
                if !fn.Nbody.isterminating() {
                        yyerrorl(fn.Func.Endlineno, "missing return at end of function")
                }