diff --git a/src/cmd/compile/internal/ir/fmt.go b/src/cmd/compile/internal/ir/fmt.go index e1e3813368b..9682bae39b1 100644 --- a/src/cmd/compile/internal/ir/fmt.go +++ b/src/cmd/compile/internal/ir/fmt.go @@ -247,7 +247,7 @@ type fmtNode struct { m FmtMode } -func (f *fmtNode) Format(s fmt.State, verb rune) { f.x.format(s, verb, f.m) } +func (f *fmtNode) Format(s fmt.State, verb rune) { nodeFormat(f.x, s, verb, f.m) } type fmtOp struct { x Op @@ -282,7 +282,7 @@ func (n *Node) Format(s fmt.State, verb rune) { } func FmtNode(n *Node, s fmt.State, verb rune) { - n.format(s, verb, FErr) + nodeFormat(n, s, verb, FErr) } func (o Op) Format(s fmt.State, verb rune) { o.format(s, verb, FErr) } @@ -313,6 +313,8 @@ func (m FmtMode) prepareArgs(args []interface{}) { args[i] = &fmtOp{arg, m} case *Node: args[i] = &fmtNode{arg, m} + case nil: + args[i] = &fmtNode{nil, m} // assume this was a node interface case *types.Type: args[i] = &fmtType{arg, m} case *types.Sym: @@ -327,7 +329,7 @@ func (m FmtMode) prepareArgs(args []interface{}) { } } -func (n *Node) format(s fmt.State, verb rune, mode FmtMode) { +func nodeFormat(n *Node, s fmt.State, verb rune, mode FmtMode) { switch verb { case 'v', 'S', 'L': nconvFmt(n, s, fmtFlag(s, verb), mode) diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go index b42ca5b8a3c..d700c593906 100644 --- a/src/cmd/compile/internal/ir/node.go +++ b/src/cmd/compile/internal/ir/node.go @@ -7,6 +7,7 @@ package ir import ( + "fmt" "go/constant" "sort" "strings" @@ -18,6 +19,119 @@ import ( "cmd/internal/src" ) +// A Node is the abstract interface to an IR node. +type INode interface { + // Formatting + Format(s fmt.State, verb rune) + String() string + + // Source position. + Pos() src.XPos + SetPos(x src.XPos) + + // For making copies. Mainly used by Copy and SepCopy. + RawCopy() *Node + + // Abstract graph structure, for generic traversals. + Op() Op + SetOp(x Op) + Orig() *Node + SetOrig(x *Node) + SubOp() Op + SetSubOp(x Op) + Left() *Node + SetLeft(x *Node) + Right() *Node + SetRight(x *Node) + Init() Nodes + PtrInit() *Nodes + SetInit(x Nodes) + Body() Nodes + PtrBody() *Nodes + SetBody(x Nodes) + List() Nodes + SetList(x Nodes) + PtrList() *Nodes + Rlist() Nodes + SetRlist(x Nodes) + PtrRlist() *Nodes + + // Fields specific to certain Ops only. + Type() *types.Type + SetType(t *types.Type) + Func() *Func + SetFunc(x *Func) + Name() *Name + SetName(x *Name) + Sym() *types.Sym + SetSym(x *types.Sym) + Offset() int64 + SetOffset(x int64) + Class() Class + SetClass(x Class) + Likely() bool + SetLikely(x bool) + SliceBounds() (low, high, max *Node) + SetSliceBounds(low, high, max *Node) + Iota() int64 + SetIota(x int64) + Colas() bool + SetColas(x bool) + NoInline() bool + SetNoInline(x bool) + Transient() bool + SetTransient(x bool) + Implicit() bool + SetImplicit(x bool) + IsDDD() bool + SetIsDDD(x bool) + Embedded() bool + SetEmbedded(x bool) + IndexMapLValue() bool + SetIndexMapLValue(x bool) + TChanDir() types.ChanDir + SetTChanDir(x types.ChanDir) + ResetAux() + HasBreak() bool + SetHasBreak(x bool) + MarkReadonly() + Val() constant.Value + HasVal() bool + SetVal(v constant.Value) + Int64Val() int64 + Uint64Val() uint64 + CanInt64() bool + BoolVal() bool + StringVal() string + + // Storage for analysis passes. + Esc() uint16 + SetEsc(x uint16) + Walkdef() uint8 + SetWalkdef(x uint8) + Opt() interface{} + SetOpt(x interface{}) + HasOpt() bool + Diag() bool + SetDiag(x bool) + Bounded() bool + SetBounded(x bool) + Typecheck() uint8 + SetTypecheck(x uint8) + Initorder() uint8 + SetInitorder(x uint8) + NonNil() bool + MarkNonNil() + HasCall() bool + SetHasCall(x bool) + + // Only for SSA and should be removed when SSA starts + // using a more specific type than Node. + CanBeAnSSASym() +} + +var _ INode = (*Node)(nil) + // A Node is a single node in the syntax tree. // Actually the syntax tree is a syntax DAG, because there is only one // node with Op=ONAME for a given instance of a variable x. @@ -1512,9 +1626,9 @@ func (n *Node) RawCopy() *Node { // sepcopy returns a separate shallow copy of n, with the copy's // Orig pointing to itself. func SepCopy(n *Node) *Node { - copy := *n - copy.orig = © - return © + n = n.RawCopy() + n.SetOrig(n) + return n } // copy returns shallow copy of n and adjusts the copy's Orig if @@ -1525,11 +1639,11 @@ func SepCopy(n *Node) *Node { // (This caused the wrong complit Op to be used when printing error // messages; see issues #26855, #27765). func Copy(n *Node) *Node { - copy := *n + copy := n.RawCopy() if n.Orig() == n { - copy.orig = © + copy.SetOrig(copy) } - return © + return copy } // isNil reports whether n represents the universal untyped zero value "nil".