Commit 99b6b77e authored by Ian Lance Taylor's avatar Ian Lance Taylor

cmd/compile: convert inl.go to use nodeSeq

Passes toolstash -cmp.

Update #14473.

Change-Id: I60ef7cac553b346ca6b8cc7152cd184e59994b66
Reviewed-on: https://go-review.googlesource.com/20216
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent c0740fed
...@@ -141,7 +141,7 @@ func caninl(fn *Node) { ...@@ -141,7 +141,7 @@ func caninl(fn *Node) {
const maxBudget = 80 const maxBudget = 80
budget := maxBudget // allowed hairyness budget := maxBudget // allowed hairyness
if ishairyslice(fn.Nbody.Slice(), &budget) || budget < 0 { if ishairylist(fn.Nbody, &budget) || budget < 0 {
return return
} }
...@@ -149,8 +149,8 @@ func caninl(fn *Node) { ...@@ -149,8 +149,8 @@ func caninl(fn *Node) {
Curfn = fn Curfn = fn
fn.Func.Nname.Func.Inl.Set(fn.Nbody.Slice()) fn.Func.Nname.Func.Inl.Set(fn.Nbody.Slice())
fn.Nbody.Set(inlcopyslice(fn.Func.Nname.Func.Inl.Slice())) fn.Nbody.Set(inlcopylist(fn.Func.Nname.Func.Inl.Slice()))
inldcl := inlcopyslice(fn.Func.Nname.Name.Defn.Func.Dcl) inldcl := inlcopylist(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
} }
...@@ -170,18 +170,9 @@ func caninl(fn *Node) { ...@@ -170,18 +170,9 @@ func caninl(fn *Node) {
} }
// Look for anything we want to punt on. // Look for anything we want to punt on.
func ishairylist(ll *NodeList, budget *int) bool { func ishairylist(ll nodesOrNodeList, budget *int) bool {
for ; ll != nil; ll = ll.Next { for it := nodeSeqIterate(ll); !it.Done(); it.Next() {
if ishairy(ll.N, budget) { if ishairy(it.N(), budget) {
return true
}
}
return false
}
func ishairyslice(ll []*Node, budget *int) bool {
for _, n := range ll {
if ishairy(n, budget) {
return true return true
} }
} }
...@@ -248,18 +239,18 @@ func ishairy(n *Node, budget *int) bool { ...@@ -248,18 +239,18 @@ 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) || ishairyslice(n.Nbody.Slice(), 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)
} }
// Inlcopy and inlcopylist recursively copy the body of a function. // Inlcopy and inlcopylist recursively copy the body of a function.
// Any name-like node of non-local class is marked for re-export by adding it to // Any name-like node of non-local class is marked for re-export by adding it to
// the exportlist. // the exportlist.
func inlcopylist(ll *NodeList) *NodeList { func inlcopylist(ll nodesOrNodeList) []*Node {
var l *NodeList s := make([]*Node, 0, nodeSeqLen(ll))
for ; ll != nil; ll = ll.Next { for it := nodeSeqIterate(ll); !it.Done(); it.Next() {
l = list(l, inlcopy(ll.N)) s = append(s, inlcopy(it.N()))
} }
return l return s
} }
func inlcopy(n *Node) *Node { func inlcopy(n *Node) *Node {
...@@ -279,26 +270,14 @@ func inlcopy(n *Node) *Node { ...@@ -279,26 +270,14 @@ func inlcopy(n *Node) *Node {
} }
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) setNodeSeq(&m.List, inlcopylist(n.List))
m.Rlist = inlcopylist(n.Rlist) setNodeSeq(&m.Rlist, inlcopylist(n.Rlist))
m.Ninit = inlcopylist(n.Ninit) setNodeSeq(&m.Ninit, inlcopylist(n.Ninit))
m.Nbody.Set(inlcopyslice(n.Nbody.Slice())) m.Nbody.Set(inlcopylist(n.Nbody.Slice()))
return m return m
} }
// Inlcopyslice is like inlcopylist, but for a slice.
func inlcopyslice(ll []*Node) []*Node {
r := make([]*Node, 0, len(ll))
for _, ln := range ll {
c := inlcopy(ln)
if c != nil {
r = append(r, c)
}
}
return r
}
// Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any // Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
// calls made to inlineable functions. This is the external entry point. // calls made to inlineable functions. This is the external entry point.
func inlcalls(fn *Node) { func inlcalls(fn *Node) {
...@@ -316,17 +295,17 @@ func inlconv2stmt(n *Node) { ...@@ -316,17 +295,17 @@ func inlconv2stmt(n *Node) {
n.Op = OBLOCK n.Op = OBLOCK
// n->ninit stays // n->ninit stays
n.List = n.Nbody.NodeList() setNodeSeq(&n.List, n.Nbody)
n.Nbody.Set(nil) n.Nbody.Set(nil)
n.Rlist = nil setNodeSeq(&n.Rlist, nil)
} }
// Turn an OINLCALL into a single valued expression. // Turn an OINLCALL into a single valued expression.
func inlconv2expr(np **Node) { func inlconv2expr(np **Node) {
n := *np n := *np
r := n.Rlist.N r := nodeSeqFirst(n.Rlist)
addinit(&r, concat(n.Ninit, n.Nbody.NodeList())) addinit(&r, append(nodeSeqSlice(n.Ninit), n.Nbody.Slice()...))
*np = r *np = r
} }
...@@ -335,25 +314,19 @@ func inlconv2expr(np **Node) { ...@@ -335,25 +314,19 @@ func inlconv2expr(np **Node) {
// containing the inlined statements on the first list element so // containing the inlined statements on the first list element so
// order will be preserved Used in return, oas2func and call // order will be preserved Used in return, oas2func and call
// statements. // statements.
func inlconv2list(n *Node) *NodeList { func inlconv2list(n *Node) []*Node {
if n.Op != OINLCALL || n.Rlist == nil { if n.Op != OINLCALL || nodeSeqLen(n.Rlist) == 0 {
Fatalf("inlconv2list %v\n", Nconv(n, obj.FmtSign)) Fatalf("inlconv2list %v\n", Nconv(n, obj.FmtSign))
} }
l := n.Rlist s := nodeSeqSlice(n.Rlist)
addinit(&l.N, concat(n.Ninit, n.Nbody.NodeList())) addinit(&s[0], append(nodeSeqSlice(n.Ninit), n.Nbody.Slice()...))
return l return s
} }
func inlnodelist(l *NodeList) { func inlnodelist(l nodesOrNodeList) {
for ; l != nil; l = l.Next { for it := nodeSeqIterate(l); !it.Done(); it.Next() {
inlnode(&l.N) inlnode(it.P())
}
}
func inlnodeslice(l []*Node) {
for i := range l {
inlnode(&l[i])
} }
} }
...@@ -394,9 +367,9 @@ func inlnode(np **Node) { ...@@ -394,9 +367,9 @@ func inlnode(np **Node) {
lno := setlineno(n) lno := setlineno(n)
inlnodelist(n.Ninit) inlnodelist(n.Ninit)
for l := n.Ninit; l != nil; l = l.Next { for it := nodeSeqIterate(n.Ninit); !it.Done(); it.Next() {
if l.N.Op == OINLCALL { if it.N().Op == OINLCALL {
inlconv2stmt(l.N) inlconv2stmt(it.N())
} }
} }
...@@ -417,9 +390,9 @@ func inlnode(np **Node) { ...@@ -417,9 +390,9 @@ func inlnode(np **Node) {
inlnodelist(n.List) inlnodelist(n.List)
switch n.Op { switch n.Op {
case OBLOCK: case OBLOCK:
for l := n.List; l != nil; l = l.Next { for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
if l.N.Op == OINLCALL { if it.N().Op == OINLCALL {
inlconv2stmt(l.N) inlconv2stmt(it.N())
} }
} }
...@@ -431,16 +404,16 @@ func inlnode(np **Node) { ...@@ -431,16 +404,16 @@ func inlnode(np **Node) {
OCALLINTER, OCALLINTER,
OAPPEND, OAPPEND,
OCOMPLEX: OCOMPLEX:
if count(n.List) == 1 && n.List.N.Op == OINLCALL && count(n.List.N.Rlist) > 1 { if nodeSeqLen(n.List) == 1 && nodeSeqFirst(n.List).Op == OINLCALL && nodeSeqLen(nodeSeqFirst(n.List).Rlist) > 1 {
n.List = inlconv2list(n.List.N) setNodeSeq(&n.List, inlconv2list(nodeSeqFirst(n.List)))
break break
} }
fallthrough fallthrough
default: default:
for l := n.List; l != nil; l = l.Next { for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
if l.N.Op == OINLCALL { if it.N().Op == OINLCALL {
inlconv2expr(&l.N) inlconv2expr(it.P())
} }
} }
} }
...@@ -448,8 +421,8 @@ func inlnode(np **Node) { ...@@ -448,8 +421,8 @@ func inlnode(np **Node) {
inlnodelist(n.Rlist) inlnodelist(n.Rlist)
switch n.Op { switch n.Op {
case OAS2FUNC: case OAS2FUNC:
if n.Rlist.N.Op == OINLCALL { if nodeSeqFirst(n.Rlist).Op == OINLCALL {
n.Rlist = inlconv2list(n.Rlist.N) setNodeSeq(&n.Rlist, inlconv2list(nodeSeqFirst(n.Rlist)))
n.Op = OAS2 n.Op = OAS2
n.Typecheck = 0 n.Typecheck = 0
typecheck(np, Etop) typecheck(np, Etop)
...@@ -458,18 +431,18 @@ func inlnode(np **Node) { ...@@ -458,18 +431,18 @@ func inlnode(np **Node) {
fallthrough fallthrough
default: default:
for l := n.Rlist; l != nil; l = l.Next { for it := nodeSeqIterate(n.Rlist); !it.Done(); it.Next() {
if l.N.Op == OINLCALL { if it.N().Op == OINLCALL {
if n.Op == OIF { if n.Op == OIF {
inlconv2stmt(l.N) inlconv2stmt(it.N())
} else { } else {
inlconv2expr(&l.N) inlconv2expr(it.P())
} }
} }
} }
} }
inlnodeslice(n.Nbody.Slice()) inlnodelist(n.Nbody)
for _, n := range n.Nbody.Slice() { for _, n := range n.Nbody.Slice() {
if n.Op == OINLCALL { if n.Op == OINLCALL {
inlconv2stmt(n) inlconv2stmt(n)
...@@ -612,7 +585,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -612,7 +585,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
typecheck(&ln.Name.Inlvar, Erv) typecheck(&ln.Name.Inlvar, Erv)
if ln.Class&^PHEAP != PAUTO { if ln.Class&^PHEAP != PAUTO {
ninit = list(ninit, Nod(ODCL, ln.Name.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs appendNodeSeqNode(&ninit, Nod(ODCL, ln.Name.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs
} }
} }
} }
...@@ -630,7 +603,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -630,7 +603,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
i++ i++
} }
ninit = list(ninit, Nod(ODCL, m, nil)) appendNodeSeqNode(&ninit, Nod(ODCL, m, nil))
inlretvars = list(inlretvars, m) inlretvars = list(inlretvars, m)
} }
...@@ -652,7 +625,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -652,7 +625,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
as = Nod(OAS, tinlvar(t), n.Left.Left) as = Nod(OAS, tinlvar(t), n.Left.Left)
if as != nil { if as != nil {
typecheck(&as, Etop) typecheck(&as, Etop)
ninit = list(ninit, as) appendNodeSeqNode(&ninit, as)
} }
} }
...@@ -676,17 +649,17 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -676,17 +649,17 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
// check if argument is actually a returned tuple from call. // check if argument is actually a returned tuple from call.
multiret := 0 multiret := 0
if n.List != nil && n.List.Next == nil { if nodeSeqLen(n.List) == 1 {
switch n.List.N.Op { switch nodeSeqFirst(n.List).Op {
case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH: case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH:
if n.List.N.Left.Type.Outtuple > 1 { if nodeSeqFirst(n.List).Left.Type.Outtuple > 1 {
multiret = n.List.N.Left.Type.Outtuple - 1 multiret = nodeSeqFirst(n.List).Left.Type.Outtuple - 1
} }
} }
} }
if variadic { if variadic {
varargcount = count(n.List) + multiret varargcount = nodeSeqLen(n.List) + multiret
if n.Left.Op != ODOTMETH { if n.Left.Op != ODOTMETH {
varargcount -= fn.Type.Thistuple varargcount -= fn.Type.Thistuple
} }
...@@ -696,13 +669,13 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -696,13 +669,13 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
// assign arguments to the parameters' temp names // assign arguments to the parameters' temp names
as = Nod(OAS2, nil, nil) as = Nod(OAS2, nil, nil)
as.Rlist = n.List setNodeSeq(&as.Rlist, n.List)
ll := n.List ll := n.List
// TODO: if len(nlist) == 1 but multiple args, check that n->list->n is a call? // TODO: if len(nlist) == 1 but multiple args, check that n->list->n is a call?
if fn.Type.Thistuple != 0 && n.Left.Op != ODOTMETH { if fn.Type.Thistuple != 0 && n.Left.Op != ODOTMETH {
// non-method call to method // non-method call to method
if n.List == nil { if nodeSeqLen(n.List) == 0 {
Fatalf("non-method call to method without first arg: %v", Nconv(n, obj.FmtSign)) Fatalf("non-method call to method without first arg: %v", Nconv(n, obj.FmtSign))
} }
...@@ -715,15 +688,15 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -715,15 +688,15 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
if t == nil { if t == nil {
Fatalf("method call unknown receiver type: %v", Nconv(n, obj.FmtSign)) Fatalf("method call unknown receiver type: %v", Nconv(n, obj.FmtSign))
} }
as.List = list(as.List, tinlvar(t)) appendNodeSeqNode(&as.List, tinlvar(t))
ll = ll.Next // track argument count. ll = ll.Next // track argument count.
} }
// append ordinary arguments to LHS. // append ordinary arguments to LHS.
chkargcount := n.List != nil && n.List.Next != nil chkargcount := nodeSeqLen(n.List) > 1
var vararg *Node // the slice argument to a variadic call var vararg *Node // the slice argument to a variadic call
var varargs *NodeList // the list of LHS names to put in vararg. var varargs []*Node // the list of LHS names to put in vararg.
if !chkargcount { if !chkargcount {
// 0 or 1 expression on RHS. // 0 or 1 expression on RHS.
var i int var i int
...@@ -732,14 +705,14 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -732,14 +705,14 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
vararg = tinlvar(t) vararg = tinlvar(t)
for i = 0; i < varargcount && ll != nil; i++ { for i = 0; i < varargcount && ll != nil; i++ {
m = argvar(varargtype, i) m = argvar(varargtype, i)
varargs = list(varargs, m) varargs = append(varargs, m)
as.List = list(as.List, m) appendNodeSeqNode(&as.List, m)
} }
break break
} }
as.List = list(as.List, tinlvar(t)) appendNodeSeqNode(&as.List, tinlvar(t))
} }
} else { } else {
// match arguments except final variadic (unless the call is dotted itself) // match arguments except final variadic (unless the call is dotted itself)
...@@ -751,7 +724,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -751,7 +724,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
if variadic && t.Isddd { if variadic && t.Isddd {
break break
} }
as.List = list(as.List, tinlvar(t)) appendNodeSeqNode(&as.List, tinlvar(t))
t = t.Down t = t.Down
ll = ll.Next ll = ll.Next
} }
...@@ -762,8 +735,8 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -762,8 +735,8 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
var i int var i int
for i = 0; i < varargcount && ll != nil; i++ { for i = 0; i < varargcount && ll != nil; i++ {
m = argvar(varargtype, i) m = argvar(varargtype, i)
varargs = list(varargs, m) varargs = append(varargs, m)
as.List = list(as.List, m) appendNodeSeqNode(&as.List, m)
ll = ll.Next ll = ll.Next
} }
...@@ -777,9 +750,9 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -777,9 +750,9 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
} }
} }
if as.Rlist != nil { if nodeSeqLen(as.Rlist) != 0 {
typecheck(&as, Etop) typecheck(&as, Etop)
ninit = list(ninit, as) appendNodeSeqNode(&ninit, as)
} }
// turn the variadic args into a slice. // turn the variadic args into a slice.
...@@ -794,24 +767,24 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -794,24 +767,24 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
vararrtype.Bound = int64(varargcount) vararrtype.Bound = int64(varargcount)
as.Right = Nod(OCOMPLIT, nil, typenod(varargtype)) as.Right = Nod(OCOMPLIT, nil, typenod(varargtype))
as.Right.List = varargs setNodeSeq(&as.Right.List, varargs)
as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil)) as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil))
} }
typecheck(&as, Etop) typecheck(&as, Etop)
ninit = list(ninit, as) appendNodeSeqNode(&ninit, as)
} }
// zero the outparams // zero the outparams
for ll := inlretvars; ll != nil; ll = ll.Next { for ll := inlretvars; ll != nil; ll = ll.Next {
as = Nod(OAS, ll.N, nil) as = Nod(OAS, ll.N, nil)
typecheck(&as, Etop) typecheck(&as, Etop)
ninit = list(ninit, as) appendNodeSeqNode(&ninit, as)
} }
inlretlabel = newlabel_inl() inlretlabel = newlabel_inl()
inlgen++ inlgen++
body := inlsubstslice(fn.Func.Inl.Slice()) body := inlsubstlist(fn.Func.Inl)
body = append(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 = append(body, Nod(OLABEL, inlretlabel, nil)) body = append(body, Nod(OLABEL, inlretlabel, nil))
...@@ -822,20 +795,20 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -822,20 +795,20 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
call := Nod(OINLCALL, nil, nil) call := Nod(OINLCALL, nil, nil)
call.Ninit = ninit setNodeSeq(&call.Ninit, ninit)
call.Nbody.Set(body) call.Nbody.Set(body)
call.Rlist = inlretvars setNodeSeq(&call.Rlist, inlretvars)
call.Type = n.Type call.Type = n.Type
call.Typecheck = 1 call.Typecheck = 1
// Hide the args from setlno -- the parameters to the inlined // Hide the args from setlno -- the parameters to the inlined
// call already have good line numbers that should be preserved. // call already have good line numbers that should be preserved.
args := as.Rlist args := as.Rlist
as.Rlist = nil setNodeSeq(&as.Rlist, nil)
setlno(call, n.Lineno) setlno(call, n.Lineno)
as.Rlist = args setNodeSeq(&as.Rlist, args)
//dumplist("call body", body); //dumplist("call body", body);
...@@ -851,7 +824,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) { ...@@ -851,7 +824,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
// luckily these are small. // luckily these are small.
body = fn.Func.Inl.Slice() body = fn.Func.Inl.Slice()
fn.Func.Inl.Set(nil) // prevent infinite recursion (shouldn't happen anyway) fn.Func.Inl.Set(nil) // prevent infinite recursion (shouldn't happen anyway)
inlnodeslice(call.Nbody.Slice()) inlnodelist(call.Nbody)
for _, n := range call.Nbody.Slice() { for _, n := range call.Nbody.Slice() {
if n.Op == OINLCALL { if n.Op == OINLCALL {
inlconv2stmt(n) inlconv2stmt(n)
...@@ -922,24 +895,16 @@ func newlabel_inl() *Node { ...@@ -922,24 +895,16 @@ func newlabel_inl() *Node {
return n return n
} }
// inlsubst, inlsubstlist, and inlsubstslice recursively copy the body of the // inlsubst and inlsubstlist recursively copy the body of the saved
// saved pristine ->inl body of the function while substituting references // 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 nodesOrNodeList) []*Node {
var l *NodeList s := make([]*Node, 0, nodeSeqLen(ll))
for ; ll != nil; ll = ll.Next { for it := nodeSeqIterate(ll); !it.Done(); it.Next() {
l = list(l, inlsubst(ll.N)) s = append(s, inlsubst(it.N()))
} }
return l return s
}
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 {
...@@ -970,18 +935,18 @@ func inlsubst(n *Node) *Node { ...@@ -970,18 +935,18 @@ func inlsubst(n *Node) *Node {
case ORETURN: case ORETURN:
m := Nod(OGOTO, inlretlabel, nil) m := Nod(OGOTO, inlretlabel, nil)
m.Ninit = inlsubstlist(n.Ninit) setNodeSeq(&m.Ninit, inlsubstlist(n.Ninit))
if inlretvars != nil && n.List != nil { if inlretvars != nil && nodeSeqLen(n.List) != 0 {
as := Nod(OAS2, nil, nil) as := Nod(OAS2, nil, nil)
// shallow copy or OINLCALL->rlist will be the same list, and later walk and typecheck may clobber that. // shallow copy or OINLCALL->rlist will be the same list, and later walk and typecheck may clobber that.
for ll := inlretvars; ll != nil; ll = ll.Next { for ll := inlretvars; ll != nil; ll = ll.Next {
as.List = list(as.List, ll.N) appendNodeSeqNode(&as.List, ll.N)
} }
as.Rlist = inlsubstlist(n.List) setNodeSeq(&as.Rlist, inlsubstlist(n.List))
typecheck(&as, Etop) typecheck(&as, Etop)
m.Ninit = list(m.Ninit, as) appendNodeSeqNode(&m.Ninit, as)
} }
typechecklist(m.Ninit, Etop) typechecklist(m.Ninit, Etop)
...@@ -993,7 +958,7 @@ func inlsubst(n *Node) *Node { ...@@ -993,7 +958,7 @@ func inlsubst(n *Node) *Node {
case OGOTO, OLABEL: case OGOTO, OLABEL:
m := Nod(OXXX, nil, nil) m := Nod(OXXX, nil, nil)
*m = *n *m = *n
m.Ninit = nil setNodeSeq(&m.Ninit, nil)
p := fmt.Sprintf("%s·%d", n.Left.Sym.Name, inlgen) p := fmt.Sprintf("%s·%d", n.Left.Sym.Name, inlgen)
m.Left = newname(Lookup(p)) m.Left = newname(Lookup(p))
...@@ -1002,7 +967,7 @@ func inlsubst(n *Node) *Node { ...@@ -1002,7 +967,7 @@ func inlsubst(n *Node) *Node {
m := Nod(OXXX, nil, nil) m := Nod(OXXX, nil, nil)
*m = *n *m = *n
m.Ninit = nil setNodeSeq(&m.Ninit, nil)
if n.Op == OCLOSURE { if n.Op == OCLOSURE {
Fatalf("cannot inline function containing closure: %v", Nconv(n, obj.FmtSign)) Fatalf("cannot inline function containing closure: %v", Nconv(n, obj.FmtSign))
...@@ -1010,24 +975,18 @@ func inlsubst(n *Node) *Node { ...@@ -1010,24 +975,18 @@ func inlsubst(n *Node) *Node {
m.Left = inlsubst(n.Left) m.Left = inlsubst(n.Left)
m.Right = inlsubst(n.Right) m.Right = inlsubst(n.Right)
m.List = inlsubstlist(n.List) setNodeSeq(&m.List, inlsubstlist(n.List))
m.Rlist = inlsubstlist(n.Rlist) setNodeSeq(&m.Rlist, inlsubstlist(n.Rlist))
m.Ninit = concat(m.Ninit, inlsubstlist(n.Ninit)) setNodeSeq(&m.Ninit, append(nodeSeqSlice(m.Ninit), inlsubstlist(n.Ninit)...))
m.Nbody.Set(inlsubstslice(n.Nbody.Slice())) m.Nbody.Set(inlsubstlist(n.Nbody))
return m return m
} }
// Plaster over linenumbers // Plaster over linenumbers
func setlnolist(ll *NodeList, lno int32) { func setlnolist(ll nodesOrNodeList, lno int32) {
for ; ll != nil; ll = ll.Next { for it := nodeSeqIterate(ll); !it.Done(); it.Next() {
setlno(ll.N, lno) setlno(it.N(), lno)
}
}
func setlnoslice(ll []*Node, lno int32) {
for _, n := range ll {
setlno(n, lno)
} }
} }
...@@ -1046,5 +1005,5 @@ func setlno(n *Node, lno int32) { ...@@ -1046,5 +1005,5 @@ func setlno(n *Node, lno int32) {
setlnolist(n.List, lno) setlnolist(n.List, lno)
setlnolist(n.Rlist, lno) setlnolist(n.Rlist, lno)
setlnolist(n.Ninit, lno) setlnolist(n.Ninit, lno)
setlnoslice(n.Nbody.Slice(), lno) setlnolist(n.Nbody, lno)
} }
...@@ -292,7 +292,7 @@ func orderexprinplace(np **Node, outer *Order) { ...@@ -292,7 +292,7 @@ func orderexprinplace(np **Node, outer *Order) {
n := *np n := *np
var order Order var order Order
orderexpr(&n, &order, nil) orderexpr(&n, &order, nil)
addinitslice(&n, order.out) addinit(&n, order.out)
// insert new temporaries from order // insert new temporaries from order
// at head of outer list. // at head of outer list.
......
...@@ -2708,8 +2708,8 @@ func mkpkg(path string) *Pkg { ...@@ -2708,8 +2708,8 @@ func mkpkg(path string) *Pkg {
return p return p
} }
func addinit(np **Node, init *NodeList) { func addinit(np **Node, init nodesOrNodeList) {
if init == nil { if nodeSeqLen(init) == 0 {
return return
} }
...@@ -2725,18 +2725,10 @@ func addinit(np **Node, init *NodeList) { ...@@ -2725,18 +2725,10 @@ func addinit(np **Node, init *NodeList) {
*np = n *np = n
} }
n.Ninit = concat(init, n.Ninit) setNodeSeq(&n.Ninit, append(nodeSeqSlice(init), nodeSeqSlice(n.Ninit)...))
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",
......
...@@ -603,13 +603,15 @@ func nodeSeqIterate(ns nodesOrNodeList) nodeSeqIterator { ...@@ -603,13 +603,15 @@ func nodeSeqIterate(ns nodesOrNodeList) nodeSeqIterator {
} }
} }
// nodeSeqLen returns the length of either a *NodeList or a Nodes. // nodeSeqLen returns the length of a *NodeList, a Nodes, or a []*Node.
func nodeSeqLen(ns nodesOrNodeList) int { func nodeSeqLen(ns nodesOrNodeList) int {
switch ns := ns.(type) { switch ns := ns.(type) {
case *NodeList: case *NodeList:
return count(ns) return count(ns)
case Nodes: case Nodes:
return len(ns.Slice()) return len(ns.Slice())
case []*Node:
return len(ns)
default: default:
panic("can't happen") panic("can't happen")
} }
...@@ -641,6 +643,27 @@ func nodeSeqSecond(ns nodesOrNodeList) *Node { ...@@ -641,6 +643,27 @@ func nodeSeqSecond(ns nodesOrNodeList) *Node {
} }
} }
// nodeSeqSlice returns a []*Node containing the contents of a
// *NodeList, a Nodes, or a []*Node.
// This is an interim function during the transition from NodeList to Nodes.
// TODO(iant): Remove when transition is complete.
func nodeSeqSlice(ns nodesOrNodeList) []*Node {
switch ns := ns.(type) {
case *NodeList:
var s []*Node
for l := ns; l != nil; l = l.Next {
s = append(s, l.N)
}
return s
case Nodes:
return ns.Slice()
case []*Node:
return ns
default:
panic("can't happen")
}
}
// setNodeSeq implements *a = b. // setNodeSeq implements *a = b.
// a must have type **NodeList, *Nodes, or *[]*Node. // a must have type **NodeList, *Nodes, or *[]*Node.
// b must have type *NodeList, Nodes, []*Node, or nil. // b must have type *NodeList, Nodes, []*Node, or nil.
......
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