cmd/compile: add Fields field to Type
Switch TSTRUCT and TINTER to use Fields instead of Type, which wrings
out the remaining few direct uses of the latter.
Preparation for converting fields to use a separate "Field" type.
Passes toolstash/buildall.
Change-Id: I5a2ea7e159d0dde1be2c9afafc10a8f739d95743
Reviewed-on: https://go-review.googlesource.com/20675
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/src/cmd/compile/internal/amd64/gsubr.go b/src/cmd/compile/internal/amd64/gsubr.go
index 4d99474..aeea7c8 100644
--- a/src/cmd/compile/internal/amd64/gsubr.go
+++ b/src/cmd/compile/internal/amd64/gsubr.go
@@ -112,7 +112,7 @@
// A special case to make write barriers more efficient.
// Comparing the first field of a named struct can be done directly.
base := n1
- if n1.Op == gc.ODOT && n1.Left.Type.Etype == gc.TSTRUCT && n1.Left.Type.Type.Sym == n1.Right.Sym {
+ if n1.Op == gc.ODOT && n1.Left.Type.Etype == gc.TSTRUCT && n1.Left.Type.Field(0).Sym == n1.Right.Sym {
base = n1.Left
}
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index fb42519..007d762 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -652,7 +652,7 @@
// (look at the first parameter only since either all
// names are present or all are absent)
n := countfield(params)
- if n > 0 && parName(params.Type) == "" {
+ if n > 0 && parName(params.Field(0)) == "" {
n = -n
}
p.int(n)
diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go
index b85262b..8d1349e 100644
--- a/src/cmd/compile/internal/gc/cgen.go
+++ b/src/cmd/compile/internal/gc/cgen.go
@@ -802,7 +802,7 @@
}
wbVar := syslook("writeBarrier")
- wbEnabled := Nod(ODOT, wbVar, newname(wbVar.Type.Type.Sym))
+ wbEnabled := Nod(ODOT, wbVar, newname(wbVar.Type.Field(0).Sym))
wbEnabled = typecheck(&wbEnabled, Erv)
pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1)
Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst)
diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go
index 8e6ff39..e3c42ac 100644
--- a/src/cmd/compile/internal/gc/dcl.go
+++ b/src/cmd/compile/internal/gc/dcl.go
@@ -1133,7 +1133,7 @@
return false
}
t = t.Type
- if t.Sym != nil || t.Etype != TSTRUCT || t.Type != nil {
+ if t.Sym != nil || t.Etype != TSTRUCT || countfield(t) != 0 {
return false
}
return true
diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go
index 72654a0..ec256e1 100644
--- a/src/cmd/compile/internal/gc/esc.go
+++ b/src/cmd/compile/internal/gc/esc.go
@@ -1478,7 +1478,7 @@
var src *Node
i := 0
lls := ll.Slice()
- for t := fntype.Params().Type; i < len(lls); i++ {
+ for t, it := IterFields(fntype.Params()); i < len(lls); i++ {
src = lls[i]
if t.Isddd && !n.Isddd {
// Introduce ODDDARG node to represent ... allocation.
@@ -1523,7 +1523,7 @@
// This occurs when function parameter type Isddd and n not Isddd
break
}
- t = t.Down
+ t = it.Next()
}
for ; i < len(lls); i++ {
diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go
index 69b969d..12c51c1 100644
--- a/src/cmd/compile/internal/gc/export.go
+++ b/src/cmd/compile/internal/gc/export.go
@@ -202,8 +202,11 @@
OMAKECHAN:
t := n.Type
- if t.Sym == nil && t.Type != nil {
- t = t.Type
+ switch t.Etype {
+ case TARRAY, TCHAN, TPTR32, TPTR64:
+ if t.Sym == nil {
+ t = t.Type
+ }
}
if t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) {
if Debug['E'] != 0 {
@@ -280,25 +283,41 @@
if t == nil {
return
}
+ if t.Etype == TFIELD {
+ Fatalf("unexpected TFIELD in dumpexporttype")
+ }
if t.Printed || t == Types[t.Etype] || t == bytetype || t == runetype || t == errortype {
return
}
t.Printed = true
- if t.Sym != nil && t.Etype != TFIELD {
+ if t.Sym != nil {
dumppkg(t.Sym.Pkg)
}
- dumpexporttype(t.Type)
- dumpexporttype(t.Down)
+ switch t.Etype {
+ case TSTRUCT, TINTER:
+ for f, it := IterFields(t); f != nil; f = it.Next() {
+ dumpexporttype(f.Type)
+ }
+ case TFUNC:
+ dumpexporttype(t.Recvs())
+ dumpexporttype(t.Results())
+ dumpexporttype(t.Params())
+ case TMAP:
+ dumpexporttype(t.Type)
+ dumpexporttype(t.Down) // key
+ case TARRAY, TCHAN, TPTR32, TPTR64:
+ dumpexporttype(t.Type)
+ }
- if t.Sym == nil || t.Etype == TFIELD {
+ if t.Sym == nil {
return
}
var m []*Type
for f, it := IterMethods(t); f != nil; f = it.Next() {
- dumpexporttype(f)
+ dumpexporttype(f.Type)
m = append(m, f)
}
sort.Sort(methodbyname(m))
diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index 4597ceb..3363d49 100644
--- a/src/cmd/compile/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -602,7 +602,7 @@
buf.WriteString(";")
}
}
- if t.Type != nil {
+ if t.Fields != nil {
buf.WriteString(" ")
}
buf.WriteString("}")
@@ -629,7 +629,7 @@
case 1:
if fmtmode != FExp {
buf.WriteString(" ")
- buf.WriteString(Tconv(t.Results().Type.Type, 0)) // struct->field->field's type
+ buf.WriteString(Tconv(t.Results().Field(0).Type, 0)) // struct->field->field's type
break
}
fallthrough
@@ -687,7 +687,7 @@
buf.WriteString(";")
}
}
- if t.Type != nil {
+ if t.Fields != nil {
buf.WriteString(" ")
}
buf.WriteString("}")
diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go
index 072a666..1174703 100644
--- a/src/cmd/compile/internal/gc/gsubr.go
+++ b/src/cmd/compile/internal/gc/gsubr.go
@@ -412,7 +412,7 @@
// A special case to make write barriers more efficient.
// Taking the address of the first field of a named struct
// is the same as taking the address of the struct.
- if n.Left.Type.Etype != TSTRUCT || n.Left.Type.Type.Sym != n.Right.Sym {
+ if n.Left.Type.Etype != TSTRUCT || n.Left.Type.Field(0).Sym != n.Right.Sym {
Debug['h'] = 1
Dump("naddr", n)
Fatalf("naddr: bad %v %v", Oconv(n.Op, 0), Ctxt.Dconv(a))
diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go
index a2fee2a..45cfd6a 100644
--- a/src/cmd/compile/internal/gc/inl.go
+++ b/src/cmd/compile/internal/gc/inl.go
@@ -700,8 +700,8 @@
}
} else {
// match arguments except final variadic (unless the call is dotted itself)
- var t *Type
- for t = fn.Type.Params().Type; t != nil; {
+ t, it := IterFields(fn.Type.Params())
+ for t != nil {
if li >= n.List.Len() {
break
}
@@ -709,7 +709,7 @@
break
}
as.List.Append(tinlvar(t))
- t = t.Down
+ t = it.Next()
li++
}
@@ -725,7 +725,7 @@
}
if i == varargcount {
- t = t.Down
+ t = it.Next()
}
}
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index 1e46e44..dc1dbbd 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -371,7 +371,7 @@
ordercallargs(&n.List, order)
if n.Op == OCALLFUNC {
- t := n.Left.Type.Params().Type
+ 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
@@ -393,7 +393,7 @@
*xp = x
}
}
- t = t.Down
+ t = it.Next()
}
}
}
diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go
index 2ec54d2..bd600e0 100644
--- a/src/cmd/compile/internal/gc/sinit.go
+++ b/src/cmd/compile/internal/gc/sinit.go
@@ -883,19 +883,19 @@
tk := t.Down
tv := t.Type
- symb := Lookup("b")
- fieldb := typ(TFIELD)
- fieldb.Type = tv
- fieldb.Sym = symb
-
syma := Lookup("a")
- fielda := typ(TFIELD)
- fielda.Type = tk
- fielda.Sym = syma
- fielda.Down = fieldb
+ symb := Lookup("b")
+
+ var fields [2]*Type
+ fields[0] = typ(TFIELD)
+ fields[0].Type = tk
+ fields[0].Sym = syma
+ fields[1] = typ(TFIELD)
+ fields[1].Type = tv
+ fields[1].Sym = symb
tstruct := typ(TSTRUCT)
- tstruct.Type = fielda
+ tstruct.SetFields(fields[:])
tarr := typ(TARRAY)
tarr.Bound = int64(b)
diff --git a/src/cmd/compile/internal/gc/sizeof_test.go b/src/cmd/compile/internal/gc/sizeof_test.go
index 29e51e5..ca862fc 100644
--- a/src/cmd/compile/internal/gc/sizeof_test.go
+++ b/src/cmd/compile/internal/gc/sizeof_test.go
@@ -27,7 +27,7 @@
{Name{}, 52, 80},
{Node{}, 92, 144},
{Sym{}, 60, 112},
- {Type{}, 136, 224},
+ {Type{}, 140, 232},
}
for _, tt := range tests {
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index 9300df0..8e7704f 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -592,13 +592,7 @@
}
func isnilinter(t *Type) bool {
- if !Isinter(t) {
- return false
- }
- if t.Type != nil {
- return false
- }
- return true
+ return Isinter(t) && countfield(t) == 0
}
func isideal(t *Type) bool {
diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go
index 2b7010a..eb296a4 100644
--- a/src/cmd/compile/internal/gc/type.go
+++ b/src/cmd/compile/internal/gc/type.go
@@ -140,6 +140,9 @@
Type *Type // actual type for TFIELD, element type for TARRAY, TCHAN, TMAP, TPTRxx
Width int64 // offset in TFIELD, width in all others
+ // TSTRUCT
+ Fields *Type // first struct field
+
// TFIELD
Down *Type // next struct field, also key type in TMAP
Note *string // literal string annotation
@@ -196,7 +199,7 @@
if t.Etype != TSTRUCT && t.Etype != TINTER {
Fatalf("IterFields: type %v does not have fields", t)
}
- return RawIter(t.Type)
+ return RawIter(t.Fields)
}
// IterMethods returns the first method in type t's method set
@@ -316,7 +319,7 @@
fields[i].Down = next
next = fields[i]
}
- t.Type = next
+ t.Fields = next
}
func (t *Type) Size() int64 {
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index c49ece0..e19e161 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -1333,15 +1333,7 @@
}
ok |= Erv
if t.Outtuple == 1 {
- t := l.Type.Results().Type
- if t == nil {
- n.Type = nil
- return
- }
- if t.Etype == TFIELD {
- t = t.Type
- }
- n.Type = t
+ n.Type = l.Type.Results().Field(0).Type
if n.Op == OCALLFUNC && n.Left.Op == ONAME && (compiling_runtime != 0 || n.Left.Sym.Pkg == Runtimepkg) && n.Left.Sym.Name == "getg" {
// Emit code for runtime.getg() directly instead of calling function.
@@ -1603,7 +1595,7 @@
var funarg *Type
if Istype(t, TSTRUCT) && t.Funarg {
funarg = t
- t = t.Type.Type
+ t = t.Field(0).Type
}
n.Type = t
@@ -1642,7 +1634,8 @@
}
if funarg != nil {
- for t := funarg.Type.Down; t != nil; t = t.Down {
+ _, it := IterFields(funarg) // Skip first field
+ for t := it.Next(); t != nil; t = it.Next() {
if assignop(t.Type, n.Type.Type, nil) == 0 {
Yyerror("cannot append %v value to []%v", t.Type, n.Type.Type)
}
@@ -2403,7 +2396,7 @@
s := n.Right.Sym
if t.Etype == TINTER {
- f1 := lookdot1(n, s, t, t.Type, dostrcmp)
+ f1 := lookdot1(n, s, t, t.Fields, dostrcmp)
if f1 == nil {
return false
}
@@ -2464,7 +2457,7 @@
dowidth(t)
var f1 *Type
if t.Etype == TSTRUCT || t.Etype == TINTER {
- f1 = lookdot1(n, s, t, t.Type, dostrcmp)
+ f1 = lookdot1(n, s, t, t.Fields, dostrcmp)
}
var f2 *Type
@@ -2627,11 +2620,11 @@
}
}
- tn := n.Type.Type
+ tn, it := IterFields(n.Type)
var why string
for tl, it2 := IterFields(tstruct); tl != nil; tl = it2.Next() {
if tl.Isddd {
- for ; tn != nil; tn = tn.Down {
+ for ; tn != nil; tn = it.Next() {
if assignop(tn.Type, tl.Type.Type, &why) == 0 {
if call != nil {
Yyerror("cannot use %v as type %v in argument to %v%s", tn.Type, tl.Type.Type, call, why)
@@ -2655,7 +2648,7 @@
}
}
- tn = tn.Down
+ tn = it.Next()
}
if tn != nil {
@@ -3049,7 +3042,7 @@
bad := 0
if n.List.Len() != 0 && nokeys(n.List) {
// simple list of variables
- f := t.Type
+ f, it := IterFields(t)
var s *Sym
ls := n.List.Slice()
@@ -3075,7 +3068,7 @@
n1.Left.Type = f
n1.Left.Typecheck = 1
ls[i1] = n1
- f = f.Down
+ f = it.Next()
}
if f != nil {
@@ -3114,7 +3107,7 @@
}
}
- f := lookdot1(nil, s, t, t.Type, 0)
+ f := lookdot1(nil, s, t, t.Fields, 0)
if f == nil {
Yyerror("unknown %v field '%v' in struct literal", t, s)
continue
diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go
index 743b83f..1585383 100644
--- a/src/cmd/compile/internal/gc/universe.go
+++ b/src/cmd/compile/internal/gc/universe.go
@@ -367,17 +367,22 @@
func lexinit1() {
// t = interface { Error() string }
- rcvr := typ(TSTRUCT)
- rcvr.Type = typ(TFIELD)
- rcvr.Type.Type = Ptrto(typ(TSTRUCT))
+ rcvr := typ(TSTRUCT)
rcvr.Funarg = true
+ field := typ(TFIELD)
+ field.Type = Ptrto(typ(TSTRUCT))
+ rcvr.SetFields([]*Type{field})
+
in := typ(TSTRUCT)
in.Funarg = true
+
out := typ(TSTRUCT)
- out.Type = typ(TFIELD)
- out.Type.Type = Types[TSTRING]
out.Funarg = true
+ field = typ(TFIELD)
+ field.Type = Types[TSTRING]
+ out.SetFields([]*Type{field})
+
f := typ(TFUNC)
*f.RecvsP() = rcvr
*f.ResultsP() = out
@@ -386,10 +391,12 @@
f.Intuple = 0
f.Outnamed = false
f.Outtuple = 1
+
t := typ(TINTER)
- t.Type = typ(TFIELD)
- t.Type.Sym = Lookup("Error")
- t.Type.Type = f
+ field = typ(TFIELD)
+ field.Sym = Lookup("Error")
+ field.Type = f
+ t.SetFields([]*Type{field})
// error type
s := Pkglookup("error", builtinpkg)
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index afc560d..cfd81f0 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -658,11 +658,7 @@
// Update type of OCALLFUNC node.
// Output arguments had not changed, but their offsets could.
if n.Left.Type.Outtuple == 1 {
- t := n.Left.Type.Results().Type
- if t.Etype == TFIELD {
- t = t.Type
- }
- n.Type = t
+ n.Type = n.Left.Type.Results().Field(0).Type
} else {
n.Type = n.Left.Type.Results()
}
@@ -2008,13 +2004,7 @@
continue
}
- t = on.Type.Params()
- if t != nil {
- t = t.Type
- }
- if t != nil {
- t = t.Type
- }
+ t = on.Type.Params().Field(0).Type
if !Eqtype(t, n.Type) {
n = Nod(OCONV, n, nil)
diff --git a/src/cmd/compile/internal/x86/gsubr.go b/src/cmd/compile/internal/x86/gsubr.go
index ee9f6c2..5ca76f6 100644
--- a/src/cmd/compile/internal/x86/gsubr.go
+++ b/src/cmd/compile/internal/x86/gsubr.go
@@ -639,7 +639,7 @@
// A special case to make write barriers more efficient.
// Comparing the first field of a named struct can be done directly.
base := n1
- if n1.Op == gc.ODOT && n1.Left.Type.Etype == gc.TSTRUCT && n1.Left.Type.Type.Sym == n1.Right.Sym {
+ if n1.Op == gc.ODOT && n1.Left.Type.Etype == gc.TSTRUCT && n1.Left.Type.Field(0).Sym == n1.Right.Sym {
base = n1.Left
}