]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: adjust IR representations
authorRuss Cox <rsc@golang.org>
Mon, 7 Dec 2020 14:14:44 +0000 (09:14 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 9 Dec 2020 17:05:32 +0000 (17:05 +0000)
Based on actually using the IR when prototyping adding
type assertions, a few changes to improve it:

- Merge DeferStmt and GoStmt, since they are variants of one thing.
- Introduce LogicalExpr for && and ||, since they (alone) need an init list before Y.
- Add an explicit op to various constructors to make them easier to use.
- Add separate StructKeyExpr - it stores Value in a different abstract location (Left) than KeyExpr (Right).
- Export all fields for use by rewrites (and later reflection).

Passes buildall w/ toolstash -cmp.

Change-Id: Iefbff2386d2bb9ef511ce53b7f92ff6c709dc991
Reviewed-on: https://go-review.googlesource.com/c/go/+/275883
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/universe.go
src/cmd/compile/internal/ir/expr.go
src/cmd/compile/internal/ir/name.go
src/cmd/compile/internal/ir/node.go
src/cmd/compile/internal/ir/node_gen.go
src/cmd/compile/internal/ir/stmt.go
src/cmd/compile/internal/ir/val.go

index 990921189a439a6c8fe233209fccdc139a33dcd9..36526d4c2d6e7ce6d2c71355124b106717ae08e0 100644 (file)
@@ -2010,18 +2010,13 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
                }
                return n
 
-       case ir.ODEFER:
+       case ir.ODEFER, ir.OGO:
                n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr))
                if !n.Left().Diag() {
                        checkdefergo(n)
                }
                return n
 
-       case ir.OGO:
-               n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr))
-               checkdefergo(n)
-               return n
-
        case ir.OFOR, ir.OFORUNTIL:
                typecheckslice(n.Init().Slice(), ctxStmt)
                decldepth++
@@ -2885,9 +2880,9 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
                                if l.Op() == ir.OKEY {
                                        key := l.Left()
 
-                                       l.SetOp(ir.OSTRUCTKEY)
-                                       l.SetLeft(l.Right())
-                                       l.SetRight(nil)
+                                       sk := ir.NewStructKeyExpr(l.Pos(), nil, l.Right())
+                                       ls[i] = sk
+                                       l = sk
 
                                        // An OXDOT uses the Sym field to hold
                                        // the field to the right of the dot,
@@ -2895,7 +2890,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
                                        // is never a valid struct literal key.
                                        if key.Sym() == nil || key.Op() == ir.OXDOT || key.Sym().IsBlank() {
                                                base.Errorf("invalid field name %v in struct initializer", key)
-                                               l.SetLeft(typecheck(l.Left(), ctxExpr))
+                                               sk.SetLeft(typecheck(sk.Left(), ctxExpr))
                                                continue
                                        }
 
@@ -2909,7 +2904,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
                                                        s = s1
                                                }
                                        }
-                                       l.SetSym(s)
+                                       sk.SetSym(s)
                                }
 
                                if l.Op() != ir.OSTRUCTKEY {
index 42b996d88d918afb9dedcbca28375a406ddc21d0..c592e37497ddb23a3c809bcb19e949f3e9c7ac5d 100644 (file)
@@ -202,8 +202,7 @@ func initUniverse() {
        ir.AsNode(s.Def).SetSym(s)
 
        s = types.BuiltinPkg.Lookup("iota")
-       s.Def = ir.Nod(ir.OIOTA, nil, nil)
-       ir.AsNode(s.Def).SetSym(s)
+       s.Def = ir.NewIota(base.Pos, s)
 
        for et := types.TINT8; et <= types.TUINT64; et++ {
                isInt[et] = true
index a74e0712b91d6b0eb2dbcf04ed2b8d46e352ddab..8ea31c1929c890c6a925bd60fe2c7ab2bb3ec7be 100644 (file)
@@ -159,8 +159,8 @@ func (n *BinaryExpr) SetOp(op Op) {
        switch op {
        default:
                panic(n.no("SetOp " + op.String()))
-       case OADD, OADDSTR, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
-               OLSH, OLT, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSUB, OXOR,
+       case OADD, OADDSTR, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
+               OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR,
                OCOPY, OCOMPLEX,
                OEFACE:
                n.op = op
@@ -181,21 +181,21 @@ const (
 // A CallExpr is a function call X(Args).
 type CallExpr struct {
        miniExpr
-       orig     Node
-       X        Node
-       Args     Nodes
-       Rargs    Nodes // TODO(rsc): Delete.
-       Body_    Nodes // TODO(rsc): Delete.
-       DDD      bool
-       Use      CallUse
-       noInline bool
+       orig      Node
+       X         Node
+       Args      Nodes
+       Rargs     Nodes // TODO(rsc): Delete.
+       Body_     Nodes // TODO(rsc): Delete.
+       DDD       bool
+       Use       CallUse
+       NoInline_ bool
 }
 
-func NewCallExpr(pos src.XPos, fun Node, args []Node) *CallExpr {
+func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr {
        n := &CallExpr{X: fun}
        n.pos = pos
        n.orig = n
-       n.op = OCALL
+       n.SetOp(op)
        n.Args.Set(args)
        return n
 }
@@ -214,8 +214,8 @@ func (n *CallExpr) PtrRlist() *Nodes   { return &n.Rargs }
 func (n *CallExpr) SetRlist(x Nodes)   { n.Rargs = x }
 func (n *CallExpr) IsDDD() bool        { return n.DDD }
 func (n *CallExpr) SetIsDDD(x bool)    { n.DDD = x }
-func (n *CallExpr) NoInline() bool     { return n.noInline }
-func (n *CallExpr) SetNoInline(x bool) { n.noInline = x }
+func (n *CallExpr) NoInline() bool     { return n.NoInline_ }
+func (n *CallExpr) SetNoInline(x bool) { n.NoInline_ = x }
 func (n *CallExpr) Body() Nodes        { return n.Body_ }
 func (n *CallExpr) PtrBody() *Nodes    { return &n.Body_ }
 func (n *CallExpr) SetBody(x Nodes)    { n.Body_ = x }
@@ -233,21 +233,21 @@ func (n *CallExpr) SetOp(op Op) {
 // A CallPartExpr is a method expression X.Method (uncalled).
 type CallPartExpr struct {
        miniExpr
-       fn     *Func
+       Func_  *Func
        X      Node
        Method *types.Field
 }
 
 func NewCallPartExpr(pos src.XPos, x Node, method *types.Field, fn *Func) *CallPartExpr {
-       n := &CallPartExpr{fn: fn, X: x, Method: method}
+       n := &CallPartExpr{Func_: fn, X: x, Method: method}
        n.op = OCALLPART
        n.pos = pos
        n.typ = fn.Type()
-       n.fn = fn
+       n.Func_ = fn
        return n
 }
 
-func (n *CallPartExpr) Func() *Func     { return n.fn }
+func (n *CallPartExpr) Func() *Func     { return n.Func_ }
 func (n *CallPartExpr) Left() Node      { return n.X }
 func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym }
 func (n *CallPartExpr) SetLeft(x Node)  { n.X = x }
@@ -268,20 +268,20 @@ func NewClosureExpr(pos src.XPos, fn *Func) *ClosureExpr {
 func (n *ClosureExpr) Func() *Func { return n.Func_ }
 
 // A ClosureRead denotes reading a variable stored within a closure struct.
-type ClosureRead struct {
+type ClosureReadExpr struct {
        miniExpr
-       offset int64
+       Offset_ int64
 }
 
-func NewClosureRead(typ *types.Type, offset int64) *ClosureRead {
-       n := &ClosureRead{offset: offset}
+func NewClosureRead(typ *types.Type, offset int64) *ClosureReadExpr {
+       n := &ClosureReadExpr{Offset_: offset}
        n.typ = typ
        n.op = OCLOSUREREAD
        return n
 }
 
-func (n *ClosureRead) Type() *types.Type { return n.typ }
-func (n *ClosureRead) Offset() int64     { return n.offset }
+func (n *ClosureReadExpr) Type() *types.Type { return n.typ }
+func (n *ClosureReadExpr) Offset() int64     { return n.Offset_ }
 
 // A CompLitExpr is a composite literal Type{Vals}.
 // Before type-checking, the type is Ntype.
@@ -292,10 +292,10 @@ type CompLitExpr struct {
        List_ Nodes // initialized values
 }
 
-func NewCompLitExpr(pos src.XPos, typ Ntype, list []Node) *CompLitExpr {
+func NewCompLitExpr(pos src.XPos, op Op, typ Ntype, list []Node) *CompLitExpr {
        n := &CompLitExpr{Ntype: typ}
        n.pos = pos
-       n.op = OCOMPLIT
+       n.SetOp(op)
        n.List_.Set(list)
        n.orig = n
        return n
@@ -397,42 +397,48 @@ func (n *IndexExpr) SetOp(op Op) {
        }
 }
 
-// A KeyExpr is an X:Y composite literal key.
-// After type-checking, a key for a struct sets Sym to the field.
+// A KeyExpr is a Key: Value composite literal key.
 type KeyExpr struct {
        miniExpr
-       Key    Node
-       sym    *types.Sym
-       Value  Node
-       offset int64
+       Key   Node
+       Value Node
 }
 
 func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr {
        n := &KeyExpr{Key: key, Value: value}
        n.pos = pos
        n.op = OKEY
-       n.offset = types.BADWIDTH
        return n
 }
 
-func (n *KeyExpr) Left() Node          { return n.Key }
-func (n *KeyExpr) SetLeft(x Node)      { n.Key = x }
-func (n *KeyExpr) Right() Node         { return n.Value }
-func (n *KeyExpr) SetRight(y Node)     { n.Value = y }
-func (n *KeyExpr) Sym() *types.Sym     { return n.sym }
-func (n *KeyExpr) SetSym(x *types.Sym) { n.sym = x }
-func (n *KeyExpr) Offset() int64       { return n.offset }
-func (n *KeyExpr) SetOffset(x int64)   { n.offset = x }
+func (n *KeyExpr) Left() Node      { return n.Key }
+func (n *KeyExpr) SetLeft(x Node)  { n.Key = x }
+func (n *KeyExpr) Right() Node     { return n.Value }
+func (n *KeyExpr) SetRight(y Node) { n.Value = y }
 
-func (n *KeyExpr) SetOp(op Op) {
-       switch op {
-       default:
-               panic(n.no("SetOp " + op.String()))
-       case OKEY, OSTRUCTKEY:
-               n.op = op
-       }
+// A StructKeyExpr is an Field: Value composite literal key.
+type StructKeyExpr struct {
+       miniExpr
+       Field   *types.Sym
+       Value   Node
+       Offset_ int64
+}
+
+func NewStructKeyExpr(pos src.XPos, field *types.Sym, value Node) *StructKeyExpr {
+       n := &StructKeyExpr{Field: field, Value: value}
+       n.pos = pos
+       n.op = OSTRUCTKEY
+       n.Offset_ = types.BADWIDTH
+       return n
 }
 
+func (n *StructKeyExpr) Sym() *types.Sym     { return n.Field }
+func (n *StructKeyExpr) SetSym(x *types.Sym) { n.Field = x }
+func (n *StructKeyExpr) Left() Node          { return n.Value }
+func (n *StructKeyExpr) SetLeft(x Node)      { n.Value = x }
+func (n *StructKeyExpr) Offset() int64       { return n.Offset_ }
+func (n *StructKeyExpr) SetOffset(x int64)   { n.Offset_ = x }
+
 // An InlinedCallExpr is an inlined function call.
 type InlinedCallExpr struct {
        miniExpr
@@ -456,6 +462,36 @@ func (n *InlinedCallExpr) Rlist() Nodes     { return n.ReturnVars }
 func (n *InlinedCallExpr) PtrRlist() *Nodes { return &n.ReturnVars }
 func (n *InlinedCallExpr) SetRlist(x Nodes) { n.ReturnVars = x }
 
+// A LogicalExpr is a expression X Op Y where Op is && or ||.
+// It is separate from BinaryExpr to make room for statements
+// that must be executed before Y but after X.
+type LogicalExpr struct {
+       miniExpr
+       X Node
+       Y Node
+}
+
+func NewLogicalExpr(pos src.XPos, op Op, x, y Node) *LogicalExpr {
+       n := &LogicalExpr{X: x, Y: y}
+       n.pos = pos
+       n.SetOp(op)
+       return n
+}
+
+func (n *LogicalExpr) Left() Node      { return n.X }
+func (n *LogicalExpr) SetLeft(x Node)  { n.X = x }
+func (n *LogicalExpr) Right() Node     { return n.Y }
+func (n *LogicalExpr) SetRight(y Node) { n.Y = y }
+
+func (n *LogicalExpr) SetOp(op Op) {
+       switch op {
+       default:
+               panic(n.no("SetOp " + op.String()))
+       case OANDAND, OOROR:
+               n.op = op
+       }
+}
+
 // A MakeExpr is a make expression: make(Type[, Len[, Cap]]).
 // Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY,
 // but *not* OMAKE (that's a pre-typechecking CallExpr).
@@ -489,19 +525,19 @@ func (n *MakeExpr) SetOp(op Op) {
 // A MethodExpr is a method value X.M (where X is an expression, not a type).
 type MethodExpr struct {
        miniExpr
-       X      Node
-       M      Node
-       sym    *types.Sym
-       offset int64
-       class  Class
-       Method *types.Field
+       X       Node
+       M       Node
+       Sym_    *types.Sym
+       Offset_ int64
+       Class_  Class
+       Method  *types.Field
 }
 
-func NewMethodExpr(pos src.XPos, op Op, x, m Node) *MethodExpr {
+func NewMethodExpr(pos src.XPos, x, m Node) *MethodExpr {
        n := &MethodExpr{X: x, M: m}
        n.pos = pos
        n.op = OMETHEXPR
-       n.offset = types.BADWIDTH
+       n.Offset_ = types.BADWIDTH
        return n
 }
 
@@ -509,18 +545,18 @@ func (n *MethodExpr) Left() Node          { return n.X }
 func (n *MethodExpr) SetLeft(x Node)      { n.X = x }
 func (n *MethodExpr) Right() Node         { return n.M }
 func (n *MethodExpr) SetRight(y Node)     { n.M = y }
-func (n *MethodExpr) Sym() *types.Sym     { return n.sym }
-func (n *MethodExpr) SetSym(x *types.Sym) { n.sym = x }
-func (n *MethodExpr) Offset() int64       { return n.offset }
-func (n *MethodExpr) SetOffset(x int64)   { n.offset = x }
-func (n *MethodExpr) Class() Class        { return n.class }
-func (n *MethodExpr) SetClass(x Class)    { n.class = x }
+func (n *MethodExpr) Sym() *types.Sym     { return n.Sym_ }
+func (n *MethodExpr) SetSym(x *types.Sym) { n.Sym_ = x }
+func (n *MethodExpr) Offset() int64       { return n.Offset_ }
+func (n *MethodExpr) SetOffset(x int64)   { n.Offset_ = x }
+func (n *MethodExpr) Class() Class        { return n.Class_ }
+func (n *MethodExpr) SetClass(x Class)    { n.Class_ = x }
 
 // A NilExpr represents the predefined untyped constant nil.
 // (It may be copied and assigned a type, though.)
 type NilExpr struct {
        miniExpr
-       sym *types.Sym // TODO: Remove
+       Sym_ *types.Sym // TODO: Remove
 }
 
 func NewNilExpr(pos src.XPos) *NilExpr {
@@ -530,8 +566,8 @@ func NewNilExpr(pos src.XPos) *NilExpr {
        return n
 }
 
-func (n *NilExpr) Sym() *types.Sym     { return n.sym }
-func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x }
+func (n *NilExpr) Sym() *types.Sym     { return n.Sym_ }
+func (n *NilExpr) SetSym(x *types.Sym) { n.Sym_ = x }
 
 // A ParenExpr is a parenthesized expression (X).
 // It may end up being a value or a type.
@@ -563,34 +599,34 @@ func (n *ParenExpr) SetOTYPE(t *types.Type) {
 // A ResultExpr represents a direct access to a result slot on the stack frame.
 type ResultExpr struct {
        miniExpr
-       offset int64
+       Offset_ int64
 }
 
 func NewResultExpr(pos src.XPos, typ *types.Type, offset int64) *ResultExpr {
-       n := &ResultExpr{offset: offset}
+       n := &ResultExpr{Offset_: offset}
        n.pos = pos
        n.op = ORESULT
        n.typ = typ
        return n
 }
 
-func (n *ResultExpr) Offset() int64     { return n.offset }
-func (n *ResultExpr) SetOffset(x int64) { n.offset = x }
+func (n *ResultExpr) Offset() int64     { return n.Offset_ }
+func (n *ResultExpr) SetOffset(x int64) { n.Offset_ = x }
 
 // A SelectorExpr is a selector expression X.Sym.
 type SelectorExpr struct {
        miniExpr
        X         Node
        Sel       *types.Sym
-       offset    int64
+       Offset_   int64
        Selection *types.Field
 }
 
-func NewSelectorExpr(pos src.XPos, x Node, sel *types.Sym) *SelectorExpr {
+func NewSelectorExpr(pos src.XPos, op Op, x Node, sel *types.Sym) *SelectorExpr {
        n := &SelectorExpr{X: x, Sel: sel}
        n.pos = pos
-       n.op = OXDOT
-       n.offset = types.BADWIDTH
+       n.Offset_ = types.BADWIDTH
+       n.SetOp(op)
        return n
 }
 
@@ -607,8 +643,8 @@ func (n *SelectorExpr) Left() Node          { return n.X }
 func (n *SelectorExpr) SetLeft(x Node)      { n.X = x }
 func (n *SelectorExpr) Sym() *types.Sym     { return n.Sel }
 func (n *SelectorExpr) SetSym(x *types.Sym) { n.Sel = x }
-func (n *SelectorExpr) Offset() int64       { return n.offset }
-func (n *SelectorExpr) SetOffset(x int64)   { n.offset = x }
+func (n *SelectorExpr) Offset() int64       { return n.Offset_ }
+func (n *SelectorExpr) SetOffset(x int64)   { n.Offset_ = x }
 
 // Before type-checking, bytes.Buffer is a SelectorExpr.
 // After type-checking it becomes a Name.
index 319c40e4e93733029ac9e59573110f5f86340fce..4cf12f2c5d7f9efee201317dc7ff15450f4bd084 100644 (file)
@@ -132,6 +132,14 @@ func NewNameAt(pos src.XPos, sym *types.Sym) *Name {
        return newNameAt(pos, ONAME, sym)
 }
 
+// NewIota returns a new OIOTA Node.
+func NewIota(pos src.XPos, sym *types.Sym) *Name {
+       if sym == nil {
+               base.Fatalf("NewIota nil")
+       }
+       return newNameAt(pos, OIOTA, sym)
+}
+
 // NewDeclNameAt returns a new ONONAME Node associated with symbol s at position pos.
 // The caller is responsible for setting Curfn.
 func NewDeclNameAt(pos src.XPos, sym *types.Sym) *Name {
index d6dab0b9e21bd963df1ed9774ba979ce0235a932..0191014133c2af89e1eab41366c57855d36d147d 100644 (file)
@@ -681,30 +681,31 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
        switch op {
        default:
                panic("NodAt " + op.String())
-       case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
-               OLSH, OLT, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSUB, OXOR,
+       case OADD, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
+               OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR,
                OCOPY, OCOMPLEX,
                OEFACE:
                return NewBinaryExpr(pos, op, nleft, nright)
-       case OADDR, OPTRLIT:
+       case OADDR:
                return NewAddrExpr(pos, nleft)
        case OADDSTR:
                return NewAddStringExpr(pos, nil)
+       case OANDAND, OOROR:
+               return NewLogicalExpr(pos, op, nleft, nright)
        case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT:
                var typ Ntype
                if nright != nil {
                        typ = nright.(Ntype)
                }
-               n := NewCompLitExpr(pos, typ, nil)
-               n.SetOp(op)
-               return n
+               return NewCompLitExpr(pos, op, typ, nil)
        case OAS, OSELRECV:
                n := NewAssignStmt(pos, nleft, nright)
-               n.SetOp(op)
+               if op != OAS {
+                       n.SetOp(op)
+               }
                return n
        case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, OSELRECV2:
-               n := NewAssignListStmt(pos, nil, nil)
-               n.SetOp(op)
+               n := NewAssignListStmt(pos, op, nil, nil)
                return n
        case OASOP:
                return NewAssignOpStmt(pos, OXXX, nleft, nright)
@@ -722,9 +723,7 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
                return NewBranchStmt(pos, op, nil)
        case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH,
                OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER:
-               n := NewCallExpr(pos, nleft, nil)
-               n.SetOp(op)
-               return n
+               return NewCallExpr(pos, op, nleft, nil)
        case OCASE:
                return NewCaseStmt(pos, nil, nil)
        case OCONV, OCONVIFACE, OCONVNOP, ORUNESTR:
@@ -733,38 +732,38 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
                return NewDecl(pos, op, nleft)
        case ODCLFUNC:
                return NewFunc(pos)
-       case ODEFER:
-               return NewDeferStmt(pos, nleft)
+       case ODEFER, OGO:
+               return NewGoDeferStmt(pos, op, nleft)
        case ODEREF:
                return NewStarExpr(pos, nleft)
        case ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT:
-               n := NewSelectorExpr(pos, nleft, nil)
-               n.SetOp(op)
-               return n
+               return NewSelectorExpr(pos, op, nleft, nil)
        case ODOTTYPE, ODOTTYPE2:
                var typ Ntype
                if nright != nil {
                        typ = nright.(Ntype)
                }
                n := NewTypeAssertExpr(pos, nleft, typ)
-               n.SetOp(op)
+               if op != ODOTTYPE {
+                       n.SetOp(op)
+               }
                return n
        case OFOR:
                return NewForStmt(pos, nil, nleft, nright, nil)
-       case OGO:
-               return NewGoStmt(pos, nleft)
        case OIF:
                return NewIfStmt(pos, nleft, nil, nil)
        case OINDEX, OINDEXMAP:
                n := NewIndexExpr(pos, nleft, nright)
-               n.SetOp(op)
+               if op != OINDEX {
+                       n.SetOp(op)
+               }
                return n
        case OINLMARK:
                return NewInlineMarkStmt(pos, types.BADWIDTH)
-       case OKEY, OSTRUCTKEY:
-               n := NewKeyExpr(pos, nleft, nright)
-               n.SetOp(op)
-               return n
+       case OKEY:
+               return NewKeyExpr(pos, nleft, nright)
+       case OSTRUCTKEY:
+               return NewStructKeyExpr(pos, nil, nleft)
        case OLABEL:
                return NewLabelStmt(pos, nil)
        case OLITERAL, OTYPE, OIOTA:
@@ -772,7 +771,7 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
        case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY:
                return NewMakeExpr(pos, op, nleft, nright)
        case OMETHEXPR:
-               return NewMethodExpr(pos, op, nleft, nright)
+               return NewMethodExpr(pos, nleft, nright)
        case ONIL:
                return NewNilExpr(pos)
        case OPACK:
index b3fd89c3670b7356033386b9644eeb028bbf7ec8..4eedcfdd29bc8f4a77eed1e41204a85a48d8a1a2 100644 (file)
@@ -280,19 +280,19 @@ func (n *ClosureExpr) editChildren(edit func(Node) Node) {
        editList(n.init, edit)
 }
 
-func (n *ClosureRead) String() string                { return fmt.Sprint(n) }
-func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
-func (n *ClosureRead) copy() Node {
+func (n *ClosureReadExpr) String() string                { return fmt.Sprint(n) }
+func (n *ClosureReadExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *ClosureReadExpr) copy() Node {
        c := *n
        c.init = c.init.Copy()
        return &c
 }
-func (n *ClosureRead) doChildren(do func(Node) error) error {
+func (n *ClosureReadExpr) doChildren(do func(Node) error) error {
        var err error
        err = maybeDoList(n.init, err, do)
        return err
 }
-func (n *ClosureRead) editChildren(edit func(Node) Node) {
+func (n *ClosureReadExpr) editChildren(edit func(Node) Node) {
        editList(n.init, edit)
 }
 
@@ -366,24 +366,6 @@ func (n *Decl) editChildren(edit func(Node) Node) {
        n.X = maybeEdit(n.X, edit)
 }
 
-func (n *DeferStmt) String() string                { return fmt.Sprint(n) }
-func (n *DeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
-func (n *DeferStmt) copy() Node {
-       c := *n
-       c.init = c.init.Copy()
-       return &c
-}
-func (n *DeferStmt) doChildren(do func(Node) error) error {
-       var err error
-       err = maybeDoList(n.init, err, do)
-       err = maybeDo(n.Call, err, do)
-       return err
-}
-func (n *DeferStmt) editChildren(edit func(Node) Node) {
-       editList(n.init, edit)
-       n.Call = maybeEdit(n.Call, edit)
-}
-
 func (n *ForStmt) String() string                { return fmt.Sprint(n) }
 func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
 func (n *ForStmt) copy() Node {
@@ -450,20 +432,20 @@ func (n *FuncType) editChildren(edit func(Node) Node) {
        editFields(n.Results, edit)
 }
 
-func (n *GoStmt) String() string                { return fmt.Sprint(n) }
-func (n *GoStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
-func (n *GoStmt) copy() Node {
+func (n *GoDeferStmt) String() string                { return fmt.Sprint(n) }
+func (n *GoDeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *GoDeferStmt) copy() Node {
        c := *n
        c.init = c.init.Copy()
        return &c
 }
-func (n *GoStmt) doChildren(do func(Node) error) error {
+func (n *GoDeferStmt) doChildren(do func(Node) error) error {
        var err error
        err = maybeDoList(n.init, err, do)
        err = maybeDo(n.Call, err, do)
        return err
 }
-func (n *GoStmt) editChildren(edit func(Node) Node) {
+func (n *GoDeferStmt) editChildren(edit func(Node) Node) {
        editList(n.init, edit)
        n.Call = maybeEdit(n.Call, edit)
 }
@@ -602,6 +584,26 @@ func (n *LabelStmt) editChildren(edit func(Node) Node) {
        editList(n.init, edit)
 }
 
+func (n *LogicalExpr) String() string                { return fmt.Sprint(n) }
+func (n *LogicalExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *LogicalExpr) copy() Node {
+       c := *n
+       c.init = c.init.Copy()
+       return &c
+}
+func (n *LogicalExpr) doChildren(do func(Node) error) error {
+       var err error
+       err = maybeDoList(n.init, err, do)
+       err = maybeDo(n.X, err, do)
+       err = maybeDo(n.Y, err, do)
+       return err
+}
+func (n *LogicalExpr) editChildren(edit func(Node) Node) {
+       editList(n.init, edit)
+       n.X = maybeEdit(n.X, edit)
+       n.Y = maybeEdit(n.Y, edit)
+}
+
 func (n *MakeExpr) String() string                { return fmt.Sprint(n) }
 func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
 func (n *MakeExpr) copy() Node {
@@ -913,6 +915,24 @@ func (n *StarExpr) editChildren(edit func(Node) Node) {
        n.X = maybeEdit(n.X, edit)
 }
 
+func (n *StructKeyExpr) String() string                { return fmt.Sprint(n) }
+func (n *StructKeyExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
+func (n *StructKeyExpr) copy() Node {
+       c := *n
+       c.init = c.init.Copy()
+       return &c
+}
+func (n *StructKeyExpr) doChildren(do func(Node) error) error {
+       var err error
+       err = maybeDoList(n.init, err, do)
+       err = maybeDo(n.Value, err, do)
+       return err
+}
+func (n *StructKeyExpr) editChildren(edit func(Node) Node) {
+       editList(n.init, edit)
+       n.Value = maybeEdit(n.Value, edit)
+}
+
 func (n *StructType) String() string                { return fmt.Sprint(n) }
 func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
 func (n *StructType) copy() Node {
index 68f9b0bd7c5dbedaff000082416a1a0971dae635..28c40c07813579d52dd9688937f5a5b3771e1d82 100644 (file)
@@ -63,19 +63,19 @@ func (n *miniStmt) SetHasCall(b bool) { n.bits.set(miniHasCall, b) }
 // If Def is true, the assignment is a :=.
 type AssignListStmt struct {
        miniStmt
-       Lhs    Nodes
-       Def    bool
-       Rhs    Nodes
-       offset int64 // for initorder
+       Lhs     Nodes
+       Def     bool
+       Rhs     Nodes
+       Offset_ int64 // for initorder
 }
 
-func NewAssignListStmt(pos src.XPos, lhs, rhs []Node) *AssignListStmt {
+func NewAssignListStmt(pos src.XPos, op Op, lhs, rhs []Node) *AssignListStmt {
        n := &AssignListStmt{}
        n.pos = pos
-       n.op = OAS2
+       n.SetOp(op)
        n.Lhs.Set(lhs)
        n.Rhs.Set(rhs)
-       n.offset = types.BADWIDTH
+       n.Offset_ = types.BADWIDTH
        return n
 }
 
@@ -87,8 +87,8 @@ func (n *AssignListStmt) PtrRlist() *Nodes  { return &n.Rhs }
 func (n *AssignListStmt) SetRlist(x Nodes)  { n.Rhs = x }
 func (n *AssignListStmt) Colas() bool       { return n.Def }
 func (n *AssignListStmt) SetColas(x bool)   { n.Def = x }
-func (n *AssignListStmt) Offset() int64     { return n.offset }
-func (n *AssignListStmt) SetOffset(x int64) { n.offset = x }
+func (n *AssignListStmt) Offset() int64     { return n.Offset_ }
+func (n *AssignListStmt) SetOffset(x int64) { n.Offset_ = x }
 
 func (n *AssignListStmt) SetOp(op Op) {
        switch op {
@@ -103,17 +103,17 @@ func (n *AssignListStmt) SetOp(op Op) {
 // If Def is true, the assignment is a :=.
 type AssignStmt struct {
        miniStmt
-       X      Node
-       Def    bool
-       Y      Node
-       offset int64 // for initorder
+       X       Node
+       Def     bool
+       Y       Node
+       Offset_ int64 // for initorder
 }
 
 func NewAssignStmt(pos src.XPos, x, y Node) *AssignStmt {
        n := &AssignStmt{X: x, Y: y}
        n.pos = pos
        n.op = OAS
-       n.offset = types.BADWIDTH
+       n.Offset_ = types.BADWIDTH
        return n
 }
 
@@ -123,8 +123,8 @@ func (n *AssignStmt) Right() Node       { return n.Y }
 func (n *AssignStmt) SetRight(y Node)   { n.Y = y }
 func (n *AssignStmt) Colas() bool       { return n.Def }
 func (n *AssignStmt) SetColas(x bool)   { n.Def = x }
-func (n *AssignStmt) Offset() int64     { return n.offset }
-func (n *AssignStmt) SetOffset(x int64) { n.offset = x }
+func (n *AssignStmt) Offset() int64     { return n.Offset_ }
+func (n *AssignStmt) SetOffset(x int64) { n.Offset_ = x }
 
 func (n *AssignStmt) SetOp(op Op) {
        switch op {
@@ -236,32 +236,16 @@ func (n *CaseStmt) SetRlist(x Nodes) { n.Vars = x }
 func (n *CaseStmt) Left() Node       { return n.Comm }
 func (n *CaseStmt) SetLeft(x Node)   { n.Comm = x }
 
-// A DeferStmt is a defer statement: defer Call.
-type DeferStmt struct {
-       miniStmt
-       Call Node
-}
-
-func NewDeferStmt(pos src.XPos, call Node) *DeferStmt {
-       n := &DeferStmt{Call: call}
-       n.pos = pos
-       n.op = ODEFER
-       return n
-}
-
-func (n *DeferStmt) Left() Node     { return n.Call }
-func (n *DeferStmt) SetLeft(x Node) { n.Call = x }
-
 // A ForStmt is a non-range for loop: for Init; Cond; Post { Body }
 // Op can be OFOR or OFORUNTIL (!Cond).
 type ForStmt struct {
        miniStmt
-       Label    *types.Sym
-       Cond     Node
-       Late     Nodes
-       Post     Node
-       Body_    Nodes
-       hasBreak bool
+       Label     *types.Sym
+       Cond      Node
+       Late      Nodes
+       Post      Node
+       Body_     Nodes
+       HasBreak_ bool
 }
 
 func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStmt {
@@ -285,8 +269,8 @@ func (n *ForStmt) SetBody(x Nodes)     { n.Body_ = x }
 func (n *ForStmt) List() Nodes         { return n.Late }
 func (n *ForStmt) PtrList() *Nodes     { return &n.Late }
 func (n *ForStmt) SetList(x Nodes)     { n.Late = x }
-func (n *ForStmt) HasBreak() bool      { return n.hasBreak }
-func (n *ForStmt) SetHasBreak(b bool)  { n.hasBreak = b }
+func (n *ForStmt) HasBreak() bool      { return n.HasBreak_ }
+func (n *ForStmt) SetHasBreak(b bool)  { n.HasBreak_ = b }
 
 func (n *ForStmt) SetOp(op Op) {
        if op != OFOR && op != OFORUNTIL {
@@ -295,29 +279,38 @@ func (n *ForStmt) SetOp(op Op) {
        n.op = op
 }
 
-// A GoStmt is a go statement: go Call.
-type GoStmt struct {
+// A GoDeferStmt is a go or defer statement: go Call / defer Call.
+//
+// The two opcodes use a signle syntax because the implementations
+// are very similar: both are concerned with saving Call and running it
+// in a different context (a separate goroutine or a later time).
+type GoDeferStmt struct {
        miniStmt
        Call Node
 }
 
-func NewGoStmt(pos src.XPos, call Node) *GoStmt {
-       n := &GoStmt{Call: call}
+func NewGoDeferStmt(pos src.XPos, op Op, call Node) *GoDeferStmt {
+       n := &GoDeferStmt{Call: call}
        n.pos = pos
-       n.op = OGO
+       switch op {
+       case ODEFER, OGO:
+               n.op = op
+       default:
+               panic("NewGoDeferStmt " + op.String())
+       }
        return n
 }
 
-func (n *GoStmt) Left() Node     { return n.Call }
-func (n *GoStmt) SetLeft(x Node) { n.Call = x }
+func (n *GoDeferStmt) Left() Node     { return n.Call }
+func (n *GoDeferStmt) SetLeft(x Node) { n.Call = x }
 
 // A IfStmt is a return statement: if Init; Cond { Then } else { Else }.
 type IfStmt struct {
        miniStmt
-       Cond   Node
-       Body_  Nodes
-       Else   Nodes
-       likely bool // code layout hint
+       Cond    Node
+       Body_   Nodes
+       Else    Nodes
+       Likely_ bool // code layout hint
 }
 
 func NewIfStmt(pos src.XPos, cond Node, body, els []Node) *IfStmt {
@@ -337,8 +330,8 @@ func (n *IfStmt) SetBody(x Nodes)  { n.Body_ = x }
 func (n *IfStmt) Rlist() Nodes     { return n.Else }
 func (n *IfStmt) PtrRlist() *Nodes { return &n.Else }
 func (n *IfStmt) SetRlist(x Nodes) { n.Else = x }
-func (n *IfStmt) Likely() bool     { return n.likely }
-func (n *IfStmt) SetLikely(x bool) { n.likely = x }
+func (n *IfStmt) Likely() bool     { return n.Likely_ }
+func (n *IfStmt) SetLikely(x bool) { n.Likely_ = x }
 
 // An InlineMarkStmt is a marker placed just before an inlined body.
 type InlineMarkStmt struct {
@@ -376,13 +369,13 @@ func (n *LabelStmt) SetSym(x *types.Sym) { n.Label = x }
 // Op can be OFOR or OFORUNTIL (!Cond).
 type RangeStmt struct {
        miniStmt
-       Label    *types.Sym
-       Vars     Nodes // TODO(rsc): Replace with Key, Value Node
-       Def      bool
-       X        Node
-       Body_    Nodes
-       hasBreak bool
-       typ      *types.Type // TODO(rsc): Remove - use X.Type() instead
+       Label     *types.Sym
+       Vars      Nodes // TODO(rsc): Replace with Key, Value Node
+       Def       bool
+       X         Node
+       Body_     Nodes
+       HasBreak_ bool
+       typ       *types.Type // TODO(rsc): Remove - use X.Type() instead
 }
 
 func NewRangeStmt(pos src.XPos, vars []Node, x Node, body []Node) *RangeStmt {
@@ -404,8 +397,8 @@ func (n *RangeStmt) SetBody(x Nodes)       { n.Body_ = x }
 func (n *RangeStmt) List() Nodes           { return n.Vars }
 func (n *RangeStmt) PtrList() *Nodes       { return &n.Vars }
 func (n *RangeStmt) SetList(x Nodes)       { n.Vars = x }
-func (n *RangeStmt) HasBreak() bool        { return n.hasBreak }
-func (n *RangeStmt) SetHasBreak(b bool)    { n.hasBreak = b }
+func (n *RangeStmt) HasBreak() bool        { return n.HasBreak_ }
+func (n *RangeStmt) SetHasBreak(b bool)    { n.HasBreak_ = b }
 func (n *RangeStmt) Colas() bool           { return n.Def }
 func (n *RangeStmt) SetColas(b bool)       { n.Def = b }
 func (n *RangeStmt) Type() *types.Type     { return n.typ }
@@ -437,9 +430,9 @@ func (n *ReturnStmt) IsDDD() bool     { return false } // typecheckargs asks
 // A SelectStmt is a block: { Cases }.
 type SelectStmt struct {
        miniStmt
-       Label    *types.Sym
-       Cases    Nodes
-       hasBreak bool
+       Label     *types.Sym
+       Cases     Nodes
+       HasBreak_ bool
 
        // TODO(rsc): Instead of recording here, replace with a block?
        Compiled Nodes // compiled form, after walkswitch
@@ -458,8 +451,8 @@ func (n *SelectStmt) PtrList() *Nodes     { return &n.Cases }
 func (n *SelectStmt) SetList(x Nodes)     { n.Cases = x }
 func (n *SelectStmt) Sym() *types.Sym     { return n.Label }
 func (n *SelectStmt) SetSym(x *types.Sym) { n.Label = x }
-func (n *SelectStmt) HasBreak() bool      { return n.hasBreak }
-func (n *SelectStmt) SetHasBreak(x bool)  { n.hasBreak = x }
+func (n *SelectStmt) HasBreak() bool      { return n.HasBreak_ }
+func (n *SelectStmt) SetHasBreak(x bool)  { n.HasBreak_ = x }
 func (n *SelectStmt) Body() Nodes         { return n.Compiled }
 func (n *SelectStmt) PtrBody() *Nodes     { return &n.Compiled }
 func (n *SelectStmt) SetBody(x Nodes)     { n.Compiled = x }
@@ -486,10 +479,10 @@ func (n *SendStmt) SetRight(y Node) { n.Value = y }
 // A SwitchStmt is a switch statement: switch Init; Expr { Cases }.
 type SwitchStmt struct {
        miniStmt
-       Tag      Node
-       Cases    Nodes // list of *CaseStmt
-       Label    *types.Sym
-       hasBreak bool
+       Tag       Node
+       Cases     Nodes // list of *CaseStmt
+       Label     *types.Sym
+       HasBreak_ bool
 
        // TODO(rsc): Instead of recording here, replace with a block?
        Compiled Nodes // compiled form, after walkswitch
@@ -513,8 +506,8 @@ func (n *SwitchStmt) PtrBody() *Nodes     { return &n.Compiled }
 func (n *SwitchStmt) SetBody(x Nodes)     { n.Compiled = x }
 func (n *SwitchStmt) Sym() *types.Sym     { return n.Label }
 func (n *SwitchStmt) SetSym(x *types.Sym) { n.Label = x }
-func (n *SwitchStmt) HasBreak() bool      { return n.hasBreak }
-func (n *SwitchStmt) SetHasBreak(x bool)  { n.hasBreak = x }
+func (n *SwitchStmt) HasBreak() bool      { return n.HasBreak_ }
+func (n *SwitchStmt) SetHasBreak(x bool)  { n.HasBreak_ = x }
 
 // A TypeSwitchGuard is the [Name :=] X.(type) in a type switch.
 type TypeSwitchGuard struct {
index ad0df5508d926f49a0f8367a372af82d4fa6698b..5b0506c0d04fcb2d80ac7d2b787180e39e243da0 100644 (file)
@@ -92,7 +92,7 @@ func ValidTypeForConst(t *types.Type, v constant.Value) bool {
 
 // nodlit returns a new untyped constant with value v.
 func NewLiteral(v constant.Value) Node {
-       n := Nod(OLITERAL, nil, nil)
+       n := newNameAt(base.Pos, OLITERAL, nil)
        if k := v.Kind(); k != constant.Unknown {
                n.SetType(idealType(k))
                n.SetVal(v)