]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.24] cmd/compile: for arm64 epilog, do SP increment with a single...
authorKeith Randall <khr@golang.org>
Mon, 21 Jul 2025 17:09:35 +0000 (10:09 -0700)
committerMark Freeman <mark@golang.org>
Wed, 30 Jul 2025 18:54:02 +0000 (11:54 -0700)
That way, the frame is atomically popped. Previously, for big frames
the SP was unwound in two steps (because arm64 can only add constants
up to 1<<12 in a single instruction).

Fixes #74694

Change-Id: I382c249194ad7bc9fc19607c27487c58d90d49e5
Reviewed-on: https://go-review.googlesource.com/c/go/+/689235
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Keith Randall <khr@google.com>
(cherry picked from commit f7cc61e7d7f77521e073137c6045ba73f66ef902)
Reviewed-on: https://go-review.googlesource.com/c/go/+/689596

src/cmd/internal/obj/arm64/obj7.go

index 368a631ff5b5de12cb2d2d8210c1b37c43d36300..ea1a35b09718b77ea9c2f84458be0c00924f7c3e 100644 (file)
@@ -907,18 +907,49 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                p.To.Reg = REGFP
                                p.To.Offset = REGLINK
 
-                               // ADD $aoffset, RSP, RSP
-                               q = newprog()
-                               q.As = AADD
-                               q.From.Type = obj.TYPE_CONST
-                               q.From.Offset = int64(aoffset)
-                               q.To.Type = obj.TYPE_REG
-                               q.To.Reg = REGSP
-                               q.Spadj = -aoffset
-                               q.Pos = p.Pos
-                               q.Link = p.Link
-                               p.Link = q
-                               p = q
+                               if aoffset < 1<<12 {
+                                       // ADD $aoffset, RSP, RSP
+                                       q = newprog()
+                                       q.As = AADD
+                                       q.From.Type = obj.TYPE_CONST
+                                       q.From.Offset = int64(aoffset)
+                                       q.To.Type = obj.TYPE_REG
+                                       q.To.Reg = REGSP
+                                       q.Spadj = -aoffset
+                                       q.Pos = p.Pos
+                                       q.Link = p.Link
+                                       p.Link = q
+                                       p = q
+                               } else {
+                                       // Put frame size in a separate register and
+                                       // add it in with a single instruction,
+                                       // so we never have a partial frame during
+                                       // the epilog. See issue 73259.
+
+                                       // MOVD $aoffset, REGTMP
+                                       q = newprog()
+                                       q.As = AMOVD
+                                       q.From.Type = obj.TYPE_CONST
+                                       q.From.Offset = int64(aoffset)
+                                       q.To.Type = obj.TYPE_REG
+                                       q.To.Reg = REGTMP
+                                       q.Pos = p.Pos
+                                       q.Link = p.Link
+                                       p.Link = q
+                                       p = q
+                                       // ADD REGTMP, RSP, RSP
+                                       q = newprog()
+                                       q.As = AADD
+                                       q.From.Type = obj.TYPE_REG
+                                       q.From.Reg = REGTMP
+                                       q.To.Type = obj.TYPE_REG
+                                       q.To.Reg = REGSP
+                                       q.Spadj = -aoffset
+                                       q.Pos = p.Pos
+                                       q.Link = p.Link
+                                       p.Link = q
+                                       p = q
+                               }
                        }
 
                        // If enabled, this code emits 'MOV PC, R27' before every 'MOV LR, PC',