diff options
author | David Chase <drchase@google.com> | 2021-03-12 13:37:24 -0500 |
---|---|---|
committer | David Chase <drchase@google.com> | 2021-03-22 18:42:15 +0000 |
commit | 196c33e92d86eb21fe1cb7d244ea61209b4a554e (patch) | |
tree | 4e45e3c3de287b7e46f63822c3ec55f258be2473 | |
parent | ba6b8e75ed16b3e9ecb305399e5ec2e29778e299 (diff) | |
download | go-196c33e92d86eb21fe1cb7d244ea61209b4a554e.tar.gz go-196c33e92d86eb21fe1cb7d244ea61209b4a554e.zip |
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>
-rw-r--r-- | src/cmd/compile/internal/abi/abiutils.go | 24 | ||||
-rw-r--r-- | src/cmd/compile/internal/gc/compile.go | 4 | ||||
-rw-r--r-- | src/cmd/compile/internal/liveness/plive.go | 29 | ||||
-rw-r--r-- | src/cmd/compile/internal/objw/objw.go | 6 | ||||
-rw-r--r-- | src/cmd/compile/internal/ssagen/ssa.go | 2 |
5 files changed, 41 insertions, 24 deletions
diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index 7573c13158..8495ed7c51 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -236,16 +236,22 @@ func (a *ABIParamAssignment) SpillOffset() int32 { return a.offset } -// FrameOffset returns the location that a value would spill to, if any exists. -// For register-allocated inputs, that is their spill offset reserved for morestack -// (might as well use it, it is there); for stack-allocated inputs and outputs, -// that is their location on the stack. For register-allocated outputs, there is -// no defined spill area, so return -1. +// FrameOffset returns the frame-pointer-relative location that a function +// would spill its input or output parameter to, if such a spill slot exists. +// For register-allocated inputs that is their spill offset reserved for morestack; +// for stack-allocated inputs and outputs, that is their location on the stack. +// 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 { - if len(a.Registers) == 0 || a.offset == -1 { - return int64(a.offset) + if a.offset == -1 { + 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. @@ -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 parameterUpdateMu.Lock() defer parameterUpdateMu.Unlock() - off := a.FrameOffset(result) - config.LocalsOffset() + off := a.FrameOffset(result) fOffset := f.Offset if fOffset == types.BOGUS_FUNARG_OFFSET { // Set the Offset the first time. After that, we may recompute it, but it should never change. diff --git a/src/cmd/compile/internal/gc/compile.go b/src/cmd/compile/internal/gc/compile.go index 83cfceb2c8..e066d3345e 100644 --- a/src/cmd/compile/internal/gc/compile.go +++ b/src/cmd/compile/internal/gc/compile.go @@ -45,8 +45,8 @@ func enqueueFunc(fn *ir.Func) { ssagen.InitLSym(fn, false) types.CalcSize(fn.Type()) // TODO register args; remove this once all is done by abiutils a := ssagen.AbiForFunc(fn) - a.ABIAnalyze(fn.Type(), true) // will set parameter spill/home locations correctly - liveness.WriteFuncMap(fn) + abiInfo := a.ABIAnalyze(fn.Type(), true) // will set parameter spill/home locations correctly + liveness.WriteFuncMap(fn, abiInfo) return } diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go index c09a8401f7..5d8e8b115d 100644 --- a/src/cmd/compile/internal/liveness/plive.go +++ b/src/cmd/compile/internal/liveness/plive.go @@ -22,6 +22,7 @@ import ( "sort" "strings" + "cmd/compile/internal/abi" "cmd/compile/internal/base" "cmd/compile/internal/bitvec" "cmd/compile/internal/ir" @@ -1449,32 +1450,36 @@ func isfat(t *types.Type) bool { return false } -// TODO THIS IS ALL WRONG AND NEEDS TO USE ABI. -func WriteFuncMap(fn *ir.Func) { +// WriteFuncMap writes the pointer bitmaps for bodyless function fn's +// 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 != "" { return } types.CalcSize(fn.Type()) - lsym := base.Ctxt.Lookup(fn.LSym.Name + ".args_stackmap") - nptr := int(fn.Type().ArgWidth() / int64(types.PtrSize)) + nptr := int(abiInfo.ArgWidth() / int64(types.PtrSize)) bv := bitvec.New(int32(nptr) * 2) + + for _, p := range abiInfo.InParams() { + typebits.Set(p.Type, p.FrameOffset(abiInfo), bv) + } + nbitmap := 1 if fn.Type().NumResults() > 0 { nbitmap = 2 } + lsym := base.Ctxt.Lookup(fn.LSym.Name + ".args_stackmap") off := objw.Uint32(lsym, 0, uint32(nbitmap)) 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) 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) } diff --git a/src/cmd/compile/internal/objw/objw.go b/src/cmd/compile/internal/objw/objw.go index dfbcf51556..50ce7b747d 100644 --- a/src/cmd/compile/internal/objw/objw.go +++ b/src/cmd/compile/internal/objw/objw.go @@ -11,6 +11,8 @@ import ( "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 { 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) } +// 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 { if off&(wid-1) != 0 { 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)) } +// 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 { // Runtime reads the bitmaps as byte arrays. Oblige. for j := 0; int32(j) < bv.N; j += 8 { diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index e97535e748..5d23b3bd79 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -367,7 +367,7 @@ func (s *state) emitOpenDeferInfo() { f := getParam(r.n, j) off = dvarint(x, off, -okOffset(arg.FrameOffset())) 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))) } } } |