]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: change Node.Nbody, Func.Inl from *NodeList to Nodes
authorIan Lance Taylor <iant@golang.org>
Sat, 27 Feb 2016 22:31:33 +0000 (14:31 -0800)
committerIan Lance Taylor <iant@golang.org>
Mon, 29 Feb 2016 00:33:32 +0000 (00:33 +0000)
Passes toolstash -cmp.

Casual timings show about a 3% improvement in compile times.

Update #14473.

Change-Id: I584add2e8f1a52486ba418b25ba6122b7347b643
Reviewed-on: https://go-review.googlesource.com/19989
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
24 files changed:
src/cmd/compile/internal/gc/alg.go
src/cmd/compile/internal/gc/bexport.go
src/cmd/compile/internal/gc/bimport.go
src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/esc.go
src/cmd/compile/internal/gc/export.go
src/cmd/compile/internal/gc/fmt.go
src/cmd/compile/internal/gc/gen.go
src/cmd/compile/internal/gc/init.go
src/cmd/compile/internal/gc/inl.go
src/cmd/compile/internal/gc/lex.go
src/cmd/compile/internal/gc/order.go
src/cmd/compile/internal/gc/parser.go
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/gc/racewalk.go
src/cmd/compile/internal/gc/range.go
src/cmd/compile/internal/gc/select.go
src/cmd/compile/internal/gc/sinit.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
src/cmd/compile/internal/gc/walk.go

index c99373759870cae2724d30db1e88e4177544b7a4..a0ff4890c1d706fd4a96ddef845bcea4c34bdf9a 100644 (file)
@@ -232,9 +232,9 @@ func genhash(sym *Sym, t *Type) {
                na.Etype = 1 // no escape to heap
                call.List = list(call.List, na)
                call.List = list(call.List, nh)
-               n.Nbody = list(n.Nbody, Nod(OAS, nh, call))
+               n.Nbody.Append(Nod(OAS, nh, call))
 
-               fn.Nbody = list(fn.Nbody, n)
+               fn.Nbody.Append(n)
 
        // Walk the struct using memhash for runs of AMEM
        // and calling specific hash functions for the others.
@@ -262,7 +262,7 @@ func genhash(sym *Sym, t *Type) {
                                call.List = list(call.List, na)
                                call.List = list(call.List, nh)
                                call.List = list(call.List, Nodintconst(size))
-                               fn.Nbody = list(fn.Nbody, Nod(OAS, nh, call))
+                               fn.Nbody.Append(Nod(OAS, nh, call))
                        }
 
                        if t1 == nil {
@@ -285,7 +285,7 @@ func genhash(sym *Sym, t *Type) {
                        na.Etype = 1 // no escape to heap
                        call.List = list(call.List, na)
                        call.List = list(call.List, nh)
-                       fn.Nbody = list(fn.Nbody, Nod(OAS, nh, call))
+                       fn.Nbody.Append(Nod(OAS, nh, call))
 
                        t1 = t1.Down
                }
@@ -293,17 +293,17 @@ func genhash(sym *Sym, t *Type) {
 
        r := Nod(ORETURN, nil, nil)
        r.List = list(r.List, nh)
-       fn.Nbody = list(fn.Nbody, r)
+       fn.Nbody.Append(r)
 
        if Debug['r'] != 0 {
-               dumplist("genhash body", fn.Nbody)
+               dumpslice("genhash body", fn.Nbody.Slice())
        }
 
        funcbody(fn)
        Curfn = fn
        fn.Func.Dupok = true
        typecheck(&fn, Etop)
-       typechecklist(fn.Nbody, Etop)
+       typecheckslice(fn.Nbody.Slice(), Etop)
        Curfn = nil
 
        // Disable safemode while compiling this code: the code we
@@ -429,14 +429,14 @@ func geneq(sym *Sym, t *Type) {
                nif.Left = Nod(ONE, nx, ny)
                r := Nod(ORETURN, nil, nil)
                r.List = list(r.List, Nodbool(false))
-               nif.Nbody = list(nif.Nbody, r)
-               nrange.Nbody = list(nrange.Nbody, nif)
-               fn.Nbody = list(fn.Nbody, nrange)
+               nif.Nbody.Append(r)
+               nrange.Nbody.Append(nif)
+               fn.Nbody.Append(nrange)
 
                // return true
                ret := Nod(ORETURN, nil, nil)
                ret.List = list(ret.List, Nodbool(true))
-               fn.Nbody = list(fn.Nbody, ret)
+               fn.Nbody.Append(ret)
 
        // Walk the struct using memequal for runs of AMEM
        // and calling specific equality tests for the others.
@@ -500,18 +500,18 @@ func geneq(sym *Sym, t *Type) {
 
                ret := Nod(ORETURN, nil, nil)
                ret.List = list(ret.List, and)
-               fn.Nbody = list(fn.Nbody, ret)
+               fn.Nbody.Append(ret)
        }
 
        if Debug['r'] != 0 {
-               dumplist("geneq body", fn.Nbody)
+               dumpslice("geneq body", fn.Nbody.Slice())
        }
 
        funcbody(fn)
        Curfn = fn
        fn.Func.Dupok = true
        typecheck(&fn, Etop)
-       typechecklist(fn.Nbody, Etop)
+       typecheckslice(fn.Nbody.Slice(), Etop)
        Curfn = nil
 
        // Disable safemode while compiling this code: the code we
index dc55bb023ed6a39c9b11f13ba7c9d8331db31ca8..49793bfaf7410faa29bd6de23348d86fbb9732d5 100644 (file)
@@ -748,7 +748,7 @@ func (p *exporter) float(x *Mpflt) {
 // is written out for exported functions with inlined function bodies.
 
 func (p *exporter) collectInlined(n *Node) int {
-       if n != nil && n.Func != nil && n.Func.Inl != nil {
+       if n != nil && n.Func != nil && len(n.Func.Inl.Slice()) != 0 {
                // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
                // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
                if Debug['l'] < 2 {
@@ -762,13 +762,13 @@ func (p *exporter) collectInlined(n *Node) int {
 
 func (p *exporter) body(i int, f *Func) {
        p.int(i)
-       p.block(f.Inl)
+       p.block(f.Inl.Slice())
 }
 
-func (p *exporter) block(list *NodeList) {
-       p.int(count(list))
-       for q := list; q != nil; q = q.Next {
-               p.stmt(q.N)
+func (p *exporter) block(list []*Node) {
+       p.int(len(list))
+       for _, n := range list {
+               p.stmt(n)
        }
 }
 
index f330f1b9e67222aa91a5c68de5a07acfb87bbda8..5c2ffa6888d4aa4725b359d11f57a55b24022c6c 100644 (file)
@@ -95,7 +95,7 @@ func Import(in *obj.Biobuf) {
                funchdr(n)
 
                // go.y:hidden_import
-               n.Func.Inl = nil
+               n.Func.Inl.Set(nil)
                funcbody(n)
                importlist = append(importlist, n) // TODO(gri) do this only if body is inlineable?
        }
@@ -253,7 +253,7 @@ func (p *importer) typ() *Type {
                        n.Type.Nname = n
 
                        // go.y:hidden_import
-                       n.Func.Inl = nil
+                       n.Func.Inl.Set(nil)
                        funcbody(n)
                        importlist = append(importlist, n) // TODO(gri) do this only if body is inlineable?
                }
index 9a7a5c0c277d1af5a64f6d1e789d3b82a1cf207d..d8ec05973ebc7caf407357da15aa31c1778e3cc7 100644 (file)
@@ -59,7 +59,7 @@ func closurebody(body *NodeList) *Node {
        }
 
        func_ := Curfn
-       func_.Nbody = body
+       func_.Nbody.SetToNodeList(body)
        func_.Func.Endlineno = lineno
        funcbody(func_)
 
@@ -111,7 +111,7 @@ func typecheckclosure(func_ *Node, top int) {
                Curfn = func_
                olddd := decldepth
                decldepth = 1
-               typechecklist(func_.Nbody, Etop)
+               typecheckslice(func_.Nbody.Slice(), Etop)
                decldepth = olddd
                Curfn = oldfn
        }
@@ -193,10 +193,10 @@ func makeclosure(func_ *Node) *Node {
        xfunc.Func.Endlineno = func_.Func.Endlineno
        makefuncsym(xfunc.Func.Nname.Sym)
 
-       xfunc.Nbody = func_.Nbody
+       xfunc.Nbody.Set(func_.Nbody.Slice())
        xfunc.Func.Dcl = append(func_.Func.Dcl, xfunc.Func.Dcl...)
        func_.Func.Dcl = nil
-       if xfunc.Nbody == nil {
+       if len(xfunc.Nbody.Slice()) == 0 {
                Fatalf("empty body - won't generate any code")
        }
        typecheck(&xfunc, Etop)
@@ -204,7 +204,7 @@ func makeclosure(func_ *Node) *Node {
        xfunc.Func.Closure = func_
        func_.Func.Closure = xfunc
 
-       func_.Nbody = nil
+       func_.Nbody.Set(nil)
        func_.List = nil
        func_.Rlist = nil
 
@@ -589,30 +589,30 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
        ptr.Used = true
        ptr.Name.Curfn = xfunc
        xfunc.Func.Dcl = append(xfunc.Func.Dcl, ptr)
-       var body *NodeList
+       var body []*Node
        if Isptr[rcvrtype.Etype] || Isinter(rcvrtype) {
                ptr.Name.Param.Ntype = typenod(rcvrtype)
-               body = list(body, Nod(OAS, ptr, cv))
+               body = append(body, Nod(OAS, ptr, cv))
        } else {
                ptr.Name.Param.Ntype = typenod(Ptrto(rcvrtype))
-               body = list(body, Nod(OAS, ptr, Nod(OADDR, cv, nil)))
+               body = append(body, Nod(OAS, ptr, Nod(OADDR, cv, nil)))
        }
 
        call := Nod(OCALL, Nod(OXDOT, ptr, meth), nil)
        call.List = callargs
        call.Isddd = ddd
        if t0.Outtuple == 0 {
-               body = list(body, call)
+               body = append(body, call)
        } else {
                n := Nod(OAS2, nil, nil)
                n.List = retargs
                n.Rlist = list1(call)
-               body = list(body, n)
+               body = append(body, n)
                n = Nod(ORETURN, nil, nil)
-               body = list(body, n)
+               body = append(body, n)
        }
 
-       xfunc.Nbody = body
+       xfunc.Nbody.Set(body)
 
        typecheck(&xfunc, Etop)
        sym.Def = xfunc
index 33c04c501d81b47b4af7964738a4530bb2ce01ba..52ada12f865de9a92ac298e3107426cfb15dac37 100644 (file)
@@ -1520,7 +1520,7 @@ func checknowritebarrierrec() {
                        for _, n := range list {
                                if n.Func.WBLineno == 0 {
                                        c.curfn = n
-                                       c.visitcodelist(n.Nbody)
+                                       c.visitcodeslice(n.Nbody.Slice())
                                }
                        }
                        if c.stable {
@@ -1557,6 +1557,12 @@ func (c *nowritebarrierrecChecker) visitcodelist(l *NodeList) {
        }
 }
 
+func (c *nowritebarrierrecChecker) visitcodeslice(l []*Node) {
+       for _, n := range l {
+               c.visitcode(n)
+       }
+}
+
 func (c *nowritebarrierrecChecker) visitcode(n *Node) {
        if n == nil {
                return
@@ -1570,7 +1576,7 @@ func (c *nowritebarrierrecChecker) visitcode(n *Node) {
        c.visitcode(n.Left)
        c.visitcode(n.Right)
        c.visitcodelist(n.List)
-       c.visitcodelist(n.Nbody)
+       c.visitcodeslice(n.Nbody.Slice())
        c.visitcodelist(n.Rlist)
 }
 
index 57459947853e7dbe9b0639f07122bfc13f10039a..e26cbb372bd212ca513080b30309694cee2c37f7 100644 (file)
@@ -78,7 +78,7 @@ func (v *bottomUpVisitor) visit(n *Node) uint32 {
        min := v.visitgen
 
        v.stack = append(v.stack, n)
-       min = v.visitcodelist(n.Nbody, min)
+       min = v.visitcodeslice(n.Nbody.Slice(), min)
        if (min == id || min == id+1) && n.Func.FCurfn == nil {
                // This node is the root of a strongly connected component.
 
@@ -117,6 +117,13 @@ func (v *bottomUpVisitor) visitcodelist(l *NodeList, min uint32) uint32 {
        return min
 }
 
+func (v *bottomUpVisitor) visitcodeslice(l []*Node, min uint32) uint32 {
+       for _, n := range l {
+               min = v.visitcode(n, min)
+       }
+       return min
+}
+
 func (v *bottomUpVisitor) visitcode(n *Node, min uint32) uint32 {
        if n == nil {
                return min
@@ -126,7 +133,7 @@ func (v *bottomUpVisitor) visitcode(n *Node, min uint32) uint32 {
        min = v.visitcode(n.Left, min)
        min = v.visitcode(n.Right, min)
        min = v.visitcodelist(n.List, min)
-       min = v.visitcodelist(n.Nbody, min)
+       min = v.visitcodeslice(n.Nbody.Slice(), min)
        min = v.visitcodelist(n.Rlist, min)
 
        if n.Op == OCALLFUNC || n.Op == OCALLMETH {
@@ -491,7 +498,7 @@ func escfunc(e *EscState, func_ *Node) {
                        if ln.Type != nil && !haspointers(ln.Type) {
                                break
                        }
-                       if Curfn.Nbody == nil && !Curfn.Noescape {
+                       if len(Curfn.Nbody.Slice()) == 0 && !Curfn.Noescape {
                                ln.Esc = EscHeap
                        } else {
                                ln.Esc = EscNone // prime for escflood later
@@ -509,8 +516,8 @@ func escfunc(e *EscState, func_ *Node) {
                }
        }
 
-       escloopdepthlist(e, Curfn.Nbody)
-       esclist(e, Curfn.Nbody, Curfn)
+       escloopdepthslice(e, Curfn.Nbody.Slice())
+       escslice(e, Curfn.Nbody.Slice(), Curfn)
        Curfn = savefn
        e.loopdepth = saveld
 }
@@ -528,6 +535,12 @@ func escloopdepthlist(e *EscState, l *NodeList) {
        }
 }
 
+func escloopdepthslice(e *EscState, l []*Node) {
+       for _, n := range l {
+               escloopdepth(e, n)
+       }
+}
+
 func escloopdepth(e *EscState, n *Node) {
        if n == nil {
                return
@@ -562,7 +575,7 @@ func escloopdepth(e *EscState, n *Node) {
        escloopdepth(e, n.Left)
        escloopdepth(e, n.Right)
        escloopdepthlist(e, n.List)
-       escloopdepthlist(e, n.Nbody)
+       escloopdepthslice(e, n.Nbody.Slice())
        escloopdepthlist(e, n.Rlist)
 }
 
@@ -572,6 +585,12 @@ func esclist(e *EscState, l *NodeList, up *Node) {
        }
 }
 
+func escslice(e *EscState, l []*Node, up *Node) {
+       for _, n := range l {
+               esc(e, n, up)
+       }
+}
+
 func esc(e *EscState, n *Node, up *Node) {
        if n == nil {
                return
@@ -622,7 +641,7 @@ func esc(e *EscState, n *Node, up *Node) {
 
        esc(e, n.Left, n)
        esc(e, n.Right, n)
-       esclist(e, n.Nbody, n)
+       escslice(e, n.Nbody.Slice(), n)
        esclist(e, n.List, n)
        esclist(e, n.Rlist, n)
 
@@ -1395,7 +1414,7 @@ func esccall(e *EscState, n *Node, up *Node) {
 
        nE := e.nodeEscState(n)
        if fn != nil && fn.Op == ONAME && fn.Class == PFUNC &&
-               fn.Name.Defn != nil && fn.Name.Defn.Nbody != nil && fn.Name.Param.Ntype != nil && fn.Name.Defn.Esc < EscFuncTagged {
+               fn.Name.Defn != nil && len(fn.Name.Defn.Nbody.Slice()) != 0 && fn.Name.Param.Ntype != nil && fn.Name.Defn.Esc < EscFuncTagged {
                if Debug['m'] > 2 {
                        fmt.Printf("%v::esccall:: %v in recursive group\n", Ctxt.Line(int(lineno)), Nconv(n, obj.FmtShort))
                }
@@ -1833,7 +1852,7 @@ func esctag(e *EscState, func_ *Node) {
 
        // External functions are assumed unsafe,
        // unless //go:noescape is given before the declaration.
-       if func_.Nbody == nil {
+       if len(func_.Nbody.Slice()) == 0 {
                if func_.Noescape {
                        for t := getinargx(func_.Type).Type; t != nil; t = t.Down {
                                if haspointers(t.Type) {
index 1b61d7f228f665e9f6a3179b8b12ed71ced75712..b36fe7b9e43e0dfc88c87a13a5f83d77a0e43874 100644 (file)
@@ -112,6 +112,12 @@ func reexportdeplist(ll *NodeList) {
        }
 }
 
+func reexportdepslice(ll []*Node) {
+       for _, n := range ll {
+               reexportdep(n)
+       }
+}
+
 func reexportdep(n *Node) {
        if n == nil {
                return
@@ -217,7 +223,7 @@ func reexportdep(n *Node) {
        reexportdeplist(n.List)
        reexportdeplist(n.Rlist)
        reexportdeplist(n.Ninit)
-       reexportdeplist(n.Nbody)
+       reexportdepslice(n.Nbody.Slice())
 }
 
 func dumpexportconst(s *Sym) {
@@ -249,7 +255,7 @@ func dumpexportvar(s *Sym) {
        dumpexporttype(t)
 
        if t.Etype == TFUNC && n.Class == PFUNC {
-               if n.Func != nil && n.Func.Inl != nil {
+               if n.Func != nil && len(n.Func.Inl.Slice()) != 0 {
                        // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
                        // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
                        if Debug['l'] < 2 {
@@ -257,9 +263,9 @@ func dumpexportvar(s *Sym) {
                        }
 
                        // NOTE: The space after %#S here is necessary for ld's export data parser.
-                       exportf("\tfunc %v %v { %v }\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp), Hconv(n.Func.Inl, obj.FmtSharp|obj.FmtBody))
+                       exportf("\tfunc %v %v { %v }\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp), Hconvslice(n.Func.Inl.Slice(), obj.FmtSharp|obj.FmtBody))
 
-                       reexportdeplist(n.Func.Inl)
+                       reexportdepslice(n.Func.Inl.Slice())
                } else {
                        exportf("\tfunc %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp))
                }
@@ -307,15 +313,15 @@ func dumpexporttype(t *Type) {
                if f.Nointerface {
                        exportf("\t//go:nointerface\n")
                }
-               if f.Type.Nname != nil && f.Type.Nname.Func.Inl != nil { // nname was set by caninl
+               if f.Type.Nname != nil && len(f.Type.Nname.Func.Inl.Slice()) != 0 { // nname was set by caninl
 
                        // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
                        // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
                        if Debug['l'] < 2 {
                                typecheckinl(f.Type.Nname)
                        }
-                       exportf("\tfunc (%v) %v %v { %v }\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconv(f.Type.Nname.Func.Inl, obj.FmtSharp))
-                       reexportdeplist(f.Type.Nname.Func.Inl)
+                       exportf("\tfunc (%v) %v %v { %v }\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconvslice(f.Type.Nname.Func.Inl.Slice(), obj.FmtSharp))
+                       reexportdepslice(f.Type.Nname.Func.Inl.Slice())
                } else {
                        exportf("\tfunc (%v) %v %v\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp))
                }
index 9327a13d9160fbff7d893fdf943482ebf82daa21..39b74f69680e56f09d591d5a3896c4d814fcd682 100644 (file)
@@ -1216,7 +1216,7 @@ func exprfmt(n *Node, prec int) string {
                if fmtmode == FErr {
                        return "func literal"
                }
-               if n.Nbody != nil {
+               if len(n.Nbody.Slice()) != 0 {
                        return fmt.Sprintf("%v { %v }", n.Type, n.Nbody)
                }
                return fmt.Sprintf("%v { %v }", n.Type, n.Name.Param.Closure.Nbody)
@@ -1583,7 +1583,7 @@ func nodedump(n *Node, flag int) string {
                        fmt.Fprintf(&buf, "%v-rlist%v", Oconv(int(n.Op), 0), n.Rlist)
                }
 
-               if n.Nbody != nil {
+               if len(n.Nbody.Slice()) != 0 {
                        indent(&buf)
                        fmt.Fprintf(&buf, "%v-body%v", Oconv(int(n.Op), 0), n.Nbody)
                }
@@ -1699,6 +1699,10 @@ func (l *NodeList) String() string {
        return Hconv(l, 0)
 }
 
+func (n Nodes) String() string {
+       return Hconvslice(n.Slice(), 0)
+}
+
 // Fmt '%H': NodeList.
 // Flags: all those of %N plus ',': separate with comma's instead of semicolons.
 func Hconv(l *NodeList, flag int) string {
index 4edef2b97abc900a62ce755496042dfe1abc90da..2292a564b3f5b537a1002072d3865151556f445e 100644 (file)
@@ -777,7 +777,7 @@ func gen(n *Node) {
                gen(n.Right)                     // contin:     incr
                Patch(p1, Pc)                    // test:
                Bgen(n.Left, false, -1, breakpc) //             if(!test) goto break
-               Genlist(n.Nbody)                 //             body
+               Genslice(n.Nbody.Slice())        //             body
                gjmp(continpc)
                Patch(breakpc, Pc) // done:
                continpc = scontin
@@ -792,7 +792,7 @@ func gen(n *Node) {
                p2 := gjmp(nil)                         // p2:          goto else
                Patch(p1, Pc)                           // test:
                Bgen(n.Left, false, int(-n.Likely), p2) //              if(!test) goto p2
-               Genlist(n.Nbody)                        //              then
+               Genslice(n.Nbody.Slice())               //              then
                p3 := gjmp(nil)                         //              goto done
                Patch(p2, Pc)                           // else:
                Genlist(n.Rlist)                        //              else
@@ -809,9 +809,9 @@ func gen(n *Node) {
                        lab.Breakpc = breakpc
                }
 
-               Patch(p1, Pc)      // test:
-               Genlist(n.Nbody)   //           switch(test) body
-               Patch(breakpc, Pc) // done:
+               Patch(p1, Pc)             // test:
+               Genslice(n.Nbody.Slice()) //            switch(test) body
+               Patch(breakpc, Pc)        // done:
                breakpc = sbreak
                if lab != nil {
                        lab.Breakpc = nil
@@ -828,9 +828,9 @@ func gen(n *Node) {
                        lab.Breakpc = breakpc
                }
 
-               Patch(p1, Pc)      // test:
-               Genlist(n.Nbody)   //           select() body
-               Patch(breakpc, Pc) // done:
+               Patch(p1, Pc)             // test:
+               Genslice(n.Nbody.Slice()) //            select() body
+               Patch(breakpc, Pc)        // done:
                breakpc = sbreak
                if lab != nil {
                        lab.Breakpc = nil
index 6071ab44f0d4c15edc9dc89df6719cefa517ac75..d7db786725e7c048edbc4ca6a1839ff8973ca6c8 100644 (file)
@@ -46,15 +46,15 @@ func renameinit() *Sym {
 //             initdone· = 2;                         (10)
 //             return                                  (11)
 //     }
-func anyinit(n *NodeList) bool {
+func anyinit(n []*Node) bool {
        // are there any interesting init statements
-       for l := n; l != nil; l = l.Next {
-               switch l.N.Op {
+       for _, ln := range n {
+               switch ln.Op {
                case ODCLFUNC, ODCLCONST, ODCLTYPE, OEMPTY:
                        break
 
                case OAS, OASWB:
-                       if isblank(l.N.Left) && candiscard(l.N.Right) {
+                       if isblank(ln.Left) && candiscard(ln.Right) {
                                break
                        }
                        fallthrough
@@ -94,12 +94,12 @@ func fninit(n *NodeList) {
                return
        }
 
-       n = initfix(n)
-       if !anyinit(n) {
+       nf := initfix(n)
+       if !anyinit(nf) {
                return
        }
 
-       var r *NodeList
+       var r []*Node
 
        // (1)
        gatevar := newname(Lookup("initdone·"))
@@ -120,37 +120,37 @@ func fninit(n *NodeList) {
        a := Nod(OIF, nil, nil)
 
        a.Left = Nod(ONE, gatevar, Nodintconst(0))
-       r = list(r, a)
+       r = append(r, a)
 
        // (4)
        b := Nod(OIF, nil, nil)
 
        b.Left = Nod(OEQ, gatevar, Nodintconst(2))
-       b.Nbody = list1(Nod(ORETURN, nil, nil))
-       a.Nbody = list1(b)
+       b.Nbody.Set([]*Node{Nod(ORETURN, nil, nil)})
+       a.Nbody.Set([]*Node{b})
 
        // (5)
        b = syslook("throwinit", 0)
 
        b = Nod(OCALL, b, nil)
-       a.Nbody = list(a.Nbody, b)
+       a.Nbody.Append(b)
 
        // (6)
        a = Nod(OAS, gatevar, Nodintconst(1))
 
-       r = list(r, a)
+       r = append(r, a)
 
        // (7)
        for _, s := range initSyms {
                if s.Def != nil && s != initsym {
                        // could check that it is fn of no args/returns
                        a = Nod(OCALL, s.Def, nil)
-                       r = list(r, a)
+                       r = append(r, a)
                }
        }
 
        // (8)
-       r = concat(r, n)
+       r = append(r, nf...)
 
        // (9)
        // could check that it is fn of no args/returns
@@ -160,26 +160,26 @@ func fninit(n *NodeList) {
                        break
                }
                a = Nod(OCALL, s.Def, nil)
-               r = list(r, a)
+               r = append(r, a)
        }
 
        // (10)
        a = Nod(OAS, gatevar, Nodintconst(2))
 
-       r = list(r, a)
+       r = append(r, a)
 
        // (11)
        a = Nod(ORETURN, nil, nil)
 
-       r = list(r, a)
+       r = append(r, a)
        exportsym(fn.Func.Nname)
 
-       fn.Nbody = r
+       fn.Nbody.Set(r)
        funcbody(fn)
 
        Curfn = fn
        typecheck(&fn, Etop)
-       typechecklist(r, Etop)
+       typecheckslice(r, Etop)
        Curfn = nil
        funccompile(fn)
 }
index f5c3265a82f008b7a5095cd9f3bfaafe98d19518..84065658aea9a03270ee123ebc919eafd8cacbc9 100644 (file)
@@ -79,7 +79,7 @@ func typecheckinl(fn *Node) {
        }
 
        if Debug['m'] > 2 {
-               fmt.Printf("typecheck import [%v] %v { %v }\n", fn.Sym, Nconv(fn, obj.FmtLong), Hconv(fn.Func.Inl, obj.FmtSharp))
+               fmt.Printf("typecheck import [%v] %v { %v }\n", fn.Sym, Nconv(fn, obj.FmtLong), Hconvslice(fn.Func.Inl.Slice(), obj.FmtSharp))
        }
 
        save_safemode := safemode
@@ -87,7 +87,7 @@ func typecheckinl(fn *Node) {
 
        savefn := Curfn
        Curfn = fn
-       typechecklist(fn.Func.Inl, Etop)
+       typecheckslice(fn.Func.Inl.Slice(), Etop)
        Curfn = savefn
 
        safemode = save_safemode
@@ -112,7 +112,7 @@ func caninl(fn *Node) {
        }
 
        // If fn has no body (is defined outside of Go), cannot inline it.
-       if fn.Nbody == nil {
+       if len(fn.Nbody.Slice()) == 0 {
                return
        }
 
@@ -141,15 +141,15 @@ func caninl(fn *Node) {
 
        const maxBudget = 80
        budget := maxBudget // allowed hairyness
-       if ishairylist(fn.Nbody, &budget) || budget < 0 {
+       if ishairyslice(fn.Nbody.Slice(), &budget) || budget < 0 {
                return
        }
 
        savefn := Curfn
        Curfn = fn
 
-       fn.Func.Nname.Func.Inl = fn.Nbody
-       fn.Nbody = inlcopylist(fn.Func.Nname.Func.Inl)
+       fn.Func.Nname.Func.Inl.Set(fn.Nbody.Slice())
+       fn.Nbody.Set(inlcopyslice(fn.Func.Nname.Func.Inl.Slice()))
        inldcl := inlcopyslice(fn.Func.Nname.Name.Defn.Func.Dcl)
        if len(inldcl) > 0 {
                fn.Func.Nname.Func.Inldcl = &inldcl
@@ -161,7 +161,7 @@ func caninl(fn *Node) {
        fn.Type.Nname = fn.Func.Nname
 
        if Debug['m'] > 1 {
-               fmt.Printf("%v: can inline %v as: %v { %v }\n", fn.Line(), Nconv(fn.Func.Nname, obj.FmtSharp), Tconv(fn.Type, obj.FmtSharp), Hconv(fn.Func.Nname.Func.Inl, obj.FmtSharp))
+               fmt.Printf("%v: can inline %v as: %v { %v }\n", fn.Line(), Nconv(fn.Func.Nname, obj.FmtSharp), Tconv(fn.Type, obj.FmtSharp), Hconvslice(fn.Func.Nname.Func.Inl.Slice(), obj.FmtSharp))
        } else if Debug['m'] != 0 {
                fmt.Printf("%v: can inline %v\n", fn.Line(), fn.Func.Nname)
        }
@@ -179,6 +179,15 @@ func ishairylist(ll *NodeList, budget *int) bool {
        return false
 }
 
+func ishairyslice(ll []*Node, budget *int) bool {
+       for _, n := range ll {
+               if ishairy(n, budget) {
+                       return true
+               }
+       }
+       return false
+}
+
 func ishairy(n *Node, budget *int) bool {
        if n == nil {
                return false
@@ -187,12 +196,12 @@ func ishairy(n *Node, budget *int) bool {
        switch n.Op {
        // Call is okay if inlinable and we have the budget for the body.
        case OCALLFUNC:
-               if n.Left.Func != nil && n.Left.Func.Inl != nil {
+               if n.Left.Func != nil && len(n.Left.Func.Inl.Slice()) != 0 {
                        *budget -= int(n.Left.Func.InlCost)
                        break
                }
                if n.Left.Op == ONAME && n.Left.Left != nil && n.Left.Left.Op == OTYPE && n.Left.Right != nil && n.Left.Right.Op == ONAME { // methods called as functions
-                       if n.Left.Sym.Def != nil && n.Left.Sym.Def.Func.Inl != nil {
+                       if n.Left.Sym.Def != nil && len(n.Left.Sym.Def.Func.Inl.Slice()) != 0 {
                                *budget -= int(n.Left.Sym.Def.Func.InlCost)
                                break
                        }
@@ -209,7 +218,7 @@ func ishairy(n *Node, budget *int) bool {
                if n.Left.Type.Nname == nil {
                        Fatalf("no function definition for [%p] %v\n", n.Left.Type, Tconv(n.Left.Type, obj.FmtSign))
                }
-               if n.Left.Type.Nname.Func.Inl != nil {
+               if len(n.Left.Type.Nname.Func.Inl.Slice()) != 0 {
                        *budget -= int(n.Left.Type.Nname.Func.InlCost)
                        break
                }
@@ -239,7 +248,7 @@ func ishairy(n *Node, budget *int) bool {
 
        (*budget)--
 
-       return *budget < 0 || ishairy(n.Left, budget) || ishairy(n.Right, budget) || ishairylist(n.List, budget) || ishairylist(n.Rlist, budget) || ishairylist(n.Ninit, budget) || ishairylist(n.Nbody, budget)
+       return *budget < 0 || ishairy(n.Left, budget) || ishairy(n.Right, budget) || ishairylist(n.List, budget) || ishairylist(n.Rlist, budget) || ishairylist(n.Ninit, budget) || ishairyslice(n.Nbody.Slice(), budget)
 }
 
 // Inlcopy and inlcopylist recursively copy the body of a function.
@@ -266,14 +275,14 @@ func inlcopy(n *Node) *Node {
        m := Nod(OXXX, nil, nil)
        *m = *n
        if m.Func != nil {
-               m.Func.Inl = nil
+               m.Func.Inl.Set(nil)
        }
        m.Left = inlcopy(n.Left)
        m.Right = inlcopy(n.Right)
        m.List = inlcopylist(n.List)
        m.Rlist = inlcopylist(n.Rlist)
        m.Ninit = inlcopylist(n.Ninit)
-       m.Nbody = inlcopylist(n.Nbody)
+       m.Nbody.Set(inlcopyslice(n.Nbody.Slice()))
 
        return m
 }
@@ -307,9 +316,9 @@ func inlconv2stmt(n *Node) {
        n.Op = OBLOCK
 
        // n->ninit stays
-       n.List = n.Nbody
+       n.List = n.Nbody.NodeList()
 
-       n.Nbody = nil
+       n.Nbody.Set(nil)
        n.Rlist = nil
 }
 
@@ -317,7 +326,7 @@ func inlconv2stmt(n *Node) {
 func inlconv2expr(np **Node) {
        n := *np
        r := n.Rlist.N
-       addinit(&r, concat(n.Ninit, n.Nbody))
+       addinit(&r, concat(n.Ninit, n.Nbody.NodeList()))
        *np = r
 }
 
@@ -332,7 +341,7 @@ func inlconv2list(n *Node) *NodeList {
        }
 
        l := n.Rlist
-       addinit(&l.N, concat(n.Ninit, n.Nbody))
+       addinit(&l.N, concat(n.Ninit, n.Nbody.NodeList()))
        return l
 }
 
@@ -342,6 +351,12 @@ func inlnodelist(l *NodeList) {
        }
 }
 
+func inlnodeslice(l []*Node) {
+       for i := range l {
+               inlnode(&l[i])
+       }
+}
+
 // inlnode recurses over the tree to find inlineable calls, which will
 // be turned into OINLCALLs by mkinlcall.  When the recursion comes
 // back up will examine left, right, list, rlist, ninit, ntest, nincr,
@@ -454,10 +469,10 @@ func inlnode(np **Node) {
                }
        }
 
-       inlnodelist(n.Nbody)
-       for l := n.Nbody; l != nil; l = l.Next {
-               if l.N.Op == OINLCALL {
-                       inlconv2stmt(l.N)
+       inlnodeslice(n.Nbody.Slice())
+       for _, n := range n.Nbody.Slice() {
+               if n.Op == OINLCALL {
+                       inlconv2stmt(n)
                }
        }
 
@@ -477,7 +492,7 @@ func inlnode(np **Node) {
                if Debug['m'] > 3 {
                        fmt.Printf("%v:call to func %v\n", n.Line(), Nconv(n.Left, obj.FmtSign))
                }
-               if n.Left.Func != nil && n.Left.Func.Inl != nil { // normal case
+               if n.Left.Func != nil && len(n.Left.Func.Inl.Slice()) != 0 { // normal case
                        mkinlcall(np, n.Left, n.Isddd)
                } else if n.Left.Op == ONAME && n.Left.Left != nil && n.Left.Left.Op == OTYPE && n.Left.Right != nil && n.Left.Right.Op == ONAME { // methods called as functions
                        if n.Left.Sym.Def != nil {
@@ -539,7 +554,7 @@ var inlgen int
 // parameters.
 func mkinlcall1(np **Node, fn *Node, isddd bool) {
        // For variadic fn.
-       if fn.Func.Inl == nil {
+       if len(fn.Func.Inl.Slice()) == 0 {
                return
        }
 
@@ -555,7 +570,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
 
        // Bingo, we have a function node, and it has an inlineable body
        if Debug['m'] > 1 {
-               fmt.Printf("%v: inlining call to %v %v { %v }\n", n.Line(), fn.Sym, Tconv(fn.Type, obj.FmtSharp), Hconv(fn.Func.Inl, obj.FmtSharp))
+               fmt.Printf("%v: inlining call to %v %v { %v }\n", n.Line(), fn.Sym, Tconv(fn.Type, obj.FmtSharp), Hconvslice(fn.Func.Inl.Slice(), obj.FmtSharp))
        } else if Debug['m'] != 0 {
                fmt.Printf("%v: inlining call to %v\n", n.Line(), fn)
        }
@@ -796,19 +811,19 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
 
        inlretlabel = newlabel_inl()
        inlgen++
-       body := inlsubstlist(fn.Func.Inl)
+       body := inlsubstslice(fn.Func.Inl.Slice())
 
-       body = list(body, Nod(OGOTO, inlretlabel, nil)) // avoid 'not used' when function doesn't have return
-       body = list(body, Nod(OLABEL, inlretlabel, nil))
+       body = append(body, Nod(OGOTO, inlretlabel, nil)) // avoid 'not used' when function doesn't have return
+       body = append(body, Nod(OLABEL, inlretlabel, nil))
 
-       typechecklist(body, Etop)
+       typecheckslice(body, Etop)
 
        //dumplist("ninit post", ninit);
 
        call := Nod(OINLCALL, nil, nil)
 
        call.Ninit = ninit
-       call.Nbody = body
+       call.Nbody.Set(body)
        call.Rlist = inlretvars
        call.Type = n.Type
        call.Typecheck = 1
@@ -834,15 +849,15 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
        // instead we emit the things that the body needs
        // and each use must redo the inlining.
        // luckily these are small.
-       body = fn.Func.Inl
-       fn.Func.Inl = nil // prevent infinite recursion (shouldn't happen anyway)
-       inlnodelist(call.Nbody)
-       for ll := call.Nbody; ll != nil; ll = ll.Next {
-               if ll.N.Op == OINLCALL {
-                       inlconv2stmt(ll.N)
+       body = fn.Func.Inl.Slice()
+       fn.Func.Inl.Set(nil) // prevent infinite recursion (shouldn't happen anyway)
+       inlnodeslice(call.Nbody.Slice())
+       for _, n := range call.Nbody.Slice() {
+               if n.Op == OINLCALL {
+                       inlconv2stmt(n)
                }
        }
-       fn.Func.Inl = body
+       fn.Func.Inl.Set(body)
 
        if Debug['m'] > 2 {
                fmt.Printf("%v: After inlining %v\n\n", n.Line(), Nconv(*np, obj.FmtSign))
@@ -907,8 +922,8 @@ func newlabel_inl() *Node {
        return n
 }
 
-// inlsubst and inlsubstlist recursively copy the body of the saved
-// pristine ->inl body of the function while substituting references
+// inlsubst, inlsubstlist, and inlsubstslice recursively copy the body of the
+// saved pristine ->inl body of the function while substituting references
 // to input/output parameters with ones to the tmpnames, and
 // substituting returns with assignments to the output.
 func inlsubstlist(ll *NodeList) *NodeList {
@@ -919,6 +934,14 @@ func inlsubstlist(ll *NodeList) *NodeList {
        return l
 }
 
+func inlsubstslice(ll []*Node) []*Node {
+       l := make([]*Node, 0, len(ll))
+       for _, n := range ll {
+               l = append(l, inlsubst(n))
+       }
+       return l
+}
+
 func inlsubst(n *Node) *Node {
        if n == nil {
                return nil
@@ -990,7 +1013,7 @@ func inlsubst(n *Node) *Node {
        m.List = inlsubstlist(n.List)
        m.Rlist = inlsubstlist(n.Rlist)
        m.Ninit = concat(m.Ninit, inlsubstlist(n.Ninit))
-       m.Nbody = inlsubstlist(n.Nbody)
+       m.Nbody.Set(inlsubstslice(n.Nbody.Slice()))
 
        return m
 }
@@ -1002,6 +1025,12 @@ func setlnolist(ll *NodeList, lno int) {
        }
 }
 
+func setlnoslice(ll []*Node, lno int) {
+       for _, n := range ll {
+               setlno(n, lno)
+       }
+}
+
 func setlno(n *Node, lno int) {
        if n == nil {
                return
@@ -1017,5 +1046,5 @@ func setlno(n *Node, lno int) {
        setlnolist(n.List, lno)
        setlnolist(n.Rlist, lno)
        setlnolist(n.Ninit, lno)
-       setlnolist(n.Nbody, lno)
+       setlnoslice(n.Nbody.Slice(), lno)
 }
index 62cdded120b560dc7b3898241ddbdcb7cbcd3efc..995fd130ef8c1e17e3344433d62c25d975bccaf2 100644 (file)
@@ -388,10 +388,10 @@ func Main() {
                        Curfn = l.N
                        decldepth = 1
                        saveerrors()
-                       typechecklist(l.N.Nbody, Etop)
+                       typecheckslice(l.N.Nbody.Slice(), Etop)
                        checkreturn(l.N)
                        if nerrors != 0 {
-                               l.N.Nbody = nil // type errors; do not compile
+                               l.N.Nbody.Set(nil) // type errors; do not compile
                        }
                }
        }
@@ -417,7 +417,7 @@ func Main() {
                // Typecheck imported function bodies if debug['l'] > 1,
                // otherwise lazily when used or re-exported.
                for _, n := range importlist {
-                       if n.Func.Inl != nil {
+                       if len(n.Func.Inl.Slice()) != 0 {
                                saveerrors()
                                typecheckinl(n)
                        }
index cc74ea553b4a175b2712d8cc703aad5a0a09fdd7..e94ff210b6aec345483c4738aa3ad8f6074a18c9 100644 (file)
@@ -41,8 +41,8 @@ import (
 
 // Order holds state during the ordering process.
 type Order struct {
-       out  *NodeList // list of generated statements
-       temp []*Node   // stack of temporary variables
+       out  []*Node // list of generated statements
+       temp []*Node // stack of temporary variables
 }
 
 // Order rewrites fn->nbody to apply the ordering constraints
@@ -50,10 +50,10 @@ type Order struct {
 func order(fn *Node) {
        if Debug['W'] > 1 {
                s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym)
-               dumplist(s, fn.Nbody)
+               dumpslice(s, fn.Nbody.Slice())
        }
 
-       orderblock(&fn.Nbody)
+       orderblockNodes(&fn.Nbody)
 }
 
 // Ordertemp allocates a new temporary with the given type,
@@ -64,7 +64,7 @@ func ordertemp(t *Type, order *Order, clear bool) *Node {
        if clear {
                a := Nod(OAS, var_, nil)
                typecheck(&a, Etop)
-               order.out = list(order.out, a)
+               order.out = append(order.out, a)
        }
 
        order.temp = append(order.temp, var_)
@@ -87,7 +87,7 @@ func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node {
        var_ := ordertemp(t, order, clear != 0)
        a := Nod(OAS, var_, n)
        typecheck(&a, Etop)
-       order.out = list(order.out, a)
+       order.out = append(order.out, a)
        return var_
 }
 
@@ -223,7 +223,7 @@ func poptemp(mark ordermarker, order *Order) {
 // Cleantempnopop emits to *out VARKILL instructions for each temporary
 // above the mark on the temporary stack, but it does not pop them
 // from the stack.
-func cleantempnopop(mark ordermarker, order *Order, out **NodeList) {
+func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) {
        var kill *Node
 
        for i := len(order.temp) - 1; i >= int(mark); i-- {
@@ -232,11 +232,11 @@ func cleantempnopop(mark ordermarker, order *Order, out **NodeList) {
                        n.Name.Keepalive = false
                        kill = Nod(OVARLIVE, n, nil)
                        typecheck(&kill, Etop)
-                       *out = list(*out, kill)
+                       *out = append(*out, kill)
                }
                kill = Nod(OVARKILL, n, nil)
                typecheck(&kill, Etop)
-               *out = list(*out, kill)
+               *out = append(*out, kill)
        }
 }
 
@@ -254,6 +254,13 @@ func orderstmtlist(l *NodeList, order *Order) {
        }
 }
 
+// Orderstmtslice orders each of the statements in the slice.
+func orderstmtslice(l []*Node, order *Order) {
+       for _, n := range l {
+               orderstmt(n, order)
+       }
+}
+
 // Orderblock orders the block of statements *l onto a new list,
 // and then replaces *l with that list.
 func orderblock(l **NodeList) {
@@ -261,7 +268,21 @@ func orderblock(l **NodeList) {
        mark := marktemp(&order)
        orderstmtlist(*l, &order)
        cleantemp(mark, &order)
-       *l = order.out
+       var ll *NodeList
+       for _, n := range order.out {
+               ll = list(ll, n)
+       }
+       *l = ll
+}
+
+// OrderblockNodes orders the block of statements in n into a new slice,
+// and then replaces the old slice in n with the new slice.
+func orderblockNodes(n *Nodes) {
+       var order Order
+       mark := marktemp(&order)
+       orderstmtslice(n.Slice(), &order)
+       cleantemp(mark, &order)
+       n.Set(order.out)
 }
 
 // Orderexprinplace orders the side effects in *np and
@@ -270,7 +291,7 @@ func orderexprinplace(np **Node, outer *Order) {
        n := *np
        var order Order
        orderexpr(&n, &order, nil)
-       addinit(&n, order.out)
+       addinitslice(&n, order.out)
 
        // insert new temporaries from order
        // at head of outer list.
@@ -287,7 +308,7 @@ func orderstmtinplace(np **Node) {
        mark := marktemp(&order)
        orderstmt(n, &order)
        cleantemp(mark, &order)
-       *np = liststmt(order.out)
+       *np = liststmtslice(order.out)
 }
 
 // Orderinit moves n's init list to order->out.
@@ -413,7 +434,7 @@ func ordermapassign(n *Node, order *Order) {
                Fatalf("ordermapassign %v", Oconv(int(n.Op), 0))
 
        case OAS:
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
 
                // We call writebarrierfat only for values > 4 pointers long. See walk.go.
                if (n.Left.Op == OINDEXMAP || (needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr))) && !isaddrokay(n.Right) {
@@ -421,11 +442,11 @@ func ordermapassign(n *Node, order *Order) {
                        n.Left = ordertemp(m.Type, order, false)
                        a := Nod(OAS, m, n.Left)
                        typecheck(&a, Etop)
-                       order.out = list(order.out, a)
+                       order.out = append(order.out, a)
                }
 
        case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC:
-               var post *NodeList
+               var post []*Node
                var m *Node
                var a *Node
                for l := n.List; l != nil; l = l.Next {
@@ -440,18 +461,18 @@ func ordermapassign(n *Node, order *Order) {
                                l.N = ordertemp(m.Type, order, false)
                                a = Nod(OAS, m, l.N)
                                typecheck(&a, Etop)
-                               post = list(post, a)
+                               post = append(post, a)
                        } else if instrumenting && n.Op == OAS2FUNC && !isblank(l.N) {
                                m = l.N
                                l.N = ordertemp(m.Type, order, false)
                                a = Nod(OAS, m, l.N)
                                typecheck(&a, Etop)
-                               post = list(post, a)
+                               post = append(post, a)
                        }
                }
 
-               order.out = list(order.out, n)
-               order.out = concat(order.out, post)
+               order.out = append(order.out, n)
+               order.out = append(order.out, post...)
        }
 }
 
@@ -472,7 +493,7 @@ func orderstmt(n *Node, order *Order) {
                Fatalf("orderstmt %v", Oconv(int(n.Op), 0))
 
        case OVARKILL, OVARLIVE:
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
 
        case OAS:
                t := marktemp(order)
@@ -497,7 +518,7 @@ func orderstmt(n *Node, order *Order) {
                case OAS2, OAS2DOTTYPE:
                        ordermapassign(n, order)
                default:
-                       order.out = list(order.out, n)
+                       order.out = append(order.out, n)
                }
                cleantemp(t, order)
 
@@ -561,11 +582,11 @@ func orderstmt(n *Node, order *Order) {
                orderexprlist(n.List, order)
                orderexpr(&n.Rlist.N.Left, order, nil) // i in i.(T)
                if isblank(n.List.N) {
-                       order.out = list(order.out, n)
+                       order.out = append(order.out, n)
                } else {
                        typ := n.Rlist.N.Type
                        tmp1 := ordertemp(typ, order, haspointers(typ))
-                       order.out = list(order.out, n)
+                       order.out = append(order.out, n)
                        r := Nod(OAS, n.List.N, tmp1)
                        typecheck(&r, Etop)
                        ordermapassign(r, order)
@@ -589,7 +610,7 @@ func orderstmt(n *Node, order *Order) {
                } else {
                        tmp2 = ordertemp(Types[TBOOL], order, false)
                }
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
                r := Nod(OAS, n.List.N, tmp1)
                typecheck(&r, Etop)
                ordermapassign(r, order)
@@ -614,14 +635,14 @@ func orderstmt(n *Node, order *Order) {
                OGOTO,
                OLABEL,
                ORETJMP:
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
 
                // Special: handle call arguments.
        case OCALLFUNC, OCALLINTER, OCALLMETH:
                t := marktemp(order)
 
                ordercall(n, order)
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
                cleantemp(t, order)
 
                // Special: order arguments to inner call but not call itself.
@@ -644,7 +665,7 @@ func orderstmt(n *Node, order *Order) {
                        ordercall(n.Left, order)
                }
 
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
                cleantemp(t, order)
 
        case ODELETE:
@@ -652,7 +673,7 @@ func orderstmt(n *Node, order *Order) {
                orderexpr(&n.List.N, order, nil)
                orderexpr(&n.List.Next.N, order, nil)
                orderaddrtemp(&n.List.Next.N, order) // map key
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
                cleantemp(t, order)
 
                // Clean temporaries from condition evaluation at
@@ -661,12 +682,12 @@ func orderstmt(n *Node, order *Order) {
                t := marktemp(order)
 
                orderexprinplace(&n.Left, order)
-               var l *NodeList
+               var l []*Node
                cleantempnopop(t, order, &l)
-               n.Nbody = concat(l, n.Nbody)
-               orderblock(&n.Nbody)
+               n.Nbody.Set(append(l, n.Nbody.Slice()...))
+               orderblockNodes(&n.Nbody)
                orderstmtinplace(&n.Right)
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
                cleantemp(t, order)
 
                // Clean temporaries from condition at
@@ -675,16 +696,20 @@ func orderstmt(n *Node, order *Order) {
                t := marktemp(order)
 
                orderexprinplace(&n.Left, order)
-               var l *NodeList
+               var l []*Node
                cleantempnopop(t, order, &l)
-               n.Nbody = concat(l, n.Nbody)
+               n.Nbody.Set(append(l, n.Nbody.Slice()...))
                l = nil
                cleantempnopop(t, order, &l)
-               n.Rlist = concat(l, n.Rlist)
+               var ll *NodeList
+               for _, n := range l {
+                       ll = list(ll, n)
+               }
+               n.Rlist = concat(ll, n.Rlist)
                poptemp(t, order)
-               orderblock(&n.Nbody)
+               orderblockNodes(&n.Nbody)
                orderblock(&n.Rlist)
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
 
                // Special: argument will be converted to interface using convT2E
        // so make sure it is an addressable temporary.
@@ -695,7 +720,7 @@ func orderstmt(n *Node, order *Order) {
                if !Isinter(n.Left.Type) {
                        orderaddrtemp(&n.Left, order)
                }
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
                cleantemp(t, order)
 
                // n->right is the expression being ranged over.
@@ -756,13 +781,13 @@ func orderstmt(n *Node, order *Order) {
                for l := n.List; l != nil; l = l.Next {
                        orderexprinplace(&l.N, order)
                }
-               orderblock(&n.Nbody)
-               order.out = list(order.out, n)
+               orderblockNodes(&n.Nbody)
+               order.out = append(order.out, n)
                cleantemp(t, order)
 
        case ORETURN:
                ordercallargs(&n.List, order)
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
 
        // Special: clean case temporaries in each block entry.
        // Select must enter one of its blocks, so there is no
@@ -897,19 +922,23 @@ func orderstmt(n *Node, order *Order) {
                                }
                        }
 
-                       orderblock(&l.N.Nbody)
+                       orderblockNodes(&l.N.Nbody)
                }
 
                // Now that we have accumulated all the temporaries, clean them.
                // Also insert any ninit queued during the previous loop.
                // (The temporary cleaning must follow that ninit work.)
                for l := n.List; l != nil; l = l.Next {
-                       cleantempnopop(t, order, &l.N.Ninit)
-                       l.N.Nbody = concat(l.N.Ninit, l.N.Nbody)
+                       s := make([]*Node, 0, count(l.N.Ninit))
+                       for ll := l.N.Ninit; ll != nil; ll = ll.Next {
+                               s = append(s, ll.N)
+                       }
+                       cleantempnopop(t, order, &s)
+                       l.N.Nbody.Set(append(s, l.N.Nbody.Slice()...))
                        l.N.Ninit = nil
                }
 
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
                poptemp(t, order)
 
                // Special: value being sent is passed as a pointer; make it addressable.
@@ -919,7 +948,7 @@ func orderstmt(n *Node, order *Order) {
                orderexpr(&n.Left, order, nil)
                orderexpr(&n.Right, order, nil)
                orderaddrtemp(&n.Right, order)
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
                cleantemp(t, order)
 
                // TODO(rsc): Clean temporaries more aggressively.
@@ -938,10 +967,10 @@ func orderstmt(n *Node, order *Order) {
                                Fatalf("order switch case %v", Oconv(int(l.N.Op), 0))
                        }
                        orderexprlistinplace(l.N.List, order)
-                       orderblock(&l.N.Nbody)
+                       orderblockNodes(&l.N.Nbody)
                }
 
-               order.out = list(order.out, n)
+               order.out = append(order.out, n)
                cleantemp(t, order)
        }
 
@@ -1080,9 +1109,13 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
                // Clean temporaries from first branch at beginning of second.
                // Leave them on the stack so that they can be killed in the outer
                // context in case the short circuit is taken.
-               var l *NodeList
+               var s []*Node
 
-               cleantempnopop(mark, order, &l)
+               cleantempnopop(mark, order, &s)
+               var l *NodeList
+               for _, n := range s {
+                       l = list(l, n)
+               }
                n.Right.Ninit = concat(l, n.Right.Ninit)
                orderexprinplace(&n.Right, order)
 
index 621be57b5008ddd6034d44a3868601b703a26ddf..c8dbcc56b1d38f2b5eda9cef57e6f89debdafd31 100644 (file)
@@ -858,7 +858,7 @@ func (p *parser) caseblock(tswitch *Node) *Node {
 
        stmt := p.case_(tswitch) // does markdcl
        stmt.Xoffset = int64(block)
-       stmt.Nbody = p.stmt_list()
+       stmt.Nbody.SetToNodeList(p.stmt_list())
 
        popdcl()
 
@@ -946,7 +946,7 @@ func (p *parser) for_body() *Node {
        stmt := p.for_header()
        body := p.loop_body("for clause")
 
-       stmt.Nbody = concat(stmt.Nbody, body)
+       stmt.Nbody.AppendNodeList(body)
        return stmt
 }
 
@@ -1043,7 +1043,7 @@ func (p *parser) if_stmt() *Node {
                Yyerror("missing condition in if statement")
        }
 
-       stmt.Nbody = p.loop_body("if clause")
+       stmt.Nbody.SetToNodeList(p.loop_body("if clause"))
 
        if p.got(LELSE) {
                if p.tok == LIF {
@@ -1858,7 +1858,7 @@ func (p *parser) xfndcl() *Node {
                return nil
        }
 
-       f.Nbody = body
+       f.Nbody.SetToNodeList(body)
        f.Noescape = p.pragma&Noescape != 0
        if f.Noescape && body != nil {
                Yyerror("can only use //go:noescape with external func implementations")
@@ -2079,7 +2079,7 @@ loop:
                        l = list(l, p.xfndcl())
 
                default:
-                       if p.tok == '{' && l != nil && l.End.N.Op == ODCLFUNC && l.End.N.Nbody == nil {
+                       if p.tok == '{' && l != nil && l.End.N.Op == ODCLFUNC && len(l.End.N.Nbody.Slice()) == 0 {
                                // opening { of function declaration on next line
                                p.syntax_error("unexpected semicolon or newline before {")
                        } else {
@@ -2835,14 +2835,14 @@ func (p *parser) hidden_import() {
                        return
                }
 
-               s2.Func.Inl = s3
+               s2.Func.Inl.SetToNodeList(s3)
 
                funcbody(s2)
                importlist = append(importlist, s2)
 
                if Debug['E'] > 0 {
                        fmt.Printf("import [%q] func %v \n", importpkg.Path, s2)
-                       if Debug['m'] > 2 && s2.Func.Inl != nil {
+                       if Debug['m'] > 2 && len(s2.Func.Inl.Slice()) != 0 {
                                fmt.Printf("inl body:%v\n", s2.Func.Inl)
                        }
                }
index 6c5fb2d35bb0efa9c510b5c51b04d7fcb7e3ea02..31cc3bcf3942bd467d9548325ea29e58587f8229 100644 (file)
@@ -358,7 +358,7 @@ func compile(fn *Node) {
        var nam *Node
        var gcargs *Sym
        var gclocals *Sym
-       if fn.Nbody == nil {
+       if len(fn.Nbody.Slice()) == 0 {
                if pure_go != 0 || strings.HasPrefix(fn.Func.Nname.Sym.Name, "init.") {
                        Yyerror("missing function body for %q", fn.Func.Nname.Sym.Name)
                        goto ret
@@ -385,7 +385,7 @@ func compile(fn *Node) {
                        if t.Nname != nil {
                                n = Nod(OAS, t.Nname, nil)
                                typecheck(&n, Etop)
-                               Curfn.Nbody = concat(list1(n), Curfn.Nbody)
+                               Curfn.Nbody.Set(append([]*Node{n}, Curfn.Nbody.Slice()...))
                        }
 
                        t = structnext(&save)
@@ -472,7 +472,7 @@ func compile(fn *Node) {
        }
 
        Genslice(Curfn.Func.Enter.Slice())
-       Genlist(Curfn.Nbody)
+       Genslice(Curfn.Nbody.Slice())
        gclean()
        checklabels()
        if nerrors != 0 {
index d1f6cefec52a6984db49baba3e16ff00515d94d4..352a399ed888baf3b83242f63967e23ce63d7a28 100644 (file)
@@ -55,7 +55,7 @@ func instrument(fn *Node) {
        }
 
        if flag_race == 0 || !ispkgin(norace_inst_pkgs) {
-               instrumentlist(fn.Nbody, nil)
+               instrumentslice(fn.Nbody.Slice(), nil)
 
                // nothing interesting for race detector in fn->enter
                instrumentslice(fn.Func.Exit.Slice(), nil)
@@ -78,7 +78,7 @@ func instrument(fn *Node) {
 
        if Debug['W'] != 0 {
                s := fmt.Sprintf("after instrument %v", fn.Func.Nname.Sym)
-               dumplist(s, fn.Nbody)
+               dumpslice(s, fn.Nbody.Slice())
                s = fmt.Sprintf("enter %v", fn.Func.Nname.Sym)
                dumpslice(s, fn.Func.Enter.Slice())
                s = fmt.Sprintf("exit %v", fn.Func.Nname.Sym)
@@ -439,7 +439,7 @@ ret:
        if n.Op != OBLOCK { // OBLOCK is handled above in a special way.
                instrumentlist(n.List, init)
        }
-       instrumentlist(n.Nbody, nil)
+       instrumentslice(n.Nbody.Slice(), nil)
        instrumentlist(n.Rlist, nil)
        *np = n
 }
@@ -612,12 +612,18 @@ func foreachlist(l *NodeList, f func(*Node, interface{}), c interface{}) {
        }
 }
 
+func foreachslice(l []*Node, f func(*Node, interface{}), c interface{}) {
+       for _, n := range l {
+               foreachnode(n, f, c)
+       }
+}
+
 func foreach(n *Node, f func(*Node, interface{}), c interface{}) {
        foreachlist(n.Ninit, f, c)
        foreachnode(n.Left, f, c)
        foreachnode(n.Right, f, c)
        foreachlist(n.List, f, c)
-       foreachlist(n.Nbody, f, c)
+       foreachslice(n.Nbody.Slice(), f, c)
        foreachlist(n.Rlist, f, c)
 }
 
index 4386bcfeed27af92732a4e708695faed34dab49b..2270d71621e689d695b4ea01d56f2f767ee49dfc 100644 (file)
@@ -128,7 +128,7 @@ out:
        }
 
        decldepth++
-       typechecklist(n.Nbody, Etop)
+       typecheckslice(n.Nbody.Slice(), Etop)
        decldepth--
 }
 
@@ -159,7 +159,7 @@ func walkrange(n *Node) {
        // to avoid erroneous processing by racewalk.
        n.List = nil
 
-       var body *NodeList
+       var body []*Node
        var init *NodeList
        switch t.Etype {
        default:
@@ -192,12 +192,12 @@ func walkrange(n *Node) {
                if v1 == nil {
                        body = nil
                } else if v2 == nil {
-                       body = list1(Nod(OAS, v1, hv1))
+                       body = []*Node{Nod(OAS, v1, hv1)}
                } else {
                        a := Nod(OAS2, nil, nil)
                        a.List = list(list1(v1), v2)
                        a.Rlist = list(list1(hv1), Nod(OIND, hp, nil))
-                       body = list1(a)
+                       body = []*Node{a}
 
                        // Advance pointer as part of increment.
                        // We used to advance the pointer before executing the loop body,
@@ -245,14 +245,14 @@ func walkrange(n *Node) {
                if v1 == nil {
                        body = nil
                } else if v2 == nil {
-                       body = list1(Nod(OAS, v1, key))
+                       body = []*Node{Nod(OAS, v1, key)}
                } else {
                        val := Nod(ODOT, hit, valname)
                        val = Nod(OIND, val, nil)
                        a := Nod(OAS2, nil, nil)
                        a.List = list(list1(v1), v2)
                        a.Rlist = list(list1(key), val)
-                       body = list1(a)
+                       body = []*Node{a}
                }
 
                // orderstmt arranged for a copy of the channel variable.
@@ -277,7 +277,7 @@ func walkrange(n *Node) {
                if v1 == nil {
                        body = nil
                } else {
-                       body = list1(Nod(OAS, v1, hv1))
+                       body = []*Node{Nod(OAS, v1, hv1)}
                }
 
                // orderstmt arranged for a copy of the string variable.
@@ -306,10 +306,10 @@ func walkrange(n *Node) {
 
                body = nil
                if v1 != nil {
-                       body = list1(Nod(OAS, v1, ohv1))
+                       body = []*Node{Nod(OAS, v1, ohv1)}
                }
                if v2 != nil {
-                       body = list(body, Nod(OAS, v2, hv2))
+                       body = append(body, Nod(OAS, v2, hv2))
                }
        }
 
@@ -319,8 +319,8 @@ func walkrange(n *Node) {
        typechecklist(n.Left.Ninit, Etop)
        typecheck(&n.Left, Erv)
        typecheck(&n.Right, Etop)
-       typechecklist(body, Etop)
-       n.Nbody = concat(body, n.Nbody)
+       typecheckslice(body, Etop)
+       n.Nbody.Set(append(body, n.Nbody.Slice()...))
        walkstmt(&n)
 
        lineno = int32(lno)
@@ -344,10 +344,10 @@ func memclrrange(n, v1, v2, a *Node) bool {
        if v1 == nil || v2 != nil {
                return false
        }
-       if n.Nbody == nil || n.Nbody.N == nil || n.Nbody.Next != nil {
+       if len(n.Nbody.Slice()) == 0 || n.Nbody.Slice()[0] == nil || len(n.Nbody.Slice()) > 1 {
                return false
        }
-       stmt := n.Nbody.N // only stmt in body
+       stmt := n.Nbody.Slice()[0] // only stmt in body
        if stmt.Op != OAS || stmt.Left.Op != OINDEX {
                return false
        }
@@ -368,7 +368,7 @@ func memclrrange(n, v1, v2, a *Node) bool {
        // }
        n.Op = OIF
 
-       n.Nbody = nil
+       n.Nbody.Set(nil)
        n.Left = Nod(ONE, Nod(OLEN, a, nil), Nodintconst(0))
 
        // hp = &a[0]
@@ -379,7 +379,7 @@ func memclrrange(n, v1, v2, a *Node) bool {
        tmp = Nod(OADDR, tmp, nil)
        tmp = Nod(OCONVNOP, tmp, nil)
        tmp.Type = Ptrto(Types[TUINT8])
-       n.Nbody = list(n.Nbody, Nod(OAS, hp, tmp))
+       n.Nbody.Append(Nod(OAS, hp, tmp))
 
        // hn = len(a) * sizeof(elem(a))
        hn := temp(Types[TUINTPTR])
@@ -387,20 +387,20 @@ func memclrrange(n, v1, v2, a *Node) bool {
        tmp = Nod(OLEN, a, nil)
        tmp = Nod(OMUL, tmp, Nodintconst(elemsize))
        tmp = conv(tmp, Types[TUINTPTR])
-       n.Nbody = list(n.Nbody, Nod(OAS, hn, tmp))
+       n.Nbody.Append(Nod(OAS, hn, tmp))
 
        // memclr(hp, hn)
        fn := mkcall("memclr", nil, nil, hp, hn)
 
-       n.Nbody = list(n.Nbody, fn)
+       n.Nbody.Append(fn)
 
        // i = len(a) - 1
        v1 = Nod(OAS, v1, Nod(OSUB, Nod(OLEN, a, nil), Nodintconst(1)))
 
-       n.Nbody = list(n.Nbody, v1)
+       n.Nbody.Append(v1)
 
        typecheck(&n.Left, Erv)
-       typechecklist(n.Nbody, Etop)
+       typecheckslice(n.Nbody.Slice(), Etop)
        walkstmt(&n)
        return true
 }
index e770c8f18d5102b86af6a28376ab02bda028d2f2..02439475002be291ad832066a15ee5614ac00ed8 100644 (file)
@@ -79,7 +79,7 @@ func typecheckselect(sel *Node) {
                        }
                }
 
-               typechecklist(ncase.Nbody, Etop)
+               typecheckslice(ncase.Nbody.Slice(), Etop)
        }
 
        sel.Xoffset = int64(count)
@@ -95,14 +95,14 @@ func walkselect(sel *Node) {
        i := count(sel.List)
 
        // optimization: zero-case select
-       var init *NodeList
+       var init []*Node
        var r *Node
        var n *Node
        var var_ *Node
        var selv *Node
        var cas *Node
        if i == 0 {
-               sel.Nbody = list1(mkcall("block", nil, nil))
+               sel.Nbody.Set([]*Node{mkcall("block", nil, nil)})
                goto out
        }
 
@@ -155,14 +155,18 @@ func walkselect(sel *Node) {
                        a := Nod(OIF, nil, nil)
 
                        a.Left = Nod(OEQ, ch, nodnil())
-                       a.Nbody = list1(mkcall("block", nil, &l))
+                       a.Nbody.Set([]*Node{mkcall("block", nil, &l)})
                        typecheck(&a, Etop)
                        l = list(l, a)
                        l = list(l, n)
                }
 
-               l = concat(l, cas.Nbody)
-               sel.Nbody = l
+               s := make([]*Node, 0, count(l))
+               for ll := l; ll != nil; ll = ll.Next {
+                       s = append(s, ll.N)
+               }
+               s = append(s, cas.Nbody.Slice()...)
+               sel.Nbody.Set(s)
                goto out
        }
 
@@ -242,13 +246,16 @@ func walkselect(sel *Node) {
                }
 
                typecheck(&r.Left, Erv)
-               r.Nbody = cas.Nbody
-               r.Rlist = concat(dflt.Ninit, dflt.Nbody)
-               sel.Nbody = list1(r)
+               r.Nbody.Set(cas.Nbody.Slice())
+               r.Rlist = concat(dflt.Ninit, dflt.Nbody.NodeList())
+               sel.Nbody.Set([]*Node{r})
                goto out
        }
 
-       init = sel.Ninit
+       init = make([]*Node, 0, count(sel.Ninit))
+       for ll := sel.Ninit; ll != nil; ll = ll.Next {
+               init = append(init, ll.N)
+       }
        sel.Ninit = nil
 
        // generate sel-struct
@@ -257,11 +264,11 @@ func walkselect(sel *Node) {
        selv = temp(selecttype(int32(sel.Xoffset)))
        r = Nod(OAS, selv, nil)
        typecheck(&r, Etop)
-       init = list(init, r)
+       init = append(init, r)
        var_ = conv(conv(Nod(OADDR, selv, nil), Types[TUNSAFEPTR]), Ptrto(Types[TUINT8]))
        r = mkcall("newselect", nil, nil, var_, Nodintconst(selv.Type.Width), Nodintconst(sel.Xoffset))
        typecheck(&r, Etop)
-       init = list(init, r)
+       init = append(init, r)
 
        // register cases
        for l := sel.List; l != nil; l = l.Next {
@@ -299,22 +306,22 @@ func walkselect(sel *Node) {
                }
 
                // selv is no longer alive after use.
-               r.Nbody = list(r.Nbody, Nod(OVARKILL, selv, nil))
+               r.Nbody.Append(Nod(OVARKILL, selv, nil))
 
-               r.Nbody = concat(r.Nbody, cas.Nbody)
-               r.Nbody = list(r.Nbody, Nod(OBREAK, nil, nil))
-               init = list(init, r)
+               r.Nbody.Append(cas.Nbody.Slice()...)
+               r.Nbody.Append(Nod(OBREAK, nil, nil))
+               init = append(init, r)
        }
 
        // run the select
        setlineno(sel)
 
-       init = list(init, mkcall("selectgo", nil, nil, var_))
-       sel.Nbody = init
+       init = append(init, mkcall("selectgo", nil, nil, var_))
+       sel.Nbody.Set(init)
 
 out:
        sel.List = nil
-       walkstmtlist(sel.Nbody)
+       walkstmtslice(sel.Nbody.Slice())
        lineno = int32(lno)
 }
 
index f149c2cd74771ad21bca208f3b291b7f7fce70a4..c6647cc7f56310d838f4055b80b23eeaef816a5e 100644 (file)
@@ -24,7 +24,7 @@ var (
 
 // init1 walks the AST starting at n, and accumulates in out
 // the list of definitions needing init code in dependency order.
-func init1(n *Node, out **NodeList) {
+func init1(n *Node, out *[]*Node) {
        if n == nil {
                return
        }
@@ -98,7 +98,7 @@ func init1(n *Node, out **NodeList) {
                        Fatalf("init1: bad defn")
 
                case ODCLFUNC:
-                       init2list(defn.Nbody, out)
+                       init2slice(defn.Nbody.Slice(), out)
 
                case OAS:
                        if defn.Left != n {
@@ -120,7 +120,7 @@ func init1(n *Node, out **NodeList) {
                                if Debug['%'] != 0 {
                                        Dump("nonstatic", defn)
                                }
-                               *out = list(*out, defn)
+                               *out = append(*out, defn)
                        }
 
                case OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV:
@@ -134,7 +134,7 @@ func init1(n *Node, out **NodeList) {
                        if Debug['%'] != 0 {
                                Dump("nonstatic", defn)
                        }
-                       *out = list(*out, defn)
+                       *out = append(*out, defn)
                        defn.Initorder = InitDone
                }
        }
@@ -187,7 +187,7 @@ func foundinitloop(node, visited *Node) {
 }
 
 // recurse over n, doing init1 everywhere.
-func init2(n *Node, out **NodeList) {
+func init2(n *Node, out *[]*Node) {
        if n == nil || n.Initorder == InitDone {
                return
        }
@@ -202,23 +202,29 @@ func init2(n *Node, out **NodeList) {
        init2list(n.Ninit, out)
        init2list(n.List, out)
        init2list(n.Rlist, out)
-       init2list(n.Nbody, out)
+       init2slice(n.Nbody.Slice(), out)
 
        if n.Op == OCLOSURE {
-               init2list(n.Func.Closure.Nbody, out)
+               init2slice(n.Func.Closure.Nbody.Slice(), out)
        }
        if n.Op == ODOTMETH || n.Op == OCALLPART {
                init2(n.Type.Nname, out)
        }
 }
 
-func init2list(l *NodeList, out **NodeList) {
+func init2list(l *NodeList, out *[]*Node) {
        for ; l != nil; l = l.Next {
                init2(l.N, out)
        }
 }
 
-func initreorder(l *NodeList, out **NodeList) {
+func init2slice(l []*Node, out *[]*Node) {
+       for _, n := range l {
+               init2(n, out)
+       }
+}
+
+func initreorder(l *NodeList, out *[]*Node) {
        var n *Node
 
        for ; l != nil; l = l.Next {
@@ -237,8 +243,8 @@ func initreorder(l *NodeList, out **NodeList) {
 // initfix computes initialization order for a list l of top-level
 // declarations and outputs the corresponding list of statements
 // to include in the init() function body.
-func initfix(l *NodeList) *NodeList {
-       var lout *NodeList
+func initfix(l *NodeList) []*Node {
+       var lout []*Node
        initplans = make(map[*Node]*InitPlan)
        lno := int(lineno)
        initreorder(l, &lout)
@@ -249,7 +255,7 @@ func initfix(l *NodeList) *NodeList {
 
 // compilation of top-level (static) assignments
 // into DATA statements if at all possible.
-func staticinit(n *Node, out **NodeList) bool {
+func staticinit(n *Node, out *[]*Node) bool {
        if n.Op != ONAME || n.Class != PEXTERN || n.Name.Defn == nil || n.Name.Defn.Op != OAS {
                Fatalf("staticinit")
        }
@@ -262,7 +268,7 @@ func staticinit(n *Node, out **NodeList) bool {
 
 // like staticassign but we are copying an already
 // initialized value r.
-func staticcopy(l *Node, r *Node, out **NodeList) bool {
+func staticcopy(l *Node, r *Node, out *[]*Node) bool {
        if r.Op != ONAME {
                return false
        }
@@ -291,7 +297,7 @@ func staticcopy(l *Node, r *Node, out **NodeList) bool {
                if staticcopy(l, r, out) {
                        return true
                }
-               *out = list(*out, Nod(OAS, l, r))
+               *out = append(*out, Nod(OAS, l, r))
                return true
 
        case OLITERAL:
@@ -362,7 +368,7 @@ func staticcopy(l *Node, r *Node, out **NodeList) bool {
                                        rr.Type = ll.Type
                                        rr.Xoffset += e.Xoffset
                                        setlineno(rr)
-                                       *out = list(*out, Nod(OAS, ll, rr))
+                                       *out = append(*out, Nod(OAS, ll, rr))
                                }
                        }
                }
@@ -373,7 +379,7 @@ func staticcopy(l *Node, r *Node, out **NodeList) bool {
        return false
 }
 
-func staticassign(l *Node, r *Node, out **NodeList) bool {
+func staticassign(l *Node, r *Node, out *[]*Node) bool {
        for r.Op == OCONVNOP {
                r = r.Left
        }
@@ -410,7 +416,7 @@ func staticassign(l *Node, r *Node, out **NodeList) bool {
 
                        // Init underlying literal.
                        if !staticassign(a, r.Left, out) {
-                               *out = list(*out, Nod(OAS, a, r.Left))
+                               *out = append(*out, Nod(OAS, a, r.Left))
                        }
                        return true
                }
@@ -463,7 +469,7 @@ func staticassign(l *Node, r *Node, out **NodeList) bool {
                                *a = n
                                a.Orig = a // completely separate copy
                                if !staticassign(a, e.Expr, out) {
-                                       *out = list(*out, Nod(OAS, a, e.Expr))
+                                       *out = append(*out, Nod(OAS, a, e.Expr))
                                }
                        }
                }
@@ -967,7 +973,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
                r = Nod(OAS, r, a)
 
                a = Nod(OFOR, nil, nil)
-               a.Nbody = list1(r)
+               a.Nbody.Set([]*Node{r})
 
                a.Ninit = list1(Nod(OAS, index, Nodintconst(0)))
                a.Left = Nod(OLT, index, Nodintconst(t.Bound))
index 6c558203d3d34f1c453753df10a5bdd38df20f95..204962ca85544e0c6b9e82d9454cd9af8b2b1b5d 100644 (file)
@@ -2170,8 +2170,8 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
                l = list(l, nodlit(v)) // method name
                call := Nod(OCALL, syslook("panicwrap", 0), nil)
                call.List = l
-               n.Nbody = list1(call)
-               fn.Nbody = list(fn.Nbody, n)
+               n.Nbody.Set([]*Node{call})
+               fn.Nbody.Append(n)
        }
 
        dot := adddot(Nod(OXDOT, this.Left, newname(method.Sym)))
@@ -2185,10 +2185,10 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
                }
                as := Nod(OAS, this.Left, Nod(OCONVNOP, dot, nil))
                as.Right.Type = rcvr
-               fn.Nbody = list(fn.Nbody, as)
+               fn.Nbody.Append(as)
                n := Nod(ORETJMP, nil, nil)
                n.Left = newname(methodsym(method.Sym, methodrcvr, 0))
-               fn.Nbody = list(fn.Nbody, n)
+               fn.Nbody.Append(n)
        } else {
                fn.Func.Wrapper = true // ignore frame for panic+recover matching
                call := Nod(OCALL, dot, nil)
@@ -2200,11 +2200,11 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
                        call = n
                }
 
-               fn.Nbody = list(fn.Nbody, call)
+               fn.Nbody.Append(call)
        }
 
        if false && Debug['r'] != 0 {
-               dumplist("genwrapper body", fn.Nbody)
+               dumpslice("genwrapper body", fn.Nbody.Slice())
        }
 
        funcbody(fn)
@@ -2215,7 +2215,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
                fn.Func.Dupok = true
        }
        typecheck(&fn, Etop)
-       typechecklist(fn.Nbody, Etop)
+       typecheckslice(fn.Nbody.Slice(), Etop)
 
        inlcalls(fn)
        escAnalyze([]*Node{fn}, false)
@@ -2394,6 +2394,14 @@ func liststmt(l *NodeList) *Node {
        return n
 }
 
+func liststmtslice(l []*Node) *Node {
+       var ll *NodeList
+       for _, n := range l {
+               ll = list(ll, n)
+       }
+       return liststmt(ll)
+}
+
 // return nelem of list
 func structcount(t *Type) int {
        var s Iter
@@ -2740,6 +2748,14 @@ func addinit(np **Node, init *NodeList) {
        n.Ullman = UINF
 }
 
+func addinitslice(np **Node, init []*Node) {
+       var l *NodeList
+       for _, n := range init {
+               l = list(l, n)
+       }
+       addinit(np, l)
+}
+
 var reservedimports = []string{
        "go",
        "type",
index 661b3ee5a9286222dcdbe30dd33bc7ae61465496..6e743492eb231eb84f27c8748f0935238d6e203d 100644 (file)
@@ -181,7 +181,7 @@ func typecheckswitch(n *Node) {
                        }
                }
 
-               typechecklist(ncase.Nbody, Etop)
+               typecheckslice(ncase.Nbody.Slice(), Etop)
        }
 
        lineno = int32(lno)
@@ -230,7 +230,7 @@ func (s *exprSwitch) walk(sw *Node) {
        }
 
        // convert the switch into OIF statements
-       var cas *NodeList
+       var cas []*Node
        if s.kind == switchKindTrue || s.kind == switchKindFalse {
                s.exprname = Nodbool(s.kind == switchKindTrue)
        } else if consttype(cond) >= 0 {
@@ -238,8 +238,8 @@ func (s *exprSwitch) walk(sw *Node) {
                s.exprname = cond
        } else {
                s.exprname = temp(cond.Type)
-               cas = list1(Nod(OAS, s.exprname, cond))
-               typechecklist(cas, Etop)
+               cas = []*Node{Nod(OAS, s.exprname, cond)}
+               typecheckslice(cas, Etop)
        }
 
        // enumerate the cases, and lop off the default case
@@ -258,7 +258,7 @@ func (s *exprSwitch) walk(sw *Node) {
                // deal with expressions one at a time
                if !okforcmp[t.Etype] || cc[0].typ != caseKindExprConst {
                        a := s.walkCases(cc[:1])
-                       cas = list(cas, a)
+                       cas = append(cas, a)
                        cc = cc[1:]
                        continue
                }
@@ -271,15 +271,15 @@ func (s *exprSwitch) walk(sw *Node) {
                // sort and compile constants
                sort.Sort(caseClauseByExpr(cc[:run]))
                a := s.walkCases(cc[:run])
-               cas = list(cas, a)
+               cas = append(cas, a)
                cc = cc[run:]
        }
 
        // handle default case
        if nerrors == 0 {
-               cas = list(cas, def)
-               sw.Nbody = concat(cas, sw.Nbody)
-               walkstmtlist(sw.Nbody)
+               cas = append(cas, def)
+               sw.Nbody.Set(append(cas, sw.Nbody.Slice()...))
+               walkstmtslice(sw.Nbody.Slice())
        }
 }
 
@@ -303,7 +303,7 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
                                a.Left = Nod(ONOT, n.Left, nil) // if !val
                                typecheck(&a.Left, Erv)
                        }
-                       a.Nbody = list1(n.Right) // goto l
+                       a.Nbody.Set([]*Node{n.Right}) // goto l
 
                        cas = list(cas, a)
                        lineno = int32(lno)
@@ -325,7 +325,7 @@ func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
                a.Left = le
        }
        typecheck(&a.Left, Erv)
-       a.Nbody = list1(s.walkCases(cc[:half]))
+       a.Nbody.Set([]*Node{s.walkCases(cc[:half])})
        a.Rlist = list1(s.walkCases(cc[half:]))
        return a
 }
@@ -340,9 +340,9 @@ func casebody(sw *Node, typeswvar *Node) {
 
        lno := setlineno(sw)
 
-       var cas *NodeList  // cases
-       var stat *NodeList // statements
-       var def *Node      // defaults
+       var cas *NodeList // cases
+       var stat []*Node  // statements
+       var def *Node     // defaults
        br := Nod(OBREAK, nil, nil)
 
        for l := sw.List; l != nil; l = l.Next {
@@ -377,17 +377,19 @@ func casebody(sw *Node, typeswvar *Node) {
                        }
                }
 
-               stat = list(stat, Nod(OLABEL, jmp.Left, nil))
+               stat = append(stat, Nod(OLABEL, jmp.Left, nil))
                if typeswvar != nil && needvar && n.Rlist != nil {
-                       l := list1(Nod(ODCL, n.Rlist.N, nil))
-                       l = list(l, Nod(OAS, n.Rlist.N, typeswvar))
-                       typechecklist(l, Etop)
-                       stat = concat(stat, l)
+                       l := []*Node{
+                               Nod(ODCL, n.Rlist.N, nil),
+                               Nod(OAS, n.Rlist.N, typeswvar),
+                       }
+                       typecheckslice(l, Etop)
+                       stat = append(stat, l...)
                }
-               stat = concat(stat, n.Nbody)
+               stat = append(stat, n.Nbody.Slice()...)
 
                // botch - shouldn't fall thru declaration
-               last := stat.End.N
+               last := stat[len(stat)-1]
                if last.Xoffset == n.Xoffset && last.Op == OXFALL {
                        if typeswvar != nil {
                                setlineno(last)
@@ -401,17 +403,17 @@ func casebody(sw *Node, typeswvar *Node) {
 
                        last.Op = OFALL
                } else {
-                       stat = list(stat, br)
+                       stat = append(stat, br)
                }
        }
 
-       stat = list(stat, br)
+       stat = append(stat, br)
        if def != nil {
                cas = list(cas, def)
        }
 
        sw.List = cas
-       sw.Nbody = stat
+       sw.Nbody.Set(stat)
        lineno = lno
 }
 
@@ -531,14 +533,14 @@ func (s *typeSwitch) walk(sw *Node) {
                return
        }
 
-       var cas *NodeList
+       var cas []*Node
 
        // predeclare temporary variables and the boolean var
        s.facename = temp(cond.Right.Type)
 
        a := Nod(OAS, s.facename, cond.Right)
        typecheck(&a, Etop)
-       cas = list(cas, a)
+       cas = append(cas, a)
 
        s.okname = temp(Types[TBOOL])
        typecheck(&s.okname, Erv)
@@ -579,18 +581,18 @@ func (s *typeSwitch) walk(sw *Node) {
        i.Left = Nod(OEQ, typ, nodnil())
        if typenil != nil {
                // Do explicit nil case right here.
-               i.Nbody = list1(typenil)
+               i.Nbody.Set([]*Node{typenil})
        } else {
                // Jump to default case.
                lbl := newCaseLabel()
-               i.Nbody = list1(Nod(OGOTO, lbl, nil))
+               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)
                def = blk
        }
        typecheck(&i.Left, Erv)
-       cas = list(cas, i)
+       cas = append(cas, i)
 
        if !isnilinter(cond.Right.Type) {
                // Load type from itab.
@@ -608,7 +610,7 @@ func (s *typeSwitch) walk(sw *Node) {
        h.Bounded = true                // guaranteed not to fault
        a = Nod(OAS, s.hashname, h)
        typecheck(&a, Etop)
-       cas = list(cas, a)
+       cas = append(cas, a)
 
        // insert type equality check into each case block
        for _, c := range cc {
@@ -625,7 +627,7 @@ func (s *typeSwitch) walk(sw *Node) {
        for len(cc) > 0 {
                if cc[0].typ != caseKindTypeConst {
                        n := cc[0].node
-                       cas = list(cas, n.Right)
+                       cas = append(cas, n.Right)
                        cc = cc[1:]
                        continue
                }
@@ -642,7 +644,7 @@ func (s *typeSwitch) walk(sw *Node) {
                if false {
                        for i := 0; i < run; i++ {
                                n := cc[i].node
-                               cas = list(cas, n.Right)
+                               cas = append(cas, n.Right)
                        }
                        continue
                }
@@ -659,16 +661,16 @@ func (s *typeSwitch) walk(sw *Node) {
                }
 
                // binary search among cases to narrow by hash
-               cas = list(cas, s.walkCases(cc[:ncase]))
+               cas = append(cas, s.walkCases(cc[:ncase]))
                cc = cc[ncase:]
        }
 
        // handle default case
        if nerrors == 0 {
-               cas = list(cas, def)
-               sw.Nbody = concat(cas, sw.Nbody)
+               cas = append(cas, def)
+               sw.Nbody.Set(append(cas, sw.Nbody.Slice()...))
                sw.List = nil
-               walkstmtlist(sw.Nbody)
+               walkstmtslice(sw.Nbody.Slice())
        }
 }
 
@@ -698,7 +700,7 @@ func (s *typeSwitch) typeone(t *Node) *Node {
 
        c := Nod(OIF, nil, nil)
        c.Left = s.okname
-       c.Nbody = list1(t.Right) // if ok { goto l }
+       c.Nbody.Set([]*Node{t.Right}) // if ok { goto l }
 
        return liststmt(list(init, c))
 }
@@ -715,7 +717,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
                        a := Nod(OIF, nil, nil)
                        a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash)))
                        typecheck(&a.Left, Erv)
-                       a.Nbody = list1(n.Right)
+                       a.Nbody.Set([]*Node{n.Right})
                        cas = list(cas, a)
                }
                return liststmt(cas)
@@ -726,7 +728,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
        a := Nod(OIF, nil, nil)
        a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
        typecheck(&a.Left, Erv)
-       a.Nbody = list1(s.walkCases(cc[:half]))
+       a.Nbody.Set([]*Node{s.walkCases(cc[:half])})
        a.Rlist = list1(s.walkCases(cc[half:]))
        return a
 }
index 7c34862a63114d91b2288b15ee7b37d035431d99..72944a749e78ba80e70bcf571654dfdfedd0e750 100644 (file)
@@ -16,7 +16,7 @@ type Node struct {
        Left  *Node
        Right *Node
        Ninit *NodeList
-       Nbody *NodeList
+       Nbody Nodes
        List  *NodeList
        Rlist *NodeList
 
@@ -164,7 +164,7 @@ type Func struct {
        FCurfn     *Node
        Nname      *Node
 
-       Inl     *NodeList // copy of the body for use in inlining
+       Inl     Nodes // copy of the body for use in inlining
        InlCost int32
        Depth   int32
 
@@ -503,7 +503,7 @@ func (n *Nodes) Slice() []*Node {
 
 // NodeList returns the entries in Nodes as a NodeList.
 // Changes to the NodeList entries (as in l.N = n) will *not* be
-// reflect in the Nodes.
+// reflected in the Nodes.
 // This wastes memory and should be used as little as possible.
 func (n *Nodes) NodeList() *NodeList {
        if n.slice == nil {
@@ -537,3 +537,23 @@ func (n *Nodes) Append(a ...*Node) {
                *n.slice = append(*n.slice, a...)
        }
 }
+
+// SetToNodeList sets Nodes to the contents of a NodeList.
+func (n *Nodes) SetToNodeList(l *NodeList) {
+       s := make([]*Node, 0, count(l))
+       for ; l != nil; l = l.Next {
+               s = append(s, l.N)
+       }
+       n.Set(s)
+}
+
+// AppendNodeList appends the contents of a NodeList.
+func (n *Nodes) AppendNodeList(l *NodeList) {
+       if n.slice == nil {
+               n.SetToNodeList(l)
+       } else {
+               for ; l != nil; l = l.Next {
+                       *n.slice = append(*n.slice, l.N)
+               }
+       }
+}
index 04455515e61e69a10c701c4b01e148df8b8c63f5..328859982a7afe3fa9c9cd50356379203f9235ff 100644 (file)
@@ -217,7 +217,7 @@ func callrecv(n *Node) bool {
                return true
        }
 
-       return callrecv(n.Left) || callrecv(n.Right) || callrecvlist(n.Ninit) || callrecvlist(n.Nbody) || callrecvlist(n.List) || callrecvlist(n.Rlist)
+       return callrecv(n.Left) || callrecv(n.Right) || callrecvlist(n.Ninit) || callrecvslice(n.Nbody.Slice()) || callrecvlist(n.List) || callrecvlist(n.Rlist)
 }
 
 func callrecvlist(l *NodeList) bool {
@@ -229,6 +229,15 @@ func callrecvlist(l *NodeList) bool {
        return false
 }
 
+func callrecvslice(l []*Node) bool {
+       for _, n := range l {
+               if callrecv(n) {
+                       return true
+               }
+       }
+       return false
+}
+
 // indexlit implements typechecking of untyped values as
 // array/slice indexes. It is equivalent to defaultlit
 // except for constants of numerical kind, which are acceptable
@@ -2064,7 +2073,7 @@ OpSwitch:
                        }
                }
                typecheck(&n.Right, Etop)
-               typechecklist(n.Nbody, Etop)
+               typecheckslice(n.Nbody.Slice(), Etop)
                decldepth--
                break OpSwitch
 
@@ -2078,7 +2087,7 @@ OpSwitch:
                                Yyerror("non-bool %v used as if condition", Nconv(n.Left, obj.FmtLong))
                        }
                }
-               typechecklist(n.Nbody, Etop)
+               typecheckslice(n.Nbody.Slice(), Etop)
                typechecklist(n.Rlist, Etop)
                break OpSwitch
 
@@ -2128,7 +2137,7 @@ OpSwitch:
        case OXCASE:
                ok |= Etop
                typechecklist(n.List, Erv)
-               typechecklist(n.Nbody, Etop)
+               typecheckslice(n.Nbody.Slice(), Etop)
                break OpSwitch
 
        case ODCLFUNC:
@@ -3871,7 +3880,7 @@ func markbreak(n *Node, implicit *Node) {
 
                markbreak(n.Right, implicit)
                markbreaklist(n.Ninit, implicit)
-               markbreaklist(n.Nbody, implicit)
+               markbreakslice(n.Nbody.Slice(), implicit)
                markbreaklist(n.List, implicit)
                markbreaklist(n.Rlist, implicit)
        }
@@ -3904,26 +3913,51 @@ func markbreaklist(l *NodeList, implicit *Node) {
        }
 }
 
-func isterminating(l *NodeList, top int) bool {
-       if l == nil {
-               return false
-       }
-       if top != 0 {
-               for l.Next != nil && l.N.Op != OLABEL {
-                       l = l.Next
+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] {
+                       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
+                               i++
+                               continue
+                       }
                }
-               markbreaklist(l, nil)
+
+               markbreak(n, implicit)
        }
+}
 
+// Isterminating returns whether the NodeList l ends with a
+// terminating statement.
+func (l *NodeList) isterminating() bool {
+       if l == nil {
+               return false
+       }
        for l.Next != nil {
                l = l.Next
        }
-       n := l.N
+       return l.N.isterminating()
+}
 
-       if n == nil {
+// Isterminating whether the Nodes list ends with a terminating
+// statement.
+func (l Nodes) isterminating() bool {
+       c := len(l.Slice())
+       if c == 0 {
                return false
        }
+       return l.Slice()[c-1].isterminating()
+}
 
+// Isterminating returns whether the node n, the last one in a
+// statement list, is a terminating statement.
+func (n *Node) isterminating() bool {
        switch n.Op {
        // NOTE: OLABEL is treated as a separate statement,
        // not a separate prefix, so skipping to the last statement
@@ -3931,7 +3965,7 @@ func isterminating(l *NodeList, top int) bool {
        // skipping over the label. No case OLABEL here.
 
        case OBLOCK:
-               return isterminating(n.List, 0)
+               return n.List.isterminating()
 
        case OGOTO,
                ORETURN,
@@ -3950,15 +3984,15 @@ func isterminating(l *NodeList, top int) bool {
                return true
 
        case OIF:
-               return isterminating(n.Nbody, 0) && isterminating(n.Rlist, 0)
+               return n.Nbody.isterminating() && n.Rlist.isterminating()
 
        case OSWITCH, OTYPESW, OSELECT:
                if n.Hasbreak {
                        return false
                }
                def := 0
-               for l = n.List; l != nil; l = l.Next {
-                       if !isterminating(l.N.Nbody, 0) {
+               for l := n.List; l != nil; l = l.Next {
+                       if !l.N.Nbody.isterminating() {
                                return false
                        }
                        if l.N.List == nil { // default
@@ -3976,8 +4010,9 @@ func isterminating(l *NodeList, top int) bool {
 }
 
 func checkreturn(fn *Node) {
-       if fn.Type.Outtuple != 0 && fn.Nbody != nil {
-               if !isterminating(fn.Nbody, 1) {
+       if fn.Type.Outtuple != 0 && len(fn.Nbody.Slice()) != 0 {
+               markbreakslice(fn.Nbody.Slice(), nil)
+               if !fn.Nbody.isterminating() {
                        yyerrorl(int(fn.Func.Endlineno), "missing return at end of function")
                }
        }
index 5e1db64df4dc5db786e97278f37f207e5f70d480..d0f942d8bcd77e694f74e653da02f55dcf76f141 100644 (file)
@@ -22,7 +22,7 @@ func walk(fn *Node) {
 
        if Debug['W'] != 0 {
                s := fmt.Sprintf("\nbefore %v", Curfn.Func.Nname.Sym)
-               dumplist(s, Curfn.Nbody)
+               dumpslice(s, Curfn.Nbody.Slice())
        }
 
        lno := int(lineno)
@@ -64,10 +64,10 @@ func walk(fn *Node) {
        if nerrors != 0 {
                return
        }
-       walkstmtlist(Curfn.Nbody)
+       walkstmtslice(Curfn.Nbody.Slice())
        if Debug['W'] != 0 {
                s := fmt.Sprintf("after walk %v", Curfn.Func.Nname.Sym)
-               dumplist(s, Curfn.Nbody)
+               dumpslice(s, Curfn.Nbody.Slice())
        }
 
        heapmoves()
@@ -264,11 +264,11 @@ func walkstmt(np **Node) {
                }
 
                walkstmt(&n.Right)
-               walkstmtlist(n.Nbody)
+               walkstmtslice(n.Nbody.Slice())
 
        case OIF:
                walkexpr(&n.Left, &n.Ninit)
-               walkstmtlist(n.Nbody)
+               walkstmtslice(n.Nbody.Slice())
                walkstmtlist(n.Rlist)
 
        case OPROC:
@@ -1009,7 +1009,7 @@ opswitch:
 
                                n2 := Nod(OIF, nil, nil)
                                n2.Left = Nod(OEQ, l, nodnil())
-                               n2.Nbody = list1(Nod(OAS, l, n1))
+                               n2.Nbody.Set([]*Node{Nod(OAS, l, n1)})
                                n2.Likely = -1
                                typecheck(&n2, Etop)
                                *init = list(*init, n2)
@@ -2814,7 +2814,7 @@ func appendslice(n *Node, init **NodeList) *Node {
        substArgTypes(fn, s.Type.Type, s.Type.Type)
 
        // s = growslice_n(T, s, n)
-       nif.Nbody = list1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nt)))
+       nif.Nbody.Set([]*Node{Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nt))})
 
        l = list(l, nif)
 
@@ -2944,7 +2944,7 @@ func walkappend(n *Node, init **NodeList, dst *Node) *Node {
        fn := syslook("growslice", 1) //   growslice(<type>, old []T, mincap int) (ret []T)
        substArgTypes(fn, ns.Type.Type, ns.Type.Type)
 
-       nx.Nbody = list1(Nod(OAS, ns, mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns, Nod(OADD, Nod(OLEN, ns, nil), na))))
+       nx.Nbody.Set([]*Node{Nod(OAS, ns, mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns, Nod(OADD, Nod(OLEN, ns, nil), na)))})
 
        l = list(l, nx)
 
@@ -3018,7 +3018,7 @@ func copyany(n *Node, init **NodeList, runtimecall bool) *Node {
        nif := Nod(OIF, nil, nil)
 
        nif.Left = Nod(OGT, nlen, Nod(OLEN, nr, nil))
-       nif.Nbody = list(nif.Nbody, Nod(OAS, nlen, Nod(OLEN, nr, nil)))
+       nif.Nbody.Append(Nod(OAS, nlen, Nod(OLEN, nr, nil)))
        l = list(l, nif)
 
        // Call memmove.
@@ -3804,6 +3804,15 @@ func candiscardlist(l *NodeList) bool {
        return true
 }
 
+func candiscardslice(l []*Node) bool {
+       for _, n := range l {
+               if !candiscard(n) {
+                       return false
+               }
+       }
+       return true
+}
+
 func candiscard(n *Node) bool {
        if n == nil {
                return true
@@ -3890,7 +3899,7 @@ func candiscard(n *Node) bool {
                return false
        }
 
-       if !candiscard(n.Left) || !candiscard(n.Right) || !candiscardlist(n.Ninit) || !candiscardlist(n.Nbody) || !candiscardlist(n.List) || !candiscardlist(n.Rlist) {
+       if !candiscard(n.Left) || !candiscard(n.Right) || !candiscardlist(n.Ninit) || !candiscardslice(n.Nbody.Slice()) || !candiscardlist(n.List) || !candiscardlist(n.Rlist) {
                return false
        }
 
@@ -3946,12 +3955,12 @@ func walkprintfunc(np **Node, init **NodeList) {
        typecheck(&a, Etop)
        walkstmt(&a)
 
-       fn.Nbody = list1(a)
+       fn.Nbody.Set([]*Node{a})
 
        funcbody(fn)
 
        typecheck(&fn, Etop)
-       typechecklist(fn.Nbody, Etop)
+       typecheckslice(fn.Nbody.Slice(), Etop)
        xtop = list(xtop, fn)
        Curfn = oldfn