mirror of
https://github.com/golang/go
synced 2024-11-11 20:20:23 -07:00
[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 <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
parent
6113db0bb4
commit
422f38fb6c
@ -17,12 +17,14 @@ package liveness
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/bitvec"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/objw"
|
||||
"cmd/compile/internal/reflectdata"
|
||||
"cmd/compile/internal/ssa"
|
||||
"cmd/compile/internal/typebits"
|
||||
"cmd/compile/internal/types"
|
||||
@ -174,13 +176,13 @@ type progeffectscache struct {
|
||||
initialized bool
|
||||
}
|
||||
|
||||
// ShouldTrack reports whether the liveness analysis
|
||||
// shouldTrack reports whether the liveness analysis
|
||||
// should track the variable n.
|
||||
// We don't care about variables that have no pointers,
|
||||
// nor do we care about non-local variables,
|
||||
// nor do we care about empty structs (handled by the pointer check),
|
||||
// nor do we care about the fake PAUTOHEAP variables.
|
||||
func ShouldTrack(n *ir.Name) bool {
|
||||
func shouldTrack(n *ir.Name) bool {
|
||||
return (n.Class == ir.PAUTO && n.Esc() != ir.EscHeap || n.Class == ir.PPARAM || n.Class == ir.PPARAMOUT) && n.Type().HasPointers()
|
||||
}
|
||||
|
||||
@ -189,7 +191,7 @@ func ShouldTrack(n *ir.Name) bool {
|
||||
func getvariables(fn *ir.Func) ([]*ir.Name, map[*ir.Name]int32) {
|
||||
var vars []*ir.Name
|
||||
for _, n := range fn.Dcl {
|
||||
if ShouldTrack(n) {
|
||||
if shouldTrack(n) {
|
||||
vars = append(vars, n)
|
||||
}
|
||||
}
|
||||
@ -1179,9 +1181,54 @@ func Compute(curfn *ir.Func, f *ssa.Func, stkptrsize int64, pp *objw.Progs) Map
|
||||
p.To.Name = obj.NAME_EXTERN
|
||||
p.To.Sym = fninfo.GCLocals
|
||||
|
||||
if x := lv.emitStackObjects(); x != nil {
|
||||
p := pp.Prog(obj.AFUNCDATA)
|
||||
p.From.SetConst(objabi.FUNCDATA_StackObjects)
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Name = obj.NAME_EXTERN
|
||||
p.To.Sym = x
|
||||
}
|
||||
|
||||
return lv.livenessMap
|
||||
}
|
||||
|
||||
func (lv *liveness) emitStackObjects() *obj.LSym {
|
||||
var vars []*ir.Name
|
||||
for _, n := range lv.fn.Dcl {
|
||||
if shouldTrack(n) && n.Addrtaken() && n.Esc() != ir.EscHeap {
|
||||
vars = append(vars, n)
|
||||
}
|
||||
}
|
||||
if len(vars) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sort variables from lowest to highest address.
|
||||
sort.Slice(vars, func(i, j int) bool { return vars[i].FrameOffset() < vars[j].FrameOffset() })
|
||||
|
||||
// Populate the stack object data.
|
||||
// Format must match runtime/stack.go:stackObjectRecord.
|
||||
x := base.Ctxt.Lookup(lv.fn.LSym.Name + ".stkobj")
|
||||
lv.fn.LSym.Func().StackObjects = x
|
||||
off := 0
|
||||
off = objw.Uintptr(x, off, uint64(len(vars)))
|
||||
for _, v := range vars {
|
||||
// Note: arguments and return values have non-negative Xoffset,
|
||||
// in which case the offset is relative to argp.
|
||||
// Locals have a negative Xoffset, in which case the offset is relative to varp.
|
||||
off = objw.Uintptr(x, off, uint64(v.FrameOffset()))
|
||||
off = objw.SymPtr(x, off, reflectdata.TypeLinksym(v.Type()), 0)
|
||||
}
|
||||
|
||||
if base.Flag.Live != 0 {
|
||||
for _, v := range vars {
|
||||
base.WarnfAt(v.Pos(), "stack object %v %v", v, v.Type())
|
||||
}
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// isfat reports whether a variable of type t needs multiple assignments to initialize.
|
||||
// For example:
|
||||
//
|
||||
|
@ -6467,55 +6467,6 @@ func (s *State) DebugFriendlySetPosFrom(v *ssa.Value) {
|
||||
}
|
||||
}
|
||||
|
||||
// byXoffset implements sort.Interface for []*ir.Name using Xoffset as the ordering.
|
||||
type byXoffset []*ir.Name
|
||||
|
||||
func (s byXoffset) Len() int { return len(s) }
|
||||
func (s byXoffset) Less(i, j int) bool { return s[i].FrameOffset() < s[j].FrameOffset() }
|
||||
func (s byXoffset) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
func emitStackObjects(e *ssafn, pp *objw.Progs) {
|
||||
var vars []*ir.Name
|
||||
for _, n := range e.curfn.Dcl {
|
||||
if liveness.ShouldTrack(n) && n.Addrtaken() && n.Esc() != ir.EscHeap {
|
||||
vars = append(vars, n)
|
||||
}
|
||||
}
|
||||
if len(vars) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Sort variables from lowest to highest address.
|
||||
sort.Sort(byXoffset(vars))
|
||||
|
||||
// Populate the stack object data.
|
||||
// Format must match runtime/stack.go:stackObjectRecord.
|
||||
x := base.Ctxt.Lookup(e.curfn.LSym.Name + ".stkobj")
|
||||
e.curfn.LSym.Func().StackObjects = x
|
||||
off := 0
|
||||
off = objw.Uintptr(x, off, uint64(len(vars)))
|
||||
for _, v := range vars {
|
||||
// Note: arguments and return values have non-negative Xoffset,
|
||||
// in which case the offset is relative to argp.
|
||||
// Locals have a negative Xoffset, in which case the offset is relative to varp.
|
||||
off = objw.Uintptr(x, off, uint64(v.FrameOffset()))
|
||||
off = objw.SymPtr(x, off, reflectdata.TypeLinksym(v.Type()), 0)
|
||||
}
|
||||
|
||||
// Emit a funcdata pointing at the stack object data.
|
||||
p := pp.Prog(obj.AFUNCDATA)
|
||||
p.From.SetConst(objabi.FUNCDATA_StackObjects)
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Name = obj.NAME_EXTERN
|
||||
p.To.Sym = x
|
||||
|
||||
if base.Flag.Live != 0 {
|
||||
for _, v := range vars {
|
||||
base.WarnfAt(v.Pos(), "stack object %v %s", v, v.Type().String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// genssa appends entries to pp for each instruction in f.
|
||||
func genssa(f *ssa.Func, pp *objw.Progs) {
|
||||
var s State
|
||||
@ -6523,7 +6474,6 @@ func genssa(f *ssa.Func, pp *objw.Progs) {
|
||||
e := f.Frontend().(*ssafn)
|
||||
|
||||
s.livenessMap = liveness.Compute(e.curfn, f, e.stkptrsize, pp)
|
||||
emitStackObjects(e, pp)
|
||||
|
||||
openDeferInfo := e.curfn.LSym.Func().OpenCodedDeferInfo
|
||||
if openDeferInfo != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user