]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj: set morestack arg spilling and regabi prologue on
authorSrinivas Pokala <Pokala.Srinivas@ibm.com>
Tue, 11 Nov 2025 03:47:55 +0000 (04:47 +0100)
committerKeith Randall <khr@golang.org>
Mon, 24 Nov 2025 18:21:41 +0000 (10:21 -0800)
s390x

This CL spill arg registers before calling morestack, unspill them
after morestack call. It also avoid clobbering the register that
could contain incoming argument values. Change registers on s390x to
avoid regABI arguments.

Update #40724

Change-Id: I67b20552410dd23ef0b86f14b9c5bfed9f9723a6
Reviewed-on: https://go-review.googlesource.com/c/go/+/719421
Reviewed-by: Vishwanatha HD <vishwanatha.hd@ibm.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/internal/obj/s390x/a.out.go
src/cmd/internal/obj/s390x/objz.go

index caf5ec09358a033c84d139440da1c34d3516f69f..6b16d7a9bd522594a978a27da14bbf4aa72d054b 100644 (file)
@@ -139,8 +139,8 @@ const (
        REG_RESERVED // end of allocated registers
 
        REGARG  = -1      // -1 disables passing the first argument in register
-       REGRT1  = REG_R3  // used during zeroing of the stack - not reserved
-       REGRT2  = REG_R // used during zeroing of the stack - not reserved
+       REGRT1  = REG_R1  // used during zeroing of the stack - not reserved
+       REGRT2  = REG_R10 // used during zeroing of the stack - not reserved
        REGTMP  = REG_R10 // scratch register used in the assembler and linker
        REGTMP2 = REG_R11 // scratch register used in the assembler and linker
        REGCTXT = REG_R12 // context for closures
index 44c1a7d586d5f25e2bef3cf64d34ca6811c17e67..4bfc1f7b2c00118e305a456de4f7df27ab80b429 100644 (file)
@@ -506,7 +506,13 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (pPre, pPreempt, pCh
                // Save LR and REGCTXT
                const frameSize = 16
                p = c.ctxt.StartUnsafePoint(p, c.newprog)
+
+               // Spill arguments. This has to happen before we open
+               // any more frame space.
+               p = c.cursym.Func().SpillRegisterArgs(p, c.newprog)
+
                // MOVD LR, -16(SP)
+
                p = obj.Appendp(p, c.newprog)
                p.As = AMOVD
                p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
@@ -549,10 +555,12 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (pPre, pPreempt, pCh
                p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REGSP}
                p.Spadj = -frameSize
 
+               // Unspill arguments
+               p = c.cursym.Func().UnspillRegisterArgs(p, c.newprog)
                p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
        }
 
-       // MOVD g_stackguard(g), R3
+       // MOVD g_stackguard(g), R10
        p = obj.Appendp(p, c.newprog)
        // Jump back to here after morestack returns.
        pCheck = p
@@ -565,7 +573,7 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (pPre, pPreempt, pCh
                p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1
        }
        p.To.Type = obj.TYPE_REG
-       p.To.Reg = REG_R3
+       p.To.Reg = REG_R10
 
        // Mark the stack bound check and morestack call async nonpreemptible.
        // If we get preempted here, when resumed the preemption request is
@@ -579,7 +587,7 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (pPre, pPreempt, pCh
 
                p = obj.Appendp(p, c.newprog)
                p.From.Type = obj.TYPE_REG
-               p.From.Reg = REG_R3
+               p.From.Reg = REG_R10
                p.Reg = REGSP
                p.As = ACMPUBGE
                p.To.Type = obj.TYPE_BRANCH
@@ -598,40 +606,40 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (pPre, pPreempt, pCh
                // stack guard to incorrectly succeed. We explicitly
                // guard against underflow.
                //
-               //      MOVD    $(framesize-StackSmall), R4
-               //      CMPUBLT SP, R4, label-of-call-to-morestack
+               //      MOVD    $(framesize-StackSmall), R11
+               //      CMPUBLT SP, R11, label-of-call-to-morestack
 
                p = obj.Appendp(p, c.newprog)
                p.As = AMOVD
                p.From.Type = obj.TYPE_CONST
                p.From.Offset = offset
                p.To.Type = obj.TYPE_REG
-               p.To.Reg = REG_R4
+               p.To.Reg = REG_R11
 
                p = obj.Appendp(p, c.newprog)
                pPreempt = p
                p.As = ACMPUBLT
                p.From.Type = obj.TYPE_REG
                p.From.Reg = REGSP
-               p.Reg = REG_R4
+               p.Reg = REG_R11
                p.To.Type = obj.TYPE_BRANCH
        }
 
        // Check against the stack guard. We've ensured this won't underflow.
-       //      ADD $-(framesize-StackSmall), SP, R4
-       //      CMPUBGE stackguard, R4, label-of-call-to-morestack
+       //      ADD $-(framesize-StackSmall), SP, R11
+       //      CMPUBGE stackguard, R11, label-of-call-to-morestack
        p = obj.Appendp(p, c.newprog)
        p.As = AADD
        p.From.Type = obj.TYPE_CONST
        p.From.Offset = -offset
        p.Reg = REGSP
        p.To.Type = obj.TYPE_REG
-       p.To.Reg = REG_R4
+       p.To.Reg = REG_R11
 
        p = obj.Appendp(p, c.newprog)
        p.From.Type = obj.TYPE_REG
-       p.From.Reg = REG_R3
-       p.Reg = REG_R4
+       p.From.Reg = REG_R10
+       p.Reg = REG_R11
        p.As = ACMPUBGE
        p.To.Type = obj.TYPE_BRANCH
 
@@ -654,18 +662,22 @@ func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre, pPreempt, pCheck *obj.Prog, fr
 
        pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
        pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
+       if pPreempt != nil {
+               pPreempt.To.SetTarget(pcdata)
+       }
+       pPre.To.SetTarget(pcdata)
+
+       // Spill the register args that could be clobbered by the
+       // morestack code.
+       spill := c.cursym.Func().SpillRegisterArgs(pcdata, c.newprog)
 
        // MOVD LR, R5
-       p = obj.Appendp(pcdata, c.newprog)
-       pPre.To.SetTarget(p)
+       p = obj.Appendp(spill, c.newprog)
        p.As = AMOVD
        p.From.Type = obj.TYPE_REG
        p.From.Reg = REG_LR
        p.To.Type = obj.TYPE_REG
        p.To.Reg = REG_R5
-       if pPreempt != nil {
-               pPreempt.To.SetTarget(p)
-       }
 
        // BL   runtime.morestack(SB)
        p = obj.Appendp(p, c.newprog)
@@ -680,10 +692,12 @@ func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre, pPreempt, pCheck *obj.Prog, fr
                p.To.Sym = c.ctxt.Lookup("runtime.morestack")
        }
 
+       // The instructions which unspill regs should be preemptible.
        p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
+       unspill := c.cursym.Func().UnspillRegisterArgs(p, c.newprog)
 
        // BR   pCheck
-       p = obj.Appendp(p, c.newprog)
+       p = obj.Appendp(unspill, c.newprog)
 
        p.As = ABR
        p.To.Type = obj.TYPE_BRANCH