]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: spill all the parameters around morestack
authorDavid Chase <drchase@google.com>
Fri, 16 Apr 2021 04:15:31 +0000 (00:15 -0400)
committerDavid Chase <drchase@google.com>
Fri, 16 Apr 2021 20:12:20 +0000 (20:12 +0000)
former code only spilled those parameters mentioned in code
AT THE REGISTER LEVEL, this caused problems with liveness
sometimes (which worked on whole variables including
aggregates).

Updates #40724.

Change-Id: Ib9fdc50d95d1d2b1f1e405dd370540e88582ac71
Reviewed-on: https://go-review.googlesource.com/c/go/+/310690
Trust: David Chase <drchase@google.com>
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/amd64/ssa.go
src/cmd/compile/internal/ssa/func.go
src/cmd/compile/internal/ssa/location.go
src/cmd/compile/internal/ssa/stackalloc.go
src/cmd/compile/internal/ssagen/ssa.go

index 42c12953f95a7685b24e309cd3f23bdfddd86680..38d2d43e2790be01d9aeb0fa742c96fb13db9cea 100644 (file)
@@ -989,9 +989,9 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
                // The loop only runs once.
                for _, ap := range v.Block.Func.RegArgs {
                        // Pass the spill/unspill information along to the assembler, offset by size of return PC pushed on stack.
-                       addr := ssagen.SpillSlotAddr(ap.Mem(), x86.REG_SP, v.Block.Func.Config.PtrSize)
+                       addr := ssagen.SpillSlotAddr(ap, x86.REG_SP, v.Block.Func.Config.PtrSize)
                        s.FuncInfo().AddSpill(
-                               obj.RegSpill{Reg: ap.Reg(), Addr: addr, Unspill: loadByType(ap.Type()), Spill: storeByType(ap.Type())})
+                               obj.RegSpill{Reg: ap.Reg, Addr: addr, Unspill: loadByType(ap.Type), Spill: storeByType(ap.Type)})
                }
                v.Block.Func.RegArgs = nil
                ssagen.CheckArgReg(v)
index 819d7573d6b495772200d939bad95f57319152c6..378a73a95ac60b9dc65257f033b07c46a28080a6 100644 (file)
@@ -64,7 +64,7 @@ type Func struct {
        Names []LocalSlot
 
        // RegArgs is a slice of register-memory pairs that must be spilled and unspilled in the uncommon path of function entry.
-       RegArgs []ArgPair
+       RegArgs []Spill
        // AuxCall describing parameters and results for this function.
        OwnAux *AuxCall
 
index af0a913d17e45a64f0e986a3dc93977ef3226ed3..252c47cdebc8b6ab4a4523e4042c3d34724520be 100644 (file)
@@ -102,28 +102,8 @@ func (t LocResults) String() string {
        return a
 }
 
-type ArgPair struct {
-       reg *Register
-       mem LocalSlot
-}
-
-func (ap *ArgPair) Reg() int16 {
-       return ap.reg.objNum
-}
-
-func (ap *ArgPair) Type() *types.Type {
-       return ap.mem.Type
-}
-
-func (ap *ArgPair) Mem() *LocalSlot {
-       return &ap.mem
-}
-
-func (t ArgPair) String() string {
-       n0 := "nil"
-       if t.reg != nil {
-               n0 = t.reg.String()
-       }
-       n1 := t.mem.String()
-       return fmt.Sprintf("<%s,%s>", n0, n1)
+type Spill struct {
+       Type   *types.Type
+       Offset int64
+       Reg    int16
 }
index 45058d4e720e37ad7c5165ab652d212456afc4fe..8fe18e5f02d18edfb7fcf14cd342c641840ce682 100644 (file)
@@ -165,15 +165,6 @@ func (s *stackAllocState) stackalloc() {
                        f.setHome(v, loc)
                        continue
                }
-
-               nameOff := v.Aux.(*AuxNameOffset)
-               loc := LocalSlot{N: nameOff.Name, Type: v.Type, Off: nameOff.Offset}
-               if f.pass.debug > stackDebug {
-                       fmt.Printf("stackalloc Op%s %s to %s\n", v.Op, v, loc)
-               }
-               // register args already allocated to registers, but need to know the stack allocation for later
-               reg := f.getHome(v.ID).(*Register)
-               f.RegArgs = append(f.RegArgs, ArgPair{reg: reg, mem: loc})
        }
 
        // For each type, we keep track of all the stack slots we
index f0bce0756a97f7369cf062ccd6f7cd6863883bb3..e7d486537579535684ed8a83afbc35a55ab1a88f 100644 (file)
@@ -641,6 +641,22 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func {
                s.emitOpenDeferInfo()
        }
 
+       // Record incoming parameter spill information for morestack calls emitted in the assembler.
+       // This is done here, using all the parameters (used, partially used, and unused) because
+       // it mimics the behavior of the former ABI (everything stored) and because it's not 100%
+       // clear if naming conventions are respected in autogenerated code.
+       // TODO figure out exactly what's unused, don't spill it. Make liveness fine-grained, also.
+       // TODO non-amd64 architectures have link registers etc that may require adjustment here.
+       for _, p := range params.InParams() {
+               typs, offs := p.RegisterTypesAndOffsets()
+               for i, t := range typs {
+                       o := offs[i]                // offset within parameter
+                       fo := p.FrameOffset(params) // offset of parameter in frame
+                       reg := ssa.ObjRegForAbiReg(p.Registers[i], s.f.Config)
+                       s.f.RegArgs = append(s.f.RegArgs, ssa.Spill{Reg: reg, Offset: fo + o, Type: t})
+               }
+       }
+
        return s.f
 }
 
@@ -7578,16 +7594,12 @@ func deferstruct(stksize int64) *types.Type {
 // The resulting addr is used in a non-standard context -- in the prologue
 // of a function, before the frame has been constructed, so the standard
 // addressing for the parameters will be wrong.
-func SpillSlotAddr(slot *ssa.LocalSlot, baseReg int16, extraOffset int64) obj.Addr {
-       n, off := slot.N, slot.Off
-       if n.Class != ir.PPARAM && n.Class != ir.PPARAMOUT {
-               panic("Only expected to see param and returns here")
-       }
+func SpillSlotAddr(spill ssa.Spill, baseReg int16, extraOffset int64) obj.Addr {
        return obj.Addr{
                Name:   obj.NAME_NONE,
                Type:   obj.TYPE_MEM,
                Reg:    baseReg,
-               Offset: off + extraOffset + n.FrameOffset(),
+               Offset: spill.Offset + extraOffset,
        }
 }