Commit 19ee2ef9 authored by Daniel Martí's avatar Daniel Martí

cmd/compile: introduce gc.Node.copy method

When making a shallow copy of a node, various methods were used,
including calling nod(OXXX, nil, nil) and then overwriting it, or
"n1 := *n" and then using &n1.

Add a copy method instead, simplifying all of those and making them
consistent.

Passes toolstash -cmp on std cmd.

Change-Id: I3f3fc88bad708edc712bf6d87214cda4ddc43b01
Reviewed-on: https://go-review.googlesource.com/72710
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent 321bd8c9
......@@ -223,8 +223,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, reuse canReuseNode) *Node {
if n.Op == OLITERAL && !reuse {
// Can't always set n.Type directly on OLITERAL nodes.
// See discussion on CL 20813.
nn := *n
n = &nn
n = n.copy()
reuse = true
}
......@@ -1333,8 +1332,7 @@ func defaultlitreuse(n *Node, t *types.Type, reuse canReuseNode) *Node {
}
if n.Op == OLITERAL && !reuse {
nn := *n
n = &nn
n = n.copy()
reuse = true
}
......
......@@ -466,11 +466,11 @@ func funcargs(nt *Node) {
// So the two cases must be distinguished.
// We do not record a pointer to the original node (n->orig).
// Having multiple names causes too much confusion in later passes.
nn := *n.Left
nn.Orig = &nn
nn := n.Left.copy()
nn.Orig = nn
nn.Sym = lookupN("~b", gen)
gen++
n.Left = &nn
n.Left = nn
}
n.Left.Name.Param.Ntype = n.Right
......
......@@ -392,7 +392,7 @@ func inlcopy(n *Node) *Node {
return n
}
m := *n
m := n.copy()
if m.Func != nil {
m.Func.Inl.Set(nil)
}
......@@ -403,7 +403,7 @@ func inlcopy(n *Node) *Node {
m.Ninit.Set(inlcopylist(n.Ninit.Slice()))
m.Nbody.Set(inlcopylist(n.Nbody.Slice()))
return &m
return m
}
// Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
......@@ -1192,8 +1192,7 @@ func (subst *inlsubst) node(n *Node) *Node {
return m
case OGOTO, OLABEL:
m := nod(OXXX, nil, nil)
*m = *n
m := n.copy()
m.Pos = subst.updatedPos(m.Pos)
m.Ninit.Set(nil)
p := fmt.Sprintf("%s·%d", n.Left.Sym.Name, inlgen)
......@@ -1202,8 +1201,7 @@ func (subst *inlsubst) node(n *Node) *Node {
return m
}
m := nod(OXXX, nil, nil)
*m = *n
m := n.copy()
m.Pos = subst.updatedPos(m.Pos)
m.Ninit.Set(nil)
......
......@@ -109,10 +109,10 @@ func (o *Order) cheapExpr(n *Node) *Node {
if l == n.Left {
return n
}
a := *n
a.Orig = &a
a := n.copy()
a.Orig = a
a.Left = l
return typecheck(&a, Erv)
return typecheck(a, Erv)
}
return o.copyExpr(n, n.Type, false)
......@@ -135,20 +135,20 @@ func (o *Order) safeExpr(n *Node) *Node {
if l == n.Left {
return n
}
a := *n
a.Orig = &a
a := n.copy()
a.Orig = a
a.Left = l
return typecheck(&a, Erv)
return typecheck(a, Erv)
case ODOTPTR, OIND:
l := o.cheapExpr(n.Left)
if l == n.Left {
return n
}
a := *n
a.Orig = &a
a := n.copy()
a.Orig = a
a.Left = l
return typecheck(&a, Erv)
return typecheck(a, Erv)
case OINDEX, OINDEXMAP:
var l *Node
......@@ -161,11 +161,11 @@ func (o *Order) safeExpr(n *Node) *Node {
if l == n.Left && r == n.Right {
return n
}
a := *n
a.Orig = &a
a := n.copy()
a.Orig = a
a.Left = l
a.Right = r
return typecheck(&a, Erv)
return typecheck(a, Erv)
default:
Fatalf("ordersafeexpr %v", n.Op)
......
......@@ -67,17 +67,17 @@ func instrument(fn *Node) {
// nodpc is the PC of the caller as extracted by
// getcallerpc. We use -widthptr(FP) for x86.
// BUG: this will not work on arm.
nodpc := *nodfp
nodpc := nodfp.copy()
nodpc.Type = types.Types[TUINTPTR]
nodpc.Xoffset = int64(-Widthptr)
savedLineno := lineno
lineno = src.NoXPos
nd := mkcall("racefuncenter", nil, nil, &nodpc)
nd := mkcall("racefuncenter", nil, nil, nodpc)
fn.Func.Enter.Prepend(nd)
nd = mkcall("racefuncexit", nil, nil)
fn.Func.Exit.Append(nd)
fn.Func.Dcl = append(fn.Func.Dcl, &nodpc)
fn.Func.Dcl = append(fn.Func.Dcl, nodpc)
lineno = savedLineno
}
......
......@@ -328,35 +328,32 @@ func staticcopy(l *Node, r *Node, out *[]*Node) bool {
// copy slice
a := inittemps[r]
n := *l
n := l.copy()
n.Xoffset = l.Xoffset + int64(array_array)
gdata(&n, nod(OADDR, a, nil), Widthptr)
gdata(n, nod(OADDR, a, nil), Widthptr)
n.Xoffset = l.Xoffset + int64(array_nel)
gdata(&n, r.Right, Widthptr)
gdata(n, r.Right, Widthptr)
n.Xoffset = l.Xoffset + int64(array_cap)
gdata(&n, r.Right, Widthptr)
gdata(n, r.Right, Widthptr)
return true
case OARRAYLIT, OSTRUCTLIT:
p := initplans[r]
n := *l
n := l.copy()
for i := range p.E {
e := &p.E[i]
n.Xoffset = l.Xoffset + e.Xoffset
n.Type = e.Expr.Type
if e.Expr.Op == OLITERAL {
gdata(&n, e.Expr, int(n.Type.Width))
gdata(n, e.Expr, int(n.Type.Width))
} else {
ll := nod(OXXX, nil, nil)
*ll = n
ll := n.copy()
ll.Orig = ll // completely separate copy
if !staticassign(ll, e.Expr, out) {
// Requires computation, but we're
// copying someone else's computation.
rr := nod(OXXX, nil, nil)
*rr = *orig
rr := orig.copy()
rr.Orig = rr // completely separate copy
rr.Type = ll.Type
rr.Xoffset += e.Xoffset
......@@ -429,13 +426,13 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
ta := types.NewArray(r.Type.Elem(), bound)
a := staticname(ta)
inittemps[r] = a
n := *l
n := l.copy()
n.Xoffset = l.Xoffset + int64(array_array)
gdata(&n, nod(OADDR, a, nil), Widthptr)
gdata(n, nod(OADDR, a, nil), Widthptr)
n.Xoffset = l.Xoffset + int64(array_nel)
gdata(&n, r.Right, Widthptr)
gdata(n, r.Right, Widthptr)
n.Xoffset = l.Xoffset + int64(array_cap)
gdata(&n, r.Right, Widthptr)
gdata(n, r.Right, Widthptr)
// Fall through to init underlying array.
l = a
......@@ -445,17 +442,16 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
initplan(r)
p := initplans[r]
n := *l
n := l.copy()
for i := range p.E {
e := &p.E[i]
n.Xoffset = l.Xoffset + e.Xoffset
n.Type = e.Expr.Type
if e.Expr.Op == OLITERAL {
gdata(&n, e.Expr, int(n.Type.Width))
gdata(n, e.Expr, int(n.Type.Width))
} else {
setlineno(e.Expr)
a := nod(OXXX, nil, nil)
*a = n
a := n.copy()
a.Orig = a // completely separate copy
if !staticassign(a, e.Expr, out) {
*out = append(*out, nod(OAS, a, e.Expr))
......@@ -522,11 +518,10 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
// Copy val directly into n.
n.Type = val.Type
setlineno(val)
a := nod(OXXX, nil, nil)
*a = n
a.Orig = a
if !staticassign(a, val, out) {
*out = append(*out, nod(OAS, a, val))
a := n
a.Orig = &a
if !staticassign(&a, val, out) {
*out = append(*out, nod(OAS, &a, val))
}
} else {
// Construct temp to hold val, write pointer to temp into n.
......
......@@ -364,6 +364,11 @@ func nodSym(op Op, left *Node, sym *types.Sym) *Node {
return n
}
func (n *Node) copy() *Node {
n2 := *n
return &n2
}
// methcmp sorts methods by name with exported methods first,
// and then non-exported methods by their package path.
type methcmp []*types.Field
......@@ -439,8 +444,8 @@ func treecopy(n *Node, pos src.XPos) *Node {
switch n.Op {
default:
m := *n
m.Orig = &m
m := n.copy()
m.Orig = m
m.Left = treecopy(n.Left, pos)
m.Right = treecopy(n.Right, pos)
m.List.Set(listtreecopy(n.List.Slice(), pos))
......@@ -451,7 +456,7 @@ func treecopy(n *Node, pos src.XPos) *Node {
Dump("treecopy", n)
Fatalf("treecopy Name")
}
return &m
return m
case OPACK:
// OPACK nodes are never valid in const value declarations,
......@@ -1252,8 +1257,7 @@ func safeexpr(n *Node, init *Nodes) *Node {
if l == n.Left {
return n
}
r := nod(OXXX, nil, nil)
*r = *n
r := n.copy()
r.Left = l
r = typecheck(r, Erv)
r = walkexpr(r, init)
......@@ -1264,8 +1268,7 @@ func safeexpr(n *Node, init *Nodes) *Node {
if l == n.Left {
return n
}
a := nod(OXXX, nil, nil)
*a = *n
a := n.copy()
a.Left = l
a = walkexpr(a, init)
return a
......@@ -1276,8 +1279,7 @@ func safeexpr(n *Node, init *Nodes) *Node {
if l == n.Left && r == n.Right {
return n
}
a := nod(OXXX, nil, nil)
*a = *n
a := n.copy()
a.Left = l
a.Right = r
a = walkexpr(a, init)
......
......@@ -2873,9 +2873,7 @@ func typecheckcomplit(n *Node) *Node {
}
// Save original node (including n.Right)
norig := nod(n.Op, nil, nil)
*norig = *n
norig := n.copy()
setlineno(n.Right)
n.Right = typecheck(n.Right, Etype|Ecomplit)
......
......@@ -3894,7 +3894,7 @@ func wrapCall(n *Node, init *Nodes) *Node {
// The result of substArgTypes MUST be assigned back to old, e.g.
// n.Left = substArgTypes(n.Left, t1, t2)
func substArgTypes(old *Node, types_ ...*types.Type) *Node {
n := *old // make shallow copy
n := old.copy() // make shallow copy
for _, t := range types_ {
dowidth(t)
......@@ -3903,5 +3903,5 @@ func substArgTypes(old *Node, types_ ...*types.Type) *Node {
if len(types_) > 0 {
Fatalf("substArgTypes: too many argument types")
}
return &n
return n
}
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