1
0
mirror of https://github.com/golang/go synced 2024-11-23 22:00:11 -07:00

cmd/compile/internal/gc: simplify ascompatte

Passes toolstash -cmp.

Change-Id: Ibb51ccaf29ee97c3463543175c9ac7b85ea10a7f
Reviewed-on: https://go-review.googlesource.com/37339
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
Matthew Dempsky 2017-02-22 14:43:21 -08:00
parent ba6e5776fd
commit f7f3514bd8

View File

@ -338,7 +338,7 @@ func walkstmt(n *Node) *Node {
break break
} }
ll := ascompatte(n.Op, nil, false, Curfn.Type.Results(), n.List.Slice(), 1, &n.Ninit) ll := ascompatte(nil, false, Curfn.Type.Results(), n.List.Slice(), 1, &n.Ninit)
n.List.Set(ll) n.List.Set(ll)
case ORETJMP: case ORETJMP:
@ -611,7 +611,7 @@ opswitch:
} }
n.Left = walkexpr(n.Left, init) n.Left = walkexpr(n.Left, init)
walkexprlist(n.List.Slice(), init) walkexprlist(n.List.Slice(), init)
ll := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init) ll := ascompatte(n, n.Isddd, t.Params(), n.List.Slice(), 0, init)
n.List.Set(reorder1(ll)) n.List.Set(reorder1(ll))
case OCALLFUNC: case OCALLFUNC:
@ -644,7 +644,7 @@ opswitch:
n.Left = walkexpr(n.Left, init) n.Left = walkexpr(n.Left, init)
walkexprlist(n.List.Slice(), init) walkexprlist(n.List.Slice(), init)
ll := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init) ll := ascompatte(n, n.Isddd, t.Params(), n.List.Slice(), 0, init)
n.List.Set(reorder1(ll)) n.List.Set(reorder1(ll))
case OCALLMETH: case OCALLMETH:
@ -654,8 +654,8 @@ opswitch:
} }
n.Left = walkexpr(n.Left, init) n.Left = walkexpr(n.Left, init)
walkexprlist(n.List.Slice(), init) walkexprlist(n.List.Slice(), init)
ll := ascompatte(n.Op, n, false, t.Recvs(), []*Node{n.Left.Left}, 0, init) ll := ascompatte(n, false, t.Recvs(), []*Node{n.Left.Left}, 0, init)
lr := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init) lr := ascompatte(n, n.Isddd, t.Params(), n.List.Slice(), 0, init)
ll = append(ll, lr...) ll = append(ll, lr...)
n.Left.Left = nil n.Left.Left = nil
ullmancalc(n.Left) ullmancalc(n.Left)
@ -1737,162 +1737,82 @@ func ascompatet(op Op, nl Nodes, nr *Type) []*Node {
} }
// 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, nn []*Node, l *Field, fp int, init *Nodes, ddd *Node) []*Node { func mkdotargslice(typ *Type, args []*Node, init *Nodes, ddd *Node) *Node {
esc := uint16(EscUnknown) esc := uint16(EscUnknown)
if ddd != nil { if ddd != nil {
esc = ddd.Esc esc = ddd.Esc
} }
tslice := typSlice(l.Type.Elem()) if len(args) == 0 {
n := nodnil()
var n *Node n.Type = typ
if len(lr0) == 0 { return n
n = nodnil()
n.Type = tslice
} else {
n = nod(OCOMPLIT, nil, typenod(tslice))
if ddd != nil && prealloc[ddd] != nil {
prealloc[n] = prealloc[ddd] // temporary to use
}
n.List.Set(lr0)
n.Esc = esc
n = typecheck(n, Erv)
if n.Type == nil {
Fatalf("mkdotargslice: typecheck failed")
}
n = walkexpr(n, init)
} }
a := nod(OAS, nodarg(l, fp), n) n := nod(OCOMPLIT, nil, typenod(typ))
nn = append(nn, convas(a, init)) if ddd != nil && prealloc[ddd] != nil {
return nn prealloc[n] = prealloc[ddd] // temporary to use
}
// helpers for shape errors
func dumptypes(nl *Type, what string) string {
s := ""
for _, l := range nl.Fields().Slice() {
if s != "" {
s += ", "
}
s += fldconv(l, 0)
} }
if s == "" { n.List.Set(args)
s = fmt.Sprintf("[no arguments %s]", what) n.Esc = esc
n = typecheck(n, Erv)
if n.Type == nil {
Fatalf("mkdotargslice: typecheck failed")
} }
return s n = walkexpr(n, init)
} return n
func dumpnodetypes(l []*Node, what string) string {
s := ""
for _, r := range l {
if s != "" {
s += ", "
}
s += r.Type.String()
}
if s == "" {
s = fmt.Sprintf("[no arguments %s]", what)
}
return s
} }
// check assign expression list to // check assign expression list to
// 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 []*Node, fp int, init *Nodes) []*Node { func ascompatte(call *Node, isddd bool, lhs *Type, rhs []*Node, fp int, init *Nodes) []*Node {
lr0 := lr
l, savel := iterFields(nl)
var r *Node
if len(lr) > 0 {
r = lr[0]
}
var nn []*Node var nn []*Node
// f(g()) where g has multiple return values // f(g()) where g has multiple return values
if r != nil && len(lr) <= 1 && r.Type.IsFuncArgStruct() { if len(rhs) == 1 && rhs[0].Type.IsFuncArgStruct() {
// optimization - can do block copy // optimization - can do block copy
if eqtypenoname(r.Type, nl) { if eqtypenoname(rhs[0].Type, lhs) {
arg := nodarg(nl, fp) nl := nodarg(lhs, fp)
r = nod(OCONVNOP, r, nil) nr := nod(OCONVNOP, rhs[0], nil)
r.Type = arg.Type nr.Type = nl.Type
nn = []*Node{convas(nod(OAS, arg, r), init)} nn = []*Node{convas(nod(OAS, nl, nr), init)}
goto ret goto ret
} }
// conversions involved. // conversions involved.
// copy into temporaries. // copy into temporaries.
var alist []*Node var tmps []*Node
for _, nr := range rhs[0].Type.FieldSlice() {
for _, l := range r.Type.Fields().Slice() { tmps = append(tmps, temp(nr.Type))
tmp := temp(l.Type)
alist = append(alist, tmp)
} }
a := nod(OAS2, nil, nil) a := nod(OAS2, nil, nil)
a.List.Set(alist) a.List.Set(tmps)
a.Rlist.Set(lr) a.Rlist.Set(rhs)
a = typecheck(a, Etop) a = typecheck(a, Etop)
a = walkstmt(a) a = walkstmt(a)
init.Append(a) init.Append(a)
lr = alist
r = lr[0] rhs = tmps
l, savel = iterFields(nl)
} }
for { // For each parameter (LHS), assign its corresponding argument (RHS).
if l != nil && l.Isddd { // If there's a ... parameter (which is only valid as the final
// the ddd parameter must be last // parameter) and this is not a ... call expression,
ll := savel.Next() // then assign the remaining arguments as a slice.
for i, nl := range lhs.FieldSlice() {
if ll != nil { var nr *Node
yyerror("... must be last argument") if nl.Isddd && !isddd {
} nr = mkdotargslice(nl.Type, rhs[i:], init, call.Right)
} else {
// special case -- nr = rhs[i]
// only if we are assigning a single ddd
// argument to a ddd parameter then it is
// passed through unencapsulated
if r != nil && len(lr) <= 1 && isddd && eqtype(l.Type, r.Type) {
a := nod(OAS, nodarg(l, fp), r)
a = convas(a, init)
nn = append(nn, a)
break
}
// normal case -- make a slice of all
// remaining arguments and pass it to
// the ddd parameter.
nn = mkdotargslice(lr, nn, l, fp, init, call.Right)
break
} }
if l == nil || r == nil { a := nod(OAS, nodarg(nl, fp), nr)
if l != nil || r != nil {
l1 := dumptypes(nl, "expected")
l2 := dumpnodetypes(lr0, "given")
if l != nil {
yyerror("not enough arguments to %v\n\t%s\n\t%s", op, l1, l2)
} else {
yyerror("too many arguments to %v\n\t%s\n\t%s", op, l1, l2)
}
}
break
}
a := nod(OAS, nodarg(l, fp), r)
a = convas(a, init) a = convas(a, init)
nn = append(nn, a) nn = append(nn, a)
l = savel.Next()
r = nil
lr = lr[1:]
if len(lr) > 0 {
r = lr[0]
}
} }
ret: ret: