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.
// 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
}

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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++ {

View File

@ -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))

View File

@ -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("}")

View File

@ -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))

View File

@ -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()
}
}

View File

@ -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()
}
}
}

View File

@ -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)

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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

View File

@ -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)

View File

@ -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)

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.
// 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
}