Commit 385c13cf authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile/internal/gc: remove a bunch of uses of iterField

Passes toolstash-check -all.

Change-Id: I9fb91dd78dff149b5e1e1329d00855fd41f12523
Reviewed-on: https://go-review.googlesource.com/39796
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarJosh Bleecher Snyder <josharian@gmail.com>
parent a680a85e
......@@ -1608,72 +1608,59 @@ func (e *EscState) esccall(call *Node, parent *Node) {
}
}
var arg *Node
var note string
param, it := iterFields(fntype.Params())
i := 0
for ; i < len(args); i++ {
arg = args[i]
note = param.Note
for i, param := range fntype.Params().FieldSlice() {
note := param.Note
var arg *Node
if param.Isddd() && !call.Isddd() {
rest := args[i:]
if len(rest) == 0 {
break
}
// Introduce ODDDARG node to represent ... allocation.
arg = nod(ODDDARG, nil, nil)
arg.Pos = call.Pos
arr := typArray(param.Type.Elem(), int64(len(args)-i))
arr := typArray(param.Type.Elem(), int64(len(rest)))
arg.Type = typPtr(arr) // make pointer so it will be tracked
e.track(arg)
call.Right = arg
}
if haspointers(param.Type) {
if e.escassignfromtag(note, cE.Retval, arg, call)&EscMask == EscNone && parent.Op != ODEFER && parent.Op != OPROC {
a := arg
for a.Op == OCONVNOP {
a = a.Left
// Store arguments into slice for ... arg.
for _, a := range rest {
if Debug['m'] > 3 {
fmt.Printf("%v::esccall:: ... <- %S\n", linestr(lineno), a)
}
switch a.Op {
// The callee has already been analyzed, so its arguments have esc tags.
// The argument is marked as not escaping at all.
// Record that fact so that any temporary used for
// synthesizing this expression can be reclaimed when
// the function returns.
// This 'noescape' is even stronger than the usual esc == EscNone.
// arg.Esc == EscNone means that arg does not escape the current function.
// arg.SetNoescape(true) here means that arg does not escape this statement
// in the current function.
case OCALLPART,
OCLOSURE,
ODDDARG,
OARRAYLIT,
OSLICELIT,
OPTRLIT,
OSTRUCTLIT:
a.SetNoescape(true)
if note == uintptrEscapesTag {
e.escassignSinkWhyWhere(arg, a, "arg to uintptrescapes ...", call)
} else {
e.escassignWhyWhere(arg, a, "arg to ...", call)
}
}
} else {
arg = args[i]
if note == uintptrEscapesTag {
e.escassignSinkWhy(arg, arg, "escaping uintptr")
}
}
if arg != args[i] {
// This occurs when function parameter field Isddd and call not Isddd
break
}
if note == uintptrEscapesTag {
e.escassignSinkWhy(arg, arg, "escaping uintptr")
}
param = it.Next()
}
// Store arguments into slice for ... arg.
for ; i < len(args); i++ {
if Debug['m'] > 3 {
fmt.Printf("%v::esccall:: ... <- %S\n", linestr(lineno), args[i])
}
if note == uintptrEscapesTag {
e.escassignSinkWhyWhere(arg, args[i], "arg to uintptrescapes ...", call)
} else {
e.escassignWhyWhere(arg, args[i], "arg to ...", call)
if haspointers(param.Type) && e.escassignfromtag(note, cE.Retval, arg, call)&EscMask == EscNone && parent.Op != ODEFER && parent.Op != OPROC {
a := arg
for a.Op == OCONVNOP {
a = a.Left
}
switch a.Op {
// The callee has already been analyzed, so its arguments have esc tags.
// The argument is marked as not escaping at all.
// Record that fact so that any temporary used for
// synthesizing this expression can be reclaimed when
// the function returns.
// This 'noescape' is even stronger than the usual esc == EscNone.
// arg.Esc == EscNone means that arg does not escape the current function.
// arg.SetNoescape(true) here means that arg does not escape this statement
// in the current function.
case OCALLPART, OCLOSURE, ODDDARG, OARRAYLIT, OSLICELIT, OPTRLIT, OSTRUCTLIT:
a.SetNoescape(true)
}
}
}
}
......
......@@ -390,33 +390,36 @@ func ordercall(n *Node, order *Order) {
ordercallargs(&n.List, order)
if n.Op == OCALLFUNC {
t, it := iterFields(n.Left.Type.Params())
for i := range n.List.Slice() {
// Check for "unsafe-uintptr" tag provided by escape analysis.
// If present and the argument is really a pointer being converted
// to uintptr, arrange for the pointer to be kept alive until the call
// returns, by copying it into a temp and marking that temp
keepAlive := func(i int) {
// If the argument is really a pointer being converted to uintptr,
// arrange for the pointer to be kept alive until the call returns,
// by copying it into a temp and marking that temp
// still alive when we pop the temp stack.
if t == nil {
break
xp := n.List.Addr(i)
for (*xp).Op == OCONVNOP && !(*xp).Type.IsPtr() {
xp = &(*xp).Left
}
if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag {
xp := n.List.Addr(i)
for (*xp).Op == OCONVNOP && !(*xp).Type.IsPtr() {
xp = &(*xp).Left
x := *xp
if x.Type.IsPtr() {
x = ordercopyexpr(x, x.Type, order, 0)
x.Name.SetKeepalive(true)
*xp = x
}
}
for i, t := range n.Left.Type.Params().FieldSlice() {
// Check for "unsafe-uintptr" tag provided by escape analysis.
if t.Isddd() && !n.Isddd() {
if t.Note == uintptrEscapesTag {
for ; i < n.List.Len(); i++ {
keepAlive(i)
}
}
x := *xp
if x.Type.IsPtr() {
x = ordercopyexpr(x, x.Type, order, 0)
x.Name.SetKeepalive(true)
*xp = x
} else {
if t.Note == unsafeUintptrTag || t.Note == uintptrEscapesTag {
keepAlive(i)
}
}
next := it.Next()
if next == nil && t.Isddd() && t.Note == uintptrEscapesTag {
next = t
}
t = next
}
}
}
......
......@@ -655,19 +655,32 @@ func eqtype1(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) boo
assumedEqual[typePair{t1, t2}] = struct{}{}
switch t1.Etype {
case TINTER, TSTRUCT:
t1, i1 := iterFields(t1)
t2, i2 := iterFields(t2)
for ; t1 != nil && t2 != nil; t1, t2 = i1.Next(), i2.Next() {
if t1.Sym != t2.Sym || t1.Embedded != t2.Embedded || !eqtype1(t1.Type, t2.Type, cmpTags, assumedEqual) || cmpTags && t1.Note != t2.Note {
case TINTER:
if t1.NumFields() != t2.NumFields() {
return false
}
for i, f1 := range t1.FieldSlice() {
f2 := t2.Field(i)
if f1.Sym != f2.Sym || !eqtype1(f1.Type, f2.Type, cmpTags, assumedEqual) {
return false
}
}
return true
if t1 == nil && t2 == nil {
return true
case TSTRUCT:
if t1.NumFields() != t2.NumFields() {
return false
}
return false
for i, f1 := range t1.FieldSlice() {
f2 := t2.Field(i)
if f1.Sym != f2.Sym || f1.Embedded != f2.Embedded || !eqtype1(f1.Type, f2.Type, cmpTags, assumedEqual) {
return false
}
if cmpTags && f1.Note != f2.Note {
return false
}
}
return true
case TFUNC:
// Check parameters and result parameters for type equality.
......@@ -675,16 +688,16 @@ func eqtype1(t1, t2 *Type, cmpTags bool, assumedEqual map[typePair]struct{}) boo
// equality, because they're never relevant.
for _, f := range paramsResults {
// Loop over fields in structs, ignoring argument names.
ta, ia := iterFields(f(t1))
tb, ib := iterFields(f(t2))
for ; ta != nil && tb != nil; ta, tb = ia.Next(), ib.Next() {
if ta.Isddd() != tb.Isddd() || !eqtype1(ta.Type, tb.Type, cmpTags, assumedEqual) {
fs1, fs2 := f(t1).FieldSlice(), f(t2).FieldSlice()
if len(fs1) != len(fs2) {
return false
}
for i, f1 := range fs1 {
f2 := fs2[i]
if f1.Isddd() != f2.Isddd() || !eqtype1(f1.Type, f2.Type, cmpTags, assumedEqual) {
return false
}
}
if ta != nil || tb != nil {
return false
}
}
return true
......@@ -716,18 +729,16 @@ func eqtypenoname(t1 *Type, t2 *Type) bool {
return false
}
f1, i1 := iterFields(t1)
f2, i2 := iterFields(t2)
for {
if t1.NumFields() != t2.NumFields() {
return false
}
for i, f1 := range t1.FieldSlice() {
f2 := t2.Field(i)
if !eqtype(f1.Type, f2.Type) {
return false
}
if f1 == nil {
return true
}
f1 = i1.Next()
f2 = i2.Next()
}
return true
}
// Is type src assignment compatible to type dst?
......
......@@ -1063,11 +1063,10 @@ func (t *Type) cmp(x *Type) ssa.Cmp {
return ssa.CMPgt // bucket maps are least
} // If t != t.Map.Bucket, fall through to general case
fallthrough
case TINTER:
t1, ti := iterFields(t)
x1, xi := iterFields(x)
for ; t1 != nil && x1 != nil; t1, x1 = ti.Next(), xi.Next() {
tfs := t.FieldSlice()
xfs := x.FieldSlice()
for i := 0; i < len(tfs) && i < len(xfs); i++ {
t1, x1 := tfs[i], xfs[i]
if t1.Embedded != x1.Embedded {
return cmpForNe(t1.Embedded < x1.Embedded)
}
......@@ -1081,17 +1080,36 @@ func (t *Type) cmp(x *Type) ssa.Cmp {
return c
}
}
if t1 != x1 {
return cmpForNe(t1 == nil)
if len(tfs) != len(xfs) {
return cmpForNe(len(tfs) < len(xfs))
}
return ssa.CMPeq
case TINTER:
tfs := t.FieldSlice()
xfs := x.FieldSlice()
for i := 0; i < len(tfs) && i < len(xfs); i++ {
t1, x1 := tfs[i], xfs[i]
if c := t1.Sym.cmpsym(x1.Sym); c != ssa.CMPeq {
return c
}
if c := t1.Type.cmp(x1.Type); c != ssa.CMPeq {
return c
}
}
if len(tfs) != len(xfs) {
return cmpForNe(len(tfs) < len(xfs))
}
return ssa.CMPeq
case TFUNC:
for _, f := range recvsParamsResults {
// Loop over fields in structs, ignoring argument names.
ta, ia := iterFields(f(t))
tb, ib := iterFields(f(x))
for ; ta != nil && tb != nil; ta, tb = ia.Next(), ib.Next() {
tfs := f(t).FieldSlice()
xfs := f(x).FieldSlice()
for i := 0; i < len(tfs) && i < len(xfs); i++ {
ta := tfs[i]
tb := xfs[i]
if ta.Isddd() != tb.Isddd() {
return cmpForNe(!ta.Isddd())
}
......@@ -1099,8 +1117,8 @@ func (t *Type) cmp(x *Type) ssa.Cmp {
return c
}
}
if ta != tb {
return cmpForNe(ta == nil)
if len(tfs) != len(xfs) {
return cmpForNe(len(tfs) < len(xfs))
}
}
return ssa.CMPeq
......
......@@ -1604,8 +1604,7 @@ OpSwitch:
}
if funarg != nil {
_, it := iterFields(funarg) // Skip first field
for t := it.Next(); t != nil; t = it.Next() {
for _, t := range funarg.FieldSlice()[1:] {
if assignop(t.Type, n.Type.Elem(), nil) == 0 {
yyerror("cannot append %v value to []%v", t.Type, n.Type.Elem())
}
......@@ -2591,11 +2590,12 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
}
}
tn, it := iterFields(n.Type)
lfs := tstruct.FieldSlice()
rfs := n.Type.FieldSlice()
var why string
for _, tl := range tstruct.Fields().Slice() {
for i, tl := range lfs {
if tl.Isddd() {
for ; tn != nil; tn = it.Next() {
for _, tn := range rfs[i:] {
if assignop(tn.Type, tl.Type.Elem(), &why) == 0 {
if call != nil {
yyerror("cannot use %v as type %v in argument to %v%s", tn.Type, tl.Type.Elem(), call, why)
......@@ -2604,13 +2604,13 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
}
}
}
goto out
}
if tn == nil {
if i >= len(rfs) {
goto notenough
}
tn := rfs[i]
if assignop(tn.Type, tl.Type, &why) == 0 {
if call != nil {
yyerror("cannot use %v as type %v in argument to %v%s", tn.Type, tl.Type, call, why)
......@@ -2618,11 +2618,9 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
yyerror("cannot use %v as type %v in %s%s", tn.Type, tl.Type, desc(), why)
}
}
tn = it.Next()
}
if tn != nil {
if len(rfs) > len(lfs) {
goto toomany
}
goto out
......@@ -3055,14 +3053,12 @@ func typecheckcomplit(n *Node) *Node {
bad := 0
if n.List.Len() != 0 && nokeys(n.List) {
// simple list of variables
f, it := iterFields(t)
ls := n.List.Slice()
for i1, n1 := range ls {
for i, n1 := range ls {
setlineno(n1)
ls[i1] = typecheck(ls[i1], Erv)
n1 = ls[i1]
if f == nil {
n1 = typecheck(n1, Erv)
ls[i] = n1
if i >= t.NumFields() {
if bad == 0 {
yyerror("too many values in struct initializer")
}
......@@ -3070,6 +3066,7 @@ func typecheckcomplit(n *Node) *Node {
continue
}
f := t.Field(i)
s := f.Sym
if s != nil && !exportname(s.Name) && s.Pkg != localpkg {
yyerror("implicit assignment of unexported field '%s' in %v literal", s.Name, t)
......@@ -3078,11 +3075,9 @@ func typecheckcomplit(n *Node) *Node {
n1 = assignconv(n1, f.Type, "field value")
n1 = nodSym(OSTRUCTKEY, n1, f.Sym)
n1.Xoffset = f.Offset
ls[i1] = n1
f = it.Next()
ls[i] = n1
}
if f != nil {
if len(ls) < t.NumFields() {
yyerror("too few values in struct initializer")
}
} else {
......@@ -3384,17 +3379,15 @@ func typecheckas2(n *Node) {
goto mismatch
}
n.Op = OAS2FUNC
t, s := iterFields(r.Type)
for _, n3 := range n.List.Slice() {
if t.Type != nil && n3.Type != nil {
checkassignto(t.Type, n3)
for i, l := range n.List.Slice() {
f := r.Type.Field(i)
if f.Type != nil && l.Type != nil {
checkassignto(f.Type, l)
}
if n3.Name != nil && n3.Name.Defn == n && n3.Name.Param.Ntype == nil {
n3.Type = t.Type
if l.Name != nil && l.Name.Defn == n && l.Name.Param.Ntype == nil {
l.Type = f.Type
}
t = s.Next()
}
goto out
}
}
......
......@@ -1697,20 +1697,16 @@ func fncall(l *Node, rt *Type) bool {
// a expression list. called in
// expr-list = func()
func ascompatet(op Op, nl Nodes, nr *Type) []*Node {
r, saver := iterFields(nr)
if nl.Len() != nr.NumFields() {
Fatalf("ascompatet: assignment count mismatch: %d = %d", nl.Len(), nr.NumFields())
}
var nn, mm Nodes
var ullmanOverflow bool
var i int
for i = 0; i < nl.Len(); i++ {
if r == nil {
break
}
l := nl.Index(i)
for i, l := range nl.Slice() {
if isblank(l) {
r = saver.Next()
continue
}
r := nr.Field(i)
// any lv that causes a fn call must be
// deferred until all the return arguments
......@@ -1729,19 +1725,10 @@ func ascompatet(op Op, nl Nodes, nr *Type) []*Node {
updateHasCall(a)
if a.HasCall() {
Dump("ascompatet ucount", a)
ullmanOverflow = true
Fatalf("ascompatet: too many function calls evaluating parameters")
}
nn.Append(a)
r = saver.Next()
}
if i < nl.Len() || r != nil {
Fatalf("ascompatet: assignment count mismatch: %d = %d", nl.Len(), nr.NumFields())
}
if ullmanOverflow {
Fatalf("ascompatet: too many function calls evaluating parameters")
}
return append(nn.Slice(), mm.Slice()...)
}
......
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