cmd/compile: fix WriteFuncMap for new ABI.

replaced old type-based logic with new abi-based logic;
earlier versions of this CL compared them for equality.
For not-in-a-register, they match everywhere tested.

also modified GetFrameOffset to make it more like the one it replaces;
the LocalsOffset is subtracted.

Change-Id: I65ce7f0646c493c277df6b6f46e4839a0d886ac9
Reviewed-on: https://go-review.googlesource.com/c/go/+/302072
Trust: David Chase <drchase@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
David Chase 2021-03-12 13:37:24 -05:00
parent ba6b8e75ed
commit 196c33e92d
5 changed files with 41 additions and 24 deletions

View file

@ -236,16 +236,22 @@ func (a *ABIParamAssignment) SpillOffset() int32 {
return a.offset return a.offset
} }
// FrameOffset returns the location that a value would spill to, if any exists. // FrameOffset returns the frame-pointer-relative location that a function
// For register-allocated inputs, that is their spill offset reserved for morestack // would spill its input or output parameter to, if such a spill slot exists.
// (might as well use it, it is there); for stack-allocated inputs and outputs, // For register-allocated inputs that is their spill offset reserved for morestack;
// that is their location on the stack. For register-allocated outputs, there is // for stack-allocated inputs and outputs, that is their location on the stack.
// no defined spill area, so return -1. // For register-allocated outputs, there is no defined spill area, so return -1.
// (In a future version of the ABI, register-resident inputs may lose their defined
// spill area to help reduce stack sizes.)
func (a *ABIParamAssignment) FrameOffset(i *ABIParamResultInfo) int64 { func (a *ABIParamAssignment) FrameOffset(i *ABIParamResultInfo) int64 {
if len(a.Registers) == 0 || a.offset == -1 { if a.offset == -1 {
return int64(a.offset) return -1
} }
return int64(a.offset) + i.SpillAreaOffset() if len(a.Registers) == 0 { // passed on stack
return int64(a.offset) - i.config.LocalsOffset()
}
// spill area for registers
return int64(a.offset) + i.SpillAreaOffset() - i.config.LocalsOffset()
} }
// RegAmounts holds a specified number of integer/float registers. // RegAmounts holds a specified number of integer/float registers.
@ -462,7 +468,7 @@ func (config *ABIConfig) updateOffset(result *ABIParamResultInfo, f *types.Field
// Getting this wrong breaks stackmaps, see liveness/plive.go:WriteFuncMap and typebits/typebits.go:Set // Getting this wrong breaks stackmaps, see liveness/plive.go:WriteFuncMap and typebits/typebits.go:Set
parameterUpdateMu.Lock() parameterUpdateMu.Lock()
defer parameterUpdateMu.Unlock() defer parameterUpdateMu.Unlock()
off := a.FrameOffset(result) - config.LocalsOffset() off := a.FrameOffset(result)
fOffset := f.Offset fOffset := f.Offset
if fOffset == types.BOGUS_FUNARG_OFFSET { if fOffset == types.BOGUS_FUNARG_OFFSET {
// Set the Offset the first time. After that, we may recompute it, but it should never change. // Set the Offset the first time. After that, we may recompute it, but it should never change.

View file

@ -45,8 +45,8 @@ func enqueueFunc(fn *ir.Func) {
ssagen.InitLSym(fn, false) ssagen.InitLSym(fn, false)
types.CalcSize(fn.Type()) // TODO register args; remove this once all is done by abiutils types.CalcSize(fn.Type()) // TODO register args; remove this once all is done by abiutils
a := ssagen.AbiForFunc(fn) a := ssagen.AbiForFunc(fn)
a.ABIAnalyze(fn.Type(), true) // will set parameter spill/home locations correctly abiInfo := a.ABIAnalyze(fn.Type(), true) // will set parameter spill/home locations correctly
liveness.WriteFuncMap(fn) liveness.WriteFuncMap(fn, abiInfo)
return return
} }

View file

@ -22,6 +22,7 @@ import (
"sort" "sort"
"strings" "strings"
"cmd/compile/internal/abi"
"cmd/compile/internal/base" "cmd/compile/internal/base"
"cmd/compile/internal/bitvec" "cmd/compile/internal/bitvec"
"cmd/compile/internal/ir" "cmd/compile/internal/ir"
@ -1449,32 +1450,36 @@ func isfat(t *types.Type) bool {
return false return false
} }
// TODO THIS IS ALL WRONG AND NEEDS TO USE ABI. // WriteFuncMap writes the pointer bitmaps for bodyless function fn's
func WriteFuncMap(fn *ir.Func) { // inputs and outputs as the value of symbol <fn>.args_stackmap.
// If fn has outputs, two bitmaps are written, otherwise just one.
func WriteFuncMap(fn *ir.Func, abiInfo *abi.ABIParamResultInfo) {
if ir.FuncName(fn) == "_" || fn.Sym().Linkname != "" { if ir.FuncName(fn) == "_" || fn.Sym().Linkname != "" {
return return
} }
types.CalcSize(fn.Type()) types.CalcSize(fn.Type())
lsym := base.Ctxt.Lookup(fn.LSym.Name + ".args_stackmap") nptr := int(abiInfo.ArgWidth() / int64(types.PtrSize))
nptr := int(fn.Type().ArgWidth() / int64(types.PtrSize))
bv := bitvec.New(int32(nptr) * 2) bv := bitvec.New(int32(nptr) * 2)
for _, p := range abiInfo.InParams() {
typebits.Set(p.Type, p.FrameOffset(abiInfo), bv)
}
nbitmap := 1 nbitmap := 1
if fn.Type().NumResults() > 0 { if fn.Type().NumResults() > 0 {
nbitmap = 2 nbitmap = 2
} }
lsym := base.Ctxt.Lookup(fn.LSym.Name + ".args_stackmap")
off := objw.Uint32(lsym, 0, uint32(nbitmap)) off := objw.Uint32(lsym, 0, uint32(nbitmap))
off = objw.Uint32(lsym, off, uint32(bv.N)) off = objw.Uint32(lsym, off, uint32(bv.N))
if ir.IsMethod(fn) {
typebits.Set(fn.Type().Recvs(), 0, bv)
}
if fn.Type().NumParams() > 0 {
typebits.Set(fn.Type().Params(), 0, bv)
}
off = objw.BitVec(lsym, off, bv) off = objw.BitVec(lsym, off, bv)
if fn.Type().NumResults() > 0 { if fn.Type().NumResults() > 0 {
typebits.Set(fn.Type().Results(), 0, bv) for _, p := range abiInfo.OutParams() {
if len(p.Registers) == 0 {
typebits.Set(p.Type, p.FrameOffset(abiInfo), bv)
}
}
off = objw.BitVec(lsym, off, bv) off = objw.BitVec(lsym, off, bv)
} }

View file

@ -11,6 +11,8 @@ import (
"cmd/internal/obj" "cmd/internal/obj"
) )
// Uint8 writes an unsigned byte v into s at offset off,
// and returns the next unused offset (i.e., off+1).
func Uint8(s *obj.LSym, off int, v uint8) int { func Uint8(s *obj.LSym, off int, v uint8) int {
return UintN(s, off, uint64(v), 1) return UintN(s, off, uint64(v), 1)
} }
@ -27,6 +29,8 @@ func Uintptr(s *obj.LSym, off int, v uint64) int {
return UintN(s, off, v, types.PtrSize) return UintN(s, off, v, types.PtrSize)
} }
// UintN writes an unsigned integer v of size wid bytes into s at offset off,
// and returns the next unused offset.
func UintN(s *obj.LSym, off int, v uint64, wid int) int { func UintN(s *obj.LSym, off int, v uint64, wid int) int {
if off&(wid-1) != 0 { if off&(wid-1) != 0 {
base.Fatalf("duintxxLSym: misaligned: v=%d wid=%d off=%d", v, wid, off) base.Fatalf("duintxxLSym: misaligned: v=%d wid=%d off=%d", v, wid, off)
@ -62,6 +66,8 @@ func Global(s *obj.LSym, width int32, flags int16) {
base.Ctxt.Globl(s, int64(width), int(flags)) base.Ctxt.Globl(s, int64(width), int(flags))
} }
// Bitvec writes the contents of bv into s as sequence of bytes
// in little-endian order, and returns the next unused offset.
func BitVec(s *obj.LSym, off int, bv bitvec.BitVec) int { func BitVec(s *obj.LSym, off int, bv bitvec.BitVec) int {
// Runtime reads the bitmaps as byte arrays. Oblige. // Runtime reads the bitmaps as byte arrays. Oblige.
for j := 0; int32(j) < bv.N; j += 8 { for j := 0; int32(j) < bv.N; j += 8 {

View file

@ -367,7 +367,7 @@ func (s *state) emitOpenDeferInfo() {
f := getParam(r.n, j) f := getParam(r.n, j)
off = dvarint(x, off, -okOffset(arg.FrameOffset())) off = dvarint(x, off, -okOffset(arg.FrameOffset()))
off = dvarint(x, off, f.Type.Size()) off = dvarint(x, off, f.Type.Size())
off = dvarint(x, off, okOffset(pri.InParam(j+argAdjust).FrameOffset(pri))-ab.LocalsOffset()) // defer does not want the fixed frame adjustment off = dvarint(x, off, okOffset(pri.InParam(j+argAdjust).FrameOffset(pri)))
} }
} }
} }