[dev.regabi] cmd/compile: adjust IR representations

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>
This commit is contained in:
Russ Cox 2020-12-07 09:14:44 -05:00
parent 0c49440664
commit 837b35cc55
8 changed files with 266 additions and 216 deletions

View file

@ -2010,18 +2010,13 @@ func typecheck1(n ir.Node, top int) (res ir.Node) {
} }
return n return n
case ir.ODEFER: case ir.ODEFER, ir.OGO:
n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr)) n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr))
if !n.Left().Diag() { if !n.Left().Diag() {
checkdefergo(n) checkdefergo(n)
} }
return n return n
case ir.OGO:
n.SetLeft(typecheck(n.Left(), ctxStmt|ctxExpr))
checkdefergo(n)
return n
case ir.OFOR, ir.OFORUNTIL: case ir.OFOR, ir.OFORUNTIL:
typecheckslice(n.Init().Slice(), ctxStmt) typecheckslice(n.Init().Slice(), ctxStmt)
decldepth++ decldepth++
@ -2885,9 +2880,9 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
if l.Op() == ir.OKEY { if l.Op() == ir.OKEY {
key := l.Left() key := l.Left()
l.SetOp(ir.OSTRUCTKEY) sk := ir.NewStructKeyExpr(l.Pos(), nil, l.Right())
l.SetLeft(l.Right()) ls[i] = sk
l.SetRight(nil) l = sk
// An OXDOT uses the Sym field to hold // An OXDOT uses the Sym field to hold
// the field to the right of the dot, // 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. // is never a valid struct literal key.
if key.Sym() == nil || key.Op() == ir.OXDOT || key.Sym().IsBlank() { if key.Sym() == nil || key.Op() == ir.OXDOT || key.Sym().IsBlank() {
base.Errorf("invalid field name %v in struct initializer", key) base.Errorf("invalid field name %v in struct initializer", key)
l.SetLeft(typecheck(l.Left(), ctxExpr)) sk.SetLeft(typecheck(sk.Left(), ctxExpr))
continue continue
} }
@ -2909,7 +2904,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
s = s1 s = s1
} }
} }
l.SetSym(s) sk.SetSym(s)
} }
if l.Op() != ir.OSTRUCTKEY { if l.Op() != ir.OSTRUCTKEY {

View file

@ -202,8 +202,7 @@ func initUniverse() {
ir.AsNode(s.Def).SetSym(s) ir.AsNode(s.Def).SetSym(s)
s = types.BuiltinPkg.Lookup("iota") s = types.BuiltinPkg.Lookup("iota")
s.Def = ir.Nod(ir.OIOTA, nil, nil) s.Def = ir.NewIota(base.Pos, s)
ir.AsNode(s.Def).SetSym(s)
for et := types.TINT8; et <= types.TUINT64; et++ { for et := types.TINT8; et <= types.TUINT64; et++ {
isInt[et] = true isInt[et] = true

View file

@ -159,8 +159,8 @@ func (n *BinaryExpr) SetOp(op Op) {
switch op { switch op {
default: default:
panic(n.no("SetOp " + op.String())) panic(n.no("SetOp " + op.String()))
case OADD, OADDSTR, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, case OADD, OADDSTR, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
OLSH, OLT, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSUB, OXOR, OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR,
OCOPY, OCOMPLEX, OCOPY, OCOMPLEX,
OEFACE: OEFACE:
n.op = op n.op = op
@ -188,14 +188,14 @@ type CallExpr struct {
Body_ Nodes // TODO(rsc): Delete. Body_ Nodes // TODO(rsc): Delete.
DDD bool DDD bool
Use CallUse Use CallUse
noInline bool 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 := &CallExpr{X: fun}
n.pos = pos n.pos = pos
n.orig = n n.orig = n
n.op = OCALL n.SetOp(op)
n.Args.Set(args) n.Args.Set(args)
return n 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) SetRlist(x Nodes) { n.Rargs = x }
func (n *CallExpr) IsDDD() bool { return n.DDD } func (n *CallExpr) IsDDD() bool { return n.DDD }
func (n *CallExpr) SetIsDDD(x bool) { n.DDD = x } func (n *CallExpr) SetIsDDD(x bool) { n.DDD = x }
func (n *CallExpr) NoInline() bool { return n.noInline } func (n *CallExpr) NoInline() bool { return n.NoInline_ }
func (n *CallExpr) SetNoInline(x bool) { n.noInline = x } func (n *CallExpr) SetNoInline(x bool) { n.NoInline_ = x }
func (n *CallExpr) Body() Nodes { return n.Body_ } func (n *CallExpr) Body() Nodes { return n.Body_ }
func (n *CallExpr) PtrBody() *Nodes { return &n.Body_ } func (n *CallExpr) PtrBody() *Nodes { return &n.Body_ }
func (n *CallExpr) SetBody(x Nodes) { n.Body_ = x } 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). // A CallPartExpr is a method expression X.Method (uncalled).
type CallPartExpr struct { type CallPartExpr struct {
miniExpr miniExpr
fn *Func Func_ *Func
X Node X Node
Method *types.Field Method *types.Field
} }
func NewCallPartExpr(pos src.XPos, x Node, method *types.Field, fn *Func) *CallPartExpr { 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.op = OCALLPART
n.pos = pos n.pos = pos
n.typ = fn.Type() n.typ = fn.Type()
n.fn = fn n.Func_ = fn
return n 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) Left() Node { return n.X }
func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym } func (n *CallPartExpr) Sym() *types.Sym { return n.Method.Sym }
func (n *CallPartExpr) SetLeft(x Node) { n.X = x } 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_ } func (n *ClosureExpr) Func() *Func { return n.Func_ }
// A ClosureRead denotes reading a variable stored within a closure struct. // A ClosureRead denotes reading a variable stored within a closure struct.
type ClosureRead struct { type ClosureReadExpr struct {
miniExpr miniExpr
offset int64 Offset_ int64
} }
func NewClosureRead(typ *types.Type, offset int64) *ClosureRead { func NewClosureRead(typ *types.Type, offset int64) *ClosureReadExpr {
n := &ClosureRead{offset: offset} n := &ClosureReadExpr{Offset_: offset}
n.typ = typ n.typ = typ
n.op = OCLOSUREREAD n.op = OCLOSUREREAD
return n return n
} }
func (n *ClosureRead) Type() *types.Type { return n.typ } func (n *ClosureReadExpr) Type() *types.Type { return n.typ }
func (n *ClosureRead) Offset() int64 { return n.offset } func (n *ClosureReadExpr) Offset() int64 { return n.Offset_ }
// A CompLitExpr is a composite literal Type{Vals}. // A CompLitExpr is a composite literal Type{Vals}.
// Before type-checking, the type is Ntype. // Before type-checking, the type is Ntype.
@ -292,10 +292,10 @@ type CompLitExpr struct {
List_ Nodes // initialized values 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 := &CompLitExpr{Ntype: typ}
n.pos = pos n.pos = pos
n.op = OCOMPLIT n.SetOp(op)
n.List_.Set(list) n.List_.Set(list)
n.orig = n n.orig = n
return n return n
@ -397,21 +397,17 @@ func (n *IndexExpr) SetOp(op Op) {
} }
} }
// A KeyExpr is an X:Y composite literal key. // A KeyExpr is a Key: Value composite literal key.
// After type-checking, a key for a struct sets Sym to the field.
type KeyExpr struct { type KeyExpr struct {
miniExpr miniExpr
Key Node Key Node
sym *types.Sym
Value Node Value Node
offset int64
} }
func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr { func NewKeyExpr(pos src.XPos, key, value Node) *KeyExpr {
n := &KeyExpr{Key: key, Value: value} n := &KeyExpr{Key: key, Value: value}
n.pos = pos n.pos = pos
n.op = OKEY n.op = OKEY
n.offset = types.BADWIDTH
return n return n
} }
@ -419,20 +415,30 @@ func (n *KeyExpr) Left() Node { return n.Key }
func (n *KeyExpr) SetLeft(x Node) { n.Key = x } func (n *KeyExpr) SetLeft(x Node) { n.Key = x }
func (n *KeyExpr) Right() Node { return n.Value } func (n *KeyExpr) Right() Node { return n.Value }
func (n *KeyExpr) SetRight(y Node) { n.Value = y } 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) SetOp(op Op) { // A StructKeyExpr is an Field: Value composite literal key.
switch op { type StructKeyExpr struct {
default: miniExpr
panic(n.no("SetOp " + op.String())) Field *types.Sym
case OKEY, OSTRUCTKEY: Value Node
n.op = op 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. // An InlinedCallExpr is an inlined function call.
type InlinedCallExpr struct { type InlinedCallExpr struct {
miniExpr miniExpr
@ -456,6 +462,36 @@ func (n *InlinedCallExpr) Rlist() Nodes { return n.ReturnVars }
func (n *InlinedCallExpr) PtrRlist() *Nodes { return &n.ReturnVars } func (n *InlinedCallExpr) PtrRlist() *Nodes { return &n.ReturnVars }
func (n *InlinedCallExpr) SetRlist(x Nodes) { n.ReturnVars = x } 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]]). // A MakeExpr is a make expression: make(Type[, Len[, Cap]]).
// Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY, // Op is OMAKECHAN, OMAKEMAP, OMAKESLICE, or OMAKESLICECOPY,
// but *not* OMAKE (that's a pre-typechecking CallExpr). // but *not* OMAKE (that's a pre-typechecking CallExpr).
@ -491,17 +527,17 @@ type MethodExpr struct {
miniExpr miniExpr
X Node X Node
M Node M Node
sym *types.Sym Sym_ *types.Sym
offset int64 Offset_ int64
class Class Class_ Class
Method *types.Field 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 := &MethodExpr{X: x, M: m}
n.pos = pos n.pos = pos
n.op = OMETHEXPR n.op = OMETHEXPR
n.offset = types.BADWIDTH n.Offset_ = types.BADWIDTH
return n 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) SetLeft(x Node) { n.X = x }
func (n *MethodExpr) Right() Node { return n.M } func (n *MethodExpr) Right() Node { return n.M }
func (n *MethodExpr) SetRight(y Node) { n.M = y } func (n *MethodExpr) SetRight(y Node) { n.M = y }
func (n *MethodExpr) Sym() *types.Sym { return n.sym } func (n *MethodExpr) Sym() *types.Sym { return n.Sym_ }
func (n *MethodExpr) SetSym(x *types.Sym) { n.sym = x } func (n *MethodExpr) SetSym(x *types.Sym) { n.Sym_ = x }
func (n *MethodExpr) Offset() int64 { return n.offset } func (n *MethodExpr) Offset() int64 { return n.Offset_ }
func (n *MethodExpr) SetOffset(x int64) { n.offset = x } func (n *MethodExpr) SetOffset(x int64) { n.Offset_ = x }
func (n *MethodExpr) Class() Class { return n.class } func (n *MethodExpr) Class() Class { return n.Class_ }
func (n *MethodExpr) SetClass(x Class) { n.class = x } func (n *MethodExpr) SetClass(x Class) { n.Class_ = x }
// A NilExpr represents the predefined untyped constant nil. // A NilExpr represents the predefined untyped constant nil.
// (It may be copied and assigned a type, though.) // (It may be copied and assigned a type, though.)
type NilExpr struct { type NilExpr struct {
miniExpr miniExpr
sym *types.Sym // TODO: Remove Sym_ *types.Sym // TODO: Remove
} }
func NewNilExpr(pos src.XPos) *NilExpr { func NewNilExpr(pos src.XPos) *NilExpr {
@ -530,8 +566,8 @@ func NewNilExpr(pos src.XPos) *NilExpr {
return n return n
} }
func (n *NilExpr) Sym() *types.Sym { return n.sym } func (n *NilExpr) Sym() *types.Sym { return n.Sym_ }
func (n *NilExpr) SetSym(x *types.Sym) { n.sym = x } func (n *NilExpr) SetSym(x *types.Sym) { n.Sym_ = x }
// A ParenExpr is a parenthesized expression (X). // A ParenExpr is a parenthesized expression (X).
// It may end up being a value or a type. // 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. // A ResultExpr represents a direct access to a result slot on the stack frame.
type ResultExpr struct { type ResultExpr struct {
miniExpr miniExpr
offset int64 Offset_ int64
} }
func NewResultExpr(pos src.XPos, typ *types.Type, offset int64) *ResultExpr { func NewResultExpr(pos src.XPos, typ *types.Type, offset int64) *ResultExpr {
n := &ResultExpr{offset: offset} n := &ResultExpr{Offset_: offset}
n.pos = pos n.pos = pos
n.op = ORESULT n.op = ORESULT
n.typ = typ n.typ = typ
return n return n
} }
func (n *ResultExpr) Offset() int64 { return n.offset } func (n *ResultExpr) Offset() int64 { return n.Offset_ }
func (n *ResultExpr) SetOffset(x int64) { n.offset = x } func (n *ResultExpr) SetOffset(x int64) { n.Offset_ = x }
// A SelectorExpr is a selector expression X.Sym. // A SelectorExpr is a selector expression X.Sym.
type SelectorExpr struct { type SelectorExpr struct {
miniExpr miniExpr
X Node X Node
Sel *types.Sym Sel *types.Sym
offset int64 Offset_ int64
Selection *types.Field 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 := &SelectorExpr{X: x, Sel: sel}
n.pos = pos n.pos = pos
n.op = OXDOT n.Offset_ = types.BADWIDTH
n.offset = types.BADWIDTH n.SetOp(op)
return n 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) SetLeft(x Node) { n.X = x }
func (n *SelectorExpr) Sym() *types.Sym { return n.Sel } func (n *SelectorExpr) Sym() *types.Sym { return n.Sel }
func (n *SelectorExpr) SetSym(x *types.Sym) { n.Sel = x } func (n *SelectorExpr) SetSym(x *types.Sym) { n.Sel = x }
func (n *SelectorExpr) Offset() int64 { return n.offset } func (n *SelectorExpr) Offset() int64 { return n.Offset_ }
func (n *SelectorExpr) SetOffset(x int64) { n.offset = x } func (n *SelectorExpr) SetOffset(x int64) { n.Offset_ = x }
// Before type-checking, bytes.Buffer is a SelectorExpr. // Before type-checking, bytes.Buffer is a SelectorExpr.
// After type-checking it becomes a Name. // After type-checking it becomes a Name.

View file

@ -132,6 +132,14 @@ func NewNameAt(pos src.XPos, sym *types.Sym) *Name {
return newNameAt(pos, ONAME, sym) 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. // NewDeclNameAt returns a new ONONAME Node associated with symbol s at position pos.
// The caller is responsible for setting Curfn. // The caller is responsible for setting Curfn.
func NewDeclNameAt(pos src.XPos, sym *types.Sym) *Name { func NewDeclNameAt(pos src.XPos, sym *types.Sym) *Name {

View file

@ -681,30 +681,31 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
switch op { switch op {
default: default:
panic("NodAt " + op.String()) panic("NodAt " + op.String())
case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, case OADD, OAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE,
OLSH, OLT, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSUB, OXOR, OLSH, OLT, OMOD, OMUL, ONE, OOR, ORSH, OSUB, OXOR,
OCOPY, OCOMPLEX, OCOPY, OCOMPLEX,
OEFACE: OEFACE:
return NewBinaryExpr(pos, op, nleft, nright) return NewBinaryExpr(pos, op, nleft, nright)
case OADDR, OPTRLIT: case OADDR:
return NewAddrExpr(pos, nleft) return NewAddrExpr(pos, nleft)
case OADDSTR: case OADDSTR:
return NewAddStringExpr(pos, nil) return NewAddStringExpr(pos, nil)
case OANDAND, OOROR:
return NewLogicalExpr(pos, op, nleft, nright)
case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT: case OARRAYLIT, OCOMPLIT, OMAPLIT, OSTRUCTLIT, OSLICELIT:
var typ Ntype var typ Ntype
if nright != nil { if nright != nil {
typ = nright.(Ntype) typ = nright.(Ntype)
} }
n := NewCompLitExpr(pos, typ, nil) return NewCompLitExpr(pos, op, typ, nil)
n.SetOp(op)
return n
case OAS, OSELRECV: case OAS, OSELRECV:
n := NewAssignStmt(pos, nleft, nright) n := NewAssignStmt(pos, nleft, nright)
if op != OAS {
n.SetOp(op) n.SetOp(op)
}
return n return n
case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, OSELRECV2: case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV, OSELRECV2:
n := NewAssignListStmt(pos, nil, nil) n := NewAssignListStmt(pos, op, nil, nil)
n.SetOp(op)
return n return n
case OASOP: case OASOP:
return NewAssignOpStmt(pos, OXXX, nleft, nright) 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) return NewBranchStmt(pos, op, nil)
case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH,
OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER: OAPPEND, ODELETE, OGETG, OMAKE, OPRINT, OPRINTN, ORECOVER:
n := NewCallExpr(pos, nleft, nil) return NewCallExpr(pos, op, nleft, nil)
n.SetOp(op)
return n
case OCASE: case OCASE:
return NewCaseStmt(pos, nil, nil) return NewCaseStmt(pos, nil, nil)
case OCONV, OCONVIFACE, OCONVNOP, ORUNESTR: 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) return NewDecl(pos, op, nleft)
case ODCLFUNC: case ODCLFUNC:
return NewFunc(pos) return NewFunc(pos)
case ODEFER: case ODEFER, OGO:
return NewDeferStmt(pos, nleft) return NewGoDeferStmt(pos, op, nleft)
case ODEREF: case ODEREF:
return NewStarExpr(pos, nleft) return NewStarExpr(pos, nleft)
case ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT: case ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT:
n := NewSelectorExpr(pos, nleft, nil) return NewSelectorExpr(pos, op, nleft, nil)
n.SetOp(op)
return n
case ODOTTYPE, ODOTTYPE2: case ODOTTYPE, ODOTTYPE2:
var typ Ntype var typ Ntype
if nright != nil { if nright != nil {
typ = nright.(Ntype) typ = nright.(Ntype)
} }
n := NewTypeAssertExpr(pos, nleft, typ) n := NewTypeAssertExpr(pos, nleft, typ)
if op != ODOTTYPE {
n.SetOp(op) n.SetOp(op)
}
return n return n
case OFOR: case OFOR:
return NewForStmt(pos, nil, nleft, nright, nil) return NewForStmt(pos, nil, nleft, nright, nil)
case OGO:
return NewGoStmt(pos, nleft)
case OIF: case OIF:
return NewIfStmt(pos, nleft, nil, nil) return NewIfStmt(pos, nleft, nil, nil)
case OINDEX, OINDEXMAP: case OINDEX, OINDEXMAP:
n := NewIndexExpr(pos, nleft, nright) n := NewIndexExpr(pos, nleft, nright)
if op != OINDEX {
n.SetOp(op) n.SetOp(op)
}
return n return n
case OINLMARK: case OINLMARK:
return NewInlineMarkStmt(pos, types.BADWIDTH) return NewInlineMarkStmt(pos, types.BADWIDTH)
case OKEY, OSTRUCTKEY: case OKEY:
n := NewKeyExpr(pos, nleft, nright) return NewKeyExpr(pos, nleft, nright)
n.SetOp(op) case OSTRUCTKEY:
return n return NewStructKeyExpr(pos, nil, nleft)
case OLABEL: case OLABEL:
return NewLabelStmt(pos, nil) return NewLabelStmt(pos, nil)
case OLITERAL, OTYPE, OIOTA: case OLITERAL, OTYPE, OIOTA:
@ -772,7 +771,7 @@ func NodAt(pos src.XPos, op Op, nleft, nright Node) Node {
case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY: case OMAKECHAN, OMAKEMAP, OMAKESLICE, OMAKESLICECOPY:
return NewMakeExpr(pos, op, nleft, nright) return NewMakeExpr(pos, op, nleft, nright)
case OMETHEXPR: case OMETHEXPR:
return NewMethodExpr(pos, op, nleft, nright) return NewMethodExpr(pos, nleft, nright)
case ONIL: case ONIL:
return NewNilExpr(pos) return NewNilExpr(pos)
case OPACK: case OPACK:

View file

@ -280,19 +280,19 @@ func (n *ClosureExpr) editChildren(edit func(Node) Node) {
editList(n.init, edit) editList(n.init, edit)
} }
func (n *ClosureRead) String() string { return fmt.Sprint(n) } func (n *ClosureReadExpr) String() string { return fmt.Sprint(n) }
func (n *ClosureRead) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ClosureReadExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *ClosureRead) copy() Node { func (n *ClosureReadExpr) copy() Node {
c := *n c := *n
c.init = c.init.Copy() c.init = c.init.Copy()
return &c return &c
} }
func (n *ClosureRead) doChildren(do func(Node) error) error { func (n *ClosureReadExpr) doChildren(do func(Node) error) error {
var err error var err error
err = maybeDoList(n.init, err, do) err = maybeDoList(n.init, err, do)
return err return err
} }
func (n *ClosureRead) editChildren(edit func(Node) Node) { func (n *ClosureReadExpr) editChildren(edit func(Node) Node) {
editList(n.init, edit) editList(n.init, edit)
} }
@ -366,24 +366,6 @@ func (n *Decl) editChildren(edit func(Node) Node) {
n.X = maybeEdit(n.X, edit) 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) String() string { return fmt.Sprint(n) }
func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *ForStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *ForStmt) copy() Node { func (n *ForStmt) copy() Node {
@ -450,20 +432,20 @@ func (n *FuncType) editChildren(edit func(Node) Node) {
editFields(n.Results, edit) editFields(n.Results, edit)
} }
func (n *GoStmt) String() string { return fmt.Sprint(n) } func (n *GoDeferStmt) String() string { return fmt.Sprint(n) }
func (n *GoStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *GoDeferStmt) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *GoStmt) copy() Node { func (n *GoDeferStmt) copy() Node {
c := *n c := *n
c.init = c.init.Copy() c.init = c.init.Copy()
return &c return &c
} }
func (n *GoStmt) doChildren(do func(Node) error) error { func (n *GoDeferStmt) doChildren(do func(Node) error) error {
var err error var err error
err = maybeDoList(n.init, err, do) err = maybeDoList(n.init, err, do)
err = maybeDo(n.Call, err, do) err = maybeDo(n.Call, err, do)
return err return err
} }
func (n *GoStmt) editChildren(edit func(Node) Node) { func (n *GoDeferStmt) editChildren(edit func(Node) Node) {
editList(n.init, edit) editList(n.init, edit)
n.Call = maybeEdit(n.Call, edit) n.Call = maybeEdit(n.Call, edit)
} }
@ -602,6 +584,26 @@ func (n *LabelStmt) editChildren(edit func(Node) Node) {
editList(n.init, edit) 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) String() string { return fmt.Sprint(n) }
func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *MakeExpr) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *MakeExpr) copy() Node { func (n *MakeExpr) copy() Node {
@ -913,6 +915,24 @@ func (n *StarExpr) editChildren(edit func(Node) Node) {
n.X = maybeEdit(n.X, edit) 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) String() string { return fmt.Sprint(n) }
func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) } func (n *StructType) Format(s fmt.State, verb rune) { FmtNode(n, s, verb) }
func (n *StructType) copy() Node { func (n *StructType) copy() Node {

View file

@ -66,16 +66,16 @@ type AssignListStmt struct {
Lhs Nodes Lhs Nodes
Def bool Def bool
Rhs Nodes Rhs Nodes
offset int64 // for initorder 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 := &AssignListStmt{}
n.pos = pos n.pos = pos
n.op = OAS2 n.SetOp(op)
n.Lhs.Set(lhs) n.Lhs.Set(lhs)
n.Rhs.Set(rhs) n.Rhs.Set(rhs)
n.offset = types.BADWIDTH n.Offset_ = types.BADWIDTH
return n 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) SetRlist(x Nodes) { n.Rhs = x }
func (n *AssignListStmt) Colas() bool { return n.Def } func (n *AssignListStmt) Colas() bool { return n.Def }
func (n *AssignListStmt) SetColas(x bool) { n.Def = x } func (n *AssignListStmt) SetColas(x bool) { n.Def = x }
func (n *AssignListStmt) Offset() int64 { return n.offset } func (n *AssignListStmt) Offset() int64 { return n.Offset_ }
func (n *AssignListStmt) SetOffset(x int64) { n.offset = x } func (n *AssignListStmt) SetOffset(x int64) { n.Offset_ = x }
func (n *AssignListStmt) SetOp(op Op) { func (n *AssignListStmt) SetOp(op Op) {
switch op { switch op {
@ -106,14 +106,14 @@ type AssignStmt struct {
X Node X Node
Def bool Def bool
Y Node Y Node
offset int64 // for initorder Offset_ int64 // for initorder
} }
func NewAssignStmt(pos src.XPos, x, y Node) *AssignStmt { func NewAssignStmt(pos src.XPos, x, y Node) *AssignStmt {
n := &AssignStmt{X: x, Y: y} n := &AssignStmt{X: x, Y: y}
n.pos = pos n.pos = pos
n.op = OAS n.op = OAS
n.offset = types.BADWIDTH n.Offset_ = types.BADWIDTH
return n 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) SetRight(y Node) { n.Y = y }
func (n *AssignStmt) Colas() bool { return n.Def } func (n *AssignStmt) Colas() bool { return n.Def }
func (n *AssignStmt) SetColas(x bool) { n.Def = x } func (n *AssignStmt) SetColas(x bool) { n.Def = x }
func (n *AssignStmt) Offset() int64 { return n.offset } func (n *AssignStmt) Offset() int64 { return n.Offset_ }
func (n *AssignStmt) SetOffset(x int64) { n.offset = x } func (n *AssignStmt) SetOffset(x int64) { n.Offset_ = x }
func (n *AssignStmt) SetOp(op Op) { func (n *AssignStmt) SetOp(op Op) {
switch op { switch op {
@ -236,22 +236,6 @@ func (n *CaseStmt) SetRlist(x Nodes) { n.Vars = x }
func (n *CaseStmt) Left() Node { return n.Comm } func (n *CaseStmt) Left() Node { return n.Comm }
func (n *CaseStmt) SetLeft(x Node) { n.Comm = x } 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 } // A ForStmt is a non-range for loop: for Init; Cond; Post { Body }
// Op can be OFOR or OFORUNTIL (!Cond). // Op can be OFOR or OFORUNTIL (!Cond).
type ForStmt struct { type ForStmt struct {
@ -261,7 +245,7 @@ type ForStmt struct {
Late Nodes Late Nodes
Post Node Post Node
Body_ Nodes Body_ Nodes
hasBreak bool HasBreak_ bool
} }
func NewForStmt(pos src.XPos, init []Node, cond, post Node, body []Node) *ForStmt { 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) List() Nodes { return n.Late }
func (n *ForStmt) PtrList() *Nodes { return &n.Late } func (n *ForStmt) PtrList() *Nodes { return &n.Late }
func (n *ForStmt) SetList(x Nodes) { n.Late = x } func (n *ForStmt) SetList(x Nodes) { n.Late = x }
func (n *ForStmt) HasBreak() bool { return n.hasBreak } func (n *ForStmt) HasBreak() bool { return n.HasBreak_ }
func (n *ForStmt) SetHasBreak(b bool) { n.hasBreak = b } func (n *ForStmt) SetHasBreak(b bool) { n.HasBreak_ = b }
func (n *ForStmt) SetOp(op Op) { func (n *ForStmt) SetOp(op Op) {
if op != OFOR && op != OFORUNTIL { if op != OFOR && op != OFORUNTIL {
@ -295,21 +279,30 @@ func (n *ForStmt) SetOp(op Op) {
n.op = op n.op = op
} }
// A GoStmt is a go statement: go Call. // A GoDeferStmt is a go or defer statement: go Call / defer Call.
type GoStmt struct { //
// 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 miniStmt
Call Node Call Node
} }
func NewGoStmt(pos src.XPos, call Node) *GoStmt { func NewGoDeferStmt(pos src.XPos, op Op, call Node) *GoDeferStmt {
n := &GoStmt{Call: call} n := &GoDeferStmt{Call: call}
n.pos = pos n.pos = pos
n.op = OGO switch op {
case ODEFER, OGO:
n.op = op
default:
panic("NewGoDeferStmt " + op.String())
}
return n return n
} }
func (n *GoStmt) Left() Node { return n.Call } func (n *GoDeferStmt) Left() Node { return n.Call }
func (n *GoStmt) SetLeft(x Node) { n.Call = x } func (n *GoDeferStmt) SetLeft(x Node) { n.Call = x }
// A IfStmt is a return statement: if Init; Cond { Then } else { Else }. // A IfStmt is a return statement: if Init; Cond { Then } else { Else }.
type IfStmt struct { type IfStmt struct {
@ -317,7 +310,7 @@ type IfStmt struct {
Cond Node Cond Node
Body_ Nodes Body_ Nodes
Else Nodes Else Nodes
likely bool // code layout hint Likely_ bool // code layout hint
} }
func NewIfStmt(pos src.XPos, cond Node, body, els []Node) *IfStmt { 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) Rlist() Nodes { return n.Else }
func (n *IfStmt) PtrRlist() *Nodes { return &n.Else } func (n *IfStmt) PtrRlist() *Nodes { return &n.Else }
func (n *IfStmt) SetRlist(x Nodes) { n.Else = x } func (n *IfStmt) SetRlist(x Nodes) { n.Else = x }
func (n *IfStmt) Likely() bool { return n.likely } func (n *IfStmt) Likely() bool { return n.Likely_ }
func (n *IfStmt) SetLikely(x bool) { n.likely = x } func (n *IfStmt) SetLikely(x bool) { n.Likely_ = x }
// An InlineMarkStmt is a marker placed just before an inlined body. // An InlineMarkStmt is a marker placed just before an inlined body.
type InlineMarkStmt struct { type InlineMarkStmt struct {
@ -381,7 +374,7 @@ type RangeStmt struct {
Def bool Def bool
X Node X Node
Body_ Nodes Body_ Nodes
hasBreak bool HasBreak_ bool
typ *types.Type // TODO(rsc): Remove - use X.Type() instead typ *types.Type // TODO(rsc): Remove - use X.Type() instead
} }
@ -404,8 +397,8 @@ func (n *RangeStmt) SetBody(x Nodes) { n.Body_ = x }
func (n *RangeStmt) List() Nodes { return n.Vars } func (n *RangeStmt) List() Nodes { return n.Vars }
func (n *RangeStmt) PtrList() *Nodes { return &n.Vars } func (n *RangeStmt) PtrList() *Nodes { return &n.Vars }
func (n *RangeStmt) SetList(x Nodes) { n.Vars = x } func (n *RangeStmt) SetList(x Nodes) { n.Vars = x }
func (n *RangeStmt) HasBreak() bool { return n.hasBreak } func (n *RangeStmt) HasBreak() bool { return n.HasBreak_ }
func (n *RangeStmt) SetHasBreak(b bool) { n.hasBreak = b } func (n *RangeStmt) SetHasBreak(b bool) { n.HasBreak_ = b }
func (n *RangeStmt) Colas() bool { return n.Def } func (n *RangeStmt) Colas() bool { return n.Def }
func (n *RangeStmt) SetColas(b bool) { n.Def = b } func (n *RangeStmt) SetColas(b bool) { n.Def = b }
func (n *RangeStmt) Type() *types.Type { return n.typ } func (n *RangeStmt) Type() *types.Type { return n.typ }
@ -439,7 +432,7 @@ type SelectStmt struct {
miniStmt miniStmt
Label *types.Sym Label *types.Sym
Cases Nodes Cases Nodes
hasBreak bool HasBreak_ bool
// TODO(rsc): Instead of recording here, replace with a block? // TODO(rsc): Instead of recording here, replace with a block?
Compiled Nodes // compiled form, after walkswitch 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) SetList(x Nodes) { n.Cases = x }
func (n *SelectStmt) Sym() *types.Sym { return n.Label } func (n *SelectStmt) Sym() *types.Sym { return n.Label }
func (n *SelectStmt) SetSym(x *types.Sym) { n.Label = x } func (n *SelectStmt) SetSym(x *types.Sym) { n.Label = x }
func (n *SelectStmt) HasBreak() bool { return n.hasBreak } func (n *SelectStmt) HasBreak() bool { return n.HasBreak_ }
func (n *SelectStmt) SetHasBreak(x bool) { n.hasBreak = x } func (n *SelectStmt) SetHasBreak(x bool) { n.HasBreak_ = x }
func (n *SelectStmt) Body() Nodes { return n.Compiled } func (n *SelectStmt) Body() Nodes { return n.Compiled }
func (n *SelectStmt) PtrBody() *Nodes { return &n.Compiled } func (n *SelectStmt) PtrBody() *Nodes { return &n.Compiled }
func (n *SelectStmt) SetBody(x Nodes) { n.Compiled = x } func (n *SelectStmt) SetBody(x Nodes) { n.Compiled = x }
@ -489,7 +482,7 @@ type SwitchStmt struct {
Tag Node Tag Node
Cases Nodes // list of *CaseStmt Cases Nodes // list of *CaseStmt
Label *types.Sym Label *types.Sym
hasBreak bool HasBreak_ bool
// TODO(rsc): Instead of recording here, replace with a block? // TODO(rsc): Instead of recording here, replace with a block?
Compiled Nodes // compiled form, after walkswitch 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) SetBody(x Nodes) { n.Compiled = x }
func (n *SwitchStmt) Sym() *types.Sym { return n.Label } func (n *SwitchStmt) Sym() *types.Sym { return n.Label }
func (n *SwitchStmt) SetSym(x *types.Sym) { n.Label = x } func (n *SwitchStmt) SetSym(x *types.Sym) { n.Label = x }
func (n *SwitchStmt) HasBreak() bool { return n.hasBreak } func (n *SwitchStmt) HasBreak() bool { return n.HasBreak_ }
func (n *SwitchStmt) SetHasBreak(x bool) { n.hasBreak = x } func (n *SwitchStmt) SetHasBreak(x bool) { n.HasBreak_ = x }
// A TypeSwitchGuard is the [Name :=] X.(type) in a type switch. // A TypeSwitchGuard is the [Name :=] X.(type) in a type switch.
type TypeSwitchGuard struct { type TypeSwitchGuard struct {

View file

@ -92,7 +92,7 @@ func ValidTypeForConst(t *types.Type, v constant.Value) bool {
// nodlit returns a new untyped constant with value v. // nodlit returns a new untyped constant with value v.
func NewLiteral(v constant.Value) Node { func NewLiteral(v constant.Value) Node {
n := Nod(OLITERAL, nil, nil) n := newNameAt(base.Pos, OLITERAL, nil)
if k := v.Kind(); k != constant.Unknown { if k := v.Kind(); k != constant.Unknown {
n.SetType(idealType(k)) n.SetType(idealType(k))
n.SetVal(v) n.SetVal(v)