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
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
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
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
}
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
addEdge(b, lab.target)
case OAS, OASWB:
+ // Check whether we can generate static data rather than code.
+ // If so, ignore n and defer data generation until codegen.
+ // Failure to do this causes writes to readonly symbols.
+ if gen_as_init(n, true) {
+ var data []*Node
+ if s.f.StaticData != nil {
+ data = s.f.StaticData.([]*Node)
+ }
+ s.f.StaticData = append(data, n)
+ return
+ }
s.assign(n.Op, n.Left, n.Right)
case OIF:
Pc.As = obj.ARET // overwrite AEND
+ // Emit static data
+ if f.StaticData != nil {
+ for _, n := range f.StaticData.([]*Node) {
+ if !gen_as_init(n, false) {
+ Fatal("non-static data marked as static: %v\n\n", n, f)
+ }
+ }
+ }
+
// TODO: liveness
// TODO: gcargs
// TODO: gclocals
// A Func represents a Go func declaration (or function literal) and
// its body. This package compiles each Func independently.
type Func struct {
- Config *Config // architecture information
- Name string // e.g. bytes·Compare
- Type Type // type signature of the function.
- Blocks []*Block // unordered set of all basic blocks (note: not indexable by ID)
- Entry *Block // the entry basic block
- bid idAlloc // block ID allocator
- vid idAlloc // value ID allocator
+ Config *Config // architecture information
+ Name string // e.g. bytes·Compare
+ Type Type // type signature of the function.
+ StaticData interface{} // associated static data, untouched by the ssa package
+ Blocks []*Block // unordered set of all basic blocks (note: not indexable by ID)
+ Entry *Block // the entry basic block
+ bid idAlloc // block ID allocator
+ vid idAlloc // value ID allocator
// when register allocation is done, maps value ids to locations
RegAlloc []Location