Commit 54e10f6fa1 for perl

commit 54e10f6fa1ce68937cb8d8b3e2f06e4fd901444b
Author: Yves Orton <demerphq@gmail.com>
Date:   Tue Oct 27 21:36:24 2026 +0100

    regcomp: name GOSUB target properties

    Give GOSUB nodes separate names for the capture number, unresolved fixup
    index, and resolved target offset. The shared storage changes meaning
    during compilation, so the accessors make that distinction explicit
    while preserving the existing offsets and behavior.

diff --git a/regcomp.c b/regcomp.c
index 1a94ca3970..0041f2c15c 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -2445,11 +2445,11 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
          *
          * If for some reason someone writes code that optimises
          * away a GOSUB opcode then the assert should be changed to
-         * an if(scan) to guard the ARG2i_SET() - Yves
+         * an if(scan) to guard GOSUB_TARGET_OFFSET_SET() - Yves
          *
          */
         assert(scan && OP(scan) == GOSUB);
-        ARG2i_SET( scan, RExC_open_parens[ARG1u(scan)] - REGNODE_OFFSET(scan));
+        GOSUB_TARGET_OFFSET_SET( scan, RExC_open_parens[GOSUB_CAPTURE(scan)] - REGNODE_OFFSET(scan));
     }
     if (RExC_logical_total_parens != RExC_total_parens) {
         Newxz(RExC_parno_to_logical_next, RExC_total_parens, I32);
@@ -4018,7 +4018,7 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
                 }

                 /* We keep track how many GOSUB items we have produced.
-                   To start off the ARG2i() of the GOSUB holds its "id",
+                   Initially GOSUB_FIXUP_INDEX() holds its fixup index,
                    which is used later in conjunction with RExC_recurse
                    to calculate the offset we need to jump for the GOSUB,
                    which it will store in the final representation.
@@ -4030,8 +4030,8 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
                 DEBUG_OPTIMISE_MORE_r(re_printf(
                     "%*s%*s Recurse #%" UVuf " to %" IVdf "\n",
                             22, "|    |", (int)(depth * 2 + 1), "",
-                            (UV)ARG1u(REGNODE_p(ret)),
-                            (IV)ARG2i(REGNODE_p(ret))));
+                            (UV)GOSUB_CAPTURE(REGNODE_p(ret)),
+                            (IV)GOSUB_FIXUP_INDEX(REGNODE_p(ret))));
                 RExC_seen |= REG_RECURSE_SEEN;

                 *flagp |= POSTPONED;
diff --git a/regcomp.h b/regcomp.h
index 65d4e53f81..a9d88a00b8 100644
--- a/regcomp.h
+++ b/regcomp.h
@@ -562,6 +562,27 @@ struct regnode_ssc {
     ARG1u_SET((p), (val));                                                    \
 } STMT_END

+#define GOSUB_CAPTURE(p)                                                      \
+    (assert(OP(p) == GOSUB), PREVENT_LVALUE(ARG1u(p)))
+#define GOSUB_CAPTURE_SET(p, val) STMT_START {                                \
+    assert(OP(p) == GOSUB);                                                   \
+    ARG1u_SET((p), (val));                                                    \
+} STMT_END
+
+#define GOSUB_FIXUP_INDEX(p)                                                  \
+    (assert(OP(p) == GOSUB), PREVENT_LVALUE(ARG2i(p)))
+#define GOSUB_FIXUP_INDEX_SET(p, val) STMT_START {                            \
+    assert(OP(p) == GOSUB);                                                   \
+    ARG2i_SET((p), (val));                                                    \
+} STMT_END
+
+#define GOSUB_TARGET_OFFSET(p)                                                \
+    (assert(OP(p) == GOSUB), PREVENT_LVALUE(ARG2i(p)))
+#define GOSUB_TARGET_OFFSET_SET(p, val) STMT_START {                          \
+    assert(OP(p) == GOSUB);                                                   \
+    ARG2i_SET((p), (val));                                                    \
+} STMT_END
+
 #define REF_IS_VOLATILE(p)                                                    \
     (assert(REGNODE_TYPE(OP(p)) == REF), PREVENT_LVALUE((FLAGS(p) &           \
         VOLATILE_REF) != 0))
diff --git a/regcomp_debug.c b/regcomp_debug.c
index c09406d54c..094533a12f 100644
--- a/regcomp_debug.c
+++ b/regcomp_debug.c
@@ -728,7 +728,7 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o, const regmatch_
         }
     } else if (k == GOSUB) {
         AV *name_list= NULL;
-        IV parno = ARG1u(o);
+        IV parno = GOSUB_CAPTURE(o);
         IV logical_parno = (parno && prog->parno_to_logical)
                          ? prog->parno_to_logical[parno]
                          : parno;
@@ -743,10 +743,10 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o, const regmatch_
         if (logical_parno != parno)
             sv_catpvf(sv, "/%" IVdf, parno);

-        sv_catpvf(sv, "[%+d:%d]", (int)ARG2i(o),
-                (int)((o + (int)ARG2i(o)) - progi->program) );
+        sv_catpvf(sv, "[%+d:%d]", (int)GOSUB_TARGET_OFFSET(o),
+                (int)((o + (int)GOSUB_TARGET_OFFSET(o)) - progi->program) );
         if (name_list) {
-            SV **name= av_fetch_simple(name_list, ARG1u(o), 0 );
+            SV **name= av_fetch_simple(name_list, GOSUB_CAPTURE(o), 0 );
             if (name)
                 sv_catpvf(sv, " '%" SVf "'", SVfARG(*name));
         }
diff --git a/regcomp_study.c b/regcomp_study.c
index 264c46095f..8428881f4c 100644
--- a/regcomp_study.c
+++ b/regcomp_study.c
@@ -2200,8 +2200,8 @@ Perl_study_chunk(pTHX_
                  * the rest of this block. Specifically setting
                  * RExC_recurse[] must happen at least once during
                  * study_chunk(). */
-                paren = ARG1u(scan);
-                RExC_recurse[ARG2i(scan)] = scan;
+                paren = GOSUB_CAPTURE(scan);
+                RExC_recurse[GOSUB_FIXUP_INDEX(scan)] = scan;
                 start = REGNODE_p(RExC_open_parens[paren]);
                 end   = REGNODE_p(RExC_close_parens[paren]);

diff --git a/regexec.c b/regexec.c
index 596f84ea03..99426c3e45 100644
--- a/regexec.c
+++ b/regexec.c
@@ -8927,7 +8927,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
             U32 arg;

         case GOSUB: /*    /(...(?1))/   /(...(?&foo))/   */
-            arg = ARG1u(scan);
+            arg = GOSUB_CAPTURE(scan);
             if (cur_eval && cur_eval->locinput == locinput) {
                 if ( ++nochange_depth > max_nochange_depth )
                     croak(
@@ -8939,7 +8939,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
             re_sv = rex_sv;
             re = rex;
             rei = rexi;
-            startpoint = scan + ARG2i(scan);
+            startpoint = scan + GOSUB_TARGET_OFFSET(scan);
             EVAL_CLOSE_PAREN_SET( st, arg );
             /* Detect infinite recursion
              *