1
0
mirror of https://github.com/golang/go synced 2024-11-19 11:04:47 -07:00

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>
This commit is contained in:
Matthew Dempsky 2016-03-13 23:02:38 -07:00
parent 7971864267
commit 0d2e92c2ca
18 changed files with 89 additions and 83 deletions

View File

@ -112,7 +112,7 @@ func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
// A special case to make write barriers more efficient. // A special case to make write barriers more efficient.
// Comparing the first field of a named struct can be done directly. // Comparing the first field of a named struct can be done directly.
base := n1 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 base = n1.Left
} }

View File

@ -652,7 +652,7 @@ func (p *exporter) paramList(params *Type) {
// (look at the first parameter only since either all // (look at the first parameter only since either all
// names are present or all are absent) // names are present or all are absent)
n := countfield(params) n := countfield(params)
if n > 0 && parName(params.Type) == "" { if n > 0 && parName(params.Field(0)) == "" {
n = -n n = -n
} }
p.int(n) p.int(n)

View File

@ -802,7 +802,7 @@ func cgen_wbptr(n, res *Node) {
} }
wbVar := syslook("writeBarrier") 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) wbEnabled = typecheck(&wbEnabled, Erv)
pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1) pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1)
Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst) Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst)

View File

@ -1133,7 +1133,7 @@ func isifacemethod(f *Type) bool {
return false return false
} }
t = t.Type 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 false
} }
return true return true

View File

@ -1478,7 +1478,7 @@ func esccall(e *EscState, n *Node, up *Node) {
var src *Node var src *Node
i := 0 i := 0
lls := ll.Slice() 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] src = lls[i]
if t.Isddd && !n.Isddd { if t.Isddd && !n.Isddd {
// Introduce ODDDARG node to represent ... allocation. // Introduce ODDDARG node to represent ... allocation.
@ -1523,7 +1523,7 @@ func esccall(e *EscState, n *Node, up *Node) {
// This occurs when function parameter type Isddd and n not Isddd // This occurs when function parameter type Isddd and n not Isddd
break break
} }
t = t.Down t = it.Next()
} }
for ; i < len(lls); i++ { for ; i < len(lls); i++ {

View File

@ -202,8 +202,11 @@ func reexportdep(n *Node) {
OMAKECHAN: OMAKECHAN:
t := n.Type t := n.Type
if t.Sym == nil && t.Type != nil { switch t.Etype {
t = t.Type 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 t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) {
if Debug['E'] != 0 { if Debug['E'] != 0 {
@ -280,25 +283,41 @@ func dumpexporttype(t *Type) {
if t == nil { if t == nil {
return return
} }
if t.Etype == TFIELD {
Fatalf("unexpected TFIELD in dumpexporttype")
}
if t.Printed || t == Types[t.Etype] || t == bytetype || t == runetype || t == errortype { if t.Printed || t == Types[t.Etype] || t == bytetype || t == runetype || t == errortype {
return return
} }
t.Printed = true t.Printed = true
if t.Sym != nil && t.Etype != TFIELD { if t.Sym != nil {
dumppkg(t.Sym.Pkg) dumppkg(t.Sym.Pkg)
} }
dumpexporttype(t.Type) switch t.Etype {
dumpexporttype(t.Down) 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 return
} }
var m []*Type var m []*Type
for f, it := IterMethods(t); f != nil; f = it.Next() { for f, it := IterMethods(t); f != nil; f = it.Next() {
dumpexporttype(f) dumpexporttype(f.Type)
m = append(m, f) m = append(m, f)
} }
sort.Sort(methodbyname(m)) sort.Sort(methodbyname(m))

View File

@ -602,7 +602,7 @@ func typefmt(t *Type, flag int) string {
buf.WriteString(";") buf.WriteString(";")
} }
} }
if t.Type != nil { if t.Fields != nil {
buf.WriteString(" ") buf.WriteString(" ")
} }
buf.WriteString("}") buf.WriteString("}")
@ -629,7 +629,7 @@ func typefmt(t *Type, flag int) string {
case 1: case 1:
if fmtmode != FExp { if fmtmode != FExp {
buf.WriteString(" ") 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 break
} }
fallthrough fallthrough
@ -687,7 +687,7 @@ func typefmt(t *Type, flag int) string {
buf.WriteString(";") buf.WriteString(";")
} }
} }
if t.Type != nil { if t.Fields != nil {
buf.WriteString(" ") buf.WriteString(" ")
} }
buf.WriteString("}") buf.WriteString("}")

View File

@ -412,7 +412,7 @@ func Naddr(a *obj.Addr, n *Node) {
// A special case to make write barriers more efficient. // A special case to make write barriers more efficient.
// Taking the address of the first field of a named struct // Taking the address of the first field of a named struct
// is the same as taking the address of the 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 Debug['h'] = 1
Dump("naddr", n) Dump("naddr", n)
Fatalf("naddr: bad %v %v", Oconv(n.Op, 0), Ctxt.Dconv(a)) Fatalf("naddr: bad %v %v", Oconv(n.Op, 0), Ctxt.Dconv(a))

View File

@ -700,8 +700,8 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
} }
} else { } else {
// match arguments except final variadic (unless the call is dotted itself) // match arguments except final variadic (unless the call is dotted itself)
var t *Type t, it := IterFields(fn.Type.Params())
for t = fn.Type.Params().Type; t != nil; { for t != nil {
if li >= n.List.Len() { if li >= n.List.Len() {
break break
} }
@ -709,7 +709,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
break break
} }
as.List.Append(tinlvar(t)) as.List.Append(tinlvar(t))
t = t.Down t = it.Next()
li++ li++
} }
@ -725,7 +725,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
} }
if i == varargcount { if i == varargcount {
t = t.Down t = it.Next()
} }
} }

View File

@ -371,7 +371,7 @@ func ordercall(n *Node, order *Order) {
ordercallargs(&n.List, order) ordercallargs(&n.List, order)
if n.Op == OCALLFUNC { if n.Op == OCALLFUNC {
t := n.Left.Type.Params().Type t, it := IterFields(n.Left.Type.Params())
for i := range n.List.Slice() { for i := range n.List.Slice() {
// Check for "unsafe-uintptr" tag provided by escape analysis. // Check for "unsafe-uintptr" tag provided by escape analysis.
// If present and the argument is really a pointer being converted // If present and the argument is really a pointer being converted
@ -393,7 +393,7 @@ func ordercall(n *Node, order *Order) {
*xp = x *xp = x
} }
} }
t = t.Down t = it.Next()
} }
} }
} }

View File

@ -883,19 +883,19 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
tk := t.Down tk := t.Down
tv := t.Type tv := t.Type
symb := Lookup("b")
fieldb := typ(TFIELD)
fieldb.Type = tv
fieldb.Sym = symb
syma := Lookup("a") syma := Lookup("a")
fielda := typ(TFIELD) symb := Lookup("b")
fielda.Type = tk
fielda.Sym = syma var fields [2]*Type
fielda.Down = fieldb 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 := typ(TSTRUCT)
tstruct.Type = fielda tstruct.SetFields(fields[:])
tarr := typ(TARRAY) tarr := typ(TARRAY)
tarr.Bound = int64(b) tarr.Bound = int64(b)

View File

@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) {
{Name{}, 52, 80}, {Name{}, 52, 80},
{Node{}, 92, 144}, {Node{}, 92, 144},
{Sym{}, 60, 112}, {Sym{}, 60, 112},
{Type{}, 136, 224}, {Type{}, 140, 232},
} }
for _, tt := range tests { for _, tt := range tests {

View File

@ -592,13 +592,7 @@ func Isinter(t *Type) bool {
} }
func isnilinter(t *Type) bool { func isnilinter(t *Type) bool {
if !Isinter(t) { return Isinter(t) && countfield(t) == 0
return false
}
if t.Type != nil {
return false
}
return true
} }
func isideal(t *Type) bool { func isideal(t *Type) bool {

View File

@ -140,6 +140,9 @@ type Type struct {
Type *Type // actual type for TFIELD, element type for TARRAY, TCHAN, TMAP, TPTRxx Type *Type // actual type for TFIELD, element type for TARRAY, TCHAN, TMAP, TPTRxx
Width int64 // offset in TFIELD, width in all others Width int64 // offset in TFIELD, width in all others
// TSTRUCT
Fields *Type // first struct field
// TFIELD // TFIELD
Down *Type // next struct field, also key type in TMAP Down *Type // next struct field, also key type in TMAP
Note *string // literal string annotation Note *string // literal string annotation
@ -196,7 +199,7 @@ func IterFields(t *Type) (*Type, Iter) {
if t.Etype != TSTRUCT && t.Etype != TINTER { if t.Etype != TSTRUCT && t.Etype != TINTER {
Fatalf("IterFields: type %v does not have fields", t) 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 // IterMethods returns the first method in type t's method set
@ -316,7 +319,7 @@ func (t *Type) SetFields(fields []*Type) {
fields[i].Down = next fields[i].Down = next
next = fields[i] next = fields[i]
} }
t.Type = next t.Fields = next
} }
func (t *Type) Size() int64 { func (t *Type) Size() int64 {

View File

@ -1333,15 +1333,7 @@ OpSwitch:
} }
ok |= Erv ok |= Erv
if t.Outtuple == 1 { if t.Outtuple == 1 {
t := l.Type.Results().Type n.Type = l.Type.Results().Field(0).Type
if t == nil {
n.Type = nil
return
}
if t.Etype == TFIELD {
t = t.Type
}
n.Type = t
if n.Op == OCALLFUNC && n.Left.Op == ONAME && (compiling_runtime != 0 || n.Left.Sym.Pkg == Runtimepkg) && n.Left.Sym.Name == "getg" { 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. // Emit code for runtime.getg() directly instead of calling function.
@ -1603,7 +1595,7 @@ OpSwitch:
var funarg *Type var funarg *Type
if Istype(t, TSTRUCT) && t.Funarg { if Istype(t, TSTRUCT) && t.Funarg {
funarg = t funarg = t
t = t.Type.Type t = t.Field(0).Type
} }
n.Type = t n.Type = t
@ -1642,7 +1634,8 @@ OpSwitch:
} }
if funarg != nil { 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 { if assignop(t.Type, n.Type.Type, nil) == 0 {
Yyerror("cannot append %v value to []%v", t.Type, n.Type.Type) Yyerror("cannot append %v value to []%v", t.Type, n.Type.Type)
} }
@ -2403,7 +2396,7 @@ func looktypedot(n *Node, t *Type, dostrcmp int) bool {
s := n.Right.Sym s := n.Right.Sym
if t.Etype == TINTER { if t.Etype == TINTER {
f1 := lookdot1(n, s, t, t.Type, dostrcmp) f1 := lookdot1(n, s, t, t.Fields, dostrcmp)
if f1 == nil { if f1 == nil {
return false return false
} }
@ -2464,7 +2457,7 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Type {
dowidth(t) dowidth(t)
var f1 *Type var f1 *Type
if t.Etype == TSTRUCT || t.Etype == TINTER { 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 var f2 *Type
@ -2627,11 +2620,11 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
} }
} }
tn := n.Type.Type tn, it := IterFields(n.Type)
var why string var why string
for tl, it2 := IterFields(tstruct); tl != nil; tl = it2.Next() { for tl, it2 := IterFields(tstruct); tl != nil; tl = it2.Next() {
if tl.Isddd { 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 assignop(tn.Type, tl.Type.Type, &why) == 0 {
if call != nil { if call != nil {
Yyerror("cannot use %v as type %v in argument to %v%s", tn.Type, tl.Type.Type, call, why) Yyerror("cannot use %v as type %v in argument to %v%s", tn.Type, tl.Type.Type, call, why)
@ -2655,7 +2648,7 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
} }
} }
tn = tn.Down tn = it.Next()
} }
if tn != nil { if tn != nil {
@ -3049,7 +3042,7 @@ func typecheckcomplit(np **Node) {
bad := 0 bad := 0
if n.List.Len() != 0 && nokeys(n.List) { if n.List.Len() != 0 && nokeys(n.List) {
// simple list of variables // simple list of variables
f := t.Type f, it := IterFields(t)
var s *Sym var s *Sym
ls := n.List.Slice() ls := n.List.Slice()
@ -3075,7 +3068,7 @@ func typecheckcomplit(np **Node) {
n1.Left.Type = f n1.Left.Type = f
n1.Left.Typecheck = 1 n1.Left.Typecheck = 1
ls[i1] = n1 ls[i1] = n1
f = f.Down f = it.Next()
} }
if f != nil { if f != nil {
@ -3114,7 +3107,7 @@ func typecheckcomplit(np **Node) {
} }
} }
f := lookdot1(nil, s, t, t.Type, 0) f := lookdot1(nil, s, t, t.Fields, 0)
if f == nil { if f == nil {
Yyerror("unknown %v field '%v' in struct literal", t, s) Yyerror("unknown %v field '%v' in struct literal", t, s)
continue continue

View File

@ -367,17 +367,22 @@ func typeinit() {
func lexinit1() { func lexinit1() {
// t = interface { Error() string } // t = interface { Error() string }
rcvr := typ(TSTRUCT)
rcvr.Type = typ(TFIELD) rcvr := typ(TSTRUCT)
rcvr.Type.Type = Ptrto(typ(TSTRUCT))
rcvr.Funarg = true rcvr.Funarg = true
field := typ(TFIELD)
field.Type = Ptrto(typ(TSTRUCT))
rcvr.SetFields([]*Type{field})
in := typ(TSTRUCT) in := typ(TSTRUCT)
in.Funarg = true in.Funarg = true
out := typ(TSTRUCT) out := typ(TSTRUCT)
out.Type = typ(TFIELD)
out.Type.Type = Types[TSTRING]
out.Funarg = true out.Funarg = true
field = typ(TFIELD)
field.Type = Types[TSTRING]
out.SetFields([]*Type{field})
f := typ(TFUNC) f := typ(TFUNC)
*f.RecvsP() = rcvr *f.RecvsP() = rcvr
*f.ResultsP() = out *f.ResultsP() = out
@ -386,10 +391,12 @@ func lexinit1() {
f.Intuple = 0 f.Intuple = 0
f.Outnamed = false f.Outnamed = false
f.Outtuple = 1 f.Outtuple = 1
t := typ(TINTER) t := typ(TINTER)
t.Type = typ(TFIELD) field = typ(TFIELD)
t.Type.Sym = Lookup("Error") field.Sym = Lookup("Error")
t.Type.Type = f field.Type = f
t.SetFields([]*Type{field})
// error type // error type
s := Pkglookup("error", builtinpkg) s := Pkglookup("error", builtinpkg)

View File

@ -658,11 +658,7 @@ opswitch:
// Update type of OCALLFUNC node. // Update type of OCALLFUNC node.
// Output arguments had not changed, but their offsets could. // Output arguments had not changed, but their offsets could.
if n.Left.Type.Outtuple == 1 { if n.Left.Type.Outtuple == 1 {
t := n.Left.Type.Results().Type n.Type = n.Left.Type.Results().Field(0).Type
if t.Etype == TFIELD {
t = t.Type
}
n.Type = t
} else { } else {
n.Type = n.Left.Type.Results() n.Type = n.Left.Type.Results()
} }
@ -2008,13 +2004,7 @@ func walkprint(nn *Node, init *Nodes) *Node {
continue continue
} }
t = on.Type.Params() t = on.Type.Params().Field(0).Type
if t != nil {
t = t.Type
}
if t != nil {
t = t.Type
}
if !Eqtype(t, n.Type) { if !Eqtype(t, n.Type) {
n = Nod(OCONV, n, nil) n = Nod(OCONV, n, nil)

View File

@ -639,7 +639,7 @@ func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
// A special case to make write barriers more efficient. // A special case to make write barriers more efficient.
// Comparing the first field of a named struct can be done directly. // Comparing the first field of a named struct can be done directly.
base := n1 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 base = n1.Left
} }