Commit 1d5001af authored by Ian Lance Taylor's avatar Ian Lance Taylor

cmd/compile: change Node.Nbody, Func.Inl from *NodeList to Nodes

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