From 989a3f5041d2055e165e363d3fb2d27e75e2fa38 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 2 Dec 2020 22:42:24 -0500 Subject: [PATCH] [dev.regabi] cmd/compile: adjustments to Copy and DeepCopy DeepCopy is not called DeepSepCopy, so it should use Copy, not SepCopy. Also, the old gc.treecopy, which became ir.DeepCopy, only copied the Left, Right, and List fields - not Init, Rlist, Body - and I didn't notice when I moved it over. A general utility function should of course copy the whole node, so do that. Finally, the semantics of Copy should not depend on whether a particular child node is held directly in a field or in a slice, so make Copy duplicate the slice backing arrays as well. (Logically, those backing arrays are part of the node storage.) Passes buildall w/ toolstash -cmp. Change-Id: I18fbe3f2b40078f566ed6370684d5585052b36a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/275309 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/copy.go | 43 +++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/ir/copy.go b/src/cmd/compile/internal/ir/copy.go index a356074bb8..705de0195b 100644 --- a/src/cmd/compile/internal/ir/copy.go +++ b/src/cmd/compile/internal/ir/copy.go @@ -61,9 +61,33 @@ func Copy(n Node) Node { if n, ok := n.(OrigNode); ok && n.Orig() == n { copy.(OrigNode).SetOrig(copy) } + + // Copy lists so that updates to n.List[0] + // don't affect copy.List[0] and vice versa, + // same as updates to Left and Right. + // TODO(rsc): Eventually the Node implementations will need to do this. + if l := copy.List(); l.Len() > 0 { + copy.SetList(copyList(l)) + } + if l := copy.Rlist(); l.Len() > 0 { + copy.SetRlist(copyList(l)) + } + if l := copy.Init(); l.Len() > 0 { + copy.SetInit(copyList(l)) + } + if l := copy.Body(); l.Len() > 0 { + copy.SetBody(copyList(l)) + } + return copy } +func copyList(x Nodes) Nodes { + out := make([]Node, x.Len()) + copy(out, x.Slice()) + return AsNodes(out) +} + // A Node can implement DeepCopyNode to provide a custom implementation // of DeepCopy. If the compiler only needs access to a Node's structure during // DeepCopy, then a Node can implement DeepCopyNode instead of providing @@ -94,10 +118,15 @@ func DeepCopy(pos src.XPos, n Node) Node { switch n.Op() { default: - m := SepCopy(n) + m := Copy(n) m.SetLeft(DeepCopy(pos, n.Left())) m.SetRight(DeepCopy(pos, n.Right())) - m.PtrList().Set(deepCopyList(pos, n.List().Slice())) + // deepCopyList instead of DeepCopyList + // because Copy already copied all these slices. + deepCopyList(pos, m.PtrList().Slice()) + deepCopyList(pos, m.PtrRlist().Slice()) + deepCopyList(pos, m.PtrInit().Slice()) + deepCopyList(pos, m.PtrBody().Slice()) if pos.IsKnown() { m.SetPos(pos) } @@ -118,10 +147,18 @@ func DeepCopy(pos src.XPos, n Node) Node { } } -func deepCopyList(pos src.XPos, list []Node) []Node { +// DeepCopyList returns a list of deep copies (using DeepCopy) of the nodes in list. +func DeepCopyList(pos src.XPos, list []Node) []Node { var out []Node for _, n := range list { out = append(out, DeepCopy(pos, n)) } return out } + +// deepCopyList edits list to point to deep copies of its elements. +func deepCopyList(pos src.XPos, list []Node) { + for i, n := range list { + list[i] = DeepCopy(pos, n) + } +}