Skip to content

Commit 422f38f

Browse files
committed
[dev.regabi] cmd/compile: move stack objects to liveness
Calculating and emitting stack objects are essentially part of liveness analysis, so move the code from ssagen to liveness. Allows unexporting liveness.ShouldTrack. Passes toolstash -cmp. Change-Id: I88b5b2e75b8dfb46b8b03a2fa09a9236865cbf3e Reviewed-on: https://go-review.googlesource.com/c/go/+/284413 Trust: Matthew Dempsky <[email protected]> Run-TryBot: Matthew Dempsky <[email protected]> Reviewed-by: Cuong Manh Le <[email protected]> TryBot-Result: Go Bot <[email protected]>
1 parent 6113db0 commit 422f38f

File tree

2 files changed

+50
-53
lines changed

2 files changed

+50
-53
lines changed

src/cmd/compile/internal/liveness/plive.go

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ package liveness
1717
import (
1818
"crypto/md5"
1919
"fmt"
20+
"sort"
2021
"strings"
2122

2223
"cmd/compile/internal/base"
2324
"cmd/compile/internal/bitvec"
2425
"cmd/compile/internal/ir"
2526
"cmd/compile/internal/objw"
27+
"cmd/compile/internal/reflectdata"
2628
"cmd/compile/internal/ssa"
2729
"cmd/compile/internal/typebits"
2830
"cmd/compile/internal/types"
@@ -174,13 +176,13 @@ type progeffectscache struct {
174176
initialized bool
175177
}
176178

177-
// ShouldTrack reports whether the liveness analysis
179+
// shouldTrack reports whether the liveness analysis
178180
// should track the variable n.
179181
// We don't care about variables that have no pointers,
180182
// nor do we care about non-local variables,
181183
// nor do we care about empty structs (handled by the pointer check),
182184
// nor do we care about the fake PAUTOHEAP variables.
183-
func ShouldTrack(n *ir.Name) bool {
185+
func shouldTrack(n *ir.Name) bool {
184186
return (n.Class == ir.PAUTO && n.Esc() != ir.EscHeap || n.Class == ir.PPARAM || n.Class == ir.PPARAMOUT) && n.Type().HasPointers()
185187
}
186188

@@ -189,7 +191,7 @@ func ShouldTrack(n *ir.Name) bool {
189191
func getvariables(fn *ir.Func) ([]*ir.Name, map[*ir.Name]int32) {
190192
var vars []*ir.Name
191193
for _, n := range fn.Dcl {
192-
if ShouldTrack(n) {
194+
if shouldTrack(n) {
193195
vars = append(vars, n)
194196
}
195197
}
@@ -1179,9 +1181,54 @@ func Compute(curfn *ir.Func, f *ssa.Func, stkptrsize int64, pp *objw.Progs) Map
11791181
p.To.Name = obj.NAME_EXTERN
11801182
p.To.Sym = fninfo.GCLocals
11811183

1184+
if x := lv.emitStackObjects(); x != nil {
1185+
p := pp.Prog(obj.AFUNCDATA)
1186+
p.From.SetConst(objabi.FUNCDATA_StackObjects)
1187+
p.To.Type = obj.TYPE_MEM
1188+
p.To.Name = obj.NAME_EXTERN
1189+
p.To.Sym = x
1190+
}
1191+
11821192
return lv.livenessMap
11831193
}
11841194

1195+
func (lv *liveness) emitStackObjects() *obj.LSym {
1196+
var vars []*ir.Name
1197+
for _, n := range lv.fn.Dcl {
1198+
if shouldTrack(n) && n.Addrtaken() && n.Esc() != ir.EscHeap {
1199+
vars = append(vars, n)
1200+
}
1201+
}
1202+
if len(vars) == 0 {
1203+
return nil
1204+
}
1205+
1206+
// Sort variables from lowest to highest address.
1207+
sort.Slice(vars, func(i, j int) bool { return vars[i].FrameOffset() < vars[j].FrameOffset() })
1208+
1209+
// Populate the stack object data.
1210+
// Format must match runtime/stack.go:stackObjectRecord.
1211+
x := base.Ctxt.Lookup(lv.fn.LSym.Name + ".stkobj")
1212+
lv.fn.LSym.Func().StackObjects = x
1213+
off := 0
1214+
off = objw.Uintptr(x, off, uint64(len(vars)))
1215+
for _, v := range vars {
1216+
// Note: arguments and return values have non-negative Xoffset,
1217+
// in which case the offset is relative to argp.
1218+
// Locals have a negative Xoffset, in which case the offset is relative to varp.
1219+
off = objw.Uintptr(x, off, uint64(v.FrameOffset()))
1220+
off = objw.SymPtr(x, off, reflectdata.TypeLinksym(v.Type()), 0)
1221+
}
1222+
1223+
if base.Flag.Live != 0 {
1224+
for _, v := range vars {
1225+
base.WarnfAt(v.Pos(), "stack object %v %v", v, v.Type())
1226+
}
1227+
}
1228+
1229+
return x
1230+
}
1231+
11851232
// isfat reports whether a variable of type t needs multiple assignments to initialize.
11861233
// For example:
11871234
//

src/cmd/compile/internal/ssagen/ssa.go

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6467,63 +6467,13 @@ func (s *State) DebugFriendlySetPosFrom(v *ssa.Value) {
64676467
}
64686468
}
64696469

6470-
// byXoffset implements sort.Interface for []*ir.Name using Xoffset as the ordering.
6471-
type byXoffset []*ir.Name
6472-
6473-
func (s byXoffset) Len() int { return len(s) }
6474-
func (s byXoffset) Less(i, j int) bool { return s[i].FrameOffset() < s[j].FrameOffset() }
6475-
func (s byXoffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
6476-
6477-
func emitStackObjects(e *ssafn, pp *objw.Progs) {
6478-
var vars []*ir.Name
6479-
for _, n := range e.curfn.Dcl {
6480-
if liveness.ShouldTrack(n) && n.Addrtaken() && n.Esc() != ir.EscHeap {
6481-
vars = append(vars, n)
6482-
}
6483-
}
6484-
if len(vars) == 0 {
6485-
return
6486-
}
6487-
6488-
// Sort variables from lowest to highest address.
6489-
sort.Sort(byXoffset(vars))
6490-
6491-
// Populate the stack object data.
6492-
// Format must match runtime/stack.go:stackObjectRecord.
6493-
x := base.Ctxt.Lookup(e.curfn.LSym.Name + ".stkobj")
6494-
e.curfn.LSym.Func().StackObjects = x
6495-
off := 0
6496-
off = objw.Uintptr(x, off, uint64(len(vars)))
6497-
for _, v := range vars {
6498-
// Note: arguments and return values have non-negative Xoffset,
6499-
// in which case the offset is relative to argp.
6500-
// Locals have a negative Xoffset, in which case the offset is relative to varp.
6501-
off = objw.Uintptr(x, off, uint64(v.FrameOffset()))
6502-
off = objw.SymPtr(x, off, reflectdata.TypeLinksym(v.Type()), 0)
6503-
}
6504-
6505-
// Emit a funcdata pointing at the stack object data.
6506-
p := pp.Prog(obj.AFUNCDATA)
6507-
p.From.SetConst(objabi.FUNCDATA_StackObjects)
6508-
p.To.Type = obj.TYPE_MEM
6509-
p.To.Name = obj.NAME_EXTERN
6510-
p.To.Sym = x
6511-
6512-
if base.Flag.Live != 0 {
6513-
for _, v := range vars {
6514-
base.WarnfAt(v.Pos(), "stack object %v %s", v, v.Type().String())
6515-
}
6516-
}
6517-
}
6518-
65196470
// genssa appends entries to pp for each instruction in f.
65206471
func genssa(f *ssa.Func, pp *objw.Progs) {
65216472
var s State
65226473

65236474
e := f.Frontend().(*ssafn)
65246475

65256476
s.livenessMap = liveness.Compute(e.curfn, f, e.stkptrsize, pp)
6526-
emitStackObjects(e, pp)
65276477

65286478
openDeferInfo := e.curfn.LSym.Func().OpenCodedDeferInfo
65296479
if openDeferInfo != nil {

0 commit comments

Comments
 (0)