Commit c278f930 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: stop storing TFIELD types in Node.Type

Currently, the only use for this is on the Left side of OKEY nodes
within struct literals.  esc and fmt only care so they can recognize
that the ONAME nodes are actually field names, which need special
handling.

sinit additionally needs to know the field's offset within the struct,
which we can provide via Xoffset.

Passes toolstash/buildall.

Change-Id: I362d965e161f4d80fcd9c9bae0dfacc657dc0b29
Reviewed-on: https://go-review.googlesource.com/20676Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 9bffcf38
...@@ -576,7 +576,7 @@ func esc(e *EscState, n *Node, up *Node) { ...@@ -576,7 +576,7 @@ func esc(e *EscState, n *Node, up *Node) {
if n == nil { if n == nil {
return return
} }
if n.Type != nil && n.Type.Etype == TFIELD { if n.Type == structkey {
// This is the left side of x:y in a struct literal. // This is the left side of x:y in a struct literal.
// x is syntax, not an expression. // x is syntax, not an expression.
// See #14405. // See #14405.
......
...@@ -1287,7 +1287,7 @@ func exprfmt(n *Node, prec int) string { ...@@ -1287,7 +1287,7 @@ func exprfmt(n *Node, prec int) string {
case OKEY: case OKEY:
if n.Left != nil && n.Right != nil { if n.Left != nil && n.Right != nil {
if fmtmode == FExp && n.Left.Type != nil && n.Left.Type.Etype == TFIELD { if fmtmode == FExp && n.Left.Type == structkey {
// requires special handling of field names // requires special handling of field names
return fmt.Sprintf("%v:%v", Sconv(n.Left.Sym, obj.FmtShort|obj.FmtByte), n.Right) return fmt.Sprintf("%v:%v", Sconv(n.Left.Sym, obj.FmtShort|obj.FmtByte), n.Right)
} else { } else {
......
...@@ -1246,10 +1246,10 @@ func initplan(n *Node) { ...@@ -1246,10 +1246,10 @@ func initplan(n *Node) {
case OSTRUCTLIT: case OSTRUCTLIT:
for _, a := range n.List.Slice() { for _, a := range n.List.Slice() {
if a.Op != OKEY || a.Left.Type == nil { if a.Op != OKEY || a.Left.Type != structkey {
Fatalf("initplan structlit") Fatalf("initplan structlit")
} }
addvalue(p, a.Left.Type.Width, a.Right) addvalue(p, a.Left.Xoffset, a.Right)
} }
case OMAPLIT: case OMAPLIT:
......
...@@ -33,6 +33,13 @@ type Node struct { ...@@ -33,6 +33,13 @@ type Node struct {
Sym *Sym // various Sym *Sym // various
E interface{} // Opt or Val, see methods below E interface{} // Opt or Val, see methods below
// Various. Usually an offset into a struct. For example, ONAME nodes
// that refer to local variables use it to identify their stack frame
// position. ODOT, ODOTPTR, and OINDREG use it to indicate offset
// relative to their base address. ONAME nodes on the left side of an
// OKEY within an OSTRUCTLIT use it to store the named field's offset.
// OXCASE and OXFALL use it to validate the use of fallthrough.
// Possibly still more uses. If you find any, document them.
Xoffset int64 Xoffset int64
Lineno int32 Lineno int32
......
...@@ -2893,6 +2893,11 @@ func pushtype(n *Node, t *Type) { ...@@ -2893,6 +2893,11 @@ func pushtype(n *Node, t *Type) {
} }
} }
// Marker type so esc, fmt, and sinit can recognize the LHS of an OKEY node
// in a struct literal.
// TODO(mdempsky): Find a nicer solution.
var structkey = typ(Txxx)
func typecheckcomplit(np **Node) { func typecheckcomplit(np **Node) {
n := *np n := *np
lno := lineno lno := lineno
...@@ -3039,6 +3044,9 @@ func typecheckcomplit(np **Node) { ...@@ -3039,6 +3044,9 @@ func typecheckcomplit(np **Node) {
n.Op = OMAPLIT n.Op = OMAPLIT
case TSTRUCT: case TSTRUCT:
// Need valid field offsets for Xoffset below.
dowidth(t)
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
...@@ -3065,7 +3073,8 @@ func typecheckcomplit(np **Node) { ...@@ -3065,7 +3073,8 @@ func typecheckcomplit(np **Node) {
// No pushtype allowed here. Must name fields for that. // No pushtype allowed here. Must name fields for that.
n1 = assignconv(n1, f.Type, "field value") n1 = assignconv(n1, f.Type, "field value")
n1 = Nod(OKEY, newname(f.Sym), n1) n1 = Nod(OKEY, newname(f.Sym), n1)
n1.Left.Type = f n1.Left.Type = structkey
n1.Left.Xoffset = f.Width
n1.Left.Typecheck = 1 n1.Left.Typecheck = 1
ls[i1] = n1 ls[i1] = n1
f = it.Next() f = it.Next()
...@@ -3114,8 +3123,9 @@ func typecheckcomplit(np **Node) { ...@@ -3114,8 +3123,9 @@ func typecheckcomplit(np **Node) {
} }
l.Left = newname(s) l.Left = newname(s)
l.Left.Type = structkey
l.Left.Xoffset = f.Width
l.Left.Typecheck = 1 l.Left.Typecheck = 1
l.Left.Type = f
s = f.Sym s = f.Sym
fielddup(newname(s), hash) fielddup(newname(s), hash)
r = l.Right r = l.Right
......
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