X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/4e0538d9cb1446f7d7f4c30a62975e21aa184042..55b62dee2d8dffa7b36b3b613ee4727fbefdb9e3:/regen/op_private diff --git a/regen/op_private b/regen/op_private index 6a34dcf..a94c0c3 100644 --- a/regen/op_private +++ b/regen/op_private @@ -35,7 +35,8 @@ bit bit field. Here's a general example: addbits('aelem', 7 => qw(OPpLVAL_INTRO LVINTRO), - '5..6' => { + 6 => qw(OPpLVAL_DEFER LVDEFER), + '4..5' => { mask_def => 'OPpDEREF', enum => [ qw( 1 OPpDEREF_AV DREFAV @@ -43,10 +44,9 @@ bit bit field. Here's a general example: 3 OPpDEREF_SV DREFSV )], }, - 4 => qw(OPpLVAL_DEFER LVDEFER), ); -Here for the op C, bits 4 and 7 (bits are numbered 0..7) are +Here for the op C, bits 6 and 7 (bits are numbered 0..7) are defined as single-bit flags. The first string following the bit number is the define name that gets emitted in F, and the second string is the label, which will be displayed by F and Perl_do_op_dump() @@ -198,25 +198,28 @@ use strict; # find which ops use 0,1,2,3 or 4 bits of op_private for arg count info - $args0{$_} = 1 for qw(entersub); # UNOPs that usurp bit 0 + $args0{$_} = 1 for qw(entersub avhvswitch + rv2hv); # UNOPs that usurp bit 0 $args1{$_} = 1 for ( qw(reverse), # ck_fun(), but most bits stolen + qw(mapstart grepstart), # set in ck_fun, but + # cleared in ck_grep, + # unless there is an error grep !$maxarg{$_} && !$args0{$_}, ops_with_flag('1'), # UNOP + ops_with_flag('+'), # UNOP_AUX ops_with_flag('%'), # BASEOP/UNOP ops_with_flag('|'), # LOGOP ops_with_flag('-'), # FILESTATOP ops_with_flag('}'), # LOOPEXOP + ops_with_flag('.'), # METHOP ); $args2{$_} = 1 for ( qw(vec), grep !$maxarg{$_} && !$args0{$_} && !$args1{$_}, ops_with_flag('2'), # BINOP - # this is a binop, but special-cased as a - # baseop in regen/opcodes - 'sassign', ); $args3{$_} = 1 for grep !$maxarg{$_} && !$args0{$_} @@ -238,6 +241,7 @@ use strict; ops_with_check('ck_lfun'), ops_with_check('ck_open'), ops_with_check('ck_select'), + ops_with_check('ck_stringify'), ops_with_check('ck_tell'), ops_with_check('ck_trunc'), ; @@ -285,10 +289,6 @@ use strict; for (qw(nextstate dbstate)) { addbits($_, 5 => qw(OPpHUSH_VMSISH HUSH), - # should match HINT_M_VMSISH_STATUS, HINT_M_VMSISH_TIME - 6 => qw(OPpHINT_M_VMSISH_STATUS VMSISH_STATUS), - 7 => qw(OPpHINT_M_VMSISH_TIME VMSISH_TIME), - ); } @@ -298,9 +298,10 @@ for (qw(nextstate dbstate)) { # my $x addbits($_, 7 => qw(OPpLVAL_INTRO LVINTRO)) - for qw(gvsv rv2sv rv2hv rv2gv rv2av aelem helem aslice + for qw(gvsv rv2sv rv2hv rv2gv rv2av aelem helem aslice split hslice delete padsv padav padhv enteriter entersub padrange - pushmark cond_expr), + pushmark cond_expr refassign lvref lvrefslice lvavref multideref + multiconcat), 'list', # this gets set in my_attrs() for some reason ; @@ -320,23 +321,26 @@ addbits($_, 7 => qw(OPpLVAL_INTRO LVINTRO)) # Safe to set if the ppcode uses: # tryAMAGICbin, tryAMAGICun, SETn, SETi, SETu, PUSHn, PUSHTARG, SETTARG, # SETs(TARG), XPUSHn, XPUSHu, +# but make sure set-magic is invoked separately for SETs(TARG) (or change +# it to SETTARG). # # Unsafe to set if the ppcode uses dTARG or [X]RETPUSH[YES|NO|UNDEF] # -# lt and friends do SETs (including ncmp, but not scmp) +# Only the code paths that handle scalar rvalue context matter. If dTARG +# or RETPUSHNO occurs only in list or lvalue paths, T is safe. +# +# lt and friends do SETs (including ncmp, but not scmp or i_ncmp) # # Additional mode of failure: the opcode can modify TARG before it "used" # all the arguments (or may call an external function which does the same). # If the target coincides with one of the arguments ==> kaboom. # # pp.c pos substr each not OK (RETPUSHUNDEF) -# substr vec also not OK due to LV to target (are they???) # ref not OK (RETPUSHNO) -# trans not OK (dTARG; TARG = sv_newmortal();) +# trans not OK (target is used for lhs, not retval) # ucfirst etc not OK: TMP arg processed inplace # quotemeta not OK (unsafe when TARG == arg) -# each repeat not OK too due to list context -# pack split - unknown whether they are safe +# pack - unknown whether it is safe # sprintf: is calling do_sprintf(TARG,...) which can act on TARG # before other args are processed. # @@ -353,8 +357,8 @@ addbits($_, 7 => qw(OPpLVAL_INTRO LVINTRO)) # grepwhile not OK (not always setting) # join not OK (unsafe when TARG == arg) # -# Suspicious wrt "additional mode of failure": concat (dealt with -# in ck_sassign()), join (same). +# concat - pp_concat special-cases TARG==arg to avoid +# "additional mode of failure" # # pp_ctl.c # mapwhile flip caller not OK (not always setting) @@ -374,9 +378,6 @@ addbits($_, 7 => qw(OPpLVAL_INTRO LVINTRO)) addbits($_, 4 => qw(OPpTARGET_MY TARGMY)) for ops_with_flag('T'), - # This flag is also used to indicate matches against implicit $_, - # where $_ is lexical; e.g. my $_; ....; /foo/ - qw(match subst trans transr); ; @@ -394,15 +395,9 @@ addbits($_, 7 => qw(OPpLVALUE LV)) for qw(leave leaveloop); -# Pattern coming in on the stack -addbits($_, 6 => qw(OPpRUNTIME RTIME)) - for qw(match subst substcont qr pushre); - - - # autovivify: Want ref to something for (qw(rv2gv rv2sv padsv aelem helem entersub)) { - addbits($_, '5..6' => { + addbits($_, '4..5' => { mask_def => 'OPpDEREF', enum => [ qw( 1 OPpDEREF_AV DREFAV @@ -416,7 +411,7 @@ for (qw(rv2gv rv2sv padsv aelem helem entersub)) { # Defer creation of array/hash elem -addbits($_, 4 => qw(OPpLVAL_DEFER LVDEFER)) for qw(aelem helem); +addbits($_, 6 => qw(OPpLVAL_DEFER LVDEFER)) for qw(aelem helem multideref); @@ -427,28 +422,38 @@ addbits($_, 2 => qw(OPpSLICEWARNING SLICEWARN)) # warn about @hash{$scalar} # XXX Concise seemed to think that OPpOUR_INTRO is used in rv2gv too, # but I can't see it - DAPM -addbits($_, 4 => qw(OPpOUR_INTRO OURINTR)) # Variable was in an our() - for qw(gvsv rv2sv rv2av rv2hv enteriter); +addbits($_, 6 => qw(OPpOUR_INTRO OURINTR)) # Variable was in an our() + for qw(gvsv rv2sv rv2av rv2hv enteriter split); # We might be an lvalue to return +# 'values' doesn't actually use this bit, but we reserve it here as +# pp_values may call Perl_do_kv() which is shared among several ops which +# do. + addbits($_, 3 => qw(OPpMAYBE_LVSUB LVSUB)) for qw(aassign rv2av rv2gv rv2hv padav padhv aelem helem aslice hslice - av2arylen keys rkeys kvaslice kvhslice substr pos vec); + av2arylen keys akeys avhvswitch kvaslice kvhslice substr pos vec + multideref values); -for (qw(rv2hv padhv)) { +for (qw(rv2hv padhv ref)) { addbits($_, # e.g. %hash in (%hash || $foo) ... - 5 => qw(OPpTRUEBOOL BOOL), # ... in void cxt - 6 => qw(OPpMAYBE_TRUEBOOL BOOL?), # ... cx not known till run time + 4 => qw(OPpMAYBE_TRUEBOOL BOOL?), # but cx not known till run time + 5 => qw(OPpTRUEBOOL BOOL), + ); +} +for (qw(grepwhile index length padav pos rindex rv2av subst)) { + addbits($_, + 5 => qw(OPpTRUEBOOL BOOL), # if (@a) {...} ); } - -addbits($_, 1 => qw(OPpHINT_STRICT_REFS STRICT)) for qw(rv2sv rv2av rv2hv rv2gv); +addbits($_, 1 => qw(OPpHINT_STRICT_REFS STRICT)) + for qw(rv2sv rv2av rv2hv rv2gv multideref); @@ -471,13 +476,33 @@ addbits($_, 7 => qw(OPpPV_IS_UTF8 UTF)) for qw(last redo next goto dump); -addbits($_, 4 => qw(OPpPAD_STATE STATE)) for qw(padav padhv padsv pushmark); +# note that for refassign, this bit can mean either OPpPAD_STATE or +# OPpOUR_INTRO depending on the type of the LH child, .e.g. +# \our $foo = ... +# \state $foo = ... +addbits($_, 6 => qw(OPpPAD_STATE STATE)) for qw(padav padhv padsv lvavref + lvref refassign pushmark); + +# NB: both sassign and aassign use the 'OPpASSIGN' naming convention +# for their private flags + +# there *may* be common scalar items on both sides of a list assign: +# run-time checking will be needed. +addbits('aassign', 6 => qw(OPpASSIGN_COMMON_SCALAR COM_SCALAR)); +# +# as above, but it's possible to check for non-commonality with just +# a SvREFCNT(lhs) == 1 test for each lhs element +addbits('aassign', 5 => qw(OPpASSIGN_COMMON_RC1 COM_RC1)); +# run-time checking is required for an aggregate on the LHS +addbits('aassign', 4 => qw(OPpASSIGN_COMMON_AGG COM_AGG)); -addbits('aassign', 6 => qw(OPpASSIGN_COMMON COMMON)); +addbits('aassign', 2 => qw(OPpASSIGN_TRUEBOOL BOOL)); # if (@a = (...)) {...} +# NB: both sassign and aassign use the 'OPpASSIGN' naming convention +# for their private flags addbits('sassign', 6 => qw(OPpASSIGN_BACKWARDS BKWARD), # Left & right switched @@ -488,14 +513,15 @@ addbits('sassign', for (qw(trans transr)) { addbits($_, - 0 => qw(OPpTRANS_FROM_UTF qw(OPpTRANS_TO_UTF >UTF), + 0 => qw(OPpTRANS_FROM_UTF qw(OPpTRANS_TO_UTF >UTF), # replacement chars are utf8 2 => qw(OPpTRANS_IDENTICAL IDENT), # right side is same as left - 3 => qw(OPpTRANS_SQUASH SQUASH), + 3 => qw(OPpTRANS_SQUASH SQUASH), # /s # 4 is used for OPpTARGET_MY - 5 => qw(OPpTRANS_COMPLEMENT COMPL), - 6 => qw(OPpTRANS_GROWS GROWS), - 7 => qw(OPpTRANS_DELETE DEL), + 5 => qw(OPpTRANS_COMPLEMENT COMPL), # /c + 6 => qw(OPpTRANS_GROWS GROWS), # replacement chars longer than + # src chars + 7 => qw(OPpTRANS_DELETE DEL), # /d ); } @@ -525,9 +551,9 @@ addbits('repeat', 6 => qw(OPpREPEAT_DOLIST DOLIST)); # List replication # 1 HINT_STRICT_REFS check HINT_STRICT_REFS check # 2 OPpENTERSUB_HASTARG checki OPpENTERSUB_HASTARG # 3 OPpENTERSUB_AMPER check OPpENTERSUB_AMPER parser -# 4 OPpENTERSUB_DB check OPpENTERSUB_DB -# 5 OPpDEREF_AV context -# 6 OPpDEREF_HV context OPpMAY_RETURN_CONSTANT parser/context +# 4 OPpDEREF_AV context +# 5 OPpDEREF_HV context OPpMAY_RETURN_CONSTANT parser/context +# 6 OPpENTERSUB_DB check OPpENTERSUB_DB # 7 OPpLVAL_INTRO context OPpENTERSUB_NOPAREN parser # NB: OPpHINT_STRICT_REFS must equal HINT_STRICT_REFS @@ -537,8 +563,8 @@ addbits('entersub', 1 => qw(OPpHINT_STRICT_REFS STRICT), # 'use strict' in scope 2 => qw(OPpENTERSUB_HASTARG TARG ), # Called from OP tree 3 => qw(OPpENTERSUB_AMPER AMPER), # Used & form to call - 4 => qw(OPpENTERSUB_DB DBG ), # Debug subroutine - # 5..6 => OPpDEREF, already defined above + # 4..5 => OPpDEREF, already defined above + 6 => qw(OPpENTERSUB_DB DBG ), # Debug subroutine # 7 => OPpLVAL_INTRO, already defined above ); @@ -549,9 +575,9 @@ addbits('rv2cv', 1 => qw(OPpHINT_STRICT_REFS STRICT), # 'use strict' in scope 2 => qw(OPpENTERSUB_HASTARG TARG ), # If const sub, return the const 3 => qw(OPpENTERSUB_AMPER AMPER ), # Used & form to call - 4 => qw(OPpENTERSUB_DB DBG ), # Debug subroutine - 6 => qw(OPpMAY_RETURN_CONSTANT CONST ), + 5 => qw(OPpMAY_RETURN_CONSTANT CONST ), + 6 => qw(OPpENTERSUB_DB DBG ), # Debug subroutine 7 => qw(OPpENTERSUB_NOPAREN NO() ), # bare sub call (without parens) ); @@ -570,7 +596,7 @@ addbits('substr', 4 => qw(OPpSUBSTR_REPL_FIRST REPL1ST)); addbits('padrange', # bits 0..6 hold target range '0..6' => { - label => '-', + label => 'range', mask_def => 'OPpPADRANGE_COUNTMASK', bitcount_def => 'OPpPADRANGE_COUNTSHIFT', } @@ -582,7 +608,7 @@ addbits('padrange', for (qw(aelemfast aelemfast_lex)) { addbits($_, '0..7' => { - label => '-', + label => 'key', } ); } @@ -593,16 +619,17 @@ addbits('rv2gv', 2 => qw(OPpDONT_INIT_GV NOINIT), # Call gv_fetchpv with GV_NOINIT # (Therefore will return whatever is currently in # the symbol table, not guaranteed to be a PVGV) - 4 => qw(OPpALLOW_FAKE FAKE), # OK to return fake glob + 6 => qw(OPpALLOW_FAKE FAKE), # OK to return fake glob ); +# NB OPpITER_REVERSED must always be bit 1: see pp_iter() addbits('enteriter', - 2 => qw(OPpITER_REVERSED REVERSED),# for (reverse ...) - 3 => qw(OPpITER_DEF DEF), # 'for $_' or 'for my $_' + 1 => qw(OPpITER_REVERSED REVERSED),# for (reverse ...) + 3 => qw(OPpITER_DEF DEF), # 'for $_' ); -addbits('iter', 2 => qw(OPpITER_REVERSED REVERSED)); +addbits('iter', 1 => qw(OPpITER_REVERSED REVERSED)); @@ -626,9 +653,11 @@ addbits('list', 6 => qw(OPpLIST_GUESSED GUESSED)); -# Operating on a list of keys -addbits('delete', 6 => qw(OPpSLICE SLICE)); -# also 7 => OPpLVAL_INTRO, already defined above +addbits('delete', + 5 => qw(OPpKVSLICE KVSLICE), # Operating on a list of key/value pairs + 6 => qw(OPpSLICE SLICE ), # Operating on a list of keys + #7 => OPpLVAL_INTRO, already defined above +); @@ -643,8 +672,8 @@ addbits('sort', 2 => qw(OPpSORT_REVERSE REV ), # Reversed sort 3 => qw(OPpSORT_INPLACE INPLACE), # sort in-place; eg @a = sort @a 4 => qw(OPpSORT_DESCEND DESC ), # Descending sort - 5 => qw(OPpSORT_QSORT QSORT ), # Use quicksort (not mergesort) 6 => qw(OPpSORT_STABLE STABLE ), # Use a stable algorithm + 7 => qw(OPpSORT_UNSTABLE UNSTABLE),# Use an unstable algorithm ); @@ -684,11 +713,6 @@ for (grep { $_ !~ /^l?stat$/ } ops_with_flag('-')) { -addbits($_, 1 => qw(OPpGREP_LEX GREPLEX)) # iterate over lexical $_ - for qw(mapwhile mapstart grepwhile grepstart); - - - addbits('entereval', 1 => qw(OPpEVAL_HAS_HH HAS_HH ), # Does it have a copy of %^H ? 2 => qw(OPpEVAL_UNICODE UNI ), @@ -712,7 +736,98 @@ addbits('coreargs', -addbits('split', 7 => qw(OPpSPLIT_IMPLIM IMPLIM)); # implicit limit +addbits('split', + # @a = split() has been replaced with split() where split itself + # does the array assign + 4 => qw(OPpSPLIT_ASSIGN ASSIGN), + 3 => qw(OPpSPLIT_LEX LEX), # the OPpSPLIT_ASSIGN is a lexical array + 2 => qw(OPpSPLIT_IMPLIM IMPLIM), # implicit limit +); + + +addbits($_, + 2 => qw(OPpLVREF_ELEM ELEM ), + 3 => qw(OPpLVREF_ITER ITER ), +'4..5'=> { + mask_def => 'OPpLVREF_TYPE', + enum => [ qw( + 0 OPpLVREF_SV SV + 1 OPpLVREF_AV AV + 2 OPpLVREF_HV HV + 3 OPpLVREF_CV CV + )], + }, + #6 => qw(OPpPAD_STATE STATE), + #7 => qw(OPpLVAL_INTRO LVINTRO), +) for 'refassign', 'lvref'; + + + +addbits('multideref', + 4 => qw(OPpMULTIDEREF_EXISTS EXISTS), # deref is actually exists + 5 => qw(OPpMULTIDEREF_DELETE DELETE), # deref is actually delete +); + + + +addbits('avhvswitch', + '0..1' => { + mask_def => 'OPpAVHVSWITCH_MASK', + label => 'offset', + } +); + + +addbits('argelem', + '1..2' => { + mask_def => 'OPpARGELEM_MASK', + enum => [ qw( + 0 OPpARGELEM_SV SV + 1 OPpARGELEM_AV AV + 2 OPpARGELEM_HV HV + )], + }, +); + + +# rv2hv and padhv in void/scalar context implementing 'keys %h' +# directly, without a following OP_KEYS + +addbits('padhv', + 0 => qw(OPpPADHV_ISKEYS KEYS), +); +addbits('rv2hv', + 0 => qw(OPpRV2HV_ISKEYS KEYS), +); + +# In conjunction with OPpTRUEBOOL, indicates that the test should be +# inverted. This allows both (index() == -1) and (index() != -1) +# to optimise away the const and eq/ne + +for (qw(index rindex)) { + addbits($_, 6 => qw(OPpINDEX_BOOLNEG NEG)); +} + + +addbits('concat', + # OPf_STACKED normally indicates .=; but it also gets set to optimise + # $a . $b . $c into ($a . $b) .= $c + # so that the first concat's PADTMP (which holds the result of $a.$b) + # can be reused. Set a flag in this case to help deparse and warn + # distinguish the cases. + 6 => qw(OPpCONCAT_NESTED NESTED), +); + + +addbits('multiconcat', + # 7 OPpLVAL_INTRO + 6 => qw(OPpMULTICONCAT_APPEND APPEND), # $x .= .... + 5 => qw(OPpMULTICONCAT_FAKE FAKE), # sprintf() optimised to MC. + # 4 OPpTARGET_MY + 3 => qw(OPpMULTICONCAT_STRINGIFY STRINGIFY), # "$a$b..." +); + + 1;