]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: adjustments to Copy and DeepCopy
authorRuss Cox <rsc@golang.org>
Thu, 3 Dec 2020 03:42:24 +0000 (22:42 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 4 Dec 2020 16:52:46 +0000 (16:52 +0000)
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 <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/ir/copy.go

index a356074bb843541e8013b3ce53fd6d26f11a8fdd..705de0195b5e0dad28c6de9917864a199aace0a3 100644 (file)
@@ -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)
+       }
+}