Commit 0d2e92c2 authored by Matthew Dempsky's avatar Matthew Dempsky

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: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: 's avatarRobert Griesemer <gri@golang.org>
parent 79718642
......@@ -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,8 +202,11 @@ func reexportdep(n *Node) {
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 @@ 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)
}
dumpexporttype(t.Type)
dumpexporttype(t.Down)
if t.Sym == nil || t.Etype == TFIELD {
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 {
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
syma := Lookup("a")
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
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
}
......
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