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:
parent
7971864267
commit
0d2e92c2ca
@ -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.
|
||||
// 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
|
||||
}
|
||||
|
||||
|
@ -652,7 +652,7 @@ func (p *exporter) paramList(params *Type) {
|
||||
// (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)
|
||||
|
@ -802,7 +802,7 @@ func cgen_wbptr(n, res *Node) {
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -1133,7 +1133,7 @@ func isifacemethod(f *Type) bool {
|
||||
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
|
||||
|
@ -1478,7 +1478,7 @@ func esccall(e *EscState, n *Node, up *Node) {
|
||||
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 @@ func esccall(e *EscState, n *Node, up *Node) {
|
||||
// This occurs when function parameter type Isddd and n not Isddd
|
||||
break
|
||||
}
|
||||
t = t.Down
|
||||
t = it.Next()
|
||||
}
|
||||
|
||||
for ; i < len(lls); i++ {
|
||||
|
@ -202,9 +202,12 @@ func reexportdep(n *Node) {
|
||||
OMAKECHAN:
|
||||
t := n.Type
|
||||
|
||||
if t.Sym == nil && t.Type != nil {
|
||||
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 {
|
||||
fmt.Printf("reexport type for expression %v\n", t.Sym)
|
||||
@ -280,25 +283,41 @@ func dumpexporttype(t *Type) {
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
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))
|
||||
|
@ -602,7 +602,7 @@ func typefmt(t *Type, flag int) string {
|
||||
buf.WriteString(";")
|
||||
}
|
||||
}
|
||||
if t.Type != nil {
|
||||
if t.Fields != nil {
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
buf.WriteString("}")
|
||||
@ -629,7 +629,7 @@ func typefmt(t *Type, flag int) string {
|
||||
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 @@ func typefmt(t *Type, flag int) string {
|
||||
buf.WriteString(";")
|
||||
}
|
||||
}
|
||||
if t.Type != nil {
|
||||
if t.Fields != nil {
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
buf.WriteString("}")
|
||||
|
@ -412,7 +412,7 @@ func Naddr(a *obj.Addr, n *Node) {
|
||||
// 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))
|
||||
|
@ -700,8 +700,8 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
}
|
||||
} 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 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
break
|
||||
}
|
||||
as.List.Append(tinlvar(t))
|
||||
t = t.Down
|
||||
t = it.Next()
|
||||
li++
|
||||
}
|
||||
|
||||
@ -725,7 +725,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
|
||||
}
|
||||
|
||||
if i == varargcount {
|
||||
t = t.Down
|
||||
t = it.Next()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,7 +371,7 @@ func ordercall(n *Node, order *Order) {
|
||||
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 @@ func ordercall(n *Node, order *Order) {
|
||||
*xp = x
|
||||
}
|
||||
}
|
||||
t = t.Down
|
||||
t = it.Next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -883,19 +883,19 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||
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)
|
||||
|
@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) {
|
||||
{Name{}, 52, 80},
|
||||
{Node{}, 92, 144},
|
||||
{Sym{}, 60, 112},
|
||||
{Type{}, 136, 224},
|
||||
{Type{}, 140, 232},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
@ -592,13 +592,7 @@ func Isinter(t *Type) bool {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -140,6 +140,9 @@ type Type struct {
|
||||
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 @@ func IterFields(t *Type) (*Type, Iter) {
|
||||
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 @@ func (t *Type) SetFields(fields []*Type) {
|
||||
fields[i].Down = next
|
||||
next = fields[i]
|
||||
}
|
||||
t.Type = next
|
||||
t.Fields = next
|
||||
}
|
||||
|
||||
func (t *Type) Size() int64 {
|
||||
|
@ -1333,15 +1333,7 @@ OpSwitch:
|
||||
}
|
||||
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 @@ OpSwitch:
|
||||
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 @@ OpSwitch:
|
||||
}
|
||||
|
||||
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 @@ func looktypedot(n *Node, t *Type, dostrcmp int) bool {
|
||||
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 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Type {
|
||||
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 @@ 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
|
||||
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 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
|
||||
}
|
||||
}
|
||||
|
||||
tn = tn.Down
|
||||
tn = it.Next()
|
||||
}
|
||||
|
||||
if tn != nil {
|
||||
@ -3049,7 +3042,7 @@ func typecheckcomplit(np **Node) {
|
||||
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 @@ func typecheckcomplit(np **Node) {
|
||||
n1.Left.Type = f
|
||||
n1.Left.Typecheck = 1
|
||||
ls[i1] = n1
|
||||
f = f.Down
|
||||
f = it.Next()
|
||||
}
|
||||
|
||||
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 {
|
||||
Yyerror("unknown %v field '%v' in struct literal", t, s)
|
||||
continue
|
||||
|
@ -367,17 +367,22 @@ func typeinit() {
|
||||
|
||||
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 @@ func lexinit1() {
|
||||
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)
|
||||
|
@ -658,11 +658,7 @@ opswitch:
|
||||
// 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 @@ func walkprint(nn *Node, init *Nodes) *Node {
|
||||
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)
|
||||
|
@ -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.
|
||||
// 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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user