From 067d8a664e65d7a42102c3984c8e155224555150 Mon Sep 17 00:00:00 2001 From: David Mitchell Date: Wed, 12 Nov 2025 13:57:12 +0000 Subject: [PATCH] op_dump(): display names of variables for pad ops. Make op_dump(), as used by 'perl -Dx', display the names of pad variables when dumping pad ops. The runtime perl -Dt already does this (note the $x, $y etc appearing in the op name displays): $ perl -Dt -e'my ($x, $y); $y = 1+$x' (-e:0) enter (-e:0) nextstate (-e:1) padrange($x,$y) (-e:1) nextstate (-e:1) const(IV(1)) (-e:1) padsv($x) (-e:1) add($y) (-e:1) leave While the (typically compile-time) -Dx detailed optree dumping didn't. Here are some 'before this commit' and 'after' examples of how some of those ops were/are now displayed. Note the changes in the 'TARG = N' lines for the following code: $ perl -Dx -e'my ($x, $y); $y = 1+$x' Before: 4 | +--padrange OP(0x31b08960) ===> 6 [nextstate 0x31b09fc0] | | TARG = 1 | | FLAGS = (VOID,MOD,SLABBED,MORESIB) | | PRIVATE = (LVINTRO,range=0x2) 10 +--add BINOP(0x31b0a060) ===> 1 [leave 0x31b08880] TARG = 2 FLAGS = (VOID,KIDS,SLABBED) PRIVATE = (TARGMY,0x2) 11 +--padsv OP(0x31b0a0a0) ===> 10 [add 0x31b0a060] TARG = 1 FLAGS = (SCALAR,SLABBED) After: 4 | +--padrange OP(0x18ffe920) ===> 6 [nextstate 0x18ffff80] | | TARG = 1 ($x,$y) | | FLAGS = (VOID,MOD,SLABBED,MORESIB) | | PRIVATE = (LVINTRO,range=0x2) 10 +--add BINOP(0x19000020) ===> 1 [leave 0x18ffe840] TARG = 2 ($y) FLAGS = (VOID,KIDS,SLABBED) PRIVATE = (TARGMY,0x2) 11 +--padsv OP(0x19000060) ===> 10 [add 0x19000020] TARG = 1 ($x) FLAGS = (SCALAR,SLABBED) --- dump.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/dump.c b/dump.c index 077cc80aba..126d630dce 100644 --- a/dump.c +++ b/dump.c @@ -1285,7 +1285,9 @@ S_sequence_num(pTHX_ const OP *o) } - +/* forward declaration */ +STATIC void +S_deb_padvar_cv(pTHX_ CV *cv, PADOFFSET off, int n, bool paren); const struct flag_to_name op_flags_names[] = { @@ -1379,9 +1381,39 @@ S_do_op_dump_bar(pTHX_ I32 level, UV bar, PerlIO *file, const OP *o, } } - if (o->op_targ && optype != OP_NULL) - S_opdump_indent(aTHX_ o, level, bar, file, "TARG = %ld\n", - (long)o->op_targ); + if (o->op_targ && optype != OP_NULL) { + S_opdump_indent(aTHX_ o, level, bar, file, "TARG = %ld", + (long)o->op_targ); + + /* Display the names of the lexical variables (if any) + * associated with op_targ */ + int n = 1; + + switch (o->op_type) { + case OP_PADRANGE: + n = o->op_private & OPpPADRANGE_COUNTMASK; + /* FALLTHROUGH */ + case OP_PADSV: + case OP_PADAV: + case OP_PADHV: + case OP_ARGELEM: + case OP_PADSV_STORE: + case OP_AELEMFAST_LEX: + do_lex: + PerlIO_puts(file, " "); + S_deb_padvar_cv(aTHX_ S_get_cv_from_op(aTHX_ o, rootcv), + o->op_targ, + n, 1); + break; + + default: + if ( (PL_opargs[o->op_type] & OA_TARGLEX) + && (o->op_private & OPpTARGET_MY)) + goto do_lex; + } + + PerlIO_puts(file, "\n"); + } if (o->op_flags || o->op_slabbed || o->op_savefree || o->op_static) { SV * const tmpsv = newSVpvs("");