mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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/20195 Reviewed-by: David Crawshaw <crawshaw@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
ca56c590d4
commit
bf3909824c
5 changed files with 124 additions and 61 deletions
|
|
@ -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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
//
|
//
|
||||||
// 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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
// 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) {
|
||||||
|
|
||||||
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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) {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
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
|
||||||
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 {
|
||||||
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 {
|
||||||
// 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,
|
||||||
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,
|
||||||
|
|
||||||
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:
|
||||||
// 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:
|
||||||
// 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:
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue