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

cmd/compile: convert cgen/gen/pgen and friends to nodeListSeq

Added Seq method to nodeListIterator. Added new functions nodeSeqLen,
nodeSeqFirst, nodeSeqSecond. Allow nil as source argument to setNodeSeq.

Change-Id: Ifc1cd4d7207b7a125b3830c92c4d6d6f00eedd54
Reviewed-on: https://go-review.googlesource.com/20195Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent ca56c590
...@@ -1753,7 +1753,7 @@ func Bvgen(n, res *Node, wantTrue bool) { ...@@ -1753,7 +1753,7 @@ func Bvgen(n, res *Node, wantTrue bool) {
func bvgenjump(n, res *Node, wantTrue, geninit bool) { func bvgenjump(n, res *Node, wantTrue, geninit bool) {
init := n.Ninit init := n.Ninit
if !geninit { if !geninit {
n.Ninit = nil setNodeSeq(&n.Ninit, nil)
} }
p1 := Gbranch(obj.AJMP, nil, 0) p1 := Gbranch(obj.AJMP, nil, 0)
p2 := Pc p2 := Pc
...@@ -1763,7 +1763,7 @@ func bvgenjump(n, res *Node, wantTrue, geninit bool) { ...@@ -1763,7 +1763,7 @@ func bvgenjump(n, res *Node, wantTrue, geninit bool) {
Bgen(n, wantTrue, 0, p2) Bgen(n, wantTrue, 0, p2)
Thearch.Gmove(Nodbool(false), res) Thearch.Gmove(Nodbool(false), res)
Patch(p3, Pc) Patch(p3, Pc)
n.Ninit = init setNodeSeq(&n.Ninit, init)
} }
// bgenx is the backend for Bgen and Bvgen. // bgenx is the backend for Bgen and Bvgen.
...@@ -1921,11 +1921,11 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { ...@@ -1921,11 +1921,11 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
if Isfloat[nr.Type.Etype] { if Isfloat[nr.Type.Etype] {
// Brcom is not valid on floats when NaN is involved. // Brcom is not valid on floats when NaN is involved.
ll := n.Ninit // avoid re-genning Ninit ll := n.Ninit // avoid re-genning Ninit
n.Ninit = nil setNodeSeq(&n.Ninit, nil)
if genval { if genval {
bgenx(n, res, true, likely, to) bgenx(n, res, true, likely, to)
Thearch.Gins(Thearch.Optoas(OXOR, Types[TUINT8]), Nodintconst(1), res) // res = !res Thearch.Gins(Thearch.Optoas(OXOR, Types[TUINT8]), Nodintconst(1), res) // res = !res
n.Ninit = ll setNodeSeq(&n.Ninit, ll)
return return
} }
p1 := Gbranch(obj.AJMP, nil, 0) p1 := Gbranch(obj.AJMP, nil, 0)
...@@ -1934,7 +1934,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) { ...@@ -1934,7 +1934,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
bgenx(n, res, true, -likely, p2) bgenx(n, res, true, -likely, p2)
Patch(Gbranch(obj.AJMP, nil, 0), to) Patch(Gbranch(obj.AJMP, nil, 0), to)
Patch(p2, Pc) Patch(p2, Pc)
n.Ninit = ll setNodeSeq(&n.Ninit, ll)
return return
} }
...@@ -2621,7 +2621,7 @@ func cgen_ret(n *Node) { ...@@ -2621,7 +2621,7 @@ func cgen_ret(n *Node) {
if hasdefer { if hasdefer {
Ginscall(Deferreturn, 0) Ginscall(Deferreturn, 0)
} }
Genslice(Curfn.Func.Exit.Slice()) Genlist(Curfn.Func.Exit)
p := Thearch.Gins(obj.ARET, nil, nil) p := Thearch.Gins(obj.ARET, nil, nil)
if n != nil && n.Op == ORETJMP { if n != nil && n.Op == ORETJMP {
p.To.Type = obj.TYPE_MEM p.To.Type = obj.TYPE_MEM
...@@ -2803,13 +2803,13 @@ func cgen_append(n, res *Node) { ...@@ -2803,13 +2803,13 @@ func cgen_append(n, res *Node) {
Dump("cgen_append-n", n) Dump("cgen_append-n", n)
Dump("cgen_append-res", res) Dump("cgen_append-res", res)
} }
if res.Op != ONAME && !samesafeexpr(res, n.List.N) { if res.Op != ONAME && !samesafeexpr(res, nodeSeqFirst(n.List)) {
Dump("cgen_append-n", n) Dump("cgen_append-n", n)
Dump("cgen_append-res", res) Dump("cgen_append-res", res)
Fatalf("append not lowered") Fatalf("append not lowered")
} }
for l := n.List; l != nil; l = l.Next { for it := nodeSeqIterate(n.List); !it.Done(); it.Next() {
if l.N.Ullman >= UINF { if it.N().Ullman >= UINF {
Fatalf("append with function call arguments") Fatalf("append with function call arguments")
} }
} }
...@@ -2818,7 +2818,7 @@ func cgen_append(n, res *Node) { ...@@ -2818,7 +2818,7 @@ func cgen_append(n, res *Node) {
// //
// If res and src are the same, we can avoid writing to base and cap // If res and src are the same, we can avoid writing to base and cap
// unless we grow the underlying array. // unless we grow the underlying array.
needFullUpdate := !samesafeexpr(res, n.List.N) needFullUpdate := !samesafeexpr(res, nodeSeqFirst(n.List))
// Copy src triple into base, len, cap. // Copy src triple into base, len, cap.
base := temp(Types[Tptr]) base := temp(Types[Tptr])
...@@ -2826,7 +2826,7 @@ func cgen_append(n, res *Node) { ...@@ -2826,7 +2826,7 @@ func cgen_append(n, res *Node) {
cap := temp(Types[TUINT]) cap := temp(Types[TUINT])
var src Node var src Node
Igen(n.List.N, &src, nil) Igen(nodeSeqFirst(n.List), &src, nil)
src.Type = Types[Tptr] src.Type = Types[Tptr]
Thearch.Gmove(&src, base) Thearch.Gmove(&src, base)
src.Type = Types[TUINT] src.Type = Types[TUINT]
...@@ -2839,7 +2839,7 @@ func cgen_append(n, res *Node) { ...@@ -2839,7 +2839,7 @@ func cgen_append(n, res *Node) {
var rlen Node var rlen Node
Regalloc(&rlen, Types[TUINT], nil) Regalloc(&rlen, Types[TUINT], nil)
Thearch.Gmove(len, &rlen) Thearch.Gmove(len, &rlen)
Thearch.Ginscon(Thearch.Optoas(OADD, Types[TUINT]), int64(count(n.List)-1), &rlen) Thearch.Ginscon(Thearch.Optoas(OADD, Types[TUINT]), int64(nodeSeqLen(n.List)-1), &rlen)
p := Thearch.Ginscmp(OLE, Types[TUINT], &rlen, cap, +1) p := Thearch.Ginscmp(OLE, Types[TUINT], &rlen, cap, +1)
// Note: rlen and src are Regrealloc'ed below at the target of the // Note: rlen and src are Regrealloc'ed below at the target of the
// branch we just emitted; do not reuse these Go variables for // branch we just emitted; do not reuse these Go variables for
...@@ -2909,7 +2909,7 @@ func cgen_append(n, res *Node) { ...@@ -2909,7 +2909,7 @@ func cgen_append(n, res *Node) {
dst.Xoffset += int64(Widthptr) dst.Xoffset += int64(Widthptr)
Regalloc(&r1, Types[TUINT], nil) Regalloc(&r1, Types[TUINT], nil)
Thearch.Gmove(len, &r1) Thearch.Gmove(len, &r1)
Thearch.Ginscon(Thearch.Optoas(OADD, Types[TUINT]), int64(count(n.List)-1), &r1) Thearch.Ginscon(Thearch.Optoas(OADD, Types[TUINT]), int64(nodeSeqLen(n.List)-1), &r1)
Thearch.Gmove(&r1, &dst) Thearch.Gmove(&r1, &dst)
Regfree(&r1) Regfree(&r1)
dst.Xoffset += int64(Widthptr) dst.Xoffset += int64(Widthptr)
...@@ -2947,7 +2947,9 @@ func cgen_append(n, res *Node) { ...@@ -2947,7 +2947,9 @@ func cgen_append(n, res *Node) {
// is not going to use a write barrier. // is not going to use a write barrier.
i := 0 i := 0
var r2 Node var r2 Node
for l := n.List.Next; l != nil; l = l.Next { it := nodeSeqIterate(n.List)
it.Next()
for ; !it.Done(); it.Next() {
Regalloc(&r1, Types[Tptr], nil) Regalloc(&r1, Types[Tptr], nil)
Thearch.Gmove(base, &r1) Thearch.Gmove(base, &r1)
Regalloc(&r2, Types[TUINT], nil) Regalloc(&r2, Types[TUINT], nil)
...@@ -2968,7 +2970,7 @@ func cgen_append(n, res *Node) { ...@@ -2968,7 +2970,7 @@ func cgen_append(n, res *Node) {
r1.Op = OINDREG r1.Op = OINDREG
r1.Type = res.Type.Type r1.Type = res.Type.Type
cgen_wb(l.N, &r1, needwritebarrier(&r1, l.N)) cgen_wb(it.N(), &r1, needwritebarrier(&r1, it.N()))
Regfree(&r1) Regfree(&r1)
i++ i++
} }
......
...@@ -215,15 +215,9 @@ func stmtlabel(n *Node) *Label { ...@@ -215,15 +215,9 @@ func stmtlabel(n *Node) *Label {
} }
// compile statements // compile statements
func Genlist(l *NodeList) { func Genlist(l nodesOrNodeList) {
for ; l != nil; l = l.Next { for it := nodeSeqIterate(l); !it.Done(); it.Next() {
gen(l.N) gen(it.N())
}
}
func Genslice(l []*Node) {
for _, n := range l {
gen(n)
} }
} }
...@@ -445,8 +439,8 @@ func cgen_dottype(n *Node, res, resok *Node, wb bool) { ...@@ -445,8 +439,8 @@ func cgen_dottype(n *Node, res, resok *Node, wb bool) {
call := Nod(OCALLFUNC, fn, nil) call := Nod(OCALLFUNC, fn, nil)
r1.Type = byteptr r1.Type = byteptr
r2.Type = byteptr r2.Type = byteptr
call.List = list(list(list1(&r1), &r2), typename(n.Left.Type)) setNodeSeq(&call.List, list(list(list1(&r1), &r2), typename(n.Left.Type)))
call.List = ascompatte(OCALLFUNC, call, false, getinarg(fn.Type), call.List, 0, nil) setNodeSeq(&call.List, ascompatte(OCALLFUNC, call, false, getinarg(fn.Type), call.List, 0, nil))
gen(call) gen(call)
Regfree(&r1) Regfree(&r1)
Regfree(&r2) Regfree(&r2)
...@@ -531,8 +525,8 @@ func Cgen_As2dottype(n, res, resok *Node) { ...@@ -531,8 +525,8 @@ func Cgen_As2dottype(n, res, resok *Node) {
fn := syslook("panicdottype", 0) fn := syslook("panicdottype", 0)
dowidth(fn.Type) dowidth(fn.Type)
call := Nod(OCALLFUNC, fn, nil) call := Nod(OCALLFUNC, fn, nil)
call.List = list(list(list1(&r1), &r2), typename(n.Left.Type)) setNodeSeq(&call.List, list(list(list1(&r1), &r2), typename(n.Left.Type)))
call.List = ascompatte(OCALLFUNC, call, false, getinarg(fn.Type), call.List, 0, nil) setNodeSeq(&call.List, ascompatte(OCALLFUNC, call, false, getinarg(fn.Type), call.List, 0, nil))
gen(call) gen(call)
Regfree(&r1) Regfree(&r1)
Regfree(&r2) Regfree(&r2)
...@@ -644,7 +638,7 @@ func gen(n *Node) { ...@@ -644,7 +638,7 @@ func gen(n *Node) {
goto ret goto ret
} }
if n.Ninit != nil { if nodeSeqLen(n.Ninit) > 0 {
Genlist(n.Ninit) Genlist(n.Ninit)
} }
...@@ -779,7 +773,7 @@ func gen(n *Node) { ...@@ -779,7 +773,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
Genslice(n.Nbody.Slice()) // body Genlist(n.Nbody) // body
gjmp(continpc) gjmp(continpc)
Patch(breakpc, Pc) // done: Patch(breakpc, Pc) // done:
continpc = scontin continpc = scontin
...@@ -794,7 +788,7 @@ func gen(n *Node) { ...@@ -794,7 +788,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
Genslice(n.Nbody.Slice()) // then Genlist(n.Nbody) // 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
...@@ -811,9 +805,9 @@ func gen(n *Node) { ...@@ -811,9 +805,9 @@ func gen(n *Node) {
lab.Breakpc = breakpc lab.Breakpc = breakpc
} }
Patch(p1, Pc) // test: Patch(p1, Pc) // test:
Genslice(n.Nbody.Slice()) // switch(test) body Genlist(n.Nbody) // 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
...@@ -830,9 +824,9 @@ func gen(n *Node) { ...@@ -830,9 +824,9 @@ func gen(n *Node) {
lab.Breakpc = breakpc lab.Breakpc = breakpc
} }
Patch(p1, Pc) // test: Patch(p1, Pc) // test:
Genslice(n.Nbody.Slice()) // select() body Genlist(n.Nbody) // 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
...@@ -851,7 +845,7 @@ func gen(n *Node) { ...@@ -851,7 +845,7 @@ func gen(n *Node) {
Cgen_as_wb(n.Left, n.Right, true) Cgen_as_wb(n.Left, n.Right, true)
case OAS2DOTTYPE: case OAS2DOTTYPE:
cgen_dottype(n.Rlist.N, n.List.N, n.List.Next.N, needwritebarrier(n.List.N, n.Rlist.N)) cgen_dottype(nodeSeqFirst(n.Rlist), nodeSeqFirst(n.List), nodeSeqSecond(n.List), needwritebarrier(nodeSeqFirst(n.List), nodeSeqFirst(n.Rlist)))
case OCALLMETH: case OCALLMETH:
cgen_callmeth(n, 0) cgen_callmeth(n, 0)
......
...@@ -491,8 +491,8 @@ func compile(fn *Node) { ...@@ -491,8 +491,8 @@ func compile(fn *Node) {
ssafn.Free() ssafn.Free()
return return
} }
Genslice(Curfn.Func.Enter.Slice()) Genlist(Curfn.Func.Enter)
Genslice(Curfn.Nbody.Slice()) Genlist(Curfn.Nbody)
gclean() gclean()
checklabels() checklabels()
if nerrors != 0 { if nerrors != 0 {
......
...@@ -520,6 +520,9 @@ type nodeSeqIterator interface { ...@@ -520,6 +520,9 @@ type nodeSeqIterator interface {
P() **Node P() **Node
// Return the number of items remaining in the iteration. // Return the number of items remaining in the iteration.
Len() int Len() int
// Return the remaining items as a sequence.
// This will have the same type as that passed to nodeSeqIterate.
Seq() nodesOrNodeList
} }
// nodeListIterator is a type that implements nodeSeqIterator using a // nodeListIterator is a type that implements nodeSeqIterator using a
...@@ -548,6 +551,10 @@ func (nli *nodeListIterator) Len() int { ...@@ -548,6 +551,10 @@ func (nli *nodeListIterator) Len() int {
return count(nli.l) return count(nli.l)
} }
func (nli *nodeListIterator) Seq() nodesOrNodeList {
return nli.l
}
// nodesIterator implements nodeSeqIterator using a Nodes. // nodesIterator implements nodeSeqIterator using a Nodes.
type nodesIterator struct { type nodesIterator struct {
n Nodes n Nodes
...@@ -574,7 +581,13 @@ func (ni *nodesIterator) Len() int { ...@@ -574,7 +581,13 @@ func (ni *nodesIterator) Len() int {
return len(ni.n.Slice()) return len(ni.n.Slice())
} }
// nodeSeqIterate returns an iterator over either a *Nodelist or a *Nodes. func (ni *nodesIterator) Seq() nodesOrNodeList {
var r Nodes
r.Set(ni.n.Slice()[ni.i:])
return r
}
// nodeSeqIterate returns an iterator over either a *NodeList or a Nodes.
func nodeSeqIterate(ns nodesOrNodeList) nodeSeqIterator { func nodeSeqIterate(ns nodesOrNodeList) nodeSeqIterator {
switch ns := ns.(type) { switch ns := ns.(type) {
case *NodeList: case *NodeList:
...@@ -586,12 +599,64 @@ func nodeSeqIterate(ns nodesOrNodeList) nodeSeqIterator { ...@@ -586,12 +599,64 @@ func nodeSeqIterate(ns nodesOrNodeList) nodeSeqIterator {
} }
} }
// nodeSeqLen returns the length of either a *NodeList or a Nodes.
func nodeSeqLen(ns nodesOrNodeList) int {
switch ns := ns.(type) {
case *NodeList:
return count(ns)
case Nodes:
return len(ns.Slice())
default:
panic("can't happen")
}
}
// nodeSeqFirst returns the first element of either a *NodeList or a Nodes.
// It panics if the sequence is empty.
func nodeSeqFirst(ns nodesOrNodeList) *Node {
switch ns := ns.(type) {
case *NodeList:
return ns.N
case Nodes:
return ns.Slice()[0]
default:
panic("can't happen")
}
}
// nodeSeqSecond returns the second element of either a *NodeList or a Nodes.
// It panics if the sequence has fewer than two elements.
func nodeSeqSecond(ns nodesOrNodeList) *Node {
switch ns := ns.(type) {
case *NodeList:
return ns.Next.N
case Nodes:
return ns.Slice()[1]
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, or []*Node. // b must have type *NodeList, Nodes, []*Node, or nil.
// This is an interim function during the transition from NodeList to Nodes. // This is an interim function during the transition from NodeList to Nodes.
// TODO(iant): Remove when transition is complete. // TODO(iant): Remove when transition is complete.
func setNodeSeq(a nodesOrNodeListPtr, b nodesOrNodeList) { func setNodeSeq(a nodesOrNodeListPtr, b nodesOrNodeList) {
if b == nil {
switch a := a.(type) {
case **NodeList:
*a = nil
case *Nodes:
a.Set(nil)
case *[]*Node:
*a = nil
default:
panic("can't happen")
}
return
}
// Simplify b to either *Nodelist or []*Node. // Simplify b to either *Nodelist or []*Node.
if n, ok := b.(Nodes); ok { if n, ok := b.(Nodes); ok {
b = n.Slice() b = n.Slice()
......
...@@ -1717,7 +1717,7 @@ func ascompatet(op Op, nl *NodeList, nr **Type, fp int, init **NodeList) *NodeLi ...@@ -1717,7 +1717,7 @@ func ascompatet(op Op, nl *NodeList, nr **Type, fp int, init **NodeList) *NodeLi
} }
// package all the arguments that match a ... T parameter into a []T. // package all the arguments that match a ... T parameter into a []T.
func mkdotargslice(lr0 *NodeList, nn *NodeList, l *Type, fp int, init **NodeList, ddd *Node) *NodeList { func mkdotargslice(lr0 nodesOrNodeList, nn *NodeList, l *Type, fp int, init **NodeList, ddd *Node) *NodeList {
esc := uint16(EscUnknown) esc := uint16(EscUnknown)
if ddd != nil { if ddd != nil {
esc = ddd.Esc esc = ddd.Esc
...@@ -1728,7 +1728,7 @@ func mkdotargslice(lr0 *NodeList, nn *NodeList, l *Type, fp int, init **NodeList ...@@ -1728,7 +1728,7 @@ func mkdotargslice(lr0 *NodeList, nn *NodeList, l *Type, fp int, init **NodeList
tslice.Bound = -1 tslice.Bound = -1
var n *Node var n *Node
if count(lr0) == 0 { if nodeSeqLen(lr0) == 0 {
n = nodnil() n = nodnil()
n.Type = tslice n.Type = tslice
} else { } else {
...@@ -1736,7 +1736,7 @@ func mkdotargslice(lr0 *NodeList, nn *NodeList, l *Type, fp int, init **NodeList ...@@ -1736,7 +1736,7 @@ func mkdotargslice(lr0 *NodeList, nn *NodeList, l *Type, fp int, init **NodeList
if ddd != nil && prealloc[ddd] != nil { if ddd != nil && prealloc[ddd] != nil {
prealloc[n] = prealloc[ddd] // temporary to use prealloc[n] = prealloc[ddd] // temporary to use
} }
n.List = lr0 setNodeSeq(&n.List, lr0)
n.Esc = esc n.Esc = esc
typecheck(&n, Erv) typecheck(&n, Erv)
if n.Type == nil { if n.Type == nil {
...@@ -1772,14 +1772,14 @@ func dumptypes(nl **Type, what string) string { ...@@ -1772,14 +1772,14 @@ func dumptypes(nl **Type, what string) string {
return fmt_ return fmt_
} }
func dumpnodetypes(l *NodeList, what string) string { func dumpnodetypes(l nodesOrNodeList, what string) string {
var r *Node var r *Node
fmt_ := "" fmt_ := ""
fmt_ += "\t" fmt_ += "\t"
first := 1 first := 1
for ; l != nil; l = l.Next { for it := nodeSeqIterate(l); !it.Done(); it.Next() {
r = l.N r = it.N()
if first != 0 { if first != 0 {
first = 0 first = 0
} else { } else {
...@@ -1798,14 +1798,14 @@ func dumpnodetypes(l *NodeList, what string) string { ...@@ -1798,14 +1798,14 @@ func dumpnodetypes(l *NodeList, what string) string {
// a type list. called in // a type list. called in
// return expr-list // return expr-list
// func(expr-list) // func(expr-list)
func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr *NodeList, fp int, init **NodeList) *NodeList { func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr nodesOrNodeList, fp int, init **NodeList) *NodeList {
var savel Iter var savel Iter
lr0 := lr lr0 := lr
l := Structfirst(&savel, nl) l := Structfirst(&savel, nl)
var r *Node var r *Node
if lr != nil { if nodeSeqLen(lr) > 0 {
r = lr.N r = nodeSeqFirst(lr)
} }
var nn *NodeList var nn *NodeList
...@@ -1814,7 +1814,8 @@ func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr *NodeList, fp int, ...@@ -1814,7 +1814,8 @@ func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr *NodeList, fp int,
var l2 string var l2 string
var ll *Type var ll *Type
var l1 string var l1 string
if r != nil && lr.Next == nil && r.Type.Etype == TSTRUCT && r.Type.Funarg { var lrit nodeSeqIterator
if r != nil && nodeSeqLen(lr) <= 1 && r.Type.Etype == TSTRUCT && r.Type.Funarg {
// optimization - can do block copy // optimization - can do block copy
if eqtypenoname(r.Type, *nl) { if eqtypenoname(r.Type, *nl) {
a := nodarg(*nl, fp) a := nodarg(*nl, fp)
...@@ -1835,15 +1836,16 @@ func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr *NodeList, fp int, ...@@ -1835,15 +1836,16 @@ func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr *NodeList, fp int,
a = Nod(OAS2, nil, nil) a = Nod(OAS2, nil, nil)
a.List = alist a.List = alist
a.Rlist = lr setNodeSeq(&a.Rlist, lr)
typecheck(&a, Etop) typecheck(&a, Etop)
walkstmt(&a) walkstmt(&a)
*init = list(*init, a) *init = list(*init, a)
lr = alist lr = alist
r = lr.N r = nodeSeqFirst(lr)
l = Structfirst(&savel, nl) l = Structfirst(&savel, nl)
} }
lrit = nodeSeqIterate(lr)
loop: loop:
if l != nil && l.Isddd { if l != nil && l.Isddd {
// the ddd parameter must be last // the ddd parameter must be last
...@@ -1857,7 +1859,7 @@ loop: ...@@ -1857,7 +1859,7 @@ loop:
// only if we are assigning a single ddd // only if we are assigning a single ddd
// argument to a ddd parameter then it is // argument to a ddd parameter then it is
// passed thru unencapsulated // passed thru unencapsulated
if r != nil && lr.Next == nil && isddd && Eqtype(l.Type, r.Type) { if r != nil && lrit.Len() <= 1 && isddd && Eqtype(l.Type, r.Type) {
a = Nod(OAS, nodarg(l, fp), r) a = Nod(OAS, nodarg(l, fp), r)
a = convas(a, init) a = convas(a, init)
nn = list(nn, a) nn = list(nn, a)
...@@ -1867,7 +1869,7 @@ loop: ...@@ -1867,7 +1869,7 @@ loop:
// normal case -- make a slice of all // normal case -- make a slice of all
// remaining arguments and pass it to // remaining arguments and pass it to
// the ddd parameter. // the ddd parameter.
nn = mkdotargslice(lr, nn, l, fp, init, call.Right) nn = mkdotargslice(lrit.Seq(), nn, l, fp, init, call.Right)
goto ret goto ret
} }
...@@ -1892,15 +1894,15 @@ loop: ...@@ -1892,15 +1894,15 @@ loop:
l = structnext(&savel) l = structnext(&savel)
r = nil r = nil
lr = lr.Next lrit.Next()
if lr != nil { if !lrit.Done() {
r = lr.N r = lrit.N()
} }
goto loop goto loop
ret: ret:
for lr = nn; lr != nil; lr = lr.Next { for lrit = nodeSeqIterate(nn); !lrit.Done(); lrit.Next() {
lr.N.Typecheck = 1 lrit.N().Typecheck = 1
} }
return nn return nn
} }
......
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