]> Cypherpunks repositories - gostls13.git/commit
[dev.regabi] cmd/compile: change Nodes to be a slice
authorRuss Cox <rsc@golang.org>
Sat, 12 Dec 2020 02:29:53 +0000 (21:29 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 17 Dec 2020 03:50:09 +0000 (03:50 +0000)
commit114af2a04408d0480bb3e9253bf15aae6b7ed23e
treee4a42ccc6218150643cf14a54e83f6c64aa9af68
parent4dfc7333f4ebe67e0aa7f429ce73c9d58a2fc309
[dev.regabi] cmd/compile: change Nodes to be a slice

The Nodes type originally served two purposes:
(1) It provided a representation optimized for empty slices,
allocating only a single word in that case instead of three,
at the cost of a non-empty slice being four words instead of three.
This was particularly important with the old Node representation,
in which most Nodes were full of unused fields.
(2) It provided a few useful helper methods beyond what can be
done with slices.

The downside of Nodes is that the API is a bit overwhelming,
with many ways to spell ordinary slice operations. For example,
reassigning the first node in the list can be done with:

ns.Slice()[0] = n
ns.SetIndex(0, n)
ns.SetFirst(n)
*ns.Addr(0) = n

And APIs must decide whether to use Nodes or []ir.Node and
then conversions must be inserted when crossing the boundary.

Now that Node structs are specialized to opcode and most Nodes
lists are actually non-empty, it makes sense to simplify Nodes
to make it actually a slice type, so that ordinary slice operations can
be used, and assignments can automatically convert between
Nodes and []ir.Node.

This CL changes the representation to be a slice and adds a new
Take method, which returns the old slice and clears the receiver.

In a future CL, the Nodes method set will simplify down to:

Copy
Take
Append
Prepend
Format

with the current methods being rewritten:

ns.Len() -> len(ns)
ns.Slice() -> ns
ns.First() -> ns[0]
ns.Second() -> ns[1]
ns.Index(i) -> ns[i]
ns.Addr(i) -> &ns[i]
ns.SetIndex(i, n) -> ns[i] = n
ns.SetFirst(n) -> ns[0] = n
ns.SetSecond(n) -> ns[1] = n
ns.Set1(n) -> ns = []Node{n}
ns.Set2(n, n2) -> ns = []Node{n, n2}
ns.Set3(n, n2, n3) -> ns = []Node{n, n2, n3}
AsNodes(slice) -> Nodes(slice)
ns.AppendNodes(pns) -> ns.Append(pns.Take()...)
ns.MoveNodes(pns) -> ns = pns.Take()

and then all those other methods will be deleted.

Simplifying the API down to just those five methods will also make it
more reasonable to introduce more specialized slices like Exprs and Stmts
at some point in the future.

But again this CL just changes the representation to a slice,
introduces Take, and leaves the rest alone.

Passes buildall w/ toolstash -cmp.

Change-Id: I309ab8335c69bb582d811c92c17f938dd6e0c4fe
Reviewed-on: https://go-review.googlesource.com/c/go/+/277916
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/ir/copy.go
src/cmd/compile/internal/ir/dump.go
src/cmd/compile/internal/ir/mini.go
src/cmd/compile/internal/ir/node.go
src/cmd/compile/internal/ir/sizeof_test.go