]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix WriteFuncMap for new ABI.
authorDavid Chase <drchase@google.com>
Fri, 12 Mar 2021 18:37:24 +0000 (13:37 -0500)
committerDavid Chase <drchase@google.com>
Mon, 22 Mar 2021 18:42:15 +0000 (18:42 +0000)
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>
src/cmd/compile/internal/abi/abiutils.go
src/cmd/compile/internal/gc/compile.go
src/cmd/compile/internal/liveness/plive.go
src/cmd/compile/internal/objw/objw.go
src/cmd/compile/internal/ssagen/ssa.go

index 7573c131588d39ab3d74e606b160440e9d757821..8495ed7c51916cb8682e94092c2c899fb15d3657 100644 (file)
@@ -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.
index 83cfceb2c87e22bcaf4184f9d216156c7baf87bb..e066d3345e9e44c941f37e85d718a0d3c4612c0a 100644 (file)
@@ -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
        }
 
index c09a8401f7aa5aa927ced17cbbd6fbca9d0196e5..5d8e8b115d23dc7b09ae7c6a54fad0c79ec9ce42 100644 (file)
@@ -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)
        }
 
index dfbcf5155655c852df92cfc8559ca4b7d65f5134..50ce7b747db60a58a4d426e6cdd448e637ddcad5 100644 (file)
@@ -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 {
index e97535e74800062dcd6db752d37a1c725432f789..5d23b3bd7923f773c12031886170f390bff8c7e5 100644 (file)
@@ -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)))
                }
        }
 }