[dev.ssa] cmd/compile: implement static data generation

The existing backend recognizes special
assignment statements as being implementable
with static data rather than code.
Unfortunately, it assumes that it is in the middle
of codegen; it emits data and modifies the AST.

This does not play well with SSA's two-phase
bootstrapping approach, in which we attempt to
compile code but fall back to the existing backend
if something goes wrong.

To work around this:

* Add the ability to inquire about static data
without side-effects.
* Save the static data required for a function.
* Emit that static data during SSA codegen.

Change-Id: I2e8a506c866ea3e27dffb597095833c87f62d87e
Reviewed-on: https://go-review.googlesource.com/12790
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2015-07-28 10:56:39 -07:00
parent 2a5e6c47bc
commit 6b41665039
4 changed files with 55 additions and 21 deletions

View file

@ -1236,6 +1236,7 @@ func getlit(lit *Node) int {
return -1
}
// stataddr sets nam to the static address of n and reports whether it succeeeded.
func stataddr(nam *Node, n *Node) bool {
if n == nil {
return false
@ -1408,7 +1409,9 @@ func entry(p *InitPlan) *InitEntry {
return &p.E[len(p.E)-1]
}
func gen_as_init(n *Node) bool {
// gen_as_init attempts to emit static data for n and reports whether it succeeded.
// If reportOnly is true, it does not emit static data and does not modify the AST.
func gen_as_init(n *Node, reportOnly bool) bool {
var nr *Node
var nl *Node
var nam Node
@ -1457,7 +1460,9 @@ func gen_as_init(n *Node) bool {
case OSLICEARR:
if nr.Right.Op == OKEY && nr.Right.Left == nil && nr.Right.Right == nil {
nr = nr.Left
gused(nil) // in case the data is the dest of a goto
if !reportOnly {
gused(nil) // in case the data is the dest of a goto
}
nl := nr
if nr == nil || nr.Op != OADDR {
goto no
@ -1472,16 +1477,18 @@ func gen_as_init(n *Node) bool {
goto no
}
nam.Xoffset += int64(Array_array)
gdata(&nam, nl, int(Types[Tptr].Width))
if !reportOnly {
nam.Xoffset += int64(Array_array)
gdata(&nam, nl, int(Types[Tptr].Width))
nam.Xoffset += int64(Array_nel) - int64(Array_array)
var nod1 Node
Nodconst(&nod1, Types[TINT], nr.Type.Bound)
gdata(&nam, &nod1, Widthint)
nam.Xoffset += int64(Array_nel) - int64(Array_array)
var nod1 Node
Nodconst(&nod1, Types[TINT], nr.Type.Bound)
gdata(&nam, &nod1, Widthint)
nam.Xoffset += int64(Array_cap) - int64(Array_nel)
gdata(&nam, &nod1, Widthint)
nam.Xoffset += int64(Array_cap) - int64(Array_nel)
gdata(&nam, &nod1, Widthint)
}
return true
}
@ -1512,13 +1519,19 @@ func gen_as_init(n *Node) bool {
TPTR64,
TFLOAT32,
TFLOAT64:
gdata(&nam, nr, int(nr.Type.Width))
if !reportOnly {
gdata(&nam, nr, int(nr.Type.Width))
}
case TCOMPLEX64, TCOMPLEX128:
gdatacomplex(&nam, nr.Val().U.(*Mpcplx))
if !reportOnly {
gdatacomplex(&nam, nr.Val().U.(*Mpcplx))
}
case TSTRING:
gdatastring(&nam, nr.Val().U.(string))
if !reportOnly {
gdatastring(&nam, nr.Val().U.(string))
}
}
return true