File Coverage

blib/lib/B/CC.pm
Criterion Covered Total %
statement 103 1531 6.7
branch 25 800 3.1
condition 7 278 2.5
subroutine 19 192 9.9
pod 3 164 1.8
total 157 2965 5.3


line stmt bran cond sub pod time code
1             # CC.pm
2             #
3             # Copyright (c) 1996, 1997, 1998 Malcolm Beattie
4             # Copyright (c) 2009, 2010, 2011 Reini Urban
5             # Copyright (c) 2010 Heinz Knutzen
6             # Copyright (c) 2012-2017 cPanel Inc
7             #
8             # You may distribute under the terms of either the GNU General Public
9             # License or the Artistic License, as specified in the README file.
10              
11             =head1 NAME
12              
13             B::CC - Perl compiler's optimized C translation backend
14              
15             =head1 SYNOPSIS
16              
17             perl -MO=CC[,OPTIONS] foo.pl
18              
19             =head1 DESCRIPTION
20              
21             This compiler backend takes Perl source and generates C source code
22             corresponding to the flow of your program with unrolled ops and optimised
23             stack handling and lexicals variable types. In other words, this backend is
24             somewhat a "real" compiler in the sense that many people think about
25             compilers. Note however that, currently, it is a very poor compiler in that
26             although it generates (mostly, or at least sometimes) correct code, it
27             performs relatively few optimisations. This will change as the compiler and
28             the types develops. The result is that running an executable compiled with
29             this backend may start up more quickly than running the original Perl program
30             (a feature shared by the B compiler backend--see L) and may also
31             execute slightly faster. This is by no means a good optimising compiler--yet.
32              
33             =head1 OPTIONS
34              
35             If there are any non-option arguments, they are taken to be
36             names of objects to be saved (probably doesn't work properly yet).
37             Without extra arguments, it saves the main program.
38              
39             =over 4
40              
41             =item B<-ofilename>
42              
43             Output to filename instead of STDOUT
44              
45             =item B<-c>
46              
47             Check and abort.
48              
49             Compiles and prints only warnings, but does not emit C code.
50              
51             =item B<-v>
52              
53             Verbose compilation (prints a few compilation stages).
54              
55             =item B<-->
56              
57             Force end of options
58              
59             =item B<-uPackname>
60              
61             Force apparently unused subs from package Packname to be compiled.
62             This allows programs to use eval "foo()" even when sub foo is never
63             seen to be used at compile time. The down side is that any subs which
64             really are never used also have code generated. This option is
65             necessary, for example, if you have a signal handler foo which you
66             initialise with C<$SIG{BAR} = "foo">. A better fix, though, is just
67             to change it to C<$SIG{BAR} = \&foo>. You can have multiple B<-u>
68             options. The compiler tries to figure out which packages may possibly
69             have subs in which need compiling but the current version doesn't do
70             it very well. In particular, it is confused by nested packages (i.e.
71             of the form C) where package C does not contain any subs.
72              
73             =item B<-UPackname> "unuse" skip Package
74              
75             Ignore all subs from Package to be compiled.
76              
77             Certain packages might not be needed at run-time, even if the pessimistic
78             walker detects it.
79              
80             =item B<-mModulename>
81              
82             Instead of generating source for a runnable executable, generate
83             source for an XSUB module. The boot_Modulename function (which
84             DynaLoader can look for) does the appropriate initialisation and runs
85             the main part of the Perl source that is being compiled.
86              
87             =item B<-nInitname>
88              
89             Provide a different init name for additional objects added via cmdline.
90              
91             =item B<-strict>
92              
93             With a DEBUGGING perl compile-time errors for range and flip without
94             compile-time context are only warnings.
95             With C<-strict> these warnings are fatal, otherwise only run-time errors occur.
96              
97             =item B<-On>
98              
99             Optimisation level (n = 0, 1, 2). B<-O> means B<-O1>.
100              
101             The following L optimisations are applied automatically:
102              
103             optimize_warn_sv save_data_fh av-init2|av_init save_sig destruct
104             pv_copy_on_grow
105              
106             B<-O1> sets B<-ffreetmps-each-bblock>.
107              
108             B<-O2> adds B<-ffreetmps-each-loop>, C<-faelem> and B<-fno-destruct> from L.
109              
110             The following options must be set explicitly:
111              
112             B<-fno-taint> or B<-fomit-taint>,
113              
114             B<-fslow-signals>,
115              
116             B<-no-autovivify>,
117              
118             B<-fno-magic>.
119              
120             =item B<-f>C
121              
122             Force optimisations on or off one at a time.
123             Unknown optimizations are passed down to L.
124              
125             =item B<-ffreetmps-each-bblock>
126              
127             Delays FREETMPS from the end of each statement to the end of the each
128             basic block.
129              
130             Enabled with B<-O1>.
131              
132             =item B<-ffreetmps-each-loop>
133              
134             Delays FREETMPS from the end of each statement to the end of the group
135             of basic blocks forming a loop. At most one of the freetmps-each-*
136             options can be used.
137              
138             Enabled with B<-O2>.
139              
140             =item B<-faelem>
141              
142             Enable array element access optimizations, allowing unchecked
143             fast access under certain circumstances.
144              
145             Enabled with B<-O2> and not-threaded perls only.
146              
147             =item B<-fno-inline-ops>
148              
149             Do not inline calls to certain small pp ops.
150              
151             Most of the inlinable ops were already inlined.
152             Turns off inlining for some new ops.
153              
154             AUTOMATICALLY inlined:
155              
156             pp_null pp_stub pp_unstack pp_and pp_andassign pp_or pp_orassign pp_cond_expr
157             pp_padsv pp_const pp_nextstate pp_dbstate pp_rv2gv pp_sort pp_gv pp_gvsv
158             pp_aelemfast pp_ncmp pp_add pp_subtract pp_multiply pp_divide pp_modulo
159             pp_left_shift pp_right_shift pp_i_add pp_i_subtract pp_i_multiply pp_i_divide
160             pp_i_modulo pp_eq pp_ne pp_lt pp_gt pp_le pp_ge pp_i_eq pp_i_ne pp_i_lt
161             pp_i_gt pp_i_le pp_i_ge pp_scmp pp_slt pp_sgt pp_sle pp_sge pp_seq pp_sne
162             pp_sassign pp_preinc pp_pushmark pp_list pp_entersub pp_formline pp_goto
163             pp_enterwrite pp_leavesub pp_leavewrite pp_entergiven pp_leavegiven
164             pp_entereval pp_dofile pp_require pp_entertry pp_leavetry pp_grepstart
165             pp_mapstart pp_grepwhile pp_mapwhile pp_return pp_range pp_flip pp_flop
166             pp_enterloop pp_enteriter pp_leaveloop pp_next pp_redo pp_last pp_subst
167             pp_substcont
168              
169             DONE with -finline-ops:
170              
171             pp_enter pp_reset pp_regcreset pp_stringify
172              
173             TODO with -finline-ops:
174              
175             pp_anoncode pp_wantarray pp_srefgen pp_refgen pp_ref pp_trans pp_schop pp_chop
176             pp_schomp pp_chomp pp_not pp_sprintf pp_anonlist pp_shift pp_once pp_lock
177             pp_rcatline pp_close pp_time pp_alarm pp_av2arylen: no lvalue, pp_length: no
178             magic
179              
180             =item B<-fomit-taint>
181              
182             Omits generating code for handling perl's tainting mechanism.
183              
184             =item B<-fslow-signals>
185              
186             Add PERL_ASYNC_CHECK after every op as in the old Perl runloop before 5.13.
187              
188             perl "Safe signals" check the state of incoming signals after every op.
189             See L
190             We trade safety for more speed and delay the execution of non-IO signals
191             (IO signals are already handled in PerlIO) from after every single Perl op
192             to the same ops as used in 5.14.
193              
194             Only with -fslow-signals we get the old slow and safe behaviour.
195              
196             =item B<-fno-name-magic>
197              
198             With the default C<-fname-magic> we infer the SCALAR type for specially named
199             locals vars and most ops use C vars then, not the perl vars.
200             Arithmetic and comparison is inlined. Scalar magic is bypassed.
201              
202             With C<-fno-name-magic> do not infer a local variable type from its name:
203              
204             B<_i> suffix for int, B<_d> for double/num, B<_ir> for register int
205              
206             See the experimental C<-ftype-attr> type attributes.
207             Currently supported are B and B only. See .
208              
209             =item B<-ftype-attr> (DOES NOT WORK YET)
210              
211             Experimentally support B for B and B,
212             SCALAR only so far.
213             For most ops new C vars are used then, not the fat perl vars.
214             Very awkward to use until the basic type classes are supported from
215             within core or use types.
216              
217             Enabled with B<-O2>. See L and .
218              
219             =item B<-fno-autovivify>
220              
221             Do not vivify array and soon also hash elements when accessing them.
222             Beware: Vivified elements default to undef, unvivified elements are
223             invalid.
224              
225             This is the same as the pragma "no autovivification" and allows
226             very fast array accesses, 4-6 times faster, without the overhead of
227             L.
228              
229             =item B<-fno-magic>
230              
231             Assume certain data being optimized is never tied or is holding other magic.
232             This mainly holds for arrays being optimized, but in the future hashes also.
233              
234             =item B<-D>
235              
236             Debug options (concatenated or separate flags like C).
237             Verbose debugging options are crucial, because the interactive
238             debugger L adds a lot of ballast to the resulting code.
239              
240             =item B<-Dr>
241              
242             Writes debugging output to STDERR just as it's about to write to the
243             program's runtime (otherwise writes debugging info as comments in
244             its C output).
245              
246             =item B<-DO>
247              
248             Outputs each OP as it's compiled
249              
250             =item B<-DT>
251              
252             Outputs the contents of the B at each OP.
253             Values are B::Stackobj objects.
254              
255             =item B<-Dc>
256              
257             Outputs the contents of the loop B, the @cxstack.
258              
259             =item B<-Dw>
260              
261             Outputs the contents of the B stack at each OP.
262              
263             =item B<-Da>
264              
265             Outputs the contents of the shadow pad of lexicals as it's loaded for
266             each sub or the main program.
267              
268             =item B<-Dq>
269              
270             Outputs the name of each fake PP function in the queue as it's about
271             to process it.
272              
273             =item B<-Dl>
274              
275             Output the filename and line number of each original line of Perl
276             code as it's processed (C).
277              
278             =item B<-Dt>
279              
280             Outputs timing information of compilation stages.
281              
282             =item B<-DF>
283              
284             Add Flags info to the code.
285              
286             =back
287              
288             =head1 NOTABLE FUNCTIONS
289              
290             =cut
291              
292              
293             package B::CC;
294              
295             our $VERSION = '1.16_01';
296              
297             # Start registering the L namespaces.
298 14     14   337358 use strict;
  14         46  
  14         1214  
299             our %Config;
300             BEGIN {
301 14     14   1417 require B::C::Config;
302 14         66 *Config = \%B::C::Config::Config;
303             # make it a restricted hash
304 14 50       950 Internals::SvREADONLY(%Config, 1) if $] >= 5.008004;
305             }
306             unless ($Config{usecperl}) {
307             eval '$main::int::B_CC = $main::num::B_CC = $main::str::B_CC = $main::double::B_CC = $main::string::B_CC = $VERSION;';
308             }
309              
310             #use 5.008;
311 14         2809 use B qw(main_start main_root comppadlist peekop svref_2object
312             timing_info init_av end_av sv_undef
313             OPf_WANT_VOID OPf_WANT_SCALAR OPf_WANT_LIST OPf_WANT
314             OPf_MOD OPf_STACKED OPf_SPECIAL OPpLVAL_DEFER OPpLVAL_INTRO
315             OPpASSIGN_BACKWARDS OPpLVAL_INTRO OPpDEREF_AV OPpDEREF_HV
316 14     14   96 OPpDEREF OPpFLIP_LINENUM G_VOID G_SCALAR G_ARRAY);
  14         32  
317             #CXt_NULL CXt_SUB CXt_EVAL CXt_SUBST CXt_BLOCK
318 14         2380 use B::C qw(save_unused_subs objsym init_sections mark_unused mark_skip
319             output_all output_boilerplate output_main output_main_rest fixup_ppaddr save_sig
320 14     14   18850 svop_or_padop_pv inc_cleanup curcv set_curcv);
  14         76  
321 14     14   8076 use B::Bblock qw(find_leaders);
  14         53  
  14         980  
322 14     14   6609 use B::Stackobj qw(:types :flags);
  14         54  
  14         3013  
323 14     14   138 use B::C::Config;
  14         38  
  14         7589  
324             # use attributes qw(get reftype);
325              
326             @B::OP::ISA = qw(B); # support -Do
327             @B::LISTOP::ISA = qw(B::BINOP B); # support -Do
328             push @B::OP::ISA, 'B::NULLOP' if exists $main::B::{'NULLOP'};
329              
330             # These should probably be elsewhere
331             # Flags for $op->flags
332              
333             my $module; # module name (when compiled with -m)
334             my %done; # hash keyed by $$op of leaders of basic blocks
335             # which have already been done.
336             my $leaders; # ref to hash of basic block leaders. Keys are $$op
337             # addresses, values are the $op objects themselves.
338             my @bblock_todo; # list of leaders of basic blocks that need visiting
339             # sometime.
340             my @cc_todo; # list of tuples defining what PP code needs to be
341             # saved (e.g. CV, main or PMOP repl code). Each tuple
342             # is [$name, $root, $start, @padlist]. PMOP repl code
343             # tuples inherit padlist.
344             my %cc_pp_sub; # hashed names of pp_sub functions already saved
345             my @stack; # shadows perl's stack when contents are known.
346             # Values are objects derived from class B::Stackobj
347             my @pad; # Lexicals in current pad as Stackobj-derived objects
348             my @padlist; # Copy of current padlist so PMOP repl code can find it
349             my @cxstack; # Shadows the (compile-time) cxstack for next,last,redo
350             # This covers only a small part of the perl cxstack
351             my $labels; # hashref to array of op labels
352             my %constobj; # OP_CONST constants as Stackobj-derived objects
353             # keyed by $$sv.
354             my $need_freetmps = 0; # We may postpone FREETMPS to the end of each basic
355             # block or even to the end of each loop of blocks,
356             # depending on optimisation options.
357             my $know_op = 0; # Set when C variable op already holds the right op
358             # (from an immediately preceding DOOP(ppname)).
359             my $errors = 0; # Number of errors encountered
360             my $op_count = 0; # for B::compile_stats on verbose
361             my %no_stack; # PP names which don't need save pp restore stack
362             my %skip_stack; # PP names which don't need write_back_stack (empty)
363             my %skip_lexicals; # PP names which don't need write_back_lexicals
364             my %skip_invalidate; # PP names which don't need invalidate_lexicals
365             my %ignore_op; # ops which do nothing except returning op_next
366             my %need_curcop; # ops which need PL_curcop
367             my $package_pv; # sv->pv of previous op for method_named
368              
369             my %lexstate; # state of padsvs at the start of a bblock
370             my ( $verbose, $check );
371             my ( $entertry_defined, $vivify_ref_defined );
372             my ( $init_name, %debug, $strict );
373              
374             # Optimisation options. On the command line, use hyphens instead of
375             # underscores for compatibility with gcc-style options. We use
376             # underscores here because they are OK in (strict) barewords.
377             # Disable with -fno-
378             my ( $freetmps_each_bblock, $freetmps_each_loop, $inline_ops, $opt_taint, $opt_omit_taint,
379             $opt_slow_signals, $opt_name_magic, $opt_type_attr, $opt_autovivify, $opt_magic,
380             $opt_aelem, %c_optimise );
381             $inline_ops = 1 unless $^O eq 'MSWin32'; # Win32 cannot link to unexported pp_op() XXX
382             $opt_name_magic = 1;
383             my %optimise = (
384             freetmps_each_bblock => \$freetmps_each_bblock, # -O1
385             freetmps_each_loop => \$freetmps_each_loop, # -O2
386             aelem => \$opt_aelem, # -O2
387             inline_ops => \$inline_ops, # not on Win32
388             omit_taint => \$opt_omit_taint,
389             taint => \$opt_taint,
390             slow_signals => \$opt_slow_signals,
391             name_magic => \$opt_name_magic,
392             type_attr => \$opt_type_attr,
393             autovivify => \$opt_autovivify,
394             magic => \$opt_magic,
395             );
396             my %async_signals = map { $_ => 1 } # 5.14 ops which do PERL_ASYNC_CHECK
397             qw(wait waitpid nextstate and cond_expr unstack or subst dorassign);
398             $async_signals{$_} = 1 for # more 5.16 ops which do PERL_ASYNC_CHECK
399             qw(substcont next redo goto leavewhen);
400             # perl patchlevel to generate code for (defaults to current patchlevel)
401             my $patchlevel = int( 0.5 + 1000 * ( $] - 5 ) ); # XXX unused?
402             my $MULTI = $Config{usemultiplicity};
403             my $ITHREADS = $Config{useithreads};
404             my $PERL510 = ( $] >= 5.009005 );
405             my $PERL512 = ( $] >= 5.011 );
406              
407             my $SVt_PVLV = $PERL510 ? 10 : 9;
408             my $SVt_PVAV = $PERL510 ? 11 : 10;
409             # use sub qw(CXt_LOOP_PLAIN CXt_LOOP);
410             BEGIN {
411 14 50   14   98 if ($PERL512) {
  0         0  
412 0     0 0 0 sub CXt_LOOP_PLAIN {5} # CXt_LOOP_FOR CXt_LOOP_LAZYSV CXt_LOOP_LAZYIV
413 0         0 } else {
414 0     0 0 0 sub CXt_LOOP {3}
415             }
416             sub CxTYPE_no_LOOP {
417             $PERL512
418             ? ( $_[0]->{type} < 4 or $_[0]->{type} > 7 )
419 0 0 0 0 0 0 : $_[0]->{type} != 3
420             }
421 14 50       71 if ($] < 5.008) {
422 0         0 eval "sub SVs_RMG {0x8000};";
423             } else {
424 14         449 B->import('SVs_RMG');
425             }
426 14 50       94 if ($] <= 5.010) {
    50          
    0          
    0          
427 0         0 eval "sub PMf_ONCE() {0xff}; # unused";
428             } elsif ($] >= 5.018) { # PMf_ONCE not exported
429 14         14365 eval q[sub PMf_ONCE(){ 0x10000 }];
430             } elsif ($] >= 5.014) {
431 0         0 eval q[sub PMf_ONCE(){ 0x8000 }];
432             } elsif ($] >= 5.012) {
433 0         0 eval q[sub PMf_ONCE(){ 0x0080 }];
434             } else { # 5.10. not used with <= 5.8
435 0         0 eval q[sub PMf_ONCE(){ 0x0002 }];
436             }
437             }
438              
439             # Could rewrite push_runtime() and output_runtime() to use a
440             # temporary file if memory is at a premium.
441             my $ppname; # name of current fake PP function
442             my $runtime_list_ref;
443             my $declare_ref; # Hash ref keyed by C variable type of declarations.
444              
445             my @pp_list; # list of [$ppname, $runtime_list_ref, $declare_ref]
446             # tuples to be written out.
447              
448             my ( $init, $decl );
449              
450             sub init_hash {
451 84     84 0 204 map { $_ => 1 } @_;
  616         1637  
452             }
453              
454             # Initialise the hashes for the default PP functions where we can avoid
455             # either stack save/restore,write_back_stack, write_back_lexicals or invalidate_lexicals.
456             # XXX We should really take some of this info from Opcodes (was: CORE opcode.pl)
457             #
458             # no args and no return value = Opcodes::argnum 0
459             %no_stack = init_hash qw(pp_unstack pp_break pp_continue);
460             # pp_enter pp_leave, use/change global stack.
461             #skip write_back_stack (no args)
462             %skip_stack = init_hash qw(pp_enter pp_leave pp_nextstate pp_dbstate);
463             # which ops do not read pad vars
464             %skip_lexicals = init_hash qw(pp_enter pp_enterloop pp_leave pp_nextstate pp_dbstate);
465             # which ops no not write to pad vars
466             %skip_invalidate = init_hash qw(pp_enter pp_enterloop pp_leave pp_nextstate pp_dbstate
467             pp_return pp_leavesub pp_list pp_pushmark
468             pp_anonlist
469             );
470              
471             %need_curcop = init_hash qw(pp_rv2gv pp_bless pp_repeat pp_sort pp_caller
472             pp_reset pp_rv2cv pp_entereval pp_require pp_dofile
473             pp_entertry pp_enterloop pp_enteriter pp_entersub pp_entergiven
474             pp_enter pp_method);
475             %ignore_op = init_hash qw(pp_scalar pp_regcmaybe pp_lineseq pp_scope pp_null);
476              
477             { # block necessary for caller to work
478             my $caller = caller;
479             if ( $caller eq 'O' ) {
480             require XSLoader;
481             XSLoader::load('B::C'); # for r-magic only
482             }
483             }
484              
485             sub debug {
486 0 0   0 0 0 if ( $debug{runtime} ) {
487             # TODO: fix COP to callers line number
488 0 0       0 warn(@_) if $verbose;
489             }
490             else {
491 0         0 my @tmp = @_;
492 0         0 runtime( map { chomp; "/* $_ */" } @tmp );
  0         0  
  0         0  
493             }
494             }
495              
496             sub declare {
497 0     0 0 0 my ( $type, $var ) = @_;
498 0         0 push( @{ $declare_ref->{$type} }, $var );
  0         0  
499             }
500              
501             sub push_runtime {
502 0     0 0 0 push( @$runtime_list_ref, @_ );
503 0 0       0 warn join( "\n", @_ ) . "\n" if $debug{runtime};
504             }
505              
506             sub save_runtime {
507 0     0 0 0 push( @pp_list, [ $ppname, $runtime_list_ref, $declare_ref ] );
508             }
509              
510             sub output_runtime {
511 0     0 0 0 my $ppdata;
512 0         0 print qq(\n#include "cc_runtime.h"\n);
513             # CC coverage: 12, 32
514              
515             # Perls >=5.8.9 have a broken PP_ENTERTRY. See PERL_FLEXIBLE_EXCEPTIONS in cop.h
516             # Fixed in CORE with 5.11.4
517 0 0 0     0 print'
518             #undef PP_ENTERTRY
519             #define PP_ENTERTRY(label) \
520             STMT_START { \
521             dJMPENV; \
522             int ret; \
523             JMPENV_PUSH(ret); \
524             switch (ret) { \
525             case 1: JMPENV_POP; JMPENV_JUMP(1);\
526             case 2: JMPENV_POP; JMPENV_JUMP(2);\
527             case 3: JMPENV_POP; SPAGAIN; goto label;\
528             } \
529             } STMT_END'
530             if $entertry_defined and $] < 5.011004;
531             # XXX need to find out when PERL_FLEXIBLE_EXCEPTIONS were actually active.
532             # 5.6.2 not, 5.8.9 not. coverage 32
533              
534             # test 12. Used by entereval + dofile
535 0 0 0     0 if ($PERL510 or $MULTI) {
536             # Threads error Bug#55302: too few arguments to function
537             # CALLRUNOPS()=>CALLRUNOPS(aTHX)
538             # fixed with 5.11.4
539 0         0 print '
540             #undef PP_EVAL
541             #define PP_EVAL(ppaddr, nxt) do { \
542             dJMPENV; \
543             int ret; \
544             PUTBACK; \
545             JMPENV_PUSH(ret); \
546             switch (ret) { \
547             case 0: \
548             PL_op = ppaddr(aTHX); \\';
549 0 0       0 if ($PERL510) {
550             # pp_leaveeval sets: retop = cx->blk_eval.retop
551 0         0 print '
552             cxstack[cxstack_ix].blk_eval.retop = Nullop; \\';
553             } else {
554             # up to 5.8 pp_entereval did set the retstack to next.
555             # nullify that so that we can now exec the rest of this bblock.
556             # (nextstate .. leaveeval)
557 0         0 print '
558             PL_retstack[PL_retstack_ix - 1] = Nullop; \\';
559             }
560 0         0 print '
561             if (PL_op != nxt) CALLRUNOPS(aTHX); \
562             JMPENV_POP; \
563             break; \
564             case 1: JMPENV_POP; JMPENV_JUMP(1); \
565             case 2: JMPENV_POP; JMPENV_JUMP(2); \
566             case 3: \
567             JMPENV_POP; \
568             if (PL_restartop && PL_restartop != nxt) \
569             JMPENV_JUMP(3); \
570             } \
571             PL_op = nxt; \
572             SPAGAIN; \
573             } while (0)
574             ';
575             }
576              
577             # Perl_vivify_ref not exported on MSWin32
578             # coverage: 18
579 0 0 0     0 if ($PERL510 and $^O eq 'MSWin32') {
580             # CC coverage: 18, 29
581 0 0       0 print << '__EOV' if $vivify_ref_defined;
582              
583             /* Code to take a scalar and ready it to hold a reference */
584             # ifndef SVt_RV
585             # define SVt_RV SVt_IV
586             # endif
587             # define prepare_SV_for_RV(sv) \
588             STMT_START { \
589             if (SvTYPE(sv) < SVt_RV) \
590             sv_upgrade(sv, SVt_RV); \
591             else if (SvPVX_const(sv)) { \
592             SvPV_free(sv); \
593             SvLEN_set(sv, 0); \
594             SvCUR_set(sv, 0); \
595             } \
596             } STMT_END
597              
598             #if (PERL_VERSION > 15) || ((PERL_VERSION == 15) && (PERL_SUBVERSION >= 2))
599             SV*
600             #else
601             void
602             #endif
603             Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
604             {
605             SvGETMAGIC(sv);
606             if (!SvOK(sv)) {
607             if (SvREADONLY(sv))
608             Perl_croak(aTHX_ "%s", PL_no_modify);
609             prepare_SV_for_RV(sv);
610             switch (to_what) {
611             case OPpDEREF_SV:
612             SvRV_set(sv, newSV(0));
613             break;
614             case OPpDEREF_AV:
615             SvRV_set(sv, newAV());
616             break;
617             case OPpDEREF_HV:
618             SvRV_set(sv, newHV());
619             break;
620             }
621             SvROK_on(sv);
622             SvSETMAGIC(sv);
623             }
624             }
625              
626             __EOV
627              
628             }
629              
630 0         0 print '
631              
632             OP *Perl_pp_aelem_nolval(pTHXx);
633             #ifndef SVfARG
634             # define SVfARG(x) (void *)x
635             #endif
636             #ifndef MUTABLE_AV
637             # define MUTABLE_AV(av) av
638             #endif
639             PP(pp_aelem_nolval)
640             {
641             dSP;
642             SV** svp;
643             SV* const elemsv = POPs;
644             IV elem = SvIV(elemsv);
645             AV *const av = MUTABLE_AV(POPs);
646             SV *sv;
647              
648             #if PERL_VERSION > 6
649             if (SvROK(elemsv) && !SvGAMAGIC(elemsv) && ckWARN(WARN_MISC))
650             Perl_warner(aTHX_ packWARN(WARN_MISC),
651             "Use of reference \"%"SVf"\" as array index",
652             SVfARG(elemsv));
653             #endif
654             if (SvTYPE(av) != SVt_PVAV) RETPUSHUNDEF;
655             svp = av_fetch(av, elem, 0);
656             sv = (svp ? *svp : &PL_sv_undef);
657             if (SvRMAGICAL(av) && SvGMAGICAL(sv)) mg_get(sv);
658             PUSHs(sv);
659             RETURN;
660             }
661             ' if 0;
662              
663 0         0 foreach $ppdata (@pp_list) {
664 0         0 my ( $name, $runtime, $declare ) = @$ppdata;
665 0         0 print "\nstatic\nCCPP($name)\n{\n";
666 0         0 my ( $type, $varlist, $line );
667 0         0 while ( ( $type, $varlist ) = each %$declare ) {
668 0         0 $varlist = $declare->{$type};
669 0         0 print "\t$type ", join( ", ", @$varlist ), ";\n";
670             }
671 0         0 foreach $line (@$runtime) {
672 0         0 print $line, "\n";
673             }
674 0         0 print "}\n";
675             }
676             }
677              
678             sub runtime {
679 0     0 0 0 my $line;
680 0         0 foreach $line (@_) {
681 0         0 push_runtime("\t$line");
682             }
683             }
684              
685             sub init_pp {
686 0     0 0 0 $ppname = shift;
687 0         0 $runtime_list_ref = [];
688 0         0 $declare_ref = {};
689 0         0 runtime("dSP;");
690 0         0 declare( "I32", "oldsave" );
691 0         0 map { declare( "SV", "*$_" ) } qw(sv src dst left right);
  0         0  
692 0         0 declare( "MAGIC", "*mg" );
693 0 0 0     0 $decl->add( "#undef cxinc", "#define cxinc() Perl_cxinc(aTHX)")
694             if $] < 5.011001 and $inline_ops;
695 0         0 declare( "PERL_CONTEXT", "*cx" );
696 0         0 declare( "I32", "gimme");
697 0         0 $decl->add("static OP * $ppname (pTHX);");
698 0 0       0 debug "init_pp: $ppname\n" if $debug{queue};
699             }
700              
701             # Initialise runtime_callback function for Stackobj class
702 14     14   118 BEGIN { B::Stackobj::set_callback( \&runtime ) }
703              
704             =head2 cc_queue
705              
706             Creates a new ccpp optree.
707              
708             Initialised by saveoptree_callback in L, replaces B::C::walk_and_save_optree.
709             Called by every C if ROOT.
710             B also creates its block closure with cc_queue.
711              
712             =cut
713              
714             # coverage: test 18, 28 (fixed with B-C-1.30 r971)
715             sub cc_queue {
716 0     0 1 0 my ( $name, $root, $start, @pl ) = @_;
717             debug "cc_queue: name $name, root $root, start $start, padlist (@pl)\n"
718 0 0       0 if $debug{queue};
719 0 0 0     0 if ( $name eq "*ignore*" or $name =~ /^pp_sub_.*(FETCH|MODIFY)_SCALAR_ATTRIBUTES$/) {
720 0         0 $name = '';
721             } else {
722 0 0       0 push( @cc_todo, [ $name, $root, $start, ( @pl ? @pl : @padlist ) ] );
723             }
724 0         0 my $fakeop_next = 0;
725 0 0       0 if ($name =~ /^pp_sub_.*DESTROY$/) {
726             # curse in sv_clean_objs() checks for ->op_next->op_type
727 0         0 $fakeop_next = $start->next->save;
728             }
729 0         0 my $fakeop = B::FAKEOP->new( "next" => $fakeop_next, ppaddr => $name );
730 0         0 $start = $fakeop->save;
731 0 0       0 debug "cc_queue: name $name returns $start\n" if $debug{queue};
732 0         0 return $start;
733             }
734 14     14   121 BEGIN { B::C::set_callback( \&cc_queue ) }
735              
736 0     0 0 0 sub valid_int { $_[0]->{flags} & VALID_INT }
737 0     0 0 0 sub valid_double { $_[0]->{flags} & VALID_NUM }
738 0     0 0 0 sub valid_numeric { $_[0]->{flags} & ( VALID_INT | VALID_NUM ) }
739 0     0 0 0 sub valid_str { $_[0]->{flags} & VALID_STR }
740 0     0 0 0 sub valid_sv { $_[0]->{flags} & VALID_SV }
741              
742 0 0   0 0 0 sub top_int { @stack ? $stack[-1]->as_int : "TOPi" }
743 0 0   0 0 0 sub top_double { @stack ? $stack[-1]->as_double : "TOPn" }
744 0 0   0 0 0 sub top_numeric { @stack ? $stack[-1]->as_numeric : "TOPn" }
745 0 0   0 0 0 sub top_sv { @stack ? $stack[-1]->as_sv : "TOPs" }
746 0 0   0 0 0 sub top_str { @stack ? $stack[-1]->as_str : "TOPs" }
747 0 0   0 0 0 sub top_bool { @stack ? $stack[-1]->as_bool : "SvTRUE(TOPs)" }
748              
749 0 0   0 0 0 sub pop_int { @stack ? ( pop @stack )->as_int : "POPi" }
750 0 0   0 0 0 sub pop_double { @stack ? ( pop @stack )->as_double : "POPn" }
751 0 0   0 0 0 sub pop_numeric { @stack ? ( pop @stack )->as_numeric : "POPn" }
752 0 0   0 0 0 sub pop_str { @stack ? ( pop @stack )->as_str : "POPs" }
753 0 0   0 0 0 sub pop_sv { @stack ? ( pop @stack )->as_sv : "POPs" }
754              
755             sub pop_bool {
756 0 0   0 0 0 if (@stack) {
757 0         0 return ( ( pop @stack )->as_bool );
758             }
759             else {
760             # Careful: POPs has an auto-decrement and SvTRUE evaluates
761             # its argument more than once.
762 0         0 runtime("sv = POPs;");
763 0         0 return "SvTRUE(sv)";
764             }
765             }
766              
767             sub write_back_lexicals {
768 0   0 0 0 0 my $avoid = shift || 0;
769 0         0 debug "write_back_lexicals($avoid) called from @{[(caller(1))[3]]}\n"
770 0 0       0 if $debug{shadow};
771 0         0 my $lex;
772 0         0 foreach $lex (@pad) {
773 0 0       0 next unless ref($lex);
774 0 0       0 $lex->write_back unless $lex->{flags} & $avoid;
775             }
776             }
777              
778             =head1 save_or_restore_lexical_state
779              
780             The compiler tracks state of lexical variables in @pad to generate optimised
781             code. But multiple execution paths lead to the entry point of a basic block.
782             The state of the first execution path is saved and all other execution
783             paths are restored to the state of the first one.
784              
785             Missing flags are regenerated by loading values.
786              
787             Added flags must are removed; otherwise the compiler would be too optimistic,
788             hence generating code which doesn't match state of the other execution paths.
789              
790             =cut
791              
792             sub save_or_restore_lexical_state {
793 0     0 0 0 my $bblock = shift;
794 0 0       0 unless ( exists $lexstate{$bblock} ) {
795 0         0 foreach my $lex (@pad) {
796 0 0       0 next unless ref($lex);
797 0         0 ${ $lexstate{$bblock} }{ $lex->{iv} } = $lex->{flags};
  0         0  
798             }
799             }
800             else {
801 0         0 foreach my $lex (@pad) {
802 0 0       0 next unless ref($lex);
803 0         0 my $old_flags = ${ $lexstate{$bblock} }{ $lex->{iv} };
  0         0  
804 0 0       0 next if ( $old_flags eq $lex->{flags} );
805 0         0 my $changed = $old_flags ^ $lex->{flags};
806 0 0       0 if ( $changed & VALID_SV ) {
807 0 0       0 ( $old_flags & VALID_SV ) ? $lex->write_back : $lex->invalidate;
808             }
809 0 0       0 if ( $changed & VALID_NUM ) {
810 0 0       0 ( $old_flags & VALID_NUM ) ? $lex->load_double : $lex->invalidate_double;
811             }
812 0 0       0 if ( $changed & VALID_INT ) {
813 0 0       0 ( $old_flags & VALID_INT ) ? $lex->load_int : $lex->invalidate_int;
814             }
815 0 0       0 if ( $changed & VALID_STR ) {
816 0 0       0 ( $old_flags & VALID_STR ) ? $lex->load_str : $lex->invalidate_str;
817             }
818             }
819             }
820             }
821              
822             sub write_back_stack {
823 0         0 debug "write_back_stack() ".scalar(@stack)." called from @{[(caller(1))[3]]}\n"
824 0 0   0 0 0 if $debug{shadow};
825 0 0       0 return unless @stack;
826 0         0 runtime( sprintf( "EXTEND(sp, %d);", scalar(@stack) ) );
827 0         0 foreach my $obj (@stack) {
828 0         0 runtime( sprintf( "PUSHs((SV*)%s);", $obj->as_sv ) );
829             }
830 0         0 @stack = ();
831             }
832              
833             sub invalidate_lexicals {
834 0   0 0 0 0 my $avoid = shift || 0;
835 0         0 debug "invalidate_lexicals($avoid) called from @{[(caller(1))[3]]}\n"
836 0 0       0 if $debug{shadow};
837 0         0 my $lex;
838 0         0 foreach $lex (@pad) {
839 0 0       0 next unless ref($lex);
840 0 0       0 $lex->invalidate unless $lex->{flags} & $avoid;
841             }
842             }
843              
844             sub reload_lexicals {
845 0     0 0 0 my $lex;
846 0         0 foreach $lex (@pad) {
847 0 0       0 next unless ref($lex);
848 0         0 my $type = $lex->{type};
849 0 0       0 if ( $type == T_INT ) {
    0          
    0          
850 0         0 $lex->as_int;
851             }
852             elsif ( $type == T_NUM ) {
853 0         0 $lex->as_double;
854             }
855             elsif ( $type == T_STR ) {
856 0         0 $lex->as_str;
857             }
858             else {
859 0         0 $lex->as_sv;
860             }
861             }
862             }
863              
864             {
865              
866             package B::Pseudoreg;
867              
868             #
869             # This class allocates pseudo-registers (OK, so they're C variables).
870             #
871             my %alloc; # Keyed by variable name. A value of 1 means the
872             # variable has been declared. A value of 2 means
873             # it's in use.
874              
875 0     0   0 sub new_scope { %alloc = () }
876              
877             sub new ($$$) {
878 0     0   0 my ( $class, $type, $prefix ) = @_;
879 0         0 my ( $ptr, $i, $varname, $status, $obj );
880 0         0 $prefix =~ s/^(\**)//;
881 0         0 $ptr = $1;
882 0         0 $i = 0;
883 0         0 do {
884 0         0 $varname = "$prefix$i";
885 0 0       0 $status = exists $alloc{$varname} ? $alloc{$varname} : 0;
886             } while $status == 2;
887              
888 0 0       0 if ( $status != 1 ) {
889             # Not declared yet
890 0         0 B::CC::declare( $type, "$ptr$varname" );
891 0         0 $alloc{$varname} = 2; # declared and in use
892             }
893 0         0 $obj = bless \$varname, $class;
894 0         0 return $obj;
895             }
896              
897             sub DESTROY {
898 0     0   0 my $obj = shift;
899 0         0 $alloc{$$obj} = 1; # no longer in use but still declared
900             }
901             }
902             {
903              
904             package B::Shadow;
905              
906             #
907             # This class gives a standard API for a perl object to shadow a
908             # C variable and only generate reloads/write-backs when necessary.
909             #
910             # Use $obj->load($foo) instead of runtime("shadowed_c_var = foo").
911             # Use $obj->write_back whenever shadowed_c_var needs to be up to date.
912             # Use $obj->invalidate whenever an unknown function may have
913             # set shadow itself.
914              
915             sub new {
916 14     14   74 my ( $class, $write_back ) = @_;
917              
918             # Object fields are perl shadow variable, validity flag
919             # (for *C* variable) and callback sub for write_back
920             # (passed perl shadow variable as argument).
921 14         77 bless [ undef, 1, $write_back ], $class;
922             }
923              
924             sub load {
925 0     0   0 my ( $obj, $newval ) = @_;
926 0         0 $obj->[1] = 0; # C variable no longer valid
927 0         0 $obj->[0] = $newval;
928             }
929              
930             sub value {
931 0     0   0 return $_[0]->[0];
932             }
933              
934             sub write_back {
935 0     0   0 my $obj = shift;
936 0 0       0 if ( !( $obj->[1] ) ) {
937 0         0 $obj->[1] = 1; # C variable will now be valid
938 0         0 &{ $obj->[2] }( $obj->[0] );
  0         0  
939             }
940             }
941 0     0   0 sub invalidate { $_[0]->[1] = 0 } # force C variable to be invalid
942             }
943              
944             my $curcop = B::Shadow->new(
945             sub {
946             my $op = shift;
947             my $opsym = $op->save;
948             runtime("PL_curcop = (COP*)$opsym;");
949             }
950             );
951              
952             #
953             # Context stack shadowing. Mimics stuff in pp_ctl.c, cop.h and so on.
954             #
955             sub dopoptoloop {
956 0     0 0 0 my $cxix = $#cxstack;
957 0   0     0 while ( $cxix >= 0 && CxTYPE_no_LOOP( $cxstack[$cxix] ) ) {
958 0         0 $cxix--;
959             }
960 0 0       0 debug "dopoptoloop: returning $cxix" if $debug{cxstack};
961 0         0 return $cxix;
962             }
963              
964             sub dopoptolabel {
965 0     0 0 0 my $label = shift;
966 0         0 my $cxix = $#cxstack;
967 0   0     0 while (
      0        
968             $cxix >= 0
969             && ( CxTYPE_no_LOOP( $cxstack[$cxix] )
970             || $cxstack[$cxix]->{label} ne $label )
971             )
972             {
973 0         0 $cxix--;
974             }
975 0 0       0 debug "dopoptolabel: returning $cxix\n" if $debug{cxstack};
976 0 0 0     0 if ($cxix < 0 and $debug{cxstack}) {
977 0         0 for my $cx (0 .. $#cxstack) {
978 0         0 debug "$cx: ",$cxstack[$cx]->{label},"\n";
979             }
980 0         0 for my $op (keys %{$labels->{label}}) {
  0         0  
981 0         0 debug $labels->{label}->{$op},"\n";
982             }
983             }
984 0         0 return $cxix;
985             }
986              
987             sub push_label {
988 0     0 0 0 my $op = shift;
989 0         0 my $type = shift;
990 0         0 push @{$labels->{$type}}, ( $op );
  0         0  
991             }
992              
993             sub pop_label {
994 0     0 0 0 my $type = shift;
995 0         0 my $op = pop @{$labels->{$type}};
  0         0  
996 0         0 write_label ($op); # avoids duplicate labels
997             }
998              
999             sub error {
1000 0     0 0 0 my $format = shift;
1001 0         0 my $file = $curcop->[0]->file;
1002 0         0 my $line = $curcop->[0]->line;
1003 0         0 $errors++;
1004 0 0       0 if (@_) {
1005 0         0 warn sprintf( "ERROR at %s:%d: $format\n", $file, $line, @_ );
1006             }
1007             else {
1008 0         0 warn sprintf( "ERROR at %s:%d: %s\n", $file, $line, $format );
1009             }
1010             }
1011              
1012             # run-time eval is too late for attrs being checked by perlcore. BEGIN does not help.
1013             # use types is the right approach. But until types is fixed we use this hack.
1014             # Note that we also need a new CHECK_SCALAR_ATTRIBUTES hook, starting with v5.22.
1015             sub init_type_attrs {
1016 0     0 0 0 eval q[
1017              
1018             our $valid_attr = '^(int|num|str|double|string|unsigned|register|temporary|ro|readonly|const)$';
1019             sub MODIFY_SCALAR_ATTRIBUTES {
1020             my $pkg = shift;
1021             my $v = shift;
1022             my $attr = $B::CC::valid_attr;
1023             $attr =~ s/\b$pkg\b//;
1024             if (my @bad = grep !/$attr/, @_) {
1025             return @bad;
1026             } else {
1027             no strict 'refs';
1028             push @{"$pkg\::$v\::attributes"}, @_; # create a magic glob
1029             return ();
1030             }
1031             }
1032             sub FETCH_SCALAR_ATTRIBUTES {
1033             my ($pkg, $v) = @_;
1034             no strict 'refs';
1035             return @{"$pkg\::$v\::attributes"};
1036             }
1037              
1038             # pollute our callers namespace for attributes to be accepted with -MB::CC
1039             *main::MODIFY_SCALAR_ATTRIBUTES = \&B::CC::MODIFY_SCALAR_ATTRIBUTES;
1040             *main::FETCH_SCALAR_ATTRIBUTES = \&B::CC::FETCH_SCALAR_ATTRIBUTES;
1041              
1042             # my int $i : register : ro;
1043             *int::MODIFY_SCALAR_ATTRIBUTES = \&B::CC::MODIFY_SCALAR_ATTRIBUTES;
1044             *int::FETCH_SCALAR_ATTRIBUTES = \&B::CC::FETCH_SCALAR_ATTRIBUTES;
1045              
1046             # my double $d : ro;
1047             *num::MODIFY_SCALAR_ATTRIBUTES = \&B::CC::MODIFY_SCALAR_ATTRIBUTES;
1048             *num::FETCH_SCALAR_ATTRIBUTES = \&B::CC::FETCH_SCALAR_ATTRIBUTES;
1049             *str::MODIFY_SCALAR_ATTRIBUTES = \&B::CC::MODIFY_SCALAR_ATTRIBUTES;
1050             *str::FETCH_SCALAR_ATTRIBUTES = \&B::CC::FETCH_SCALAR_ATTRIBUTES;
1051              
1052             # deprecated:
1053             *double::MODIFY_SCALAR_ATTRIBUTES = \&B::CC::MODIFY_SCALAR_ATTRIBUTES;
1054             *double::FETCH_SCALAR_ATTRIBUTES = \&B::CC::FETCH_SCALAR_ATTRIBUTES;
1055             *string::MODIFY_SCALAR_ATTRIBUTES = \&B::CC::MODIFY_SCALAR_ATTRIBUTES;
1056             *string::FETCH_SCALAR_ATTRIBUTES = \&B::CC::FETCH_SCALAR_ATTRIBUTES;
1057             ];
1058              
1059             }
1060              
1061             =head2 load_pad
1062              
1063             Load pad takes (the elements of) a PADLIST as arguments and loads up @pad
1064             with Stackobj-derived objects which represent those lexicals.
1065              
1066             If/when perl itself can generate type information C<(my int $foo; my $foo : int)> then we'll
1067             take advantage of that here. Until then, we'll use the L<-fname-magic/-fno-name-magic>
1068             hack to tell the compiler when we want a lexical to be a particular type or to be a register.
1069              
1070             =cut
1071              
1072             sub load_pad {
1073 0     0 1 0 my ( $namelistav, $valuelistav ) = @_;
1074 0         0 @padlist = @_;
1075 0         0 my @namelist = $namelistav->ARRAY;
1076 0         0 my @valuelist = $valuelistav->ARRAY;
1077 0         0 my $ix;
1078 0         0 @pad = ();
1079 0 0       0 debug "load_pad: $#namelist names, $#valuelist values\n" if $debug{pad};
1080              
1081             # Temporary lexicals don't get named so it's possible for @valuelist
1082             # to be strictly longer than @namelist. We count $ix up to the end of
1083             # @valuelist but index into @namelist for the name. Any temporaries which
1084             # run off the end of @namelist will make $namesv undefined and we treat
1085             # that the same as having an explicit SPECIAL sv_undef object in @namelist.
1086             # [XXX If/when @_ becomes a lexical, we must start at 0 here.]
1087 0         0 for ( $ix = 1 ; $ix < @valuelist ; $ix++ ) {
1088 0         0 my $namesv = $namelist[$ix];
1089 0         0 my $type = T_UNKNOWN;
1090 0         0 my $flags = 0;
1091 0         0 my $name = "tmp";
1092 0         0 my $class = B::class($namesv);
1093 0 0 0     0 if ( !defined($namesv) || $class eq "SPECIAL" ) {
1094             # temporaries have &PL_sv_undef instead of a PVNV for a name
1095 0         0 $flags = VALID_SV | TEMPORARY | REGISTER;
1096             }
1097             else {
1098 0 0       0 my ($nametry) = $namesv->PV =~ /^\$(.+)$/ if $namesv->PV;
1099 0 0       0 $name = $nametry if $nametry;
1100              
1101             # my int $i; my num $d; compiled code only, unless the source provides the int and num packages.
1102             # With Ctypes it is easier. my c_int $i; defines an external Ctypes int, which can be efficiently
1103             # compiled in Perl also.
1104             # XXX Better use attributes, like my $i:int; my $d:num; which works un-compiled also.
1105 0 0 0     0 if (ref($namesv) eq 'B::PVMG' and ref($namesv->SvSTASH) eq 'B::HV') { # my int
1106 0         0 $class = $namesv->SvSTASH->NAME;
1107 0 0 0     0 if ($class eq 'int') {
    0 0        
    0          
1108 0         0 $type = T_INT;
1109 0         0 $flags = VALID_SV | VALID_INT;
1110             }
1111             elsif ($class eq 'num' or $class eq 'double') { # my num
1112 0         0 $type = T_NUM;
1113 0         0 $flags = VALID_SV | VALID_NUM;
1114             }
1115             elsif ($class eq 'str' or $class eq 'string') { # my str
1116 0         0 $type = T_STR;
1117 0         0 $flags = VALID_SV | VALID_STR;
1118             }
1119             #elsif ($class eq 'c_int') { # use Ctypes;
1120             # $type = T_INT;
1121             # $flags = VALID_SV | VALID_INT;
1122             #}
1123             #elsif ($class eq 'c_double') {
1124             # $type = T_NUM;
1125             # $flags = VALID_SV | VALID_NUM;
1126             #}
1127             # TODO: MooseX::Types
1128             }
1129              
1130             # Valid scalar type attributes:
1131             # int num str ro readonly const unsigned
1132             # Note: PVMG from above also.
1133             # Typed arrays and hashes later.
1134 0         0 if (0 and $class =~ /^(I|P|S|N)V/
1135             and $opt_type_attr
1136             and UNIVERSAL::can($class,"CHECK_SCALAR_ATTRIBUTES")) # with 5.18
1137             {
1138             require attributes;
1139             #my $svtype = uc reftype ($namesv);
1140             # test 105
1141             my @attr = attributes::get(\$namesv); # how to get em from B? see optimize
1142             warn "\$$name attrs: ".@attr if $verbose or $debug{pad};
1143             #my $valid_types = ${"$class\::valid_attr"}; # They ARE valid, parser checked already.
1144             }
1145              
1146             # XXX We should try Devel::TypeCheck for type inference also
1147              
1148             # magic names: my $i_ir, my $d_d. without -fno-name-magic cmdline option only
1149 0 0 0     0 if ( $type == T_UNKNOWN and $opt_name_magic and $name =~ /^(.*)_([dis])(r?)$/ ) {
      0        
1150 0         0 $name = $1;
1151 0 0       0 if ( $2 eq "i" ) {
    0          
    0          
1152 0         0 $type = T_INT;
1153 0         0 $flags = VALID_SV | VALID_INT;
1154             }
1155             elsif ( $2 eq "d" ) {
1156 0         0 $type = T_NUM;
1157 0         0 $flags = VALID_SV | VALID_NUM;
1158             }
1159             elsif ( $2 eq "s" ) {
1160 0         0 $type = T_STR;
1161 0         0 $flags = VALID_SV | VALID_STR;
1162             }
1163 0 0       0 $flags |= REGISTER if $3;
1164             }
1165             }
1166 0         0 $name = "${ix}_$name";
1167             # comppadname bug with overlong strings
1168 0 0 0     0 if ($] < 5.008008 and length($name) > 100 and $name =~ /\0\0/) {
      0        
1169 0         0 my $i = index($name,"\0");
1170 0 0       0 $name = substr($name,0,$i) if $i > -1;
1171             }
1172 0         0 $pad[$ix] =
1173             B::Stackobj::Padsv->new( $type, $flags, $ix, "i$name", "d$name" );
1174              
1175 0 0       0 debug sprintf( "PL_curpad[$ix] = %s\n", $pad[$ix]->peek ) if $debug{pad};
1176             }
1177             }
1178              
1179             sub declare_pad {
1180 0     0 0 0 my $ix;
1181 0         0 for ( $ix = 1 ; $ix <= $#pad ; $ix++ ) {
1182 0         0 my $type = $pad[$ix]->{type};
1183             declare( "IV",
1184             $type == T_INT ? sprintf( "%s=0", $pad[$ix]->{iv} ) : $pad[$ix]->{iv} )
1185 0 0       0 if $pad[$ix]->save_int;
    0          
1186             declare( "NV",
1187             $type == T_NUM
1188             ? sprintf( "%s = 0", $pad[$ix]->{nv} )
1189             : $pad[$ix]->{nv} )
1190 0 0       0 if $pad[$ix]->save_double;
    0          
1191             declare( "PV",
1192             $type == T_STR
1193             ? sprintf( "%s = 0", $pad[$ix]->{sv} )
1194             : $pad[$ix]->{sv} )
1195 0 0       0 if $pad[$ix]->save_str;
    0          
1196             }
1197             }
1198              
1199             # for cc: unique ascii representation of an utf8 string, for labels
1200             sub encode_utf8($) {
1201 0     0 0 0 my $l = shift;
1202 0 0 0     0 if ($] > 5.007 and utf8::is_utf8($l)) {
1203             # utf8::encode($l);
1204             # $l =~ s/([\x{0100}-\x{ffff}])/sprintf("u%x", $1)/ge;
1205             #$l = substr(B::cstring($l), 1, -1);
1206             #$l =~ s/\\/u/g;
1207 0 0       0 $l = join('', map { $_ < 127 ? $_ : sprintf("u_%x_", $_) } unpack("U*", $l));
  0         0  
1208             }
1209 0         0 return $l;
1210             }
1211              
1212             #
1213             # Debugging stuff
1214             #
1215             sub peek_stack {
1216 0     0 0 0 sprintf "stack = %s\n", join( " ", map( $_->minipeek, @stack ) );
1217             }
1218              
1219             #
1220             # OP stuff
1221             #
1222              
1223             =head2 label
1224              
1225             We not only mark named labels in C as such - with prefix "label_".
1226              
1227             We also have to mark each known (back jumps) and yet unknown branch targets
1228             (forward jumps) for compile-time generated branch points, with the "lab_"
1229             prefix.
1230              
1231             =cut
1232              
1233             sub label {
1234 0     0 1 0 my $op = shift;
1235             # Preserve original label name for "real" labels
1236 0 0 0     0 if ($op->can("label") and $op->label) {
1237 0         0 my $l = encode_utf8 $op->label;
1238             # cc should error on duplicate named labels
1239 0         0 return sprintf( "label_%s_%x", $l, $$op);
1240             } else {
1241 0         0 return sprintf( "lab_%x", $$op );
1242             }
1243             }
1244              
1245             sub write_label {
1246 0     0 0 0 my $op = shift;
1247 0 0       0 $op->save if $$op;
1248             # debug sprintf("lab_%x:?\n", $$op) if $debug{cxstack};
1249 0 0       0 unless ($labels->{label}->{$$op}) {
1250 0         0 my $l = label($op);
1251             # named label but op not yet known?
1252 0 0 0     0 if ( $op->can("label") and $op->label ) {
1253 0         0 $l = "label_" . encode_utf8 $op->label;
1254             # only print first such label. test 21
1255             push_runtime(sprintf( " %s:", $l))
1256 0 0       0 unless $labels->{label}->{$l};
1257 0         0 $labels->{label}->{$l} = $$op;
1258             }
1259 0 0       0 if ($verbose) {
1260 0         0 push_runtime(sprintf( " %s:\t/* %s */", label($op), $op->name ));
1261             } else {
1262 0         0 push_runtime(sprintf( " %s:", label($op) ));
1263             }
1264             # avoid printing duplicate jump labels
1265 0         0 $labels->{label}->{$$op} = $l;
1266 0 0 0     0 if ($op->can("label") and $op->label ) {
1267 0 0 0     0 push(@cxstack, {
    0 0        
    0 0        
    0 0        
1268             type => 0,
1269             op => $op,
1270             nextop => ((ref($op) eq 'B::LOOP') && $op->nextop) ? $op->nextop : $op,
1271             redoop => ((ref($op) eq 'B::LOOP') && $op->redoop) ? $op->redoop : $op,
1272             lastop => ((ref($op) eq 'B::LOOP') && $op->lastop) ? $op->lastop : $op,
1273             'label' => $op->can("label") && $op->label ? $op->label : $l
1274             });
1275             }
1276             }
1277             }
1278              
1279             sub loadop {
1280 0     0 0 0 my $op = shift;
1281 0         0 my $opsym = $op->save;
1282 0         0 $op_count++; # for statistics
1283 0 0       0 runtime("PL_op = $opsym;") unless $know_op;
1284 0         0 return $opsym;
1285             }
1286              
1287             sub doop {
1288 0     0 0 0 my $op = shift;
1289 0         0 my $ppaddr = $op->ppaddr;
1290 0         0 my $sym = loadop($op);
1291 0         0 my $ppname = "pp_" . $op->name;
1292 0 0       0 if ($inline_ops) {
1293             # inlining direct calls is safe, just CALLRUNOPS for macros not
1294 0         0 $ppaddr = "Perl_".$ppname;
1295 0 0       0 $no_stack{$ppname}
1296             ? runtime("PL_op = $ppaddr(aTHX);")
1297             : runtime("PUTBACK; PL_op = $ppaddr(aTHX); SPAGAIN;");
1298             } else {
1299 0 0       0 $no_stack{$ppname}
1300             ? runtime("PL_op = $ppaddr(aTHX);")
1301             : runtime("DOOP($ppaddr);");
1302             }
1303 0         0 $know_op = 1;
1304 0         0 return $sym;
1305             }
1306              
1307             sub gimme {
1308 0     0 0 0 my $op = shift;
1309 0         0 my $want = $op->flags & OPf_WANT;
1310 0 0       0 return ( $want == OPf_WANT_VOID ? G_VOID :
    0          
    0          
1311             $want == OPf_WANT_SCALAR ? G_SCALAR :
1312             $want == OPf_WANT_LIST ? G_ARRAY :
1313             undef );
1314             }
1315              
1316             #
1317             # Code generation for PP code
1318             #
1319              
1320             # coverage: 18,19,25,...
1321             sub pp_null {
1322 0     0 0 0 my $op = shift;
1323 0         0 $B::C::nullop_count++;
1324 0         0 return $op->next;
1325             }
1326              
1327             # coverage: 102
1328             sub pp_stub {
1329 0     0 0 0 my $op = shift;
1330 0         0 my $gimme = gimme($op);
1331 0 0       0 if ( not defined $gimme ) {
    0          
1332 0         0 write_back_stack();
1333 0         0 runtime("if (block_gimme() == G_SCALAR)",
1334             "\tXPUSHs(&PL_sv_undef);");
1335             } elsif ( $gimme == G_SCALAR ) {
1336 0         0 my $obj = B::Stackobj::Const->new(sv_undef);
1337 0         0 push( @stack, $obj );
1338             }
1339 0         0 return $op->next;
1340             }
1341              
1342             # coverage: 2,21,28,30
1343             sub pp_unstack {
1344 0     0 0 0 my $op = shift;
1345 0         0 @stack = ();
1346 0         0 runtime("PP_UNSTACK;");
1347 0         0 return $op->next;
1348             }
1349              
1350             # coverage: 2,21,27,28,30
1351             sub pp_and {
1352 0     0 0 0 my $op = shift;
1353 0         0 my $next = $op->next;
1354 0         0 reload_lexicals();
1355 0         0 unshift( @bblock_todo, $next );
1356 0 0       0 if ( @stack >= 1 ) {
1357 0         0 my $obj = pop @stack;
1358 0         0 my $bool = $obj->as_bool;
1359 0         0 write_back_stack();
1360 0         0 save_or_restore_lexical_state($$next);
1361 0 0       0 if ($bool =~ /POPs/) {
1362 0         0 runtime("sv = $bool;",
1363             sprintf("if (!sv) { PUSHs(sv); goto %s;}", label($next)));
1364             } else {
1365 0         0 runtime(sprintf(
1366             "if (!$bool) { PUSHs((SV*)%s); goto %s;}", $obj->as_sv, label($next)
1367             ));
1368             }
1369             }
1370             else {
1371 0         0 save_or_restore_lexical_state($$next);
1372 0         0 runtime( sprintf( "if (!%s) goto %s;", top_bool(), label($next) ),
1373             "sp--;" );
1374             }
1375 0         0 return $op->other;
1376             }
1377              
1378             # Nearly identical to pp_and, but leaves stack unchanged.
1379             sub pp_andassign {
1380 0     0 0 0 my $op = shift;
1381 0         0 my $next = $op->next;
1382 0         0 reload_lexicals();
1383 0         0 unshift( @bblock_todo, $next );
1384 0 0       0 if ( @stack >= 1 ) {
1385 0         0 my $obj = pop @stack;
1386 0         0 my $bool = $obj->as_bool;
1387 0         0 write_back_stack();
1388 0         0 save_or_restore_lexical_state($$next);
1389 0 0       0 if ($bool =~ /POPs/) {
1390 0         0 runtime("sv = $bool;",
1391             sprintf("PUSHs((SV*)%s); if (!$bool) { goto %s;}",
1392             $obj->as_sv, label($next)));
1393             } else {
1394 0         0 runtime(
1395             sprintf("PUSHs((SV*)%s); if (!$bool) { goto %s;}",
1396             $obj->as_sv, label($next)));
1397             }
1398             }
1399             else {
1400 0         0 save_or_restore_lexical_state($$next);
1401 0         0 runtime( sprintf( "if (!%s) goto %s;", top_bool(), label($next) ) );
1402             }
1403 0         0 return $op->other;
1404             }
1405              
1406             # coverage: 28
1407             sub pp_or {
1408 0     0 0 0 my $op = shift;
1409 0         0 my $next = $op->next;
1410 0         0 reload_lexicals();
1411 0         0 unshift( @bblock_todo, $next );
1412 0 0       0 if ( @stack >= 1 ) {
1413 0         0 my $obj = pop @stack;
1414 0         0 my $bool = $obj->as_bool;
1415 0         0 write_back_stack();
1416 0         0 save_or_restore_lexical_state($$next);
1417 0 0       0 if ($bool =~ /POPs/) {
1418 0         0 runtime("sv = $bool;",
1419             sprintf("if (sv) { PUSHs(sv); goto %s;}", label($next)));
1420             } else {
1421 0         0 runtime(
1422             sprintf("if ($bool) { PUSHs((SV*)%s); goto %s; }", $obj->as_sv, label($next)));
1423             }
1424             }
1425             else {
1426 0         0 save_or_restore_lexical_state($$next);
1427 0         0 runtime( sprintf( "if (%s) goto %s;", top_bool(), label($next) ),
1428             "sp--;" );
1429             }
1430 0         0 return $op->other;
1431             }
1432              
1433             # Nearly identical to pp_or, but leaves stack unchanged.
1434             sub pp_orassign {
1435 0     0 0 0 my $op = shift;
1436 0         0 my $next = $op->next;
1437 0         0 reload_lexicals();
1438 0         0 unshift( @bblock_todo, $next );
1439 0 0       0 if ( @stack >= 1 ) {
1440 0         0 my $obj = pop @stack;
1441 0         0 my $bool = $obj->as_bool;
1442 0         0 write_back_stack();
1443 0         0 save_or_restore_lexical_state($$next);
1444 0         0 runtime(
1445             sprintf(
1446             "PUSHs((SV*)%s); if ($bool) { goto %s; }", $obj->as_sv, label($next)
1447             )
1448             );
1449             }
1450             else {
1451 0         0 save_or_restore_lexical_state($$next);
1452 0         0 runtime( sprintf( "if (%s) goto %s;", top_bool(), label($next) ) );
1453             }
1454 0         0 return $op->other;
1455             }
1456              
1457             # coverage: issue 45 (1,2)
1458             # in CORE aliased to pp_defined
1459             # default dor is okay issue 45 (3,4)
1460             sub pp_dorassign {
1461 0     0 0 0 my $op = shift;
1462 0         0 my $next = $op->next;
1463 0         0 reload_lexicals();
1464 0         0 unshift( @bblock_todo, $next );
1465 0         0 my $sv = pop @stack;
1466 0         0 write_back_stack();
1467 0         0 save_or_restore_lexical_state($$next);
1468 0 0       0 runtime( sprintf( "PUSHs(%s); if (%s && SvANY(%s)) goto %s;\t/* dorassign */",
1469             $sv->as_sv, $sv->as_sv, $sv->as_sv, label($next)) ) if $sv;
1470 0         0 return $op->other;
1471             }
1472              
1473             # coverage: 102
1474             sub pp_cond_expr {
1475 0     0 0 0 my $op = shift;
1476 0         0 my $false = $op->next;
1477 0         0 unshift( @bblock_todo, $false );
1478 0         0 reload_lexicals();
1479 0         0 my $bool = pop_bool();
1480 0         0 write_back_stack();
1481 0         0 save_or_restore_lexical_state($$false);
1482 0         0 runtime( sprintf( "if (!$bool) goto %s;\t/* cond_expr */", label($false) ) );
1483 0         0 return $op->other;
1484             }
1485              
1486             # coverage: 9,10,12,17,18,22,28,32
1487             sub pp_padsv {
1488 0     0 0 0 my $op = shift;
1489 0         0 my $ix = $op->targ;
1490 0 0       0 push( @stack, $pad[$ix] ) if $pad[$ix];
1491 0 0       0 if ( $op->flags & OPf_MOD ) {
1492 0         0 my $private = $op->private;
1493 0 0       0 if ( $private & OPpLVAL_INTRO ) {
    0          
1494             # coverage: 9,10,12,17,18,19,20,22,27,28,31,32
1495 0         0 runtime("SAVECLEARSV(PL_curpad[$ix]);");
1496             }
1497             elsif ( $private & OPpDEREF ) {
1498             # coverage: 18
1499 0 0       0 if ($] >= 5.015002) {
1500 0         0 runtime(sprintf( "PL_curpad[%d] = Perl_vivify_ref(aTHX_ PL_curpad[%d], %d);",
1501             $ix, $ix, $private & OPpDEREF ));
1502             } else {
1503 0         0 runtime(sprintf( "Perl_vivify_ref(aTHX_ PL_curpad[%d], %d);",
1504             $ix, $private & OPpDEREF ));
1505             }
1506 0         0 $vivify_ref_defined++;
1507 0 0       0 $pad[$ix]->invalidate if $pad[$ix];
1508             }
1509             }
1510 0         0 return $op->next;
1511             }
1512              
1513             # coverage: 1-5,7-14,18-23,25,27-32
1514             sub pp_const {
1515 0     0 0 0 my $op = shift;
1516 0         0 my $sv = $op->sv;
1517 0         0 my $obj;
1518              
1519             # constant could be in the pad (under useithreads)
1520 0 0       0 if ($$sv) {
1521 0         0 $obj = $constobj{$$sv};
1522 0 0       0 if ( !defined($obj) ) {
1523 0         0 $obj = $constobj{$$sv} = B::Stackobj::Const->new($sv);
1524             }
1525             }
1526             else {
1527 0         0 $obj = $pad[ $op->targ ];
1528             }
1529             # XXX looks like method_named has only const as prev op
1530 0 0 0     0 if ($op->next
      0        
1531             and $op->next->can('name')
1532             and $op->next->name eq 'method_named'
1533             ) {
1534 0         0 $package_pv = svop_or_padop_pv($op);
1535 0 0       0 debug "save package_pv \"$package_pv\" for method_name\n" if $debug{op};
1536             }
1537 0         0 push( @stack, $obj );
1538 0         0 return $op->next;
1539             }
1540              
1541             # coverage: 1-39, fails in 33
1542             sub pp_nextstate {
1543 0     0 0 0 my $op = shift;
1544 0 0 0     0 if ($labels->{'nextstate'}->[-1] and $labels->{'nextstate'}->[-1] == $op) {
1545 0 0       0 debug sprintf("pop_label nextstate: cxstack label %s\n", $curcop->[0]->label) if $debug{cxstack};
1546 0         0 pop_label 'nextstate';
1547             } else {
1548 0         0 write_label($op);
1549             }
1550 0         0 $curcop->load($op);
1551 0         0 loadop($op);
1552             #testcc 48: protect CopFILE_free and CopSTASH_free in END block (#296)
1553 0 0 0     0 if ($ppname =~ /^pp_sub_END(_\d+)?$/ and $ITHREADS) {
1554 0         0 runtime("#ifdef USE_ITHREADS",
1555             "CopFILE((COP*)PL_op) = NULL;");
1556 0 0 0     0 if ($] >= 5.018) {
    0          
1557 0         0 runtime("CopSTASH_set((COP*)PL_op, NULL);");
1558             } elsif ($] >= 5.016 and $] <= 5.017) {
1559 0         0 runtime("CopSTASHPV_set((COP*)PL_op, NULL, 0);");
1560             } else {
1561 0         0 runtime("CopSTASHPV_set((COP*)PL_op, NULL);");
1562             }
1563 0         0 runtime("#endif");
1564             }
1565 0         0 @stack = ();
1566 0 0       0 debug( sprintf( "%s:%d\n", $op->file, $op->line ) ) if $debug{lineno};
1567 0 0 0     0 debug( sprintf( "CopLABEL %s\n", $op->label ) ) if $op->label and $debug{cxstack};
1568 0 0       0 runtime("TAINT_NOT;") if $opt_taint; # TODO Not always needed (resets PL_taint = 0)
1569 0         0 runtime("sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;"); # TODO reset sp not needed always
1570 0 0 0     0 if ( $freetmps_each_bblock || $freetmps_each_loop ) {
1571 0         0 $need_freetmps = 1;
1572             }
1573             else {
1574 0         0 runtime("FREETMPS;"); # TODO Not always needed
1575             }
1576 0         0 return $op->next;
1577             }
1578              
1579             # Like pp_nextstate, but used instead when the debugger is active.
1580 0     0 0 0 sub pp_dbstate { pp_nextstate(@_) }
1581              
1582             #default_pp will handle this:
1583             #sub pp_bless { $curcop->write_back; default_pp(@_) }
1584             #sub pp_repeat { $curcop->write_back; default_pp(@_) }
1585             # The following subs need $curcop->write_back if we decide to support arybase:
1586             # pp_pos, pp_substr, pp_index, pp_rindex, pp_aslice, pp_lslice, pp_splice
1587             #sub pp_caller { $curcop->write_back; default_pp(@_) }
1588              
1589             # coverage: ny
1590             sub bad_pp_reset {
1591 0 0   0 0 0 if ($inline_ops) {
1592 0         0 my $op = shift;
1593 0 0       0 warn "inlining reset\n" if $debug{op};
1594 0 0       0 $curcop->write_back if $curcop;
1595 0         0 runtime '{ /* pp_reset */';
1596 0         0 runtime ' const char * const tmps = (MAXARG < 1) ? (const char *)"" : POPpconstx;';
1597 0         0 runtime ' sv_reset(tmps, CopSTASH(PL_curcop));}';
1598 0         0 runtime 'PUSHs(&PL_sv_yes);';
1599 0         0 return $op->next;
1600             } else {
1601 0         0 default_pp(@_);
1602             }
1603             }
1604              
1605             # coverage: 20
1606             sub pp_regcreset {
1607 0 0   0 0 0 if ($inline_ops) {
1608 0         0 my $op = shift;
1609 0 0       0 warn "inlining regcreset\n" if $debug{op};
1610 0 0       0 $curcop->write_back if $curcop;
1611 0         0 runtime 'PL_reginterp_cnt = 0; /* pp_regcreset */';
1612 0 0       0 runtime 'TAINT_NOT;' if $opt_taint;
1613 0         0 return $op->next;
1614             } else {
1615 0         0 default_pp(@_);
1616             }
1617             }
1618              
1619             # coverage: 103
1620             sub pp_stringify {
1621 0 0 0 0 0 0 if ($inline_ops and $] >= 5.008) {
1622 0         0 my $op = shift;
1623 0 0       0 warn "inlining stringify\n" if $debug{op};
1624 0         0 my $sv = top_sv();
1625 0         0 my $ix = $op->targ;
1626 0         0 my $targ = $pad[$ix];
1627 0         0 runtime "sv_copypv(PL_curpad[$ix], $sv);\t/* pp_stringify */";
1628 0 0       0 $stack[-1] = $targ if @stack;
1629 0         0 return $op->next;
1630             } else {
1631 0         0 default_pp(@_);
1632             }
1633             }
1634              
1635             # coverage: 9,10,27
1636             sub bad_pp_anoncode {
1637 0 0   0 0 0 if ($inline_ops) {
1638 0         0 my $op = shift;
1639 0 0       0 warn "inlining anoncode\n" if $debug{op};
1640 0         0 my $ix = $op->targ;
1641 0         0 my $ppname = "pp_" . $op->name;
1642 0 0       0 write_back_lexicals() unless $skip_lexicals{$ppname};
1643 0 0       0 write_back_stack() unless $skip_stack{$ppname};
1644             # XXX finish me. this works only with >= 5.10
1645 0         0 runtime '{ /* pp_anoncode */',
1646             ' CV *cv = MUTABLE_CV(PAD_SV(PL_op->op_targ));',
1647             ' if (CvCLONE(cv))',
1648             ' cv = MUTABLE_CV(sv_2mortal(MUTABLE_SV(Perl_cv_clone(aTHX_ cv))));',
1649             ' EXTEND(SP,1);',
1650             ' PUSHs(MUTABLE_SV(cv));',
1651             '}';
1652 0 0       0 invalidate_lexicals() unless $skip_invalidate{$ppname};
1653 0         0 return $op->next;
1654             } else {
1655 0         0 default_pp(@_);
1656             }
1657             }
1658              
1659             # coverage: 35
1660             # XXX TODO get prev op. For now saved in pp_const.
1661             sub pp_method_named {
1662 0     0 0 0 my ( $op ) = @_;
1663 0         0 my $name = svop_or_padop_pv($op);
1664             # The pkg PV is at [PL_stack_base+TOPMARK+1], the previous op->sv->PV.
1665 0 0       0 my $stash = $package_pv ? $package_pv."::" : "main::";
1666 0         0 $name = $stash . $name;
1667 0 0       0 if (exists &$name) {
1668 0 0       0 debug "save method_name \"$name\"\n" if $debug{op};
1669 0         0 svref_2object( \&{$name} )->save;
  0         0  
1670             } else {
1671 0 0       0 debug "skip saving non-existing method_name \"$name\"\n" if $debug{op}; #CC 50
1672             }
1673 0         0 default_pp(@_);
1674             }
1675              
1676             # inconsequence: gvs are not passed around on the stack
1677             # coverage: 26,103
1678             sub bad_pp_srefgen {
1679 0 0   0 0 0 if ($inline_ops) {
1680 0         0 my $op = shift;
1681 0 0       0 warn "inlining srefgen\n" if $debug{op};
1682             #my $ppname = "pp_" . $op->name;
1683             #$curcop->write_back;
1684             #write_back_lexicals() unless $skip_lexicals{$ppname};
1685             #write_back_stack() unless $skip_stack{$ppname};
1686 0         0 my $svobj = $stack[-1]->as_sv;
1687 0         0 my $sv = pop_sv();
1688             # XXX fix me
1689 0         0 runtime "{ /* pp_srefgen */
1690             SV* rv;
1691             SV* sv = $sv;";
1692             # sv = POPs
1693             #B::svref_2object(\$sv);
1694 0 0 0     0 if (($svobj->flags & 0xff) == $SVt_PVLV
    0          
1695             and B::PVLV::LvTYPE($svobj) eq ord('y'))
1696             {
1697 0         0 runtime 'if (LvTARGLEN(sv))
1698             vivify_defelem(sv);
1699             if (!(sv = LvTARG(sv)))
1700             sv = &PL_sv_undef;
1701             else
1702             SvREFCNT_inc_void_NN(sv);';
1703             }
1704             elsif (($svobj->flags & 0xff) == $SVt_PVAV) {
1705 0         0 runtime 'if (!AvREAL((const AV *)sv) && AvREIFY((const AV *)sv))
1706             av_reify(MUTABLE_AV(sv));
1707             SvTEMP_off(sv);
1708             SvREFCNT_inc_void_NN(sv);';
1709             }
1710             #elsif ($sv->SvPADTMP && !IS_PADGV(sv)) {
1711             # runtime 'sv = newSVsv(sv);';
1712             #}
1713             else {
1714 0         0 runtime 'SvTEMP_off(sv);
1715             SvREFCNT_inc_void_NN(sv);';
1716             }
1717 0         0 runtime 'rv = sv_newmortal();
1718             sv_upgrade(rv, SVt_IV);
1719             SvRV_set(rv, sv);
1720             SvROK_on(rv);
1721             PUSHBACK;
1722             }';
1723 0         0 return $op->next;
1724             } else {
1725 0         0 default_pp(@_);
1726             }
1727             }
1728              
1729             # coverage: 9,10,27
1730             #sub pp_refgen
1731              
1732             # coverage: 28, 14
1733             sub pp_rv2gv {
1734 0     0 0 0 my $op = shift;
1735 0 0       0 $curcop->write_back if $curcop;
1736 0         0 my $ppname = "pp_" . $op->name;
1737 0 0       0 write_back_lexicals() unless $skip_lexicals{$ppname};
1738 0 0       0 write_back_stack() unless $skip_stack{$ppname};
1739 0         0 my $sym = doop($op);
1740 0 0       0 if ( $op->private & OPpDEREF ) {
1741 0         0 $init->add( sprintf("((UNOP *)$sym)->op_first = $sym;") );
1742 0         0 $init->add( sprintf( "((UNOP *)$sym)->op_type = %d;", $op->first->type ) );
1743             }
1744 0         0 return $op->next;
1745             }
1746              
1747             # coverage: 18,19,25
1748             sub pp_sort {
1749 0     0 0 0 my $op = shift;
1750             #my $ppname = $op->ppaddr;
1751 0 0 0     0 if ( $op->flags & OPf_SPECIAL && $op->flags & OPf_STACKED ) {
1752             # blocksort is awful. E.g. we need to the leading NULL op, invalidates -fcop
1753             # Ugly surgery required. sort expects as block: pushmark rv2gv leave => enter
1754             # pp_sort() OP *kid = cLISTOP->op_first->op_sibling;/* skip over pushmark 4 to null */
1755             # kid = cUNOPx(kid)->op_first; /* pass rv2gv (null'ed) */
1756             # kid = cUNOPx(kid)->op_first; /* pass leave */
1757             #
1758             #3 <0> pushmark s ->4
1759             #8 <@> sort lKS* ->9
1760             #4 <0> pushmark s ->5
1761             #- <1> null sK/1 ->5
1762             #- <1> ex-leave sKP ->-
1763             #- <0> enter s ->-
1764             # some code doing cmp or ncmp
1765             # Example with 3 const args: print sort { bla; $b <=> $a } 1,4,3
1766             #5 <$> const[IV 1] s ->6
1767             #6 <$> const[IV 4] s ->7
1768             #7 <$> const[IV 3] s ->8 => sort
1769             #
1770 0         0 my $root = $op->first->sibling->first; #leave or null
1771 0         0 my $start = $root->first; #enter
1772 0 0       0 warn "blocksort: root=",$root->name,", start=",$start->name,"\n" if $debug{op};
1773 0         0 my $pushmark = $op->first->save; #pushmark sibling to null
1774 0         0 $op->first->sibling->save; #null->first to leave
1775 0         0 $root->save; #ex-leave
1776 0         0 my $sym = $start->save; #enter
1777 0         0 my $fakeop = cc_queue( "pp_sort" . sprintf("%x",abs($$op)), $root, $start );
1778 0         0 $init->add( sprintf( "(%s)->op_next = %s;", $sym, $fakeop ) );
1779             }
1780 0         0 $curcop->write_back;
1781 0         0 write_back_lexicals();
1782 0         0 write_back_stack();
1783 0         0 doop($op);
1784 0         0 return $op->next;
1785             }
1786              
1787             # coverage: 2-4,6,7,13,15,21,24,26,27,30,31
1788             sub pp_gv {
1789 0     0 0 0 my $op = shift;
1790 0         0 my $gvsym;
1791 0 0       0 if ($ITHREADS) {
1792 0         0 $gvsym = $pad[ $op->padix ]->as_sv;
1793             #push @stack, ($pad[$op->padix]);
1794             }
1795             else {
1796 0         0 $gvsym = $op->gv->save;
1797             # XXX
1798             #my $obj = new B::Stackobj::Const($op->gv);
1799             #push( @stack, $obj );
1800             }
1801 0         0 write_back_stack();
1802 0         0 runtime("XPUSHs((SV*)$gvsym);");
1803 0         0 return $op->next;
1804             }
1805              
1806             # coverage: 2,3,4,9,11,14,20,21,23,28
1807             sub pp_gvsv {
1808 0     0 0 0 my $op = shift;
1809 0         0 my $gvsym;
1810 0 0       0 if ($ITHREADS) {
1811             #debug(sprintf("OP name=%s, class=%s\n",$op->name,B::class($op))) if $debug{pad};
1812 0 0       0 debug( sprintf( "GVSV->padix = %d\n", $op->padix ) ) if $debug{pad};
1813 0         0 $gvsym = $pad[ $op->padix ]->as_sv;
1814 0 0       0 debug( sprintf( "GVSV->private = 0x%x\n", $op->private ) ) if $debug{pad};
1815             }
1816             else {
1817 0         0 $gvsym = $op->gv->save;
1818             }
1819 0         0 write_back_stack();
1820             # Expects GV*, not SV* PL_curpad
1821 0 0       0 $gvsym = "(GV*)$gvsym" if $gvsym =~ /PL_curpad/;
1822 0 0       0 if ($gvsym eq '(SV*)&PL_sv_undef') {
    0          
1823 0         0 runtime("XPUSHs($gvsym);");
1824             }
1825             elsif ( $op->private & OPpLVAL_INTRO ) {
1826 0         0 runtime("XPUSHs(save_scalar($gvsym));");
1827             #my $obj = new B::Stackobj::Const($op->gv);
1828             #push( @stack, $obj );
1829             }
1830             else {
1831 0 0       0 $PERL510
1832             ? runtime("XPUSHs(GvSVn($gvsym));")
1833             : runtime("XPUSHs(GvSV($gvsym));");
1834             }
1835 0         0 return $op->next;
1836             }
1837              
1838             # Check for faster fetch calls. Returns 0 if the fast 'no' is in effect.
1839             sub autovivification {
1840 0 0   0 0 0 if (!$opt_autovivify) {
    0          
1841 0         0 return 0;
1842             } elsif ($INC{'autovivification.pm'}) {
1843 0         0 return _autovivification($curcop->[0]);
1844             } else {
1845 0         0 return 1;
1846             }
1847             }
1848              
1849             # coverage: 16, issue44
1850             sub pp_aelemfast {
1851 0     0 0 0 my $op = shift;
1852 0         0 my ($av, $rmg);
1853 0 0       0 if ($op->flags & OPf_SPECIAL) {
1854 0         0 my $sv = $pad[ $op->targ ]->as_sv;
1855 0         0 my @c = comppadlist->ARRAY;
1856 0         0 my @p = $c[1]->ARRAY;
1857 0         0 my $lex = $p[ $op->targ ];
1858 0 0 0     0 $rmg = ($lex and ref $lex eq 'B::AV' and ($lex->MAGICAL & SVs_RMG or !$lex->ARRAY)) ? 1 : 0;
1859             # MUTABLE_AV is only needed to catch compiler const loss
1860             # $av = $] > 5.01000 ? "MUTABLE_AV($sv)" : $sv;
1861 0         0 $av = "(AV*)$sv";
1862             } else {
1863 0         0 my $gvsym;
1864 0 0       0 if ($ITHREADS) { #padop XXX if it's only a OP, no PADOP? t/CORE/op/ref.t test 36
1865 0 0       0 if ($op->can('padix')) {
1866             #warn "padix\n";
1867 0         0 $gvsym = $pad[ $op->padix ]->as_sv;
1868 0         0 my @c = comppadlist->ARRAY; # XXX curpad, not comppad!!
1869 0         0 my @p = $c[1]->ARRAY;
1870 0         0 my $lex = $p[ $op->padix ];
1871 0 0 0     0 $rmg = ($lex and ref $lex eq 'B::AV' and ($lex->MAGICAL & SVs_RMG or !$lex->ARRAY)) ? 1 : 0;
1872             } else {
1873 0         0 $gvsym = 'PL_incgv'; # XXX passes, but need to investigate why. cc test 43 5.10.1
1874             #write_back_stack();
1875             #runtime("PUSHs(&PL_sv_undef);");
1876             #return $op->next;
1877             }
1878             }
1879             else { #svop
1880 0         0 my $gv = $op->gv;
1881 0         0 $gvsym = $gv->save;
1882 0         0 my $gvav = $gv->AV; # test 16, tied gvav
1883 0 0 0     0 $rmg = $] < 5.007 ? 0 : ($gvav and ($gvav->MAGICAL & SVs_RMG or !$gvav->ARRAY)) ? 1 : 0;
    0          
1884             }
1885 0         0 $av = "GvAV($gvsym)";
1886             }
1887 0         0 my $ix = $op->private;
1888 0         0 my $lval = $op->flags & OPf_MOD;
1889 0 0       0 my $vivify = !$rmg ? autovivification() : 1; # no need to call if $rmg
1890 0 0       0 debug "aelemfast: vivify=$vivify, rmg=$rmg, lval=$lval, -fautovivify=$opt_autovivify -faelem=$opt_aelem\n" if $debug{pad};
1891 0         0 return _aelem($op, $av, $ix, $lval, $rmg, $vivify);
1892             }
1893              
1894             sub _aelem {
1895 0     0   0 my ($op, $av, $ix, $lval, $rmg, $vivify) = @_;
1896 0 0 0     0 if ($opt_aelem and !$rmg and !$vivify and $ix >= 0) {
      0        
      0        
1897 0         0 push @stack, B::Stackobj::Aelem->new($av, $ix, $lval);
1898             } else {
1899 0         0 write_back_stack();
1900 0 0 0     0 runtime(
1901             "{ AV* av = (AV*)$av;",
1902             " SV** const svp = av_fetch(av, $ix, $lval);",
1903             " SV *sv = (svp ? *svp : &PL_sv_undef);",
1904             (!$lval and $rmg) ? " if (SvRMAGICAL(av) && SvGMAGICAL(sv)) mg_get(sv);" : "",
1905             " PUSHs(sv);",
1906             "}"
1907             );
1908             }
1909 0         0 return $op->next;
1910             }
1911              
1912             # coverage: ?
1913             sub pp_aelem {
1914 0     0 0 0 my $op = shift;
1915 0         0 my ($ix, $av);
1916 0 0 0     0 my $lval = ($op->flags & OPf_MOD or $op->private & (OPpLVAL_DEFER || OPpLVAL_INTRO)) ? 1 : 0;
1917 0         0 my $vivify = autovivification();
1918 0         0 my $rmg = $opt_magic; # use -fno-magic for the av (2nd stack arg)
1919 0 0       0 if (@stack >= 1) { # at least ix
1920 0         0 $ix = pop_int(); # TODO: substract CopARYBASE from ix
1921 0 0       0 if (@stack >= 1) {
1922 0         0 my $avobj = $stack[-1]->as_obj;
1923 0 0 0     0 $rmg = ($avobj and $avobj->MAGICAL & SVs_RMG) ? 1 : 0;
1924             }
1925 0         0 $av = pop_sv();
1926 0 0       0 debug "aelem: vivify = $vivify, rmg = $rmg, lval = $lval\n" if $debug{pad};
1927 0         0 return _aelem($op, $av, $ix, $lval, $rmg, $vivify);
1928             } else {
1929 0 0 0     0 if ($lval or $rmg) { # always
1930 0         0 return default_pp($op);
1931             } else {
1932 0         0 $ix = pop_int(); # TODO: substract CopARYBASE from ix
1933 0         0 $av = pop_sv();
1934 0 0       0 debug "aelem: vivify = $vivify, rmg = $rmg, lval = $lval\n" if $debug{pad};
1935 0         0 return _aelem($op, $av, $ix, $lval, $rmg, $vivify);
1936             }
1937             }
1938             }
1939              
1940             # coverage: ?
1941             sub int_binop {
1942 0     0 0 0 my ( $op, $operator, $unsigned ) = @_;
1943 0 0       0 if ( $op->flags & OPf_STACKED ) {
1944 0         0 my $right = pop_int();
1945 0 0       0 if ( @stack >= 1 ) {
1946 0         0 my $left = top_int();
1947 0         0 $stack[-1]->set_int( &$operator( $left, $right ), $unsigned );
1948             }
1949             else {
1950 0 0       0 my $sv_setxv = $unsigned ? 'sv_setuv' : 'sv_setiv';
1951 0         0 runtime( sprintf( "$sv_setxv(TOPs, %s);", &$operator( "TOPi", $right ) ) );
1952             }
1953             }
1954             else {
1955 0         0 my $targ = $pad[ $op->targ ];
1956 0         0 my $right = B::Pseudoreg->new( "IV", "riv" );
1957 0         0 my $left = B::Pseudoreg->new( "IV", "liv" );
1958 0         0 runtime( sprintf( "$$right = %s; $$left = %s;", pop_int(), pop_int ) );
1959 0         0 $targ->set_int( &$operator( $$left, $$right ), $unsigned );
1960 0         0 push( @stack, $targ );
1961             }
1962 0         0 return $op->next;
1963             }
1964              
1965             sub INTS_CLOSED () { 0x1 }
1966             sub INT_RESULT () { 0x2 }
1967             sub NUMERIC_RESULT () { 0x4 }
1968              
1969             # coverage: 101
1970             sub numeric_binop {
1971 0     0 0 0 my ( $op, $operator, $flags ) = @_;
1972 0         0 my $force_int = 0;
1973 0 0       0 $flags = 0 unless $flags;
1974 0   0     0 $force_int ||= ( $flags & INT_RESULT );
1975 0   0     0 $force_int ||=
      0        
1976             ( $flags & INTS_CLOSED
1977             && @stack >= 2
1978             && valid_int( $stack[-2] )
1979             && valid_int( $stack[-1] ) );
1980 0 0       0 if ( $op->flags & OPf_STACKED ) {
1981 0 0       0 runtime(sprintf("/* %s */", $op->name)) if $verbose;
1982 0         0 my $right = pop_numeric();
1983 0 0       0 if ( @stack >= 1 ) {
1984 0         0 my $left = top_numeric();
1985 0 0       0 if ($force_int) {
1986 0         0 $stack[-1]->set_int( &$operator( $left, $right ) );
1987             }
1988             else {
1989 0         0 $stack[-1]->set_numeric( &$operator( $left, $right ) );
1990             }
1991             }
1992             else {
1993 0 0       0 if ($force_int) {
1994 0         0 my $rightruntime = B::Pseudoreg->new( "IV", "riv" );
1995 0         0 runtime( sprintf( "$$rightruntime = %s;", $right ) );
1996 0         0 runtime(
1997             sprintf(
1998             "sv_setiv(TOPs, %s);", &$operator( "TOPi", $$rightruntime )
1999             )
2000             );
2001             }
2002             else {
2003 0         0 my $rightruntime = B::Pseudoreg->new( "NV", "rnv" );
2004 0         0 runtime( sprintf( "$$rightruntime = %s;\t/* %s */", $right, $op->name ) );
2005 0         0 runtime(
2006             sprintf(
2007             "sv_setnv(TOPs, %s);", &$operator( "TOPn", $$rightruntime )
2008             )
2009             );
2010             }
2011             }
2012             }
2013             else {
2014 0         0 my $targ = $pad[ $op->targ ];
2015 0   0     0 $force_int ||= ( $targ->{type} == T_INT );
2016 0 0       0 if ($force_int) {
2017 0         0 my $right = B::Pseudoreg->new( "IV", "riv" );
2018 0         0 my $left = B::Pseudoreg->new( "IV", "liv" );
2019 0         0 runtime(
2020             sprintf( "$$right = %s;", pop_numeric()),
2021             sprintf( "$$left = %s;\t/* %s */", pop_numeric(), pop_numeric(), $op->name ) );
2022 0         0 $targ->set_int( &$operator( $$left, $$right ) );
2023             }
2024             else {
2025 0         0 my $right = B::Pseudoreg->new( "NV", "rnv" );
2026 0         0 my $left = B::Pseudoreg->new( "NV", "lnv" );
2027 0         0 runtime(
2028             sprintf( "$$right = %s;", pop_numeric()),
2029             sprintf( "$$left = %s;\t/* %s */", pop_numeric(), $op->name ) );
2030 0         0 $targ->set_numeric( &$operator( $$left, $$right ) );
2031             }
2032 0         0 push( @stack, $targ );
2033             }
2034 0         0 return $op->next;
2035             }
2036              
2037             sub numeric_unop {
2038 0     0 0 0 my ( $op, $operator, $flags ) = @_;
2039 0         0 my $force_int = 0;
2040 0   0     0 $force_int ||= ( $flags & INT_RESULT );
2041 0   0     0 $force_int ||=
      0        
2042             ( $flags & INTS_CLOSED
2043             && @stack >= 1
2044             && valid_int( $stack[-1] ) );
2045 0         0 my $targ = $pad[ $op->targ ];
2046 0   0     0 $force_int ||= ( $targ->{type} == T_INT );
2047 0 0       0 if ($force_int) {
2048 0         0 my $arg = B::Pseudoreg->new( "IV", "liv" );
2049 0         0 runtime(sprintf( "$$arg = %s;\t/* %s */",
2050             pop_numeric, $op->name ) );
2051             # XXX set targ?
2052 0         0 $targ->set_int( &$operator( $$arg ) );
2053             }
2054             else {
2055 0         0 my $arg = B::Pseudoreg->new( "NV", "lnv" );
2056 0         0 runtime(sprintf( "$$arg = %s;\t/* %s */",
2057             pop_numeric, $op->name ) );
2058             # XXX set targ?
2059 0         0 $targ->set_numeric( &$operator( $$arg ) );
2060             }
2061 0         0 push( @stack, $targ );
2062 0         0 return $op->next;
2063             }
2064              
2065             # coverage: 18
2066             sub pp_ncmp {
2067 0     0 0 0 my ($op) = @_;
2068 0 0       0 if ( $op->flags & OPf_STACKED ) {
2069 0         0 my $right = pop_numeric();
2070 0 0       0 if ( @stack >= 1 ) {
2071 0         0 my $left = top_numeric();
2072 0         0 runtime sprintf( "if (%s > %s){\t/* %s */", $left, $right, $op->name );
2073 0         0 $stack[-1]->set_int(1);
2074 0         0 $stack[-1]->write_back();
2075 0         0 runtime sprintf( "}else if (%s < %s ) {", $left, $right );
2076 0         0 $stack[-1]->set_int(-1);
2077 0         0 $stack[-1]->write_back();
2078 0         0 runtime sprintf( "}else if (%s == %s) {", $left, $right );
2079 0         0 $stack[-1]->set_int(0);
2080 0         0 $stack[-1]->write_back();
2081 0         0 runtime sprintf("}else {");
2082 0         0 $stack[-1]->set_sv("&PL_sv_undef");
2083 0         0 runtime "}";
2084             }
2085             else {
2086 0         0 my $rightruntime = B::Pseudoreg->new( "NV", "rnv" );
2087 0         0 runtime( sprintf( "$$rightruntime = %s;\t/* %s */", $right, $op->name ) );
2088 0         0 runtime sprintf( qq/if ("TOPn" > %s){/, $rightruntime );
2089 0         0 runtime sprintf(" sv_setiv(TOPs,1);");
2090 0         0 runtime sprintf( qq/}else if ( "TOPn" < %s ) {/, $$rightruntime );
2091 0         0 runtime sprintf(" sv_setiv(TOPs,-1);");
2092 0         0 runtime sprintf( qq/} else if ("TOPn" == %s) {/, $$rightruntime );
2093 0         0 runtime sprintf(" sv_setiv(TOPs,0);");
2094 0         0 runtime sprintf(qq/}else {/);
2095 0         0 runtime sprintf(" sv_setiv(TOPs,&PL_sv_undef;");
2096 0         0 runtime "}";
2097             }
2098             }
2099             else {
2100 0         0 my $targ = $pad[ $op->targ ];
2101 0         0 my $right = B::Pseudoreg->new( "NV", "rnv" );
2102 0         0 my $left = B::Pseudoreg->new( "NV", "lnv" );
2103 0         0 runtime(
2104             sprintf( "$$right = %s; $$left = %s;\t/* %s */",
2105             pop_numeric(), pop_numeric, $op->name ) );
2106 0         0 runtime sprintf( "if (%s > %s){ /*targ*/", $$left, $$right );
2107 0         0 $targ->set_int(1);
2108 0         0 $targ->write_back();
2109 0         0 runtime sprintf( "}else if (%s < %s ) {", $$left, $$right );
2110 0         0 $targ->set_int(-1);
2111 0         0 $targ->write_back();
2112 0         0 runtime sprintf( "}else if (%s == %s) {", $$left, $$right );
2113 0         0 $targ->set_int(0);
2114 0         0 $targ->write_back();
2115 0         0 runtime sprintf("}else {");
2116 0         0 $targ->set_sv("&PL_sv_undef");
2117 0         0 runtime "}";
2118 0         0 push( @stack, $targ );
2119             }
2120             #runtime "return NULL;";
2121 0         0 return $op->next;
2122             }
2123              
2124             # coverage: ?
2125             sub sv_binop {
2126 0     0 0 0 my ( $op, $operator, $flags ) = @_;
2127 0 0       0 if ( $op->flags & OPf_STACKED ) {
2128 0         0 my $right = pop_sv();
2129 0 0       0 if ( @stack >= 1 ) {
2130 0         0 my $left = top_sv();
2131 0 0       0 if ( $flags & INT_RESULT ) {
    0          
2132 0         0 $stack[-1]->set_int( &$operator( $left, $right ) );
2133             }
2134             elsif ( $flags & NUMERIC_RESULT ) {
2135 0         0 $stack[-1]->set_numeric( &$operator( $left, $right ) );
2136             }
2137             else {
2138             # XXX Does this work?
2139 0         0 runtime(
2140             sprintf( "sv_setsv($left, %s);\t/* %s */",
2141             &$operator( $left, $right ), $op->name ) );
2142 0         0 $stack[-1]->invalidate;
2143             }
2144             }
2145             else {
2146 0         0 my $f;
2147 0 0       0 if ( $flags & INT_RESULT ) {
    0          
2148 0         0 $f = "sv_setiv";
2149             }
2150             elsif ( $flags & NUMERIC_RESULT ) {
2151 0         0 $f = "sv_setnv";
2152             }
2153             else {
2154 0         0 $f = "sv_setsv";
2155             }
2156 0         0 runtime( sprintf( "%s(TOPs, %s);\t/* %s */",
2157             $f, &$operator( "TOPs", $right ), $op->name ) );
2158             }
2159             }
2160             else {
2161 0         0 my $targ = $pad[ $op->targ ];
2162 0         0 runtime( sprintf( "right = %s; left = %s;\t/* %s */",
2163             pop_sv(), pop_sv, $op->name ) );
2164 0 0       0 if ( $flags & INT_RESULT ) {
    0          
2165 0         0 $targ->set_int( &$operator( "left", "right" ) );
2166             }
2167             elsif ( $flags & NUMERIC_RESULT ) {
2168 0         0 $targ->set_numeric( &$operator( "left", "right" ) );
2169             }
2170             else {
2171             # XXX Does this work?
2172 0         0 runtime(sprintf("sv_setsv(%s, %s);",
2173             $targ->as_sv, &$operator( "left", "right" ) ));
2174 0         0 $targ->invalidate;
2175             }
2176 0         0 push( @stack, $targ );
2177             }
2178 0         0 return $op->next;
2179             }
2180              
2181             # coverage: ?
2182             sub bool_int_binop {
2183 0     0 0 0 my ( $op, $operator ) = @_;
2184 0         0 my $right = B::Pseudoreg->new( "IV", "riv" );
2185 0         0 my $left = B::Pseudoreg->new( "IV", "liv" );
2186 0         0 runtime( sprintf( "$$right = %s; $$left = %s;\t/* %s */",
2187             pop_int(), pop_int(), $op->name ) );
2188 0         0 my $bool = B::Stackobj::Bool->new( B::Pseudoreg->new( "int", "b" ) );
2189 0         0 $bool->set_int( &$operator( $$left, $$right ) );
2190 0         0 push( @stack, $bool );
2191 0         0 return $op->next;
2192             }
2193              
2194             # coverage: ?
2195             sub bool_numeric_binop {
2196 0     0 0 0 my ( $op, $operator ) = @_;
2197 0         0 my $right = B::Pseudoreg->new( "NV", "rnv" );
2198 0         0 my $left = B::Pseudoreg->new( "NV", "lnv" );
2199 0         0 runtime(
2200             sprintf( "$$right = %s; $$left = %s;\t/* %s */",
2201             pop_numeric(), pop_numeric(), $op->name ) );
2202 0         0 my $bool = B::Stackobj::Bool->new( B::Pseudoreg->new( "int", "b" ) );
2203 0         0 $bool->set_numeric( &$operator( $$left, $$right ) );
2204 0         0 push( @stack, $bool );
2205 0         0 return $op->next;
2206             }
2207              
2208             # coverage: ?
2209             sub bool_sv_binop {
2210 0     0 0 0 my ( $op, $operator ) = @_;
2211 0         0 runtime( sprintf( "right = %s; left = %s;\t/* %s */",
2212             pop_sv(), pop_sv(), $op->name ) );
2213 0         0 my $bool = B::Stackobj::Bool->new( B::Pseudoreg->new( "int", "b" ) );
2214 0         0 $bool->set_numeric( &$operator( "left", "right" ) );
2215 0         0 push( @stack, $bool );
2216 0         0 return $op->next;
2217             }
2218              
2219             # coverage: ?
2220             sub infix_op {
2221 182     182 0 328 my $opname = shift;
2222 0     0   0 return sub { "$_[0] $opname $_[1]" }
2223 182         76865 }
2224              
2225             # coverage: ?
2226             sub prefix_op {
2227 42     42 0 88 my $opname = shift;
2228 0     0   0 return sub { sprintf( "%s(%s)", $opname, join( ", ", @_ ) ) }
2229 42         227 }
2230              
2231 0         0 BEGIN {
2232 14     14   142 my $plus_op = infix_op("+");
2233 14         68 my $minus_op = infix_op("-");
2234 14         57 my $multiply_op = infix_op("*");
2235 14         54 my $divide_op = infix_op("/");
2236 14         52 my $modulo_op = infix_op("%");
2237 14         52 my $lshift_op = infix_op("<<");
2238 14         53 my $rshift_op = infix_op(">>");
2239 14         54 my $scmp_op = prefix_op("sv_cmp");
2240 14         54 my $seq_op = prefix_op("sv_eq");
2241 14         57 my $sne_op = prefix_op("!sv_eq");
2242 14         56 my $slt_op = sub { "sv_cmp($_[0], $_[1]) < 0" };
  0         0  
2243 14         53 my $sgt_op = sub { "sv_cmp($_[0], $_[1]) > 0" };
  0         0  
2244 14         55 my $sle_op = sub { "sv_cmp($_[0], $_[1]) <= 0" };
  0         0  
2245 14         62 my $sge_op = sub { "sv_cmp($_[0], $_[1]) >= 0" };
  0         0  
2246 14         54 my $eq_op = infix_op("==");
2247 14         45 my $ne_op = infix_op("!=");
2248 14         45 my $lt_op = infix_op("<");
2249 14         48 my $gt_op = infix_op(">");
2250 14         56 my $le_op = infix_op("<=");
2251 14         48 my $ge_op = infix_op(">=");
2252              
2253             #
2254             # XXX The standard perl PP code has extra handling for
2255             # some special case arguments of these operators.
2256             #
2257 0     0 0 0 sub pp_add { numeric_binop( $_[0], $plus_op ) }
2258 0     0 0 0 sub pp_subtract { numeric_binop( $_[0], $minus_op ) }
2259 0     0 0 0 sub pp_multiply { numeric_binop( $_[0], $multiply_op ) }
2260 0     0 0 0 sub pp_divide { numeric_binop( $_[0], $divide_op ) }
2261              
2262 0     0 0 0 sub pp_modulo { int_binop( $_[0], $modulo_op ) } # differs from perl's
2263             # http://perldoc.perl.org/perlop.html#Shift-Operators:
2264             # If use integer is in force then signed C integers are used,
2265             # else unsigned C integers are used.
2266 0     0 0 0 sub pp_left_shift { int_binop( $_[0], $lshift_op, VALID_UNSIGNED ) }
2267 0     0 0 0 sub pp_right_shift { int_binop( $_[0], $rshift_op, VALID_UNSIGNED ) }
2268 0     0 0 0 sub pp_i_add { int_binop( $_[0], $plus_op ) }
2269 0     0 0 0 sub pp_i_subtract { int_binop( $_[0], $minus_op ) }
2270 0     0 0 0 sub pp_i_multiply { int_binop( $_[0], $multiply_op ) }
2271 0     0 0 0 sub pp_i_divide { int_binop( $_[0], $divide_op ) }
2272 0     0 0 0 sub pp_i_modulo { int_binop( $_[0], $modulo_op ) }
2273              
2274 0     0 0 0 sub pp_eq { bool_numeric_binop( $_[0], $eq_op ) }
2275 0     0 0 0 sub pp_ne { bool_numeric_binop( $_[0], $ne_op ) }
2276             # coverage: 21
2277 0     0 0 0 sub pp_lt { bool_numeric_binop( $_[0], $lt_op ) }
2278             # coverage: 28
2279 0     0 0 0 sub pp_gt { bool_numeric_binop( $_[0], $gt_op ) }
2280 0     0 0 0 sub pp_le { bool_numeric_binop( $_[0], $le_op ) }
2281 0     0 0 0 sub pp_ge { bool_numeric_binop( $_[0], $ge_op ) }
2282              
2283 0     0 0 0 sub pp_i_eq { bool_int_binop( $_[0], $eq_op ) }
2284 0     0 0 0 sub pp_i_ne { bool_int_binop( $_[0], $ne_op ) }
2285 0     0 0 0 sub pp_i_lt { bool_int_binop( $_[0], $lt_op ) }
2286 0     0 0 0 sub pp_i_gt { bool_int_binop( $_[0], $gt_op ) }
2287 0     0 0 0 sub pp_i_le { bool_int_binop( $_[0], $le_op ) }
2288 0     0 0 0 sub pp_i_ge { bool_int_binop( $_[0], $ge_op ) }
2289              
2290 0     0 0 0 sub pp_scmp { sv_binop( $_[0], $scmp_op, INT_RESULT ) }
2291 0     0 0 0 sub pp_slt { bool_sv_binop( $_[0], $slt_op ) }
2292 0     0 0 0 sub pp_sgt { bool_sv_binop( $_[0], $sgt_op ) }
2293 0     0 0 0 sub pp_sle { bool_sv_binop( $_[0], $sle_op ) }
2294 0     0 0 0 sub pp_sge { bool_sv_binop( $_[0], $sge_op ) }
2295 0     0 0 0 sub pp_seq { bool_sv_binop( $_[0], $seq_op ) }
2296 0     0 0 0 sub pp_sne { bool_sv_binop( $_[0], $sne_op ) }
2297              
2298             # sub pp_sin { numeric_unop( $_[0], prefix_op("Perl_sin"), NUMERIC_RESULT ) }
2299             # sub pp_cos { numeric_unop( $_[0], prefix_op("Perl_cos"), NUMERIC_RESULT ) }
2300             # sub pp_exp { numeric_unop( $_[0], prefix_op("Perl_exp"), NUMERIC_RESULT ) }
2301             # sub pp_abs { numeric_unop( $_[0], prefix_op("abs") ) }
2302             # sub pp_negate { numeric_unop( $_[0], sub { "- $_[0]" }; ) }
2303              
2304             # pow has special perl logic
2305             ## sub pp_pow { numeric_binop( $_[0], prefix_op("Perl_pow"), NUMERIC_RESULT ) }
2306             #XXX log and sqrt need to check negative args
2307             # sub pp_sqrt { numeric_unop( $_[0], prefix_op("Perl_sqrt"), NUMERIC_RESULT ) }
2308             # sub pp_log { numeric_unop( $_[0], prefix_op("Perl_log"), NUMERIC_RESULT ) }
2309             # sub pp_atan2 { numeric_binop( $_[0], prefix_op("Perl_atan2"), NUMERIC_RESULT ) }
2310              
2311             }
2312              
2313             # coverage: 3,4,9,10,11,12,17,18,20,21,23
2314             sub pp_sassign {
2315 0     0 0 0 my $op = shift;
2316 0         0 my $backwards = $op->private & OPpASSIGN_BACKWARDS;
2317 0 0       0 debug( sprintf( "sassign->private=0x%x\n", $op->private ) ) if $debug{op};
2318 0         0 my ( $dst, $src );
2319 0 0       0 runtime("/* pp_sassign */") if $verbose;
2320 0 0       0 if ( @stack >= 2 ) {
    0          
2321 0         0 $dst = pop @stack;
2322 0         0 $src = pop @stack;
2323 0 0       0 ( $src, $dst ) = ( $dst, $src ) if $backwards;
2324 0         0 my $type = $src->{type};
2325 0 0       0 if ( $type == T_INT ) {
    0          
2326 0         0 $dst->set_int( $src->as_int, $src->{flags} & VALID_UNSIGNED );
2327             }
2328             elsif ( $type == T_NUM ) {
2329 0         0 $dst->set_numeric( $src->as_numeric );
2330             }
2331             else {
2332 0         0 $dst->set_sv( $src->as_sv );
2333             }
2334 0         0 push( @stack, $dst );
2335             }
2336             elsif ( @stack == 1 ) {
2337 0 0       0 if ($backwards) {
2338 0         0 my $src = pop @stack;
2339 0         0 my $type = $src->{type};
2340 0 0       0 runtime("if (PL_tainting && PL_tainted) TAINT_NOT;") if $opt_taint;
2341 0 0       0 if ( $type == T_INT ) {
    0          
2342 0 0       0 if ( $src->{flags} & VALID_UNSIGNED ) {
2343 0         0 runtime sprintf( "sv_setuv(TOPs, %s);", $src->as_int );
2344             }
2345             else {
2346 0         0 runtime sprintf( "sv_setiv(TOPs, %s);", $src->as_int );
2347             }
2348             }
2349             elsif ( $type == T_NUM ) {
2350 0         0 runtime sprintf( "sv_setnv(TOPs, %s);", $src->as_double );
2351             }
2352             else {
2353 0         0 runtime sprintf( "sv_setsv(TOPs, %s);", $src->as_sv );
2354             }
2355 0 0       0 runtime("SvSETMAGIC(TOPs);") if $opt_magic;
2356             }
2357             else {
2358 0         0 my $dst = $stack[-1];
2359 0         0 my $type = $dst->{type};
2360 0         0 runtime("sv = POPs;");
2361 0 0       0 runtime("MAYBE_TAINT_SASSIGN_SRC(sv);") if $opt_taint;
2362 0 0       0 if ( $type == T_INT ) {
    0          
2363 0         0 $dst->set_int("SvIV(sv)");
2364             }
2365             elsif ( $type == T_NUM ) {
2366 0         0 $dst->set_double("SvNV(sv)");
2367             }
2368             else {
2369 0 0       0 $opt_magic
2370             ? runtime("SvSetMagicSV($dst->{sv}, sv);")
2371             : runtime("SvSetSV($dst->{sv}, sv);");
2372 0         0 $dst->invalidate;
2373             }
2374             }
2375             }
2376             else {
2377             # empty perl stack, both at run-time
2378 0 0       0 if ($backwards) {
2379 0         0 runtime("src = POPs; dst = TOPs;");
2380             }
2381             else {
2382 0         0 runtime("dst = POPs; src = TOPs;");
2383             }
2384 0 0       0 runtime(
    0          
2385             $opt_taint ? "MAYBE_TAINT_SASSIGN_SRC(src);" : "",
2386             "SvSetSV(dst, src);",
2387             $opt_magic ? "SvSETMAGIC(dst);" : "",
2388             "SETs(dst);"
2389             );
2390             }
2391 0         0 return $op->next;
2392             }
2393              
2394             # coverage: ny
2395             sub pp_preinc {
2396 0     0 0 0 my $op = shift;
2397 0 0       0 if ( @stack >= 1 ) {
2398 0         0 my $obj = $stack[-1];
2399 0         0 my $type = $obj->{type};
2400 0 0 0     0 if ( $type == T_INT || $type == T_NUM ) {
2401 0         0 $obj->set_int( $obj->as_int . " + 1" );
2402             }
2403             else {
2404 0         0 runtime sprintf( "PP_PREINC(%s);", $obj->as_sv );
2405 0         0 $obj->invalidate();
2406             }
2407             }
2408             else {
2409 0         0 runtime sprintf("PP_PREINC(TOPs);");
2410             }
2411 0         0 return $op->next;
2412             }
2413              
2414             # coverage: 1-32,35
2415             sub pp_pushmark {
2416 0     0 0 0 my $op = shift;
2417             # runtime(sprintf("/* %s */", $op->name)) if $verbose;
2418 0         0 write_back_stack();
2419 0         0 runtime("PUSHMARK(sp);");
2420 0         0 return $op->next;
2421             }
2422              
2423             # coverage: 28
2424             sub pp_list {
2425 0     0 0 0 my $op = shift;
2426 0 0       0 runtime(sprintf("/* %s */", $op->name)) if $verbose;
2427 0         0 write_back_stack();
2428 0         0 my $gimme = gimme($op);
2429 0 0       0 if ( not defined $gimme ) {
    0          
2430 0         0 runtime("PP_LIST(block_gimme());");
2431             } elsif ( $gimme == G_ARRAY ) { # sic
2432 0         0 runtime("POPMARK;"); # need this even though not a "full" pp_list
2433             }
2434             else {
2435 0         0 runtime("PP_LIST($gimme);");
2436             }
2437 0         0 return $op->next;
2438             }
2439              
2440             # coverage: 6,8,9,10,24,26,27,31,35
2441             sub pp_entersub {
2442 0     0 0 0 my $op = shift;
2443 0 0       0 runtime(sprintf("/* %s */", $op->name)) if $verbose;
2444 0 0       0 $curcop->write_back if $curcop;
2445 0         0 write_back_lexicals( REGISTER | TEMPORARY );
2446 0         0 write_back_stack();
2447 0         0 my $sym = doop($op);
2448 0 0       0 $op->next->save if ${$op->next};
  0         0  
2449 0 0 0     0 $op->first->save if ${$op->first} and $op->first->type;
  0         0  
2450             # sometimes needs an additional check
2451 0 0       0 my $ck_next = ${$op->next} ? "PL_op != ($sym)->op_next && " : "";
  0         0  
2452 0         0 runtime("while ($ck_next PL_op != (OP*)0 ){",
2453             "\tPL_op = (*PL_op->op_ppaddr)(aTHX);",
2454             "\tSPAGAIN;}");
2455 0         0 $know_op = 0;
2456 0         0 invalidate_lexicals( REGISTER | TEMPORARY );
2457             # B::C::check_entersub($op);
2458 0         0 return $op->next;
2459             }
2460              
2461             # coverage: 16,26,35,51,72,73
2462             sub pp_bless {
2463 0     0 0 0 my $op = shift;
2464 0 0       0 $curcop->write_back if $curcop;
2465             # B::C::check_bless($op);
2466 0         0 default_pp($op);
2467             }
2468              
2469              
2470             # coverage: ny
2471             sub pp_formline {
2472 0     0 0 0 my $op = shift;
2473 0         0 my $ppname = "pp_" . $op->name;
2474 0 0       0 runtime(sprintf("/* %s */", $ppname)) if $verbose;
2475 0 0       0 write_back_lexicals() unless $skip_lexicals{$ppname};
2476 0 0       0 write_back_stack() unless $skip_stack{$ppname};
2477 0         0 my $sym = doop($op);
2478              
2479             # See comment in pp_grepwhile to see why!
2480 0         0 $init->add("((LISTOP*)$sym)->op_first = $sym;");
2481 0         0 runtime("if (PL_op == ((LISTOP*)($sym))->op_first) {");
2482 0         0 save_or_restore_lexical_state( ${ $op->first } );
  0         0  
2483 0         0 runtime( sprintf( "goto %s;", label( $op->first ) ),
2484             "}");
2485 0         0 return $op->next;
2486             }
2487              
2488             # coverage: 2,17,21,28,30
2489             sub pp_goto {
2490 0     0 0 0 my $op = shift;
2491 0         0 my $ppname = "pp_" . $op->name;
2492 0 0       0 runtime(sprintf("/* %s */", $ppname)) if $verbose;
2493 0 0       0 write_back_lexicals() unless $skip_lexicals{$ppname};
2494 0 0       0 write_back_stack() unless $skip_stack{$ppname};
2495 0         0 my $sym = doop($op);
2496 0         0 runtime("if (PL_op != ($sym)->op_next && PL_op != (OP*)0){return PL_op;}");
2497 0 0       0 invalidate_lexicals() unless $skip_invalidate{$ppname};
2498 0         0 return $op->next;
2499             }
2500              
2501             # coverage: 1-39, c_argv.t 2
2502             sub pp_enter {
2503             # XXX fails with simple c_argv.t 2. no cxix. Disabled for now
2504 0     0 0 0 if (0 and $inline_ops) {
2505             my $op = shift;
2506             runtime(sprintf("/* %s */", $op->name)) if $verbose;
2507             warn "inlining enter\n" if $debug{op};
2508             $curcop->write_back if $curcop;
2509             if (!($op->flags & OPf_WANT)) {
2510             my $cxix = $#cxstack;
2511             if ( $cxix >= 0 ) {
2512             if ( $op->flags & OPf_SPECIAL ) {
2513             runtime "gimme = block_gimme();";
2514             } else {
2515             runtime "gimme = cxstack[cxstack_ix].blk_gimme;";
2516             }
2517             } else {
2518             runtime "gimme = G_SCALAR;";
2519             }
2520             } else {
2521             runtime "gimme = OP_GIMME(PL_op, -1);";
2522             }
2523             runtime($] >= 5.011001 and $] < 5.011004
2524             ? 'ENTER_with_name("block");' : 'ENTER;',
2525             "SAVETMPS;",
2526             "PUSHBLOCK(cx, CXt_BLOCK, SP);");
2527             return $op->next;
2528             } else {
2529 0         0 return default_pp(@_);
2530             }
2531             }
2532              
2533             # coverage: ny
2534 0     0 0 0 sub pp_enterwrite { pp_entersub(@_) }
2535              
2536             # coverage: 6,8,9,10,24,26,27,31
2537             sub pp_leavesub {
2538 0     0 0 0 my $op = shift;
2539 0         0 my $ppname = "pp_" . $op->name;
2540 0 0       0 write_back_lexicals() unless $skip_lexicals{$ppname};
2541 0 0       0 write_back_stack() unless $skip_stack{$ppname};
2542 0         0 runtime("if (PL_curstackinfo->si_type == PERLSI_SORT){",
2543             "\tPUTBACK;return 0;",
2544             "}");
2545 0         0 doop($op);
2546 0         0 return $op->next;
2547             }
2548              
2549             # coverage: ny
2550             sub pp_leavewrite {
2551 0     0 0 0 my $op = shift;
2552 0         0 write_back_lexicals( REGISTER | TEMPORARY );
2553 0         0 write_back_stack();
2554 0         0 my $sym = doop($op);
2555              
2556             # XXX Is this the right way to distinguish between it returning
2557             # CvSTART(cv) (via doform) and pop_return()?
2558             #runtime("if (PL_op) PL_op = (*PL_op->op_ppaddr)(aTHX);");
2559 0         0 runtime("SPAGAIN;");
2560 0         0 $know_op = 0;
2561 0         0 invalidate_lexicals( REGISTER | TEMPORARY );
2562 0         0 return $op->next;
2563             }
2564              
2565             # coverage: ny
2566 0     0 0 0 sub pp_entergiven { pp_enterwrite(@_) }
2567             # coverage: ny
2568 0     0 0 0 sub pp_leavegiven { pp_leavewrite(@_) }
2569              
2570             sub doeval {
2571 0     0 0 0 my $op = shift;
2572 0         0 $curcop->write_back;
2573 0         0 write_back_lexicals( REGISTER | TEMPORARY );
2574 0         0 write_back_stack();
2575 0         0 my $sym = loadop($op);
2576 0         0 my $ppaddr = $op->ppaddr;
2577 0         0 runtime("PP_EVAL($ppaddr, ($sym)->op_next);");
2578 0         0 $know_op = 1;
2579 0         0 invalidate_lexicals( REGISTER | TEMPORARY );
2580 0         0 return $op->next;
2581             }
2582              
2583             # coverage: 12
2584 0     0 0 0 sub pp_entereval { doeval(@_) }
2585             # coverage: ny
2586 0     0 0 0 sub pp_dofile { doeval(@_) }
2587              
2588             # coverage: 28
2589             #pp_require is protected by pp_entertry, so no protection for it.
2590             sub pp_require {
2591 0     0 0 0 my $op = shift;
2592 0         0 $curcop->write_back;
2593 0         0 write_back_lexicals( REGISTER | TEMPORARY );
2594 0         0 write_back_stack();
2595 0         0 my $sym = doop($op);
2596             # sometimes needs an additional check
2597 0 0       0 my $ck_next = ${$op->next} ? "PL_op != ($sym)->op_next && " : "";
  0         0  
2598 0         0 runtime("while ($ck_next PL_op != (OP*)0 ) {", #(test 28).
2599             " PL_op = (*PL_op->op_ppaddr)(aTHX);",
2600             " SPAGAIN;",
2601             "}");
2602 0         0 $know_op = 1;
2603 0         0 invalidate_lexicals( REGISTER | TEMPORARY );
2604             # B::C::check_require($op); # mark package
2605 0         0 return $op->next;
2606             }
2607              
2608             # coverage: 32
2609             sub pp_entertry {
2610 0     0 0 0 my $op = shift;
2611 0         0 $curcop->write_back;
2612 0         0 write_back_lexicals( REGISTER | TEMPORARY );
2613 0         0 write_back_stack();
2614 0         0 my $sym = doop($op);
2615 0         0 $entertry_defined = 1;
2616 0         0 my $next = $op->next; # broken in 5.12, fixed in B::C by upgrading BASEOP
2617             # jump past leavetry
2618 0 0       0 $next = $op->other->next if $op->can("other"); # before 5.11.4 and after 5.13.8
2619 0         0 my $l = label( $next );
2620 0         0 debug "ENTERTRY label=$l (".ref($op).") ->".$next->name."(".ref($next).")\n";
2621 0         0 runtime(sprintf( "PP_ENTERTRY(%s);", $l));
2622 0 0       0 if ($next->isa('B::COP')) {
2623 0         0 push_label($next, 'nextstate');
2624             } else {
2625 0 0       0 push_label($op->other, 'leavetry') if $op->can("other");
2626             }
2627 0         0 invalidate_lexicals( REGISTER | TEMPORARY );
2628 0         0 return $op->next;
2629             }
2630              
2631             # coverage: 32
2632             sub pp_leavetry {
2633 0     0 0 0 my $op = shift;
2634 0 0 0     0 pop_label 'leavetry' if $labels->{'leavetry'}->[-1] and $labels->{'leavetry'}->[-1] == $op;
2635 0         0 default_pp($op);
2636 0         0 runtime("PP_LEAVETRY;");
2637 0         0 write_label($op->next);
2638 0         0 return $op->next;
2639             }
2640              
2641             # coverage: ny
2642             sub pp_grepstart {
2643 0     0 0 0 my $op = shift;
2644 0 0 0     0 if ( $need_freetmps && $freetmps_each_loop ) {
2645 0         0 runtime("FREETMPS;"); # otherwise the grepwhile loop messes things up
2646 0         0 $need_freetmps = 0;
2647             }
2648 0         0 write_back_stack();
2649 0         0 my $sym = doop($op);
2650 0         0 my $next = $op->next;
2651 0         0 $next->save;
2652 0         0 my $nexttonext = $next->next;
2653 0         0 $nexttonext->save;
2654 0         0 save_or_restore_lexical_state($$nexttonext);
2655 0         0 runtime(
2656             sprintf( "if (PL_op == (($sym)->op_next)->op_next) goto %s;",
2657             label($nexttonext) )
2658             );
2659 0         0 return $op->next->other;
2660             }
2661              
2662             # coverage: ny
2663             sub pp_mapstart {
2664 0     0 0 0 my $op = shift;
2665 0 0 0     0 if ( $need_freetmps && $freetmps_each_loop ) {
2666 0         0 runtime("FREETMPS;"); # otherwise the mapwhile loop messes things up
2667 0         0 $need_freetmps = 0;
2668             }
2669 0         0 write_back_stack();
2670              
2671             # pp_mapstart can return either op_next->op_next or op_next->op_other and
2672             # we need to be able to distinguish the two at runtime.
2673 0         0 my $sym = doop($op);
2674 0         0 my $next = $op->next;
2675 0         0 $next->save;
2676 0         0 my $nexttonext = $next->next;
2677 0         0 $nexttonext->save;
2678 0         0 save_or_restore_lexical_state($$nexttonext);
2679 0         0 runtime(
2680             sprintf( "if (PL_op == (($sym)->op_next)->op_next) goto %s;",
2681             label($nexttonext) )
2682             );
2683 0         0 return $op->next->other;
2684             }
2685              
2686             # coverage: ny
2687             sub pp_grepwhile {
2688 0     0 0 0 my $op = shift;
2689 0         0 my $next = $op->next;
2690 0         0 unshift( @bblock_todo, $next );
2691 0         0 write_back_lexicals();
2692 0         0 write_back_stack();
2693 0         0 my $sym = doop($op);
2694              
2695             # pp_grepwhile can return either op_next or op_other and we need to
2696             # be able to distinguish the two at runtime. Since it's possible for
2697             # both ops to be "inlined", the fields could both be zero. To get
2698             # around that, we hack op_next to be our own op (purely because we
2699             # know it's a non-NULL pointer and can't be the same as op_other).
2700 0         0 $init->add("((LOGOP*)$sym)->op_next = $sym;");
2701 0         0 save_or_restore_lexical_state($$next);
2702 0         0 runtime( sprintf( "if (PL_op == ($sym)->op_next) goto %s;", label($next) ) );
2703 0         0 $know_op = 0;
2704 0         0 return $op->other;
2705             }
2706              
2707             # coverage: ny
2708 0     0 0 0 sub pp_mapwhile { pp_grepwhile(@_) }
2709              
2710             # coverage: 24
2711             sub pp_return {
2712 0     0 0 0 my $op = shift;
2713 0         0 write_back_lexicals( REGISTER | TEMPORARY );
2714 0         0 write_back_stack();
2715 0         0 doop($op);
2716 0         0 runtime( "PUTBACK;", "return PL_op;" );
2717 0         0 $know_op = 0;
2718 0         0 return $op->next;
2719             }
2720              
2721             sub nyi {
2722 0     0 0 0 my $op = shift;
2723 0         0 warn sprintf( "Warning: %s not yet implemented properly\n", $op->ppaddr );
2724 0         0 return default_pp($op);
2725             }
2726              
2727             # coverage: 17
2728             sub pp_range {
2729 0     0 0 0 my $op = shift;
2730 0         0 my $flags = $op->flags;
2731 0 0       0 if ( !( $flags & OPf_WANT ) ) {
2732 0 0       0 if ($strict) {
2733 0         0 error("context of range unknown at compile-time\n");
2734             } else {
2735 0         0 warn("Warning: context of range unknown at compile-time\n");
2736 0         0 runtime('warn("context of range unknown at compile-time");');
2737             }
2738 0         0 return default_pp($op);
2739             }
2740 0         0 write_back_lexicals();
2741 0         0 write_back_stack();
2742 0 0       0 unless ( ( $flags & OPf_WANT ) == OPf_WANT_LIST ) {
2743             # We need to save our UNOP structure since pp_flop uses
2744             # it to find and adjust out targ. We don't need it ourselves.
2745 0         0 $op->save;
2746 0         0 save_or_restore_lexical_state( ${ $op->other } );
  0         0  
2747 0         0 runtime sprintf( "if (SvTRUE(PL_curpad[%d])) goto %s;",
2748             $op->targ, label( $op->other ) );
2749 0         0 unshift( @bblock_todo, $op->other );
2750             }
2751 0         0 return $op->next;
2752             }
2753              
2754             # coverage: 17, 30
2755             sub pp_flip {
2756 0     0 0 0 my $op = shift;
2757 0         0 my $flags = $op->flags;
2758 0 0       0 if ( !( $flags & OPf_WANT ) ) {
2759 0 0       0 if ($strict) {
2760 0         0 error("context of flip unknown at compile-time\n");
2761             } else {
2762 0         0 warn("Warning: context of flip unknown at compile-time\n");
2763 0         0 runtime('warn("context of flip unknown at compile-time");');
2764             }
2765 0         0 return default_pp($op);
2766             }
2767 0 0       0 if ( ( $flags & OPf_WANT ) == OPf_WANT_LIST ) {
2768 0         0 return $op->first->other;
2769             }
2770 0         0 write_back_lexicals();
2771 0         0 write_back_stack();
2772             # We need to save our UNOP structure since pp_flop uses
2773             # it to find and adjust out targ. We don't need it ourselves.
2774 0         0 $op->save;
2775 0         0 my $ix = $op->targ;
2776 0         0 my $rangeix = $op->first->targ;
2777 0 0       0 runtime(
2778             ( $op->private & OPpFLIP_LINENUM )
2779             ? "if (PL_last_in_gv && SvIV(TOPs) == IoLINES(GvIOp(PL_last_in_gv))) {"
2780             : "if (SvTRUE(TOPs)) {"
2781             );
2782 0         0 runtime("\tsv_setiv(PL_curpad[$rangeix], 1);");
2783 0 0       0 if ( $op->flags & OPf_SPECIAL ) {
2784 0         0 runtime("sv_setiv(PL_curpad[$ix], 1);");
2785             }
2786             else {
2787 0         0 save_or_restore_lexical_state( ${ $op->first->other } );
  0         0  
2788 0         0 runtime( "\tsv_setiv(PL_curpad[$ix], 0);",
2789             "\tsp--;", sprintf( "\tgoto %s;", label( $op->first->other ) ) );
2790             }
2791 0         0 runtime( "}", qq{sv_setpv(PL_curpad[$ix], "");}, "SETs(PL_curpad[$ix]);" );
2792 0         0 $know_op = 0;
2793 0         0 return $op->next;
2794             }
2795              
2796             # coverage: 17
2797             sub pp_flop {
2798 0     0 0 0 my $op = shift;
2799 0         0 default_pp($op);
2800 0         0 $know_op = 0;
2801 0         0 return $op->next;
2802             }
2803              
2804             sub enterloop {
2805 0     0 0 0 my $op = shift;
2806 0         0 my $nextop = $op->nextop;
2807 0         0 my $lastop = $op->lastop;
2808 0         0 my $redoop = $op->redoop;
2809 0 0       0 $curcop->write_back if $curcop;
2810 0 0       0 debug "enterloop: pushing on cxstack\n" if $debug{cxstack};
2811 0 0       0 push(
2812             @cxstack,
2813             {
2814             type => $PERL512 ? CXt_LOOP_PLAIN : CXt_LOOP,
2815             op => $op,
2816             "label" => $curcop->[0]->label,
2817             nextop => $nextop,
2818             lastop => $lastop,
2819             redoop => $redoop
2820             }
2821             );
2822 0 0       0 debug sprintf("enterloop: cxstack label %s\n", $curcop->[0]->label) if $debug{cxstack};
2823 0         0 $nextop->save;
2824 0         0 $lastop->save;
2825 0         0 $redoop->save;
2826             # We need to compile the corresponding pp_leaveloop even if it's
2827             # never executed. This is needed to get @cxstack right.
2828             # Use case: while(1) { .. }
2829 0         0 unshift @bblock_todo, ($lastop);
2830 0         0 if (0 and $inline_ops and $op->name eq 'enterloop') {
2831             warn "inlining enterloop\n" if $debug{op};
2832             # XXX = GIMME_V fails on freebsd7 5.8.8 (28)
2833             # = block_gimme() fails on the rest, but passes on freebsd7
2834             runtime "gimme = GIMME_V;"; # XXX
2835             if ($PERL512) {
2836             runtime('ENTER_with_name("loop1");',
2837             'SAVETMPS;',
2838             'ENTER_with_name("loop2");',
2839             'PUSHBLOCK(cx, CXt_LOOP_PLAIN, SP);',
2840             'PUSHLOOP_PLAIN(cx, SP);');
2841             } else {
2842             runtime('ENTER;',
2843             'SAVETMPS;',
2844             'ENTER;',
2845             'PUSHBLOCK(cx, CXt_LOOP, SP);',
2846             'PUSHLOOP(cx, 0, SP);');
2847             }
2848             return $op->next;
2849             } else {
2850 0         0 return default_pp($op);
2851             }
2852             }
2853              
2854             # coverage: 6,21,28,30
2855 0     0 0 0 sub pp_enterloop { enterloop(@_) }
2856             # coverage: 2
2857 0     0 0 0 sub pp_enteriter { enterloop(@_) }
2858              
2859             # coverage: 6,21,28,30
2860             sub pp_leaveloop {
2861 0     0 0 0 my $op = shift;
2862 0 0       0 if ( !@cxstack ) {
2863 0         0 die "panic: leaveloop, no cxstack";
2864             }
2865 0 0       0 debug "leaveloop: popping from cxstack\n" if $debug{cxstack};
2866 0         0 pop(@cxstack);
2867 0         0 return default_pp($op);
2868             }
2869              
2870             # coverage: ?
2871             sub pp_next {
2872 0     0 0 0 my $op = shift;
2873 0         0 my $cxix;
2874 0 0       0 if ( $op->flags & OPf_SPECIAL ) {
2875 0         0 $cxix = dopoptoloop();
2876 0 0       0 if ( $cxix < 0 ) {
2877 0         0 warn "Warning: \"next\" used outside loop\n";
2878 0         0 return default_pp($op); # no optimization
2879             }
2880             }
2881             else {
2882 0         0 my $label = $op->pv;
2883 0 0       0 if ($label) {
2884 0         0 $cxix = dopoptolabel( $label );
2885 0 0       0 if ( $cxix < 0 ) {
2886             # coverage: t/testcc 21
2887 0         0 warn(sprintf("Warning: Label not found at compile time for \"next %s\"\n", $label ));
2888 0         0 $labels->{nlabel}->{$label} = $$op;
2889 0         0 return $op->next;
2890             }
2891             }
2892             # Add support to leave non-loop blocks.
2893 0 0       0 if ( CxTYPE_no_LOOP( $cxstack[$cxix] ) ) {
2894 0 0 0     0 if (!$cxstack[$cxix]->{'nextop'} or !$cxstack[$cxix]->{'label'}) {
2895 0         0 error("Use of \"next\" for non-loop and non-label blocks not yet implemented\n");
2896             }
2897             }
2898             }
2899 0         0 default_pp($op);
2900 0         0 my $nextop = $cxstack[$cxix]->{nextop};
2901 0 0       0 if ($nextop) {
2902 0         0 push( @bblock_todo, $nextop );
2903 0         0 save_or_restore_lexical_state($$nextop);
2904 0         0 runtime( sprintf( "goto %s;", label($nextop) ) );
2905             }
2906 0         0 return $op->next;
2907             }
2908              
2909             # coverage: ?
2910             sub pp_redo {
2911 0     0 0 0 my $op = shift;
2912 0         0 my $cxix;
2913 0 0       0 if ( $op->flags & OPf_SPECIAL ) {
2914 0         0 $cxix = dopoptoloop();
2915 0 0       0 if ( $cxix < 0 ) {
2916             #warn("Warning: \"redo\" used outside loop\n");
2917 0         0 return default_pp($op); # no optimization
2918             }
2919             }
2920             else {
2921 0         0 my $label = $op->pv;
2922 0 0       0 if ($label) {
2923 0         0 $cxix = dopoptolabel( $label );
2924 0 0       0 if ( $cxix < 0 ) {
2925 0         0 warn(sprintf("Warning: Label not found at compile time for \"redo %s\"\n", $label ));
2926 0         0 $labels->{nlabel}->{$label} = $$op;
2927 0         0 return $op->next;
2928             }
2929             }
2930             # Add support to leave non-loop blocks.
2931 0 0       0 if ( CxTYPE_no_LOOP( $cxstack[$cxix] ) ) {
2932 0 0 0     0 if (!$cxstack[$cxix]->{'redoop'} or !$cxstack[$cxix]->{'label'}) {
2933 0         0 error("Use of \"redo\" for non-loop and non-label blocks not yet implemented\n");
2934             }
2935             }
2936             }
2937 0         0 default_pp($op);
2938 0         0 my $redoop = $cxstack[$cxix]->{redoop};
2939 0 0       0 if ($redoop) {
2940 0         0 push( @bblock_todo, $redoop );
2941 0         0 save_or_restore_lexical_state($$redoop);
2942 0         0 runtime( sprintf( "goto %s;", label($redoop) ) );
2943             }
2944 0         0 return $op->next;
2945             }
2946              
2947             # coverage: issue36, cc_last.t
2948             sub pp_last {
2949 0     0 0 0 my $op = shift;
2950 0         0 my $cxix;
2951 0 0       0 if ( $op->flags & OPf_SPECIAL ) {
    0          
2952 0         0 $cxix = dopoptoloop();
2953 0 0       0 if ( $cxix < 0 ) {
2954             #warn("Warning: \"last\" used outside loop\n");
2955 0         0 return default_pp($op); # no optimization
2956             }
2957             }
2958             elsif (ref($op) eq 'B::PVOP') { # !OPf_STACKED
2959 0         0 my $label = $op->pv;
2960 0 0       0 if ($label) {
2961 0         0 $cxix = dopoptolabel( $label );
2962 0 0       0 if ( $cxix < 0 ) {
2963             # coverage: cc_last.t 2 (ok) 4 (ok)
2964 0         0 warn( sprintf("Warning: Label not found at compile time for \"last %s\"\n", $label ));
2965             # last does not jump into the future, by name without $$op
2966             # instead it should jump to the block afterwards
2967 0         0 $labels->{nlabel}->{$label} = $$op;
2968 0         0 return $op->next;
2969             }
2970             }
2971             # Add support to leave non-loop blocks. label fixed with 1.11
2972 0 0       0 if ( CxTYPE_no_LOOP( $cxstack[$cxix] ) ) {
2973 0 0 0     0 if (!$cxstack[$cxix]->{'lastop'} or !$cxstack[$cxix]->{'label'}) {
2974 0         0 error("Use of \"last\" for non-loop and non-label blocks not yet implemented\n");
2975             }
2976             }
2977             }
2978 0         0 default_pp($op);
2979 0 0 0     0 if ($cxstack[$cxix]->{lastop} and $cxstack[$cxix]->{lastop}->next) {
2980 0         0 my $lastop = $cxstack[$cxix]->{lastop}->next;
2981 0         0 push( @bblock_todo, $lastop );
2982 0         0 save_or_restore_lexical_state($$lastop);
2983 0         0 runtime( sprintf( "goto %s;", label($lastop) ) );
2984             }
2985 0         0 return $op->next;
2986             }
2987              
2988             # coverage: 3,4
2989             sub pp_subst {
2990 0     0 0 0 my $op = shift;
2991 0         0 write_back_lexicals();
2992 0         0 write_back_stack();
2993 0         0 my $sym = doop($op);
2994 0         0 my $replroot = $op->pmreplroot;
2995 0 0       0 if ($$replroot) {
2996 0         0 save_or_restore_lexical_state($$replroot);
2997 0 0       0 runtime sprintf(
2998             "if (PL_op == ((PMOP*)(%s))%s) goto %s;",
2999             $sym, $PERL510 ? "->op_pmreplrootu.op_pmreplroot" : "->op_pmreplroot",
3000             label($replroot)
3001             );
3002 0         0 $op->pmreplstart->save;
3003 0         0 push( @bblock_todo, $replroot );
3004             }
3005 0         0 invalidate_lexicals();
3006 0         0 return $op->next;
3007             }
3008              
3009             # coverage: 3
3010             sub pp_substcont {
3011 0     0 0 0 my $op = shift;
3012 0         0 write_back_lexicals();
3013 0         0 write_back_stack();
3014 0         0 doop($op);
3015 0         0 my $pmop = $op->other;
3016             #warn sprintf( "substcont: op = %s, pmop = %s\n", peekop($op), peekop($pmop) ) if $verbose;
3017              
3018             # my $pmopsym = objsym($pmop);
3019 0         0 my $pmopsym = $pmop->save; # XXX can this recurse?
3020             # warn "pmopsym = $pmopsym\n" if $verbose;
3021 0         0 save_or_restore_lexical_state( ${ $pmop->pmreplstart } );
  0         0  
3022 0 0       0 runtime sprintf(
3023             "if (PL_op == ((PMOP*)(%s))%s) goto %s;",
3024             $pmopsym,
3025             $PERL510 ? "->op_pmstashstartu.op_pmreplstart" : "->op_pmreplstart",
3026             label( $pmop->pmreplstart )
3027             );
3028 0         0 push( @bblock_todo, $pmop->pmreplstart );
3029 0         0 invalidate_lexicals();
3030 0         0 return $pmop->next;
3031             }
3032              
3033             # coverage: issue24
3034             # resolve the DBM library at compile-time, not at run-time
3035             sub pp_dbmopen {
3036 0     0 0 0 my $op = shift;
3037 0         0 require AnyDBM_File;
3038 0         0 my $dbm = $AnyDBM_File::ISA[0];
3039 0         0 svref_2object( \&{"$dbm\::bootstrap"} )->save;
  0         0  
3040 0         0 return default_pp($op);
3041             }
3042              
3043             sub default_pp {
3044 0     0 0 0 my $op = shift;
3045 0         0 my $ppname = "pp_" . $op->name;
3046             # runtime(sprintf("/* %s */", $ppname)) if $verbose;
3047 0 0 0     0 if ( $curcop and $need_curcop{$ppname} ) {
3048 0         0 $curcop->write_back;
3049             }
3050 0 0       0 write_back_lexicals() unless $skip_lexicals{$ppname};
3051 0 0       0 write_back_stack() unless $skip_stack{$ppname};
3052 0         0 doop($op);
3053              
3054             # XXX If the only way that ops can write to a TEMPORARY lexical is
3055             # when it's named in $op->targ then we could call
3056             # invalidate_lexicals(TEMPORARY) and avoid having to write back all
3057             # the temporaries. For now, we'll play it safe and write back the lot.
3058 0 0       0 invalidate_lexicals() unless $skip_invalidate{$ppname};
3059 0         0 return $op->next;
3060             }
3061              
3062             sub compile_op {
3063 0     0 0 0 my $op = shift;
3064 0         0 my $ppname = "pp_" . $op->name;
3065 0 0       0 if ( exists $ignore_op{$ppname} ) {
3066 0         0 return $op->next;
3067             }
3068 0 0       0 debug peek_stack() if $debug{stack};
3069 0 0       0 if ( $debug{op} ) {
3070 0 0       0 debug sprintf( "%s [%s]\n",
3071             peekop($op), $op->flags & OPf_STACKED ? "OPf_STACKED" : $op->targ );
3072             }
3073 14     14   230 no strict 'refs';
  14         39  
  14         45096  
3074 0 0       0 if ( defined(&$ppname) ) {
3075 0         0 $know_op = 0;
3076 0         0 return &$ppname($op);
3077             }
3078             else {
3079 0         0 return default_pp($op);
3080             }
3081             }
3082              
3083             sub compile_bblock {
3084 0     0 0 0 my $op = shift;
3085 0 0       0 warn "compile_bblock: ", peekop($op), "\n" if $debug{bblock};
3086 0         0 save_or_restore_lexical_state($$op);
3087 0         0 write_label($op);
3088 0         0 $know_op = 0;
3089             do {
3090 0         0 $op = compile_op($op);
3091 0 0 0     0 if ($] < 5.013 and ($opt_slow_signals or ($$op and $async_signals{$op->name}))) {
      0        
3092 0         0 runtime("PERL_ASYNC_CHECK();");
3093             }
3094 0   0     0 } while ( defined($op) && $$op && !exists( $leaders->{$$op} ) );
      0        
3095 0         0 write_back_stack(); # boo hoo: big loss
3096 0         0 reload_lexicals();
3097 0         0 return $op;
3098             }
3099              
3100             sub cc {
3101 0     0 0 0 my ( $name, $root, $start, @padlist ) = @_;
3102 0         0 my $op;
3103 0 0       0 if ( $done{$$start} ) {
3104 0 0       0 warn "repeat=>" . ref($start) . " $name,\n" if $verbose;
3105 0         0 $decl->add( sprintf( "#define $name %s", $done{$$start} ) );
3106 0         0 return;
3107             }
3108 0 0 0     0 return if ref($padlist[0]) !~ /^B::(AV|PADNAMELIST)$/ or ref($padlist[1]) ne 'B::AV';
3109 0 0       0 warn "cc $name\n" if $verbose;
3110 0         0 init_pp($name);
3111 0         0 load_pad(@padlist);
3112 0         0 %lexstate = ();
3113 0         0 B::Pseudoreg->new_scope;
3114 0         0 @cxstack = ();
3115 0 0       0 if ( $debug{timings} ) {
3116 0         0 warn sprintf( "Basic block analysis at %s\n", timing_info );
3117             }
3118 0         0 $leaders = find_leaders( $root, $start );
3119 0         0 my @leaders = keys %$leaders;
3120 0 0       0 if ( $#leaders > -1 ) {
3121             # Don't add basic blocks of dead code.
3122             # It would produce errors when processing $cxstack.
3123             # @bblock_todo = ( values %$leaders );
3124             # Instead, save $root (pp_leavesub) separately,
3125             # because it will not get compiled if located in dead code.
3126 0         0 $root->save;
3127 0 0       0 unshift @bblock_todo, ($start) if $$start;
3128             }
3129             else {
3130 0         0 runtime("return PL_op?PL_op->op_next:0;");
3131             }
3132 0 0       0 if ( $debug{timings} ) {
3133 0         0 warn sprintf( "Compilation at %s\n", timing_info );
3134             }
3135 0         0 while (@bblock_todo) {
3136 0         0 $op = shift @bblock_todo;
3137 0 0       0 warn sprintf( "Considering basic block %s\n", peekop($op) ) if $debug{bblock};
3138 0 0 0     0 next if !defined($op) || !$$op || $done{$$op};
      0        
3139 0 0       0 warn "...compiling it\n" if $debug{bblock};
3140             do {
3141 0         0 $done{$$op} = $name;
3142 0         0 $op = compile_bblock($op);
3143 0 0 0     0 if ( $need_freetmps && $freetmps_each_bblock ) {
3144 0         0 runtime("FREETMPS;");
3145 0         0 $need_freetmps = 0;
3146             }
3147 0   0     0 } while defined($op) && $$op && !$done{$$op};
      0        
3148 0 0 0     0 if ( $need_freetmps && $freetmps_each_loop ) {
3149 0         0 runtime("FREETMPS;");
3150 0         0 $need_freetmps = 0;
3151             }
3152 0 0       0 if ( !$$op ) {
    0          
3153 0         0 runtime( "PUTBACK;",
3154             "return NULL;" );
3155             }
3156             elsif ( $done{$$op} ) {
3157 0         0 save_or_restore_lexical_state($$op);
3158 0         0 runtime( sprintf( "goto %s;", label($op) ) );
3159             }
3160             }
3161 0 0       0 if ( $debug{timings} ) {
3162 0         0 warn sprintf( "Saving runtime at %s\n", timing_info );
3163             }
3164 0         0 declare_pad(@padlist);
3165 0         0 save_runtime();
3166             }
3167              
3168             sub cc_recurse {
3169 0     0 0 0 my ($ccinfo);
3170 0 0       0 my $start = cc_queue(@_) if @_;
3171              
3172 0         0 while ( $ccinfo = shift @cc_todo ) {
3173 0 0       0 if ($ccinfo->[0] eq 'pp_sub_warnings__register_categories') {
3174             # patch broken PADLIST
3175             #warn "cc $ccinfo->[0] patch broken PADLIST (inc-i340)\n" if $verbose;
3176             #debug "cc(ccinfo): @$ccinfo skipped (inc-i340)\n" if $debug{queue};
3177             #$ccinfo->[0] = 'NULL';
3178 0         0 my @empty = ();
3179             #$ccinfo->[3] = $ccinfo->[4] = svref_2object(\@empty);
3180             }
3181 0 0 0     0 if ($DB::deep and $ccinfo->[0] =~ /^pp_sub_(DB|Term__ReadLine)_/) {
    0          
3182 0 0       0 warn "cc $ccinfo->[0] skipped (debugging)\n" if $verbose;
3183 0 0       0 debug "cc(ccinfo): @$ccinfo skipped (debugging)\n" if $debug{queue};
3184             }
3185             elsif (exists $cc_pp_sub{$ccinfo->[0]}) { # skip duplicates
3186 0 0       0 warn "cc $ccinfo->[0] already defined\n" if $verbose;
3187 0 0       0 debug "cc(ccinfo): @$ccinfo already defined\n" if $debug{queue};
3188 0         0 while (exists $cc_pp_sub{$ccinfo->[0]}) {
3189 0 0       0 if ($ccinfo->[0] =~ /^(pp_(?:lex)?sub_.*_)(\d*)$/) {
3190 0         0 my $s = $2;
3191 0         0 $s++;
3192 0         0 $ccinfo->[0] = $1 . $s;
3193             } else {
3194 0         0 $ccinfo->[0] .= '_0';
3195             }
3196             }
3197 0 0       0 warn "cc renamed to $ccinfo->[0]\n" if $verbose;
3198 0         0 cc(@$ccinfo);
3199 0         0 $cc_pp_sub{$ccinfo->[0]}++;
3200             } else {
3201 0 0       0 debug "cc(ccinfo): @$ccinfo\n" if $debug{queue};
3202 0         0 cc(@$ccinfo);
3203 0         0 $cc_pp_sub{$ccinfo->[0]}++;
3204             }
3205             }
3206 0         0 return $start;
3207             }
3208              
3209             sub cc_obj {
3210 0     0 0 0 my ( $name, $cvref ) = @_;
3211 0         0 my $cv = svref_2object($cvref);
3212 0         0 my @padlist = $cv->PADLIST->ARRAY;
3213 0         0 my $curpad_sym = $padlist[1]->save;
3214 0         0 set_curcv $cv;
3215 0         0 cc_recurse( $name, $cv->ROOT, $cv->START, @padlist );
3216             }
3217              
3218             sub cc_main {
3219 0     0 0 0 my @comppadlist = comppadlist->ARRAY;
3220 0         0 my $curpad_nam = $comppadlist[0]->save('curpad_name');
3221 0         0 my $curpad_sym = $comppadlist[1]->save('curpad_syms');;
3222 0         0 my $init_av = init_av->save('INIT');
3223 0         0 set_curcv B::main_cv;
3224 0         0 my $start = cc_recurse( "pp_main", main_root, main_start, @comppadlist );
3225              
3226             # Do save_unused_subs before saving inc_hv
3227 0 0       0 B::C::module($module) if $module;
3228 0         0 save_unused_subs();
3229              
3230 0         0 my $warner = $SIG{__WARN__};
3231 0         0 save_sig($warner);
3232              
3233 0         0 my($inc_hv, $inc_av, $end_av);
3234 0 0       0 if ( !defined($module) ) {
3235             # forbid run-time extends of curpad syms, names and INC
3236 0 0       0 warn "save context:\n" if $verbose;
3237 0         0 $init->add("/* save context */");
3238 0         0 $init->add('/* %INC */');
3239 0         0 inc_cleanup();
3240 0         0 my $inc_gv = svref_2object( \*main::INC );
3241 0         0 $inc_hv = $inc_gv->HV->save('main::INC');
3242 0         0 $init->add( sprintf( "GvHV(%s) = s\\_%x;",
3243             $inc_gv->save('main::INC'), $inc_gv->HV ) );
3244 0         0 local ($B::C::const_strings);
3245 0 0       0 $B::C::const_strings = 1 if $B::C::ro_inc;
3246 0         0 $inc_hv = $inc_gv->HV->save('main::INC');
3247 0         0 $inc_av = $inc_gv->AV->save('main::INC');
3248             }
3249             {
3250             # >=5.10 needs to defer nullifying of all vars in END, not only new ones.
3251 0         0 local ($B::C::const_strings);
  0         0  
3252 0         0 $B::C::in_endav = 1;
3253 0         0 $end_av = end_av->save('END');
3254             }
3255 0         0 cc_recurse();
3256 0 0 0     0 return if $errors or $check;
3257              
3258 0 0       0 if ( !defined($module) ) {
3259             # XXX TODO push BEGIN/END blocks to modules code.
3260             $init->add(
3261 0         0 sprintf( "PL_main_root = s\\_%x;", ${ main_root() } ),
  0         0  
3262             "PL_main_start = $start;",
3263             "PL_curpad = AvARRAY($curpad_sym);",
3264             "PL_comppad = $curpad_sym;");
3265 0 0       0 if ($] < 5.017005) {
3266 0         0 $init->add(
3267             "av_store((AV*)CvPADLIST(PL_main_cv), 0, SvREFCNT_inc($curpad_nam)); /* namepad */",
3268             "av_store((AV*)CvPADLIST(PL_main_cv), 1, SvREFCNT_inc($curpad_sym)); /* curpad */");
3269             } else {
3270 0         0 $init->add(
3271             "PadlistARRAY(CvPADLIST(PL_main_cv))[0] = (PAD*)SvREFCNT_inc($curpad_nam); /* namepad */",
3272             "PadlistARRAY(CvPADLIST(PL_main_cv))[1] = (PAD*)SvREFCNT_inc($curpad_sym); /* curpad */");
3273             }
3274 0         0 $init->add(
3275             "GvHV(PL_incgv) = $inc_hv;",
3276             "GvAV(PL_incgv) = $inc_av;",
3277             "PL_initav = (AV*)$init_av;",
3278             "PL_endav = (AV*)$end_av;");
3279 0 0       0 if ($] < 5.017) {
3280 0         0 my $amagic_generate = B::amagic_generation;
3281 0         0 $init->add("PL_amagic_generation = $amagic_generate;");
3282             };
3283             }
3284              
3285 0         0 seek( STDOUT, 0, 0 ); #prevent print statements from BEGIN{} into the output
3286 0         0 fixup_ppaddr();
3287 0         0 print "/* using B::CC $B::CC::VERSION backend */\n";
3288 0         0 output_boilerplate();
3289 0         0 print "\n";
3290 0         0 output_all("perl_init");
3291 0         0 output_runtime();
3292 0         0 print "\n";
3293 0         0 output_main_rest();
3294              
3295 0 0       0 if ( defined($module) ) {
3296 0   0     0 my $cmodule = $module ||= 'main';
3297 0         0 $cmodule =~ s/::/__/g;
3298 0         0 print <<"EOT";
3299              
3300             #include "XSUB.h"
3301             XS(boot_$cmodule)
3302             {
3303             dXSARGS;
3304             perl_init();
3305             ENTER;
3306             SAVETMPS;
3307             SAVEVPTR(PL_curpad);
3308             SAVEVPTR(PL_op);
3309             PL_curpad = AvARRAY($curpad_sym);
3310             PL_op = $start;
3311             pp_main(aTHX);
3312             FREETMPS;
3313             LEAVE;
3314             ST(0) = &PL_sv_yes;
3315             XSRETURN(1);
3316             }
3317             EOT
3318             } else {
3319 0         0 output_main();
3320             }
3321 0 0       0 if ( $debug{timings} ) {
3322 0         0 warn sprintf( "Done at %s\n", timing_info );
3323             }
3324             }
3325              
3326             sub compile_stats {
3327 0     0 0 0 my $s = "Total number of OPs processed: $op_count\n";
3328 0 0       0 $s .= "Total number of unresolved symbols: $B::C::unresolved_count\n"
3329             if $B::C::unresolved_count;
3330 0         0 return $s;
3331             }
3332              
3333             # Accessible via use B::CC '-ftype-attr'; in user code, or -MB::CC=-O2 on the cmdline
3334             sub import {
3335 15     15   87817 my @options = @_;
3336             # Allow debugging in CHECK blocks without Od
3337 15 50       79 $DB::single = 1 if defined &DB::DB;
3338 15         42 my ( $option, $opt, $arg );
3339             # init with -O0
3340 15         144 foreach my $ref ( values %optimise ) {
3341 165         280 $$ref = 0;
3342             }
3343 15 50       80 $B::C::fold = 0 if $] >= 5.013009; # utf8::Cased tables
3344 15 50       67 $B::C::warnings = 0 if $] >= 5.013005; # Carp warnings categories and B
3345 15 50       63 $B::C::destruct = 0 unless $] < 5.008; # fast_destruct
3346 15         38 $opt_taint = 1;
3347 15         33 $opt_magic = 1; # only makes sense with -fno-magic
3348 15         34 $opt_autovivify = 1; # only makes sense with -fno-autovivify
3349             OPTION:
3350 15         66 while ( $option = shift @options ) {
3351 15 50       78 if ( $option =~ /^-(.)(.*)/ ) {
3352 0         0 $opt = $1;
3353 0         0 $arg = $2;
3354             }
3355             else {
3356 15         54 unshift @options, $option;
3357 15         49 last OPTION;
3358             }
3359 0 0 0     0 if ( $opt eq "-" && $arg eq "-" ) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
3360 0         0 shift @options;
3361 0         0 last OPTION;
3362             }
3363             elsif ( $opt eq "o" ) {
3364 0   0     0 $arg ||= shift @options;
3365 0 0       0 open( STDOUT, ">$arg" ) or return "open '>$arg': $!\n";
3366             }
3367             elsif ( $opt eq "c" ) {
3368 0         0 $check = 1;
3369 0         0 $B::C::check = 1;
3370             }
3371             elsif ( $opt eq "v" ) {
3372 0         0 $verbose = 1;
3373 0         0 B::C::verbose(1); # crashed in C _save_common_middle(B::FAKEOP)
3374             }
3375             elsif ( $opt eq "u" ) {
3376 0   0     0 $arg ||= shift @options;
3377 0         0 eval "require $arg;";
3378 0         0 mark_unused( $arg, 1 );
3379             }
3380             elsif ( $opt eq "U" ) {
3381 0   0     0 $arg ||= shift @options;
3382 0         0 mark_skip( $arg );
3383             }
3384             elsif ( $opt eq "strict" ) {
3385 0   0     0 $arg ||= shift @options;
3386 0         0 $strict++;
3387             }
3388             elsif ( $opt eq "f" ) {
3389 0   0     0 $arg ||= shift @options;
3390 0         0 my $value = $arg !~ s/^no-//;
3391 0         0 $arg =~ s/-/_/g;
3392 0         0 my $ref = $optimise{$arg};
3393 0 0       0 if ( defined($ref) ) {
3394 0         0 $$ref = $value;
3395             }
3396             else {
3397             # Pass down to B::C
3398 0         0 my $ref = $B::C::option_map{$arg};
3399 0 0       0 if ( defined($ref) ) {
3400 0         0 $$ref = $value;
3401 0         0 $c_optimise{$ref}++;
3402             }
3403             else {
3404 0         0 warn qq(Warning: ignoring unknown optimisation "$arg"\n);
3405             }
3406             }
3407             }
3408             elsif ( $opt eq "O" ) {
3409 0 0       0 $arg = 1 if $arg eq "";
3410 0         0 foreach my $ref ( values %optimise ) {
3411 0         0 $$ref = 0;
3412             }
3413 0 0       0 if ($arg >= 2) {
3414 0         0 $freetmps_each_loop = 1;
3415 0 0       0 if (!$ITHREADS) {
3416             #warn qq(Warning: ignoring -faelem with threaded perl\n);
3417 0         0 $opt_aelem = 1; # unstable, test: 68 pp_padhv targ assert
3418             }
3419             }
3420 0 0       0 if ( $arg >= 1 ) {
3421 0         0 $opt_type_attr = 1;
3422 0 0       0 $freetmps_each_bblock = 1 unless $freetmps_each_loop;
3423             }
3424             }
3425             elsif ( $opt eq "n" ) {
3426 0   0     0 $arg ||= shift @options;
3427 0         0 $init_name = $arg;
3428             }
3429             elsif ( $opt eq "m" ) {
3430 0         0 $module = $arg;
3431 0         0 mark_unused( $arg, undef );
3432             }
3433             #elsif ( $opt eq "p" ) {
3434             # $arg ||= shift @options;
3435             # $patchlevel = $arg;
3436             #}
3437             elsif ( $opt eq "D" ) {
3438 0   0     0 $arg ||= shift @options;
3439 0         0 $verbose++;
3440             # note that we should not clash too much with the B::C debug map
3441             # because we set theirs also
3442 0         0 my %debug_map = (O => 'op',
3443             T => 'stack', # was S
3444             c => 'cxstack',
3445             a => 'pad', # was p
3446             r => 'runtime',
3447             w => 'shadow', # was s
3448             q => 'queue',
3449             l => 'lineno',
3450             t => 'timings',
3451             b => 'bblock');
3452 0 0       0 $arg = join('',keys %debug_map).'Fsp' if $arg eq 'full';
3453 0         0 foreach $arg ( split( //, $arg ) ) {
3454 0 0 0     0 if ( $arg eq "o" ) {
    0          
    0          
    0          
3455 0         0 B->debug(1);
3456             }
3457             elsif ( $debug_map{$arg} ) {
3458 0         0 $debug{ $debug_map{$arg} }++;
3459             }
3460             elsif ( $arg eq "F" and eval "require B::Flags;" ) {
3461 0         0 $debug{flags}++;
3462 0         0 $B::C::debug{flags}++;
3463             }
3464             elsif ( exists $B::C::debug_map{$arg} ) {
3465 0         0 $B::C::verbose++;
3466 0         0 $B::C::debug{ $B::C::debug_map{$arg} }++;
3467             }
3468             else {
3469 0         0 warn qq(Warning: ignoring unknown -D option "$arg"\n);
3470             }
3471             }
3472             }
3473             }
3474 15 50 66     162 $strict++ if !$strict and $Config{ccflags} !~ m/-DDEBUGGING/;
3475 15 50       62 if ($opt_omit_taint) {
3476 0         0 $opt_taint = 0;
3477 0         0 warn "Warning: -fomit_taint is deprecated. Use -fno-taint instead.\n";
3478             }
3479              
3480             # rgs didn't want opcodes to be added to Opcode. So I had to add it to a
3481             # seperate Opcodes package.
3482 15         39 eval { require Opcodes; };
  15         8608  
3483 15 50 33     39201 if (!$@ and $Opcodes::VERSION) {
3484 15         84 my $MAXO = Opcodes::opcodes();
3485 15         94 for (0..$MAXO-1) {
3486 14     14   161 no strict 'refs';
  14         49  
  14         2550  
3487 5940         2353980 my $ppname = "pp_".Opcodes::opname($_);
3488             # opflags n: no args, no return values. don't need save/restore stack
3489             # But pp_enter, pp_leave use/change global stack.
3490 5940 100 100     38513 next if $ppname eq 'pp_enter' || $ppname eq 'pp_leave';
3491 5910 100       11913 $no_stack{$ppname} = 1
3492             if Opcodes::opflags($_) & 512;
3493             # XXX More Opcodes options to be added later
3494             }
3495             }
3496             #if ($debug{op}) {
3497             # warn "no_stack: ",join(" ",sort keys %no_stack),"\n";
3498             #}
3499              
3500 15         692 mark_skip(qw(B::C B::C::Config B::CC B::Asmdata B::FAKEOP
3501             B::Pseudoreg B::Shadow B::C::InitSection
3502             O B::Stackobj B::Stackobj::Bool B::Stackobj::Padsv
3503             B::Stackobj::Const B::Stackobj::Aelem B::Bblock));
3504 15         235 $B::C::all_bc_deps{$_}++ for qw(Opcodes Opcode B::Concise attributes double int num str string subs);
3505 15 50       94 mark_skip(qw(DB Term::ReadLine)) if defined &DB::DB;
3506              
3507             # Set some B::C optimizations.
3508             # optimize_ppaddr is not needed with B::CC as CC does it even better.
3509 15         57 for (qw(optimize_warn_sv save_data_fh av_init save_sig destruct const_strings)) {
3510 14     14   267 no strict 'refs';
  14         58  
  14         9736  
3511 90 50       224 ${"B::C::$_"} = 1 unless $c_optimise{$_};
  90         371  
3512             }
3513 15 50 33     242 $B::C::destruct = 0 unless $c_optimise{destruct} and $] > 5.008;
3514 15 50       72 $B::C::stash = 0 unless $c_optimise{stash};
3515 15 50       81 if (!$B::C::Config::have_independent_comalloc) {
3516 15 50       76 $B::C::av_init = 1 unless $c_optimise{av_init};
3517 15 50       76 $B::C::av_init2 = 0 unless $c_optimise{av_init2};
3518             } else {
3519 0 0       0 $B::C::av_init = 0 unless $c_optimise{av_init};
3520 0 0       0 $B::C::av_init2 = 1 unless $c_optimise{av_init2};
3521             }
3522 15 50       67 init_type_attrs() if $opt_type_attr; # but too late for -MB::CC=-O2 on import. attrs are checked before
3523 15         19959 @options;
3524             }
3525              
3526             # -MO=CC entry point
3527             sub compile {
3528 0     0 0   my @options = @_;
3529 0           @options = import(@options);
3530              
3531 0           init_sections();
3532 0           $init = B::C::Section->get("init");
3533 0           $decl = B::C::Section->get("decl");
3534              
3535             # just some subs or main?
3536 0 0         if (@options) {
3537             return sub {
3538 0     0     my ( $objname, $ppname );
3539 0           foreach $objname (@options) {
3540 0 0         $objname = "main::$objname" unless $objname =~ /::/;
3541 0           ( $ppname = $objname ) =~ s/^.*?:://;
3542 0           eval "cc_obj(qq(pp_sub_$ppname), \\&$objname)";
3543 0 0         die "cc_obj(qq(pp_sub_$ppname, \\&$objname) failed: $@" if $@;
3544 0 0         return if $errors;
3545             }
3546 0           my $warner = $SIG{__WARN__};
3547 0           save_sig($warner);
3548 0           fixup_ppaddr();
3549 0 0         return if $check;
3550 0           output_boilerplate();
3551 0           print "\n";
3552 0   0       output_all( $init_name || "init_module" );
3553 0           output_runtime();
3554 0           output_main_rest();
3555             }
3556 0           }
3557             else {
3558 0     0     return sub { cc_main() };
  0            
3559             }
3560             }
3561              
3562             1;
3563              
3564             __END__