source: for-distributions/trunk/bin/windows/perl/lib/B/CC.pm@ 14489

Last change on this file since 14489 was 14489, checked in by oranfry, 17 years ago

upgrading to perl 5.8

File size: 55.0 KB
Line 
1# CC.pm
2#
3# Copyright (c) 1996, 1997, 1998 Malcolm Beattie
4#
5# You may distribute under the terms of either the GNU General Public
6# License or the Artistic License, as specified in the README file.
7#
8package B::CC;
9
10our $VERSION = '1.00_01';
11
12use Config;
13use strict;
14use B qw(main_start main_root class comppadlist peekop svref_2object
15 timing_info init_av sv_undef amagic_generation
16 OPf_WANT_LIST OPf_WANT OPf_MOD OPf_STACKED OPf_SPECIAL
17 OPpASSIGN_BACKWARDS OPpLVAL_INTRO OPpDEREF_AV OPpDEREF_HV
18 OPpDEREF OPpFLIP_LINENUM G_ARRAY G_SCALAR
19 CXt_NULL CXt_SUB CXt_EVAL CXt_LOOP CXt_SUBST CXt_BLOCK
20 );
21use B::C qw(save_unused_subs objsym init_sections mark_unused
22 output_all output_boilerplate output_main);
23use B::Bblock qw(find_leaders);
24use B::Stackobj qw(:types :flags);
25
26# These should probably be elsewhere
27# Flags for $op->flags
28
29my $module; # module name (when compiled with -m)
30my %done; # hash keyed by $$op of leaders of basic blocks
31 # which have already been done.
32my $leaders; # ref to hash of basic block leaders. Keys are $$op
33 # addresses, values are the $op objects themselves.
34my @bblock_todo; # list of leaders of basic blocks that need visiting
35 # sometime.
36my @cc_todo; # list of tuples defining what PP code needs to be
37 # saved (e.g. CV, main or PMOP repl code). Each tuple
38 # is [$name, $root, $start, @padlist]. PMOP repl code
39 # tuples inherit padlist.
40my @stack; # shadows perl's stack when contents are known.
41 # Values are objects derived from class B::Stackobj
42my @pad; # Lexicals in current pad as Stackobj-derived objects
43my @padlist; # Copy of current padlist so PMOP repl code can find it
44my @cxstack; # Shadows the (compile-time) cxstack for next,last,redo
45my $jmpbuf_ix = 0; # Next free index for dynamically allocated jmpbufs
46my %constobj; # OP_CONST constants as Stackobj-derived objects
47 # keyed by $$sv.
48my $need_freetmps = 0; # We may postpone FREETMPS to the end of each basic
49 # block or even to the end of each loop of blocks,
50 # depending on optimisation options.
51my $know_op = 0; # Set when C variable op already holds the right op
52 # (from an immediately preceding DOOP(ppname)).
53my $errors = 0; # Number of errors encountered
54my %skip_stack; # Hash of PP names which don't need write_back_stack
55my %skip_lexicals; # Hash of PP names which don't need write_back_lexicals
56my %skip_invalidate; # Hash of PP names which don't need invalidate_lexicals
57my %ignore_op; # Hash of ops which do nothing except returning op_next
58my %need_curcop; # Hash of ops which need PL_curcop
59
60my %lexstate; #state of padsvs at the start of a bblock
61
62BEGIN {
63 foreach (qw(pp_scalar pp_regcmaybe pp_lineseq pp_scope pp_null)) {
64 $ignore_op{$_} = 1;
65 }
66}
67
68my ($module_name);
69my ($debug_op, $debug_stack, $debug_cxstack, $debug_pad, $debug_runtime,
70 $debug_shadow, $debug_queue, $debug_lineno, $debug_timings);
71
72# Optimisation options. On the command line, use hyphens instead of
73# underscores for compatibility with gcc-style options. We use
74# underscores here because they are OK in (strict) barewords.
75my ($freetmps_each_bblock, $freetmps_each_loop, $omit_taint);
76my %optimise = (freetmps_each_bblock => \$freetmps_each_bblock,
77 freetmps_each_loop => \$freetmps_each_loop,
78 omit_taint => \$omit_taint);
79# perl patchlevel to generate code for (defaults to current patchlevel)
80my $patchlevel = int(0.5 + 1000 * ($] - 5));
81
82# Could rewrite push_runtime() and output_runtime() to use a
83# temporary file if memory is at a premium.
84my $ppname; # name of current fake PP function
85my $runtime_list_ref;
86my $declare_ref; # Hash ref keyed by C variable type of declarations.
87
88my @pp_list; # list of [$ppname, $runtime_list_ref, $declare_ref]
89 # tuples to be written out.
90
91my ($init, $decl);
92
93sub init_hash { map { $_ => 1 } @_ }
94
95#
96# Initialise the hashes for the default PP functions where we can avoid
97# either write_back_stack, write_back_lexicals or invalidate_lexicals.
98#
99%skip_lexicals = init_hash qw(pp_enter pp_enterloop);
100%skip_invalidate = init_hash qw(pp_enter pp_enterloop);
101%need_curcop = init_hash qw(pp_rv2gv pp_bless pp_repeat pp_sort pp_caller
102 pp_reset pp_rv2cv pp_entereval pp_require pp_dofile
103 pp_entertry pp_enterloop pp_enteriter pp_entersub
104 pp_enter pp_method);
105
106sub debug {
107 if ($debug_runtime) {
108 warn(@_);
109 } else {
110 my @tmp=@_;
111 runtime(map { chomp; "/* $_ */"} @tmp);
112 }
113}
114
115sub declare {
116 my ($type, $var) = @_;
117 push(@{$declare_ref->{$type}}, $var);
118}
119
120sub push_runtime {
121 push(@$runtime_list_ref, @_);
122 warn join("\n", @_) . "\n" if $debug_runtime;
123}
124
125sub save_runtime {
126 push(@pp_list, [$ppname, $runtime_list_ref, $declare_ref]);
127}
128
129sub output_runtime {
130 my $ppdata;
131 print qq(#include "cc_runtime.h"\n);
132 foreach $ppdata (@pp_list) {
133 my ($name, $runtime, $declare) = @$ppdata;
134 print "\nstatic\nCCPP($name)\n{\n";
135 my ($type, $varlist, $line);
136 while (($type, $varlist) = each %$declare) {
137 print "\t$type ", join(", ", @$varlist), ";\n";
138 }
139 foreach $line (@$runtime) {
140 print $line, "\n";
141 }
142 print "}\n";
143 }
144}
145
146sub runtime {
147 my $line;
148 foreach $line (@_) {
149 push_runtime("\t$line");
150 }
151}
152
153sub init_pp {
154 $ppname = shift;
155 $runtime_list_ref = [];
156 $declare_ref = {};
157 runtime("dSP;");
158 declare("I32", "oldsave");
159 declare("SV", "**svp");
160 map { declare("SV", "*$_") } qw(sv src dst left right);
161 declare("MAGIC", "*mg");
162 $decl->add("static OP * $ppname (pTHX);");
163 debug "init_pp: $ppname\n" if $debug_queue;
164}
165
166# Initialise runtime_callback function for Stackobj class
167BEGIN { B::Stackobj::set_callback(\&runtime) }
168
169# Initialise saveoptree_callback for B::C class
170sub cc_queue {
171 my ($name, $root, $start, @pl) = @_;
172 debug "cc_queue: name $name, root $root, start $start, padlist (@pl)\n"
173 if $debug_queue;
174 if ($name eq "*ignore*") {
175 $name = 0;
176 } else {
177 push(@cc_todo, [$name, $root, $start, (@pl ? @pl : @padlist)]);
178 }
179 my $fakeop = new B::FAKEOP ("next" => 0, sibling => 0, ppaddr => $name);
180 $start = $fakeop->save;
181 debug "cc_queue: name $name returns $start\n" if $debug_queue;
182 return $start;
183}
184BEGIN { B::C::set_callback(\&cc_queue) }
185
186sub valid_int { $_[0]->{flags} & VALID_INT }
187sub valid_double { $_[0]->{flags} & VALID_DOUBLE }
188sub valid_numeric { $_[0]->{flags} & (VALID_INT | VALID_DOUBLE) }
189sub valid_sv { $_[0]->{flags} & VALID_SV }
190
191sub top_int { @stack ? $stack[-1]->as_int : "TOPi" }
192sub top_double { @stack ? $stack[-1]->as_double : "TOPn" }
193sub top_numeric { @stack ? $stack[-1]->as_numeric : "TOPn" }
194sub top_sv { @stack ? $stack[-1]->as_sv : "TOPs" }
195sub top_bool { @stack ? $stack[-1]->as_bool : "SvTRUE(TOPs)" }
196
197sub pop_int { @stack ? (pop @stack)->as_int : "POPi" }
198sub pop_double { @stack ? (pop @stack)->as_double : "POPn" }
199sub pop_numeric { @stack ? (pop @stack)->as_numeric : "POPn" }
200sub pop_sv { @stack ? (pop @stack)->as_sv : "POPs" }
201sub pop_bool {
202 if (@stack) {
203 return ((pop @stack)->as_bool);
204 } else {
205 # Careful: POPs has an auto-decrement and SvTRUE evaluates
206 # its argument more than once.
207 runtime("sv = POPs;");
208 return "SvTRUE(sv)";
209 }
210}
211
212sub write_back_lexicals {
213 my $avoid = shift || 0;
214 debug "write_back_lexicals($avoid) called from @{[(caller(1))[3]]}\n"
215 if $debug_shadow;
216 my $lex;
217 foreach $lex (@pad) {
218 next unless ref($lex);
219 $lex->write_back unless $lex->{flags} & $avoid;
220 }
221}
222
223sub save_or_restore_lexical_state {
224 my $bblock=shift;
225 unless( exists $lexstate{$bblock}){
226 foreach my $lex (@pad) {
227 next unless ref($lex);
228 ${$lexstate{$bblock}}{$lex->{iv}} = $lex->{flags} ;
229 }
230 }
231 else {
232 foreach my $lex (@pad) {
233 next unless ref($lex);
234 my $old_flags=${$lexstate{$bblock}}{$lex->{iv}} ;
235 next if ( $old_flags eq $lex->{flags});
236 if (($old_flags & VALID_SV) && !($lex->{flags} & VALID_SV)){
237 $lex->write_back;
238 }
239 if (($old_flags & VALID_DOUBLE) && !($lex->{flags} & VALID_DOUBLE)){
240 $lex->load_double;
241 }
242 if (($old_flags & VALID_INT) && !($lex->{flags} & VALID_INT)){
243 $lex->load_int;
244 }
245 }
246 }
247}
248
249sub write_back_stack {
250 my $obj;
251 return unless @stack;
252 runtime(sprintf("EXTEND(sp, %d);", scalar(@stack)));
253 foreach $obj (@stack) {
254 runtime(sprintf("PUSHs((SV*)%s);", $obj->as_sv));
255 }
256 @stack = ();
257}
258
259sub invalidate_lexicals {
260 my $avoid = shift || 0;
261 debug "invalidate_lexicals($avoid) called from @{[(caller(1))[3]]}\n"
262 if $debug_shadow;
263 my $lex;
264 foreach $lex (@pad) {
265 next unless ref($lex);
266 $lex->invalidate unless $lex->{flags} & $avoid;
267 }
268}
269
270sub reload_lexicals {
271 my $lex;
272 foreach $lex (@pad) {
273 next unless ref($lex);
274 my $type = $lex->{type};
275 if ($type == T_INT) {
276 $lex->as_int;
277 } elsif ($type == T_DOUBLE) {
278 $lex->as_double;
279 } else {
280 $lex->as_sv;
281 }
282 }
283}
284
285{
286 package B::Pseudoreg;
287 #
288 # This class allocates pseudo-registers (OK, so they're C variables).
289 #
290 my %alloc; # Keyed by variable name. A value of 1 means the
291 # variable has been declared. A value of 2 means
292 # it's in use.
293
294 sub new_scope { %alloc = () }
295
296 sub new ($$$) {
297 my ($class, $type, $prefix) = @_;
298 my ($ptr, $i, $varname, $status, $obj);
299 $prefix =~ s/^(\**)//;
300 $ptr = $1;
301 $i = 0;
302 do {
303 $varname = "$prefix$i";
304 $status = $alloc{$varname};
305 } while $status == 2;
306 if ($status != 1) {
307 # Not declared yet
308 B::CC::declare($type, "$ptr$varname");
309 $alloc{$varname} = 2; # declared and in use
310 }
311 $obj = bless \$varname, $class;
312 return $obj;
313 }
314 sub DESTROY {
315 my $obj = shift;
316 $alloc{$$obj} = 1; # no longer in use but still declared
317 }
318}
319{
320 package B::Shadow;
321 #
322 # This class gives a standard API for a perl object to shadow a
323 # C variable and only generate reloads/write-backs when necessary.
324 #
325 # Use $obj->load($foo) instead of runtime("shadowed_c_var = foo").
326 # Use $obj->write_back whenever shadowed_c_var needs to be up to date.
327 # Use $obj->invalidate whenever an unknown function may have
328 # set shadow itself.
329
330 sub new {
331 my ($class, $write_back) = @_;
332 # Object fields are perl shadow variable, validity flag
333 # (for *C* variable) and callback sub for write_back
334 # (passed perl shadow variable as argument).
335 bless [undef, 1, $write_back], $class;
336 }
337 sub load {
338 my ($obj, $newval) = @_;
339 $obj->[1] = 0; # C variable no longer valid
340 $obj->[0] = $newval;
341 }
342 sub write_back {
343 my $obj = shift;
344 if (!($obj->[1])) {
345 $obj->[1] = 1; # C variable will now be valid
346 &{$obj->[2]}($obj->[0]);
347 }
348 }
349 sub invalidate { $_[0]->[1] = 0 } # force C variable to be invalid
350}
351my $curcop = new B::Shadow (sub {
352 my $opsym = shift->save;
353 runtime("PL_curcop = (COP*)$opsym;");
354});
355
356#
357# Context stack shadowing. Mimics stuff in pp_ctl.c, cop.h and so on.
358#
359sub dopoptoloop {
360 my $cxix = $#cxstack;
361 while ($cxix >= 0 && $cxstack[$cxix]->{type} != CXt_LOOP) {
362 $cxix--;
363 }
364 debug "dopoptoloop: returning $cxix" if $debug_cxstack;
365 return $cxix;
366}
367
368sub dopoptolabel {
369 my $label = shift;
370 my $cxix = $#cxstack;
371 while ($cxix >= 0 &&
372 ($cxstack[$cxix]->{type} != CXt_LOOP ||
373 $cxstack[$cxix]->{label} ne $label)) {
374 $cxix--;
375 }
376 debug "dopoptolabel: returning $cxix" if $debug_cxstack;
377 return $cxix;
378}
379
380sub error {
381 my $format = shift;
382 my $file = $curcop->[0]->file;
383 my $line = $curcop->[0]->line;
384 $errors++;
385 if (@_) {
386 warn sprintf("%s:%d: $format\n", $file, $line, @_);
387 } else {
388 warn sprintf("%s:%d: %s\n", $file, $line, $format);
389 }
390}
391
392#
393# Load pad takes (the elements of) a PADLIST as arguments and loads
394# up @pad with Stackobj-derived objects which represent those lexicals.
395# If/when perl itself can generate type information (my int $foo) then
396# we'll take advantage of that here. Until then, we'll use various hacks
397# to tell the compiler when we want a lexical to be a particular type
398# or to be a register.
399#
400sub load_pad {
401 my ($namelistav, $valuelistav) = @_;
402 @padlist = @_;
403 my @namelist = $namelistav->ARRAY;
404 my @valuelist = $valuelistav->ARRAY;
405 my $ix;
406 @pad = ();
407 debug "load_pad: $#namelist names, $#valuelist values\n" if $debug_pad;
408 # Temporary lexicals don't get named so it's possible for @valuelist
409 # to be strictly longer than @namelist. We count $ix up to the end of
410 # @valuelist but index into @namelist for the name. Any temporaries which
411 # run off the end of @namelist will make $namesv undefined and we treat
412 # that the same as having an explicit SPECIAL sv_undef object in @namelist.
413 # [XXX If/when @_ becomes a lexical, we must start at 0 here.]
414 for ($ix = 1; $ix < @valuelist; $ix++) {
415 my $namesv = $namelist[$ix];
416 my $type = T_UNKNOWN;
417 my $flags = 0;
418 my $name = "tmp$ix";
419 my $class = class($namesv);
420 if (!defined($namesv) || $class eq "SPECIAL") {
421 # temporaries have &PL_sv_undef instead of a PVNV for a name
422 $flags = VALID_SV|TEMPORARY|REGISTER;
423 } else {
424 if ($namesv->PV =~ /^\$(.*)_([di])(r?)$/) {
425 $name = $1;
426 if ($2 eq "i") {
427 $type = T_INT;
428 $flags = VALID_SV|VALID_INT;
429 } elsif ($2 eq "d") {
430 $type = T_DOUBLE;
431 $flags = VALID_SV|VALID_DOUBLE;
432 }
433 $flags |= REGISTER if $3;
434 }
435 }
436 $pad[$ix] = new B::Stackobj::Padsv ($type, $flags, $ix,
437 "i_$name", "d_$name");
438
439 debug sprintf("PL_curpad[$ix] = %s\n", $pad[$ix]->peek) if $debug_pad;
440 }
441}
442
443sub declare_pad {
444 my $ix;
445 for ($ix = 1; $ix <= $#pad; $ix++) {
446 my $type = $pad[$ix]->{type};
447 declare("IV", $type == T_INT ?
448 sprintf("%s=0",$pad[$ix]->{iv}):$pad[$ix]->{iv}) if $pad[$ix]->save_int;
449 declare("double", $type == T_DOUBLE ?
450 sprintf("%s = 0",$pad[$ix]->{nv}):$pad[$ix]->{nv} )if $pad[$ix]->save_double;
451
452 }
453}
454#
455# Debugging stuff
456#
457sub peek_stack { sprintf "stack = %s\n", join(" ", map($_->minipeek, @stack)) }
458
459#
460# OP stuff
461#
462
463sub label {
464 my $op = shift;
465 # XXX Preserve original label name for "real" labels?
466 return sprintf("lab_%x", $$op);
467}
468
469sub write_label {
470 my $op = shift;
471 push_runtime(sprintf(" %s:", label($op)));
472}
473
474sub loadop {
475 my $op = shift;
476 my $opsym = $op->save;
477 runtime("PL_op = $opsym;") unless $know_op;
478 return $opsym;
479}
480
481sub doop {
482 my $op = shift;
483 my $ppname = $op->ppaddr;
484 my $sym = loadop($op);
485 runtime("DOOP($ppname);");
486 $know_op = 1;
487 return $sym;
488}
489
490sub gimme {
491 my $op = shift;
492 my $flags = $op->flags;
493 return (($flags & OPf_WANT) ? (($flags & OPf_WANT)== OPf_WANT_LIST? G_ARRAY:G_SCALAR) : "dowantarray()");
494}
495
496#
497# Code generation for PP code
498#
499
500sub pp_null {
501 my $op = shift;
502 return $op->next;
503}
504
505sub pp_stub {
506 my $op = shift;
507 my $gimme = gimme($op);
508 if ($gimme != G_ARRAY) {
509 my $obj= new B::Stackobj::Const(sv_undef);
510 push(@stack, $obj);
511 # XXX Change to push a constant sv_undef Stackobj onto @stack
512 #write_back_stack();
513 #runtime("if ($gimme != G_ARRAY) XPUSHs(&PL_sv_undef);");
514 }
515 return $op->next;
516}
517
518sub pp_unstack {
519 my $op = shift;
520 @stack = ();
521 runtime("PP_UNSTACK;");
522 return $op->next;
523}
524
525sub pp_and {
526 my $op = shift;
527 my $next = $op->next;
528 reload_lexicals();
529 unshift(@bblock_todo, $next);
530 if (@stack >= 1) {
531 my $bool = pop_bool();
532 write_back_stack();
533 save_or_restore_lexical_state($$next);
534 runtime(sprintf("if (!$bool) {XPUSHs(&PL_sv_no); goto %s;}", label($next)));
535 } else {
536 save_or_restore_lexical_state($$next);
537 runtime(sprintf("if (!%s) goto %s;", top_bool(), label($next)),
538 "*sp--;");
539 }
540 return $op->other;
541}
542
543sub pp_or {
544 my $op = shift;
545 my $next = $op->next;
546 reload_lexicals();
547 unshift(@bblock_todo, $next);
548 if (@stack >= 1) {
549 my $bool = pop_bool @stack;
550 write_back_stack();
551 save_or_restore_lexical_state($$next);
552 runtime(sprintf("if (%s) { XPUSHs(&PL_sv_yes); goto %s; }",
553 $bool, label($next)));
554 } else {
555 save_or_restore_lexical_state($$next);
556 runtime(sprintf("if (%s) goto %s;", top_bool(), label($next)),
557 "*sp--;");
558 }
559 return $op->other;
560}
561
562sub pp_cond_expr {
563 my $op = shift;
564 my $false = $op->next;
565 unshift(@bblock_todo, $false);
566 reload_lexicals();
567 my $bool = pop_bool();
568 write_back_stack();
569 save_or_restore_lexical_state($$false);
570 runtime(sprintf("if (!$bool) goto %s;", label($false)));
571 return $op->other;
572}
573
574sub pp_padsv {
575 my $op = shift;
576 my $ix = $op->targ;
577 push(@stack, $pad[$ix]);
578 if ($op->flags & OPf_MOD) {
579 my $private = $op->private;
580 if ($private & OPpLVAL_INTRO) {
581 runtime("SAVECLEARSV(PL_curpad[$ix]);");
582 } elsif ($private & OPpDEREF) {
583 runtime(sprintf("vivify_ref(PL_curpad[%d], %d);",
584 $ix, $private & OPpDEREF));
585 $pad[$ix]->invalidate;
586 }
587 }
588 return $op->next;
589}
590
591sub pp_const {
592 my $op = shift;
593 my $sv = $op->sv;
594 my $obj;
595 # constant could be in the pad (under useithreads)
596 if ($$sv) {
597 $obj = $constobj{$$sv};
598 if (!defined($obj)) {
599 $obj = $constobj{$$sv} = new B::Stackobj::Const ($sv);
600 }
601 }
602 else {
603 $obj = $pad[$op->targ];
604 }
605 push(@stack, $obj);
606 return $op->next;
607}
608
609sub pp_nextstate {
610 my $op = shift;
611 $curcop->load($op);
612 @stack = ();
613 debug(sprintf("%s:%d\n", $op->file, $op->line)) if $debug_lineno;
614 runtime("TAINT_NOT;") unless $omit_taint;
615 runtime("sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;");
616 if ($freetmps_each_bblock || $freetmps_each_loop) {
617 $need_freetmps = 1;
618 } else {
619 runtime("FREETMPS;");
620 }
621 return $op->next;
622}
623
624sub pp_dbstate {
625 my $op = shift;
626 $curcop->invalidate; # XXX?
627 return default_pp($op);
628}
629
630#default_pp will handle this:
631#sub pp_bless { $curcop->write_back; default_pp(@_) }
632#sub pp_repeat { $curcop->write_back; default_pp(@_) }
633# The following subs need $curcop->write_back if we decide to support arybase:
634# pp_pos, pp_substr, pp_index, pp_rindex, pp_aslice, pp_lslice, pp_splice
635#sub pp_caller { $curcop->write_back; default_pp(@_) }
636#sub pp_reset { $curcop->write_back; default_pp(@_) }
637
638sub pp_rv2gv{
639 my $op =shift;
640 $curcop->write_back;
641 write_back_lexicals() unless $skip_lexicals{$ppname};
642 write_back_stack() unless $skip_stack{$ppname};
643 my $sym=doop($op);
644 if ($op->private & OPpDEREF) {
645 $init->add(sprintf("((UNOP *)$sym)->op_first = $sym;"));
646 $init->add(sprintf("((UNOP *)$sym)->op_type = %d;",
647 $op->first->type));
648 }
649 return $op->next;
650}
651sub pp_sort {
652 my $op = shift;
653 my $ppname = $op->ppaddr;
654 if ( $op->flags & OPf_SPECIAL && $op->flags & OPf_STACKED){
655 #this indicates the sort BLOCK Array case
656 #ugly surgery required.
657 my $root=$op->first->sibling->first;
658 my $start=$root->first;
659 $op->first->save;
660 $op->first->sibling->save;
661 $root->save;
662 my $sym=$start->save;
663 my $fakeop=cc_queue("pp_sort".$$op,$root,$start);
664 $init->add(sprintf("(%s)->op_next=%s;",$sym,$fakeop));
665 }
666 $curcop->write_back;
667 write_back_lexicals();
668 write_back_stack();
669 doop($op);
670 return $op->next;
671}
672
673sub pp_gv {
674 my $op = shift;
675 my $gvsym;
676 if ($Config{useithreads}) {
677 $gvsym = $pad[$op->padix]->as_sv;
678 }
679 else {
680 $gvsym = $op->gv->save;
681 }
682 write_back_stack();
683 runtime("XPUSHs((SV*)$gvsym);");
684 return $op->next;
685}
686
687sub pp_gvsv {
688 my $op = shift;
689 my $gvsym;
690 if ($Config{useithreads}) {
691 $gvsym = $pad[$op->padix]->as_sv;
692 }
693 else {
694 $gvsym = $op->gv->save;
695 }
696 write_back_stack();
697 if ($op->private & OPpLVAL_INTRO) {
698 runtime("XPUSHs(save_scalar($gvsym));");
699 } else {
700 runtime("XPUSHs(GvSV($gvsym));");
701 }
702 return $op->next;
703}
704
705sub pp_aelemfast {
706 my $op = shift;
707 my $gvsym;
708 if ($Config{useithreads}) {
709 $gvsym = $pad[$op->padix]->as_sv;
710 }
711 else {
712 $gvsym = $op->gv->save;
713 }
714 my $ix = $op->private;
715 my $flag = $op->flags & OPf_MOD;
716 write_back_stack();
717 runtime("svp = av_fetch(GvAV($gvsym), $ix, $flag);",
718 "PUSHs(svp ? *svp : &PL_sv_undef);");
719 return $op->next;
720}
721
722sub int_binop {
723 my ($op, $operator) = @_;
724 if ($op->flags & OPf_STACKED) {
725 my $right = pop_int();
726 if (@stack >= 1) {
727 my $left = top_int();
728 $stack[-1]->set_int(&$operator($left, $right));
729 } else {
730 runtime(sprintf("sv_setiv(TOPs, %s);",&$operator("TOPi", $right)));
731 }
732 } else {
733 my $targ = $pad[$op->targ];
734 my $right = new B::Pseudoreg ("IV", "riv");
735 my $left = new B::Pseudoreg ("IV", "liv");
736 runtime(sprintf("$$right = %s; $$left = %s;", pop_int(), pop_int));
737 $targ->set_int(&$operator($$left, $$right));
738 push(@stack, $targ);
739 }
740 return $op->next;
741}
742
743sub INTS_CLOSED () { 0x1 }
744sub INT_RESULT () { 0x2 }
745sub NUMERIC_RESULT () { 0x4 }
746
747sub numeric_binop {
748 my ($op, $operator, $flags) = @_;
749 my $force_int = 0;
750 $force_int ||= ($flags & INT_RESULT);
751 $force_int ||= ($flags & INTS_CLOSED && @stack >= 2
752 && valid_int($stack[-2]) && valid_int($stack[-1]));
753 if ($op->flags & OPf_STACKED) {
754 my $right = pop_numeric();
755 if (@stack >= 1) {
756 my $left = top_numeric();
757 if ($force_int) {
758 $stack[-1]->set_int(&$operator($left, $right));
759 } else {
760 $stack[-1]->set_numeric(&$operator($left, $right));
761 }
762 } else {
763 if ($force_int) {
764 my $rightruntime = new B::Pseudoreg ("IV", "riv");
765 runtime(sprintf("$$rightruntime = %s;",$right));
766 runtime(sprintf("sv_setiv(TOPs, %s);",
767 &$operator("TOPi", $$rightruntime)));
768 } else {
769 my $rightruntime = new B::Pseudoreg ("double", "rnv");
770 runtime(sprintf("$$rightruntime = %s;",$right));
771 runtime(sprintf("sv_setnv(TOPs, %s);",
772 &$operator("TOPn",$$rightruntime)));
773 }
774 }
775 } else {
776 my $targ = $pad[$op->targ];
777 $force_int ||= ($targ->{type} == T_INT);
778 if ($force_int) {
779 my $right = new B::Pseudoreg ("IV", "riv");
780 my $left = new B::Pseudoreg ("IV", "liv");
781 runtime(sprintf("$$right = %s; $$left = %s;",
782 pop_numeric(), pop_numeric));
783 $targ->set_int(&$operator($$left, $$right));
784 } else {
785 my $right = new B::Pseudoreg ("double", "rnv");
786 my $left = new B::Pseudoreg ("double", "lnv");
787 runtime(sprintf("$$right = %s; $$left = %s;",
788 pop_numeric(), pop_numeric));
789 $targ->set_numeric(&$operator($$left, $$right));
790 }
791 push(@stack, $targ);
792 }
793 return $op->next;
794}
795
796sub pp_ncmp {
797 my ($op) = @_;
798 if ($op->flags & OPf_STACKED) {
799 my $right = pop_numeric();
800 if (@stack >= 1) {
801 my $left = top_numeric();
802 runtime sprintf("if (%s > %s){",$left,$right);
803 $stack[-1]->set_int(1);
804 $stack[-1]->write_back();
805 runtime sprintf("}else if (%s < %s ) {",$left,$right);
806 $stack[-1]->set_int(-1);
807 $stack[-1]->write_back();
808 runtime sprintf("}else if (%s == %s) {",$left,$right);
809 $stack[-1]->set_int(0);
810 $stack[-1]->write_back();
811 runtime sprintf("}else {");
812 $stack[-1]->set_sv("&PL_sv_undef");
813 runtime "}";
814 } else {
815 my $rightruntime = new B::Pseudoreg ("double", "rnv");
816 runtime(sprintf("$$rightruntime = %s;",$right));
817 runtime sprintf(qq/if ("TOPn" > %s){/,$rightruntime);
818 runtime sprintf("sv_setiv(TOPs,1);");
819 runtime sprintf(qq/}else if ( "TOPn" < %s ) {/,$$rightruntime);
820 runtime sprintf("sv_setiv(TOPs,-1);");
821 runtime sprintf(qq/} else if ("TOPn" == %s) {/,$$rightruntime);
822 runtime sprintf("sv_setiv(TOPs,0);");
823 runtime sprintf(qq/}else {/);
824 runtime sprintf("sv_setiv(TOPs,&PL_sv_undef;");
825 runtime "}";
826 }
827 } else {
828 my $targ = $pad[$op->targ];
829 my $right = new B::Pseudoreg ("double", "rnv");
830 my $left = new B::Pseudoreg ("double", "lnv");
831 runtime(sprintf("$$right = %s; $$left = %s;",
832 pop_numeric(), pop_numeric));
833 runtime sprintf("if (%s > %s){",$$left,$$right);
834 $targ->set_int(1);
835 $targ->write_back();
836 runtime sprintf("}else if (%s < %s ) {",$$left,$$right);
837 $targ->set_int(-1);
838 $targ->write_back();
839 runtime sprintf("}else if (%s == %s) {",$$left,$$right);
840 $targ->set_int(0);
841 $targ->write_back();
842 runtime sprintf("}else {");
843 $targ->set_sv("&PL_sv_undef");
844 runtime "}";
845 push(@stack, $targ);
846 }
847 return $op->next;
848}
849
850sub sv_binop {
851 my ($op, $operator, $flags) = @_;
852 if ($op->flags & OPf_STACKED) {
853 my $right = pop_sv();
854 if (@stack >= 1) {
855 my $left = top_sv();
856 if ($flags & INT_RESULT) {
857 $stack[-1]->set_int(&$operator($left, $right));
858 } elsif ($flags & NUMERIC_RESULT) {
859 $stack[-1]->set_numeric(&$operator($left, $right));
860 } else {
861 # XXX Does this work?
862 runtime(sprintf("sv_setsv($left, %s);",
863 &$operator($left, $right)));
864 $stack[-1]->invalidate;
865 }
866 } else {
867 my $f;
868 if ($flags & INT_RESULT) {
869 $f = "sv_setiv";
870 } elsif ($flags & NUMERIC_RESULT) {
871 $f = "sv_setnv";
872 } else {
873 $f = "sv_setsv";
874 }
875 runtime(sprintf("%s(TOPs, %s);", $f, &$operator("TOPs", $right)));
876 }
877 } else {
878 my $targ = $pad[$op->targ];
879 runtime(sprintf("right = %s; left = %s;", pop_sv(), pop_sv));
880 if ($flags & INT_RESULT) {
881 $targ->set_int(&$operator("left", "right"));
882 } elsif ($flags & NUMERIC_RESULT) {
883 $targ->set_numeric(&$operator("left", "right"));
884 } else {
885 # XXX Does this work?
886 runtime(sprintf("sv_setsv(%s, %s);",
887 $targ->as_sv, &$operator("left", "right")));
888 $targ->invalidate;
889 }
890 push(@stack, $targ);
891 }
892 return $op->next;
893}
894
895sub bool_int_binop {
896 my ($op, $operator) = @_;
897 my $right = new B::Pseudoreg ("IV", "riv");
898 my $left = new B::Pseudoreg ("IV", "liv");
899 runtime(sprintf("$$right = %s; $$left = %s;", pop_int(), pop_int()));
900 my $bool = new B::Stackobj::Bool (new B::Pseudoreg ("int", "b"));
901 $bool->set_int(&$operator($$left, $$right));
902 push(@stack, $bool);
903 return $op->next;
904}
905
906sub bool_numeric_binop {
907 my ($op, $operator) = @_;
908 my $right = new B::Pseudoreg ("double", "rnv");
909 my $left = new B::Pseudoreg ("double", "lnv");
910 runtime(sprintf("$$right = %s; $$left = %s;",
911 pop_numeric(), pop_numeric()));
912 my $bool = new B::Stackobj::Bool (new B::Pseudoreg ("int", "b"));
913 $bool->set_numeric(&$operator($$left, $$right));
914 push(@stack, $bool);
915 return $op->next;
916}
917
918sub bool_sv_binop {
919 my ($op, $operator) = @_;
920 runtime(sprintf("right = %s; left = %s;", pop_sv(), pop_sv()));
921 my $bool = new B::Stackobj::Bool (new B::Pseudoreg ("int", "b"));
922 $bool->set_numeric(&$operator("left", "right"));
923 push(@stack, $bool);
924 return $op->next;
925}
926
927sub infix_op {
928 my $opname = shift;
929 return sub { "$_[0] $opname $_[1]" }
930}
931
932sub prefix_op {
933 my $opname = shift;
934 return sub { sprintf("%s(%s)", $opname, join(", ", @_)) }
935}
936
937BEGIN {
938 my $plus_op = infix_op("+");
939 my $minus_op = infix_op("-");
940 my $multiply_op = infix_op("*");
941 my $divide_op = infix_op("/");
942 my $modulo_op = infix_op("%");
943 my $lshift_op = infix_op("<<");
944 my $rshift_op = infix_op(">>");
945 my $scmp_op = prefix_op("sv_cmp");
946 my $seq_op = prefix_op("sv_eq");
947 my $sne_op = prefix_op("!sv_eq");
948 my $slt_op = sub { "sv_cmp($_[0], $_[1]) < 0" };
949 my $sgt_op = sub { "sv_cmp($_[0], $_[1]) > 0" };
950 my $sle_op = sub { "sv_cmp($_[0], $_[1]) <= 0" };
951 my $sge_op = sub { "sv_cmp($_[0], $_[1]) >= 0" };
952 my $eq_op = infix_op("==");
953 my $ne_op = infix_op("!=");
954 my $lt_op = infix_op("<");
955 my $gt_op = infix_op(">");
956 my $le_op = infix_op("<=");
957 my $ge_op = infix_op(">=");
958
959 #
960 # XXX The standard perl PP code has extra handling for
961 # some special case arguments of these operators.
962 #
963 sub pp_add { numeric_binop($_[0], $plus_op) }
964 sub pp_subtract { numeric_binop($_[0], $minus_op) }
965 sub pp_multiply { numeric_binop($_[0], $multiply_op) }
966 sub pp_divide { numeric_binop($_[0], $divide_op) }
967 sub pp_modulo { int_binop($_[0], $modulo_op) } # differs from perl's
968
969 sub pp_left_shift { int_binop($_[0], $lshift_op) }
970 sub pp_right_shift { int_binop($_[0], $rshift_op) }
971 sub pp_i_add { int_binop($_[0], $plus_op) }
972 sub pp_i_subtract { int_binop($_[0], $minus_op) }
973 sub pp_i_multiply { int_binop($_[0], $multiply_op) }
974 sub pp_i_divide { int_binop($_[0], $divide_op) }
975 sub pp_i_modulo { int_binop($_[0], $modulo_op) }
976
977 sub pp_eq { bool_numeric_binop($_[0], $eq_op) }
978 sub pp_ne { bool_numeric_binop($_[0], $ne_op) }
979 sub pp_lt { bool_numeric_binop($_[0], $lt_op) }
980 sub pp_gt { bool_numeric_binop($_[0], $gt_op) }
981 sub pp_le { bool_numeric_binop($_[0], $le_op) }
982 sub pp_ge { bool_numeric_binop($_[0], $ge_op) }
983
984 sub pp_i_eq { bool_int_binop($_[0], $eq_op) }
985 sub pp_i_ne { bool_int_binop($_[0], $ne_op) }
986 sub pp_i_lt { bool_int_binop($_[0], $lt_op) }
987 sub pp_i_gt { bool_int_binop($_[0], $gt_op) }
988 sub pp_i_le { bool_int_binop($_[0], $le_op) }
989 sub pp_i_ge { bool_int_binop($_[0], $ge_op) }
990
991 sub pp_scmp { sv_binop($_[0], $scmp_op, INT_RESULT) }
992 sub pp_slt { bool_sv_binop($_[0], $slt_op) }
993 sub pp_sgt { bool_sv_binop($_[0], $sgt_op) }
994 sub pp_sle { bool_sv_binop($_[0], $sle_op) }
995 sub pp_sge { bool_sv_binop($_[0], $sge_op) }
996 sub pp_seq { bool_sv_binop($_[0], $seq_op) }
997 sub pp_sne { bool_sv_binop($_[0], $sne_op) }
998}
999
1000
1001sub pp_sassign {
1002 my $op = shift;
1003 my $backwards = $op->private & OPpASSIGN_BACKWARDS;
1004 my ($dst, $src);
1005 if (@stack >= 2) {
1006 $dst = pop @stack;
1007 $src = pop @stack;
1008 ($src, $dst) = ($dst, $src) if $backwards;
1009 my $type = $src->{type};
1010 if ($type == T_INT) {
1011 $dst->set_int($src->as_int,$src->{flags} & VALID_UNSIGNED);
1012 } elsif ($type == T_DOUBLE) {
1013 $dst->set_numeric($src->as_numeric);
1014 } else {
1015 $dst->set_sv($src->as_sv);
1016 }
1017 push(@stack, $dst);
1018 } elsif (@stack == 1) {
1019 if ($backwards) {
1020 my $src = pop @stack;
1021 my $type = $src->{type};
1022 runtime("if (PL_tainting && PL_tainted) TAINT_NOT;");
1023 if ($type == T_INT) {
1024 if ($src->{flags} & VALID_UNSIGNED){
1025 runtime sprintf("sv_setuv(TOPs, %s);", $src->as_int);
1026 }else{
1027 runtime sprintf("sv_setiv(TOPs, %s);", $src->as_int);
1028 }
1029 } elsif ($type == T_DOUBLE) {
1030 runtime sprintf("sv_setnv(TOPs, %s);", $src->as_double);
1031 } else {
1032 runtime sprintf("sv_setsv(TOPs, %s);", $src->as_sv);
1033 }
1034 runtime("SvSETMAGIC(TOPs);");
1035 } else {
1036 my $dst = $stack[-1];
1037 my $type = $dst->{type};
1038 runtime("sv = POPs;");
1039 runtime("MAYBE_TAINT_SASSIGN_SRC(sv);");
1040 if ($type == T_INT) {
1041 $dst->set_int("SvIV(sv)");
1042 } elsif ($type == T_DOUBLE) {
1043 $dst->set_double("SvNV(sv)");
1044 } else {
1045 runtime("SvSetMagicSV($dst->{sv}, sv);");
1046 $dst->invalidate;
1047 }
1048 }
1049 } else {
1050 if ($backwards) {
1051 runtime("src = POPs; dst = TOPs;");
1052 } else {
1053 runtime("dst = POPs; src = TOPs;");
1054 }
1055 runtime("MAYBE_TAINT_SASSIGN_SRC(src);",
1056 "SvSetSV(dst, src);",
1057 "SvSETMAGIC(dst);",
1058 "SETs(dst);");
1059 }
1060 return $op->next;
1061}
1062
1063sub pp_preinc {
1064 my $op = shift;
1065 if (@stack >= 1) {
1066 my $obj = $stack[-1];
1067 my $type = $obj->{type};
1068 if ($type == T_INT || $type == T_DOUBLE) {
1069 $obj->set_int($obj->as_int . " + 1");
1070 } else {
1071 runtime sprintf("PP_PREINC(%s);", $obj->as_sv);
1072 $obj->invalidate();
1073 }
1074 } else {
1075 runtime sprintf("PP_PREINC(TOPs);");
1076 }
1077 return $op->next;
1078}
1079
1080
1081sub pp_pushmark {
1082 my $op = shift;
1083 write_back_stack();
1084 runtime("PUSHMARK(sp);");
1085 return $op->next;
1086}
1087
1088sub pp_list {
1089 my $op = shift;
1090 write_back_stack();
1091 my $gimme = gimme($op);
1092 if ($gimme == G_ARRAY) { # sic
1093 runtime("POPMARK;"); # need this even though not a "full" pp_list
1094 } else {
1095 runtime("PP_LIST($gimme);");
1096 }
1097 return $op->next;
1098}
1099
1100sub pp_entersub {
1101 my $op = shift;
1102 $curcop->write_back;
1103 write_back_lexicals(REGISTER|TEMPORARY);
1104 write_back_stack();
1105 my $sym = doop($op);
1106 runtime("while (PL_op != ($sym)->op_next && PL_op != (OP*)0 ){");
1107 runtime("PL_op = (*PL_op->op_ppaddr)(aTHX);");
1108 runtime("SPAGAIN;}");
1109 $know_op = 0;
1110 invalidate_lexicals(REGISTER|TEMPORARY);
1111 return $op->next;
1112}
1113sub pp_formline {
1114 my $op = shift;
1115 my $ppname = $op->ppaddr;
1116 write_back_lexicals() unless $skip_lexicals{$ppname};
1117 write_back_stack() unless $skip_stack{$ppname};
1118 my $sym=doop($op);
1119 # See comment in pp_grepwhile to see why!
1120 $init->add("((LISTOP*)$sym)->op_first = $sym;");
1121 runtime("if (PL_op == ((LISTOP*)($sym))->op_first){");
1122 save_or_restore_lexical_state(${$op->first});
1123 runtime( sprintf("goto %s;",label($op->first)));
1124 runtime("}");
1125 return $op->next;
1126}
1127
1128sub pp_goto{
1129
1130 my $op = shift;
1131 my $ppname = $op->ppaddr;
1132 write_back_lexicals() unless $skip_lexicals{$ppname};
1133 write_back_stack() unless $skip_stack{$ppname};
1134 my $sym=doop($op);
1135 runtime("if (PL_op != ($sym)->op_next && PL_op != (OP*)0){return PL_op;}");
1136 invalidate_lexicals() unless $skip_invalidate{$ppname};
1137 return $op->next;
1138}
1139sub pp_enterwrite {
1140 my $op = shift;
1141 pp_entersub($op);
1142}
1143sub pp_leavesub{
1144 my $op = shift;
1145 write_back_lexicals() unless $skip_lexicals{$ppname};
1146 write_back_stack() unless $skip_stack{$ppname};
1147 runtime("if (PL_curstackinfo->si_type == PERLSI_SORT){");
1148 runtime("\tPUTBACK;return 0;");
1149 runtime("}");
1150 doop($op);
1151 return $op->next;
1152}
1153sub pp_leavewrite {
1154 my $op = shift;
1155 write_back_lexicals(REGISTER|TEMPORARY);
1156 write_back_stack();
1157 my $sym = doop($op);
1158 # XXX Is this the right way to distinguish between it returning
1159 # CvSTART(cv) (via doform) and pop_return()?
1160 #runtime("if (PL_op) PL_op = (*PL_op->op_ppaddr)(aTHX);");
1161 runtime("SPAGAIN;");
1162 $know_op = 0;
1163 invalidate_lexicals(REGISTER|TEMPORARY);
1164 return $op->next;
1165}
1166
1167sub doeval {
1168 my $op = shift;
1169 $curcop->write_back;
1170 write_back_lexicals(REGISTER|TEMPORARY);
1171 write_back_stack();
1172 my $sym = loadop($op);
1173 my $ppaddr = $op->ppaddr;
1174 #runtime(qq/printf("$ppaddr type eval\n");/);
1175 runtime("PP_EVAL($ppaddr, ($sym)->op_next);");
1176 $know_op = 1;
1177 invalidate_lexicals(REGISTER|TEMPORARY);
1178 return $op->next;
1179}
1180
1181sub pp_entereval { doeval(@_) }
1182sub pp_dofile { doeval(@_) }
1183
1184#pp_require is protected by pp_entertry, so no protection for it.
1185sub pp_require {
1186 my $op = shift;
1187 $curcop->write_back;
1188 write_back_lexicals(REGISTER|TEMPORARY);
1189 write_back_stack();
1190 my $sym = doop($op);
1191 runtime("while (PL_op != ($sym)->op_next && PL_op != (OP*)0 ){");
1192 runtime("PL_op = (*PL_op->op_ppaddr)(ARGS);");
1193 runtime("SPAGAIN;}");
1194 $know_op = 1;
1195 invalidate_lexicals(REGISTER|TEMPORARY);
1196 return $op->next;
1197}
1198
1199
1200sub pp_entertry {
1201 my $op = shift;
1202 $curcop->write_back;
1203 write_back_lexicals(REGISTER|TEMPORARY);
1204 write_back_stack();
1205 my $sym = doop($op);
1206 my $jmpbuf = sprintf("jmpbuf%d", $jmpbuf_ix++);
1207 declare("JMPENV", $jmpbuf);
1208 runtime(sprintf("PP_ENTERTRY(%s,%s);", $jmpbuf, label($op->other->next)));
1209 invalidate_lexicals(REGISTER|TEMPORARY);
1210 return $op->next;
1211}
1212
1213sub pp_leavetry{
1214 my $op=shift;
1215 default_pp($op);
1216 runtime("PP_LEAVETRY;");
1217 return $op->next;
1218}
1219
1220sub pp_grepstart {
1221 my $op = shift;
1222 if ($need_freetmps && $freetmps_each_loop) {
1223 runtime("FREETMPS;"); # otherwise the grepwhile loop messes things up
1224 $need_freetmps = 0;
1225 }
1226 write_back_stack();
1227 my $sym= doop($op);
1228 my $next=$op->next;
1229 $next->save;
1230 my $nexttonext=$next->next;
1231 $nexttonext->save;
1232 save_or_restore_lexical_state($$nexttonext);
1233 runtime(sprintf("if (PL_op == (($sym)->op_next)->op_next) goto %s;",
1234 label($nexttonext)));
1235 return $op->next->other;
1236}
1237
1238sub pp_mapstart {
1239 my $op = shift;
1240 if ($need_freetmps && $freetmps_each_loop) {
1241 runtime("FREETMPS;"); # otherwise the mapwhile loop messes things up
1242 $need_freetmps = 0;
1243 }
1244 write_back_stack();
1245 # pp_mapstart can return either op_next->op_next or op_next->op_other and
1246 # we need to be able to distinguish the two at runtime.
1247 my $sym= doop($op);
1248 my $next=$op->next;
1249 $next->save;
1250 my $nexttonext=$next->next;
1251 $nexttonext->save;
1252 save_or_restore_lexical_state($$nexttonext);
1253 runtime(sprintf("if (PL_op == (($sym)->op_next)->op_next) goto %s;",
1254 label($nexttonext)));
1255 return $op->next->other;
1256}
1257
1258sub pp_grepwhile {
1259 my $op = shift;
1260 my $next = $op->next;
1261 unshift(@bblock_todo, $next);
1262 write_back_lexicals();
1263 write_back_stack();
1264 my $sym = doop($op);
1265 # pp_grepwhile can return either op_next or op_other and we need to
1266 # be able to distinguish the two at runtime. Since it's possible for
1267 # both ops to be "inlined", the fields could both be zero. To get
1268 # around that, we hack op_next to be our own op (purely because we
1269 # know it's a non-NULL pointer and can't be the same as op_other).
1270 $init->add("((LOGOP*)$sym)->op_next = $sym;");
1271 save_or_restore_lexical_state($$next);
1272 runtime(sprintf("if (PL_op == ($sym)->op_next) goto %s;", label($next)));
1273 $know_op = 0;
1274 return $op->other;
1275}
1276
1277sub pp_mapwhile {
1278 pp_grepwhile(@_);
1279}
1280
1281sub pp_return {
1282 my $op = shift;
1283 write_back_lexicals(REGISTER|TEMPORARY);
1284 write_back_stack();
1285 doop($op);
1286 runtime("PUTBACK;", "return PL_op;");
1287 $know_op = 0;
1288 return $op->next;
1289}
1290
1291sub nyi {
1292 my $op = shift;
1293 warn sprintf("%s not yet implemented properly\n", $op->ppaddr);
1294 return default_pp($op);
1295}
1296
1297sub pp_range {
1298 my $op = shift;
1299 my $flags = $op->flags;
1300 if (!($flags & OPf_WANT)) {
1301 error("context of range unknown at compile-time");
1302 }
1303 write_back_lexicals();
1304 write_back_stack();
1305 unless (($flags & OPf_WANT)== OPf_WANT_LIST) {
1306 # We need to save our UNOP structure since pp_flop uses
1307 # it to find and adjust out targ. We don't need it ourselves.
1308 $op->save;
1309 save_or_restore_lexical_state(${$op->other});
1310 runtime sprintf("if (SvTRUE(PL_curpad[%d])) goto %s;",
1311 $op->targ, label($op->other));
1312 unshift(@bblock_todo, $op->other);
1313 }
1314 return $op->next;
1315}
1316
1317sub pp_flip {
1318 my $op = shift;
1319 my $flags = $op->flags;
1320 if (!($flags & OPf_WANT)) {
1321 error("context of flip unknown at compile-time");
1322 }
1323 if (($flags & OPf_WANT)==OPf_WANT_LIST) {
1324 return $op->first->other;
1325 }
1326 write_back_lexicals();
1327 write_back_stack();
1328 # We need to save our UNOP structure since pp_flop uses
1329 # it to find and adjust out targ. We don't need it ourselves.
1330 $op->save;
1331 my $ix = $op->targ;
1332 my $rangeix = $op->first->targ;
1333 runtime(($op->private & OPpFLIP_LINENUM) ?
1334 "if (PL_last_in_gv && SvIV(TOPs) == IoLINES(GvIOp(PL_last_in_gv))) {"
1335 : "if (SvTRUE(TOPs)) {");
1336 runtime("\tsv_setiv(PL_curpad[$rangeix], 1);");
1337 if ($op->flags & OPf_SPECIAL) {
1338 runtime("sv_setiv(PL_curpad[$ix], 1);");
1339 } else {
1340 save_or_restore_lexical_state(${$op->first->other});
1341 runtime("\tsv_setiv(PL_curpad[$ix], 0);",
1342 "\tsp--;",
1343 sprintf("\tgoto %s;", label($op->first->other)));
1344 }
1345 runtime("}",
1346 qq{sv_setpv(PL_curpad[$ix], "");},
1347 "SETs(PL_curpad[$ix]);");
1348 $know_op = 0;
1349 return $op->next;
1350}
1351
1352sub pp_flop {
1353 my $op = shift;
1354 default_pp($op);
1355 $know_op = 0;
1356 return $op->next;
1357}
1358
1359sub enterloop {
1360 my $op = shift;
1361 my $nextop = $op->nextop;
1362 my $lastop = $op->lastop;
1363 my $redoop = $op->redoop;
1364 $curcop->write_back;
1365 debug "enterloop: pushing on cxstack" if $debug_cxstack;
1366 push(@cxstack, {
1367 type => CXt_LOOP,
1368 op => $op,
1369 "label" => $curcop->[0]->label,
1370 nextop => $nextop,
1371 lastop => $lastop,
1372 redoop => $redoop
1373 });
1374 $nextop->save;
1375 $lastop->save;
1376 $redoop->save;
1377 return default_pp($op);
1378}
1379
1380sub pp_enterloop { enterloop(@_) }
1381sub pp_enteriter { enterloop(@_) }
1382
1383sub pp_leaveloop {
1384 my $op = shift;
1385 if (!@cxstack) {
1386 die "panic: leaveloop";
1387 }
1388 debug "leaveloop: popping from cxstack" if $debug_cxstack;
1389 pop(@cxstack);
1390 return default_pp($op);
1391}
1392
1393sub pp_next {
1394 my $op = shift;
1395 my $cxix;
1396 if ($op->flags & OPf_SPECIAL) {
1397 $cxix = dopoptoloop();
1398 if ($cxix < 0) {
1399 error('"next" used outside loop');
1400 return $op->next; # ignore the op
1401 }
1402 } else {
1403 $cxix = dopoptolabel($op->pv);
1404 if ($cxix < 0) {
1405 error('Label not found at compile time for "next %s"', $op->pv);
1406 return $op->next; # ignore the op
1407 }
1408 }
1409 default_pp($op);
1410 my $nextop = $cxstack[$cxix]->{nextop};
1411 push(@bblock_todo, $nextop);
1412 save_or_restore_lexical_state($$nextop);
1413 runtime(sprintf("goto %s;", label($nextop)));
1414 return $op->next;
1415}
1416
1417sub pp_redo {
1418 my $op = shift;
1419 my $cxix;
1420 if ($op->flags & OPf_SPECIAL) {
1421 $cxix = dopoptoloop();
1422 if ($cxix < 0) {
1423 error('"redo" used outside loop');
1424 return $op->next; # ignore the op
1425 }
1426 } else {
1427 $cxix = dopoptolabel($op->pv);
1428 if ($cxix < 0) {
1429 error('Label not found at compile time for "redo %s"', $op->pv);
1430 return $op->next; # ignore the op
1431 }
1432 }
1433 default_pp($op);
1434 my $redoop = $cxstack[$cxix]->{redoop};
1435 push(@bblock_todo, $redoop);
1436 save_or_restore_lexical_state($$redoop);
1437 runtime(sprintf("goto %s;", label($redoop)));
1438 return $op->next;
1439}
1440
1441sub pp_last {
1442 my $op = shift;
1443 my $cxix;
1444 if ($op->flags & OPf_SPECIAL) {
1445 $cxix = dopoptoloop();
1446 if ($cxix < 0) {
1447 error('"last" used outside loop');
1448 return $op->next; # ignore the op
1449 }
1450 } else {
1451 $cxix = dopoptolabel($op->pv);
1452 if ($cxix < 0) {
1453 error('Label not found at compile time for "last %s"', $op->pv);
1454 return $op->next; # ignore the op
1455 }
1456 # XXX Add support for "last" to leave non-loop blocks
1457 if ($cxstack[$cxix]->{type} != CXt_LOOP) {
1458 error('Use of "last" for non-loop blocks is not yet implemented');
1459 return $op->next; # ignore the op
1460 }
1461 }
1462 default_pp($op);
1463 my $lastop = $cxstack[$cxix]->{lastop}->next;
1464 push(@bblock_todo, $lastop);
1465 save_or_restore_lexical_state($$lastop);
1466 runtime(sprintf("goto %s;", label($lastop)));
1467 return $op->next;
1468}
1469
1470sub pp_subst {
1471 my $op = shift;
1472 write_back_lexicals();
1473 write_back_stack();
1474 my $sym = doop($op);
1475 my $replroot = $op->pmreplroot;
1476 if ($$replroot) {
1477 save_or_restore_lexical_state($$replroot);
1478 runtime sprintf("if (PL_op == ((PMOP*)(%s))->op_pmreplroot) goto %s;",
1479 $sym, label($replroot));
1480 $op->pmreplstart->save;
1481 push(@bblock_todo, $replroot);
1482 }
1483 invalidate_lexicals();
1484 return $op->next;
1485}
1486
1487sub pp_substcont {
1488 my $op = shift;
1489 write_back_lexicals();
1490 write_back_stack();
1491 doop($op);
1492 my $pmop = $op->other;
1493 # warn sprintf("substcont: op = %s, pmop = %s\n",
1494 # peekop($op), peekop($pmop));#debug
1495# my $pmopsym = objsym($pmop);
1496 my $pmopsym = $pmop->save; # XXX can this recurse?
1497# warn "pmopsym = $pmopsym\n";#debug
1498 save_or_restore_lexical_state(${$pmop->pmreplstart});
1499 runtime sprintf("if (PL_op == ((PMOP*)(%s))->op_pmreplstart) goto %s;",
1500 $pmopsym, label($pmop->pmreplstart));
1501 invalidate_lexicals();
1502 return $pmop->next;
1503}
1504
1505sub default_pp {
1506 my $op = shift;
1507 my $ppname = "pp_" . $op->name;
1508 if ($curcop and $need_curcop{$ppname}){
1509 $curcop->write_back;
1510 }
1511 write_back_lexicals() unless $skip_lexicals{$ppname};
1512 write_back_stack() unless $skip_stack{$ppname};
1513 doop($op);
1514 # XXX If the only way that ops can write to a TEMPORARY lexical is
1515 # when it's named in $op->targ then we could call
1516 # invalidate_lexicals(TEMPORARY) and avoid having to write back all
1517 # the temporaries. For now, we'll play it safe and write back the lot.
1518 invalidate_lexicals() unless $skip_invalidate{$ppname};
1519 return $op->next;
1520}
1521
1522sub compile_op {
1523 my $op = shift;
1524 my $ppname = "pp_" . $op->name;
1525 if (exists $ignore_op{$ppname}) {
1526 return $op->next;
1527 }
1528 debug peek_stack() if $debug_stack;
1529 if ($debug_op) {
1530 debug sprintf("%s [%s]\n",
1531 peekop($op),
1532 $op->flags & OPf_STACKED ? "OPf_STACKED" : $op->targ);
1533 }
1534 no strict 'refs';
1535 if (defined(&$ppname)) {
1536 $know_op = 0;
1537 return &$ppname($op);
1538 } else {
1539 return default_pp($op);
1540 }
1541}
1542
1543sub compile_bblock {
1544 my $op = shift;
1545 #warn "compile_bblock: ", peekop($op), "\n"; # debug
1546 save_or_restore_lexical_state($$op);
1547 write_label($op);
1548 $know_op = 0;
1549 do {
1550 $op = compile_op($op);
1551 } while (defined($op) && $$op && !exists($leaders->{$$op}));
1552 write_back_stack(); # boo hoo: big loss
1553 reload_lexicals();
1554 return $op;
1555}
1556
1557sub cc {
1558 my ($name, $root, $start, @padlist) = @_;
1559 my $op;
1560 if($done{$$start}){
1561 #warn "repeat=>".ref($start)."$name,\n";#debug
1562 $decl->add(sprintf("#define $name %s",$done{$$start}));
1563 return;
1564 }
1565 init_pp($name);
1566 load_pad(@padlist);
1567 %lexstate=();
1568 B::Pseudoreg->new_scope;
1569 @cxstack = ();
1570 if ($debug_timings) {
1571 warn sprintf("Basic block analysis at %s\n", timing_info);
1572 }
1573 $leaders = find_leaders($root, $start);
1574 my @leaders= keys %$leaders;
1575 if ($#leaders > -1) {
1576 @bblock_todo = ($start, values %$leaders) ;
1577 } else{
1578 runtime("return PL_op?PL_op->op_next:0;");
1579 }
1580 if ($debug_timings) {
1581 warn sprintf("Compilation at %s\n", timing_info);
1582 }
1583 while (@bblock_todo) {
1584 $op = shift @bblock_todo;
1585 #warn sprintf("Considering basic block %s\n", peekop($op)); # debug
1586 next if !defined($op) || !$$op || $done{$$op};
1587 #warn "...compiling it\n"; # debug
1588 do {
1589 $done{$$op} = $name;
1590 $op = compile_bblock($op);
1591 if ($need_freetmps && $freetmps_each_bblock) {
1592 runtime("FREETMPS;");
1593 $need_freetmps = 0;
1594 }
1595 } while defined($op) && $$op && !$done{$$op};
1596 if ($need_freetmps && $freetmps_each_loop) {
1597 runtime("FREETMPS;");
1598 $need_freetmps = 0;
1599 }
1600 if (!$$op) {
1601 runtime("PUTBACK;","return PL_op;");
1602 } elsif ($done{$$op}) {
1603 save_or_restore_lexical_state($$op);
1604 runtime(sprintf("goto %s;", label($op)));
1605 }
1606 }
1607 if ($debug_timings) {
1608 warn sprintf("Saving runtime at %s\n", timing_info);
1609 }
1610 declare_pad(@padlist) ;
1611 save_runtime();
1612}
1613
1614sub cc_recurse {
1615 my $ccinfo;
1616 my $start;
1617 $start = cc_queue(@_) if @_;
1618 while ($ccinfo = shift @cc_todo) {
1619 cc(@$ccinfo);
1620 }
1621 return $start;
1622}
1623
1624sub cc_obj {
1625 my ($name, $cvref) = @_;
1626 my $cv = svref_2object($cvref);
1627 my @padlist = $cv->PADLIST->ARRAY;
1628 my $curpad_sym = $padlist[1]->save;
1629 cc_recurse($name, $cv->ROOT, $cv->START, @padlist);
1630}
1631
1632sub cc_main {
1633 my @comppadlist = comppadlist->ARRAY;
1634 my $curpad_nam = $comppadlist[0]->save;
1635 my $curpad_sym = $comppadlist[1]->save;
1636 my $init_av = init_av->save;
1637 my $start = cc_recurse("pp_main", main_root, main_start, @comppadlist);
1638 # Do save_unused_subs before saving inc_hv
1639 save_unused_subs();
1640 cc_recurse();
1641
1642 my $inc_hv = svref_2object(\%INC)->save;
1643 my $inc_av = svref_2object(\@INC)->save;
1644 my $amagic_generate= amagic_generation;
1645 return if $errors;
1646 if (!defined($module)) {
1647 $init->add(sprintf("PL_main_root = s\\_%x;", ${main_root()}),
1648 "PL_main_start = $start;",
1649 "PL_curpad = AvARRAY($curpad_sym);",
1650 "PL_initav = (AV *) $init_av;",
1651 "GvHV(PL_incgv) = $inc_hv;",
1652 "GvAV(PL_incgv) = $inc_av;",
1653 "av_store(CvPADLIST(PL_main_cv),0,SvREFCNT_inc($curpad_nam));",
1654 "av_store(CvPADLIST(PL_main_cv),1,SvREFCNT_inc($curpad_sym));",
1655 "PL_amagic_generation= $amagic_generate;",
1656 );
1657
1658 }
1659 seek(STDOUT,0,0); #prevent print statements from BEGIN{} into the output
1660 output_boilerplate();
1661 print "\n";
1662 output_all("perl_init");
1663 output_runtime();
1664 print "\n";
1665 output_main();
1666 if (defined($module)) {
1667 my $cmodule = $module;
1668 $cmodule =~ s/::/__/g;
1669 print <<"EOT";
1670
1671#include "XSUB.h"
1672XS(boot_$cmodule)
1673{
1674 dXSARGS;
1675 perl_init();
1676 ENTER;
1677 SAVETMPS;
1678 SAVEVPTR(PL_curpad);
1679 SAVEVPTR(PL_op);
1680 PL_curpad = AvARRAY($curpad_sym);
1681 PL_op = $start;
1682 pp_main(aTHX);
1683 FREETMPS;
1684 LEAVE;
1685 ST(0) = &PL_sv_yes;
1686 XSRETURN(1);
1687}
1688EOT
1689 }
1690 if ($debug_timings) {
1691 warn sprintf("Done at %s\n", timing_info);
1692 }
1693}
1694
1695sub compile {
1696 my @options = @_;
1697 my ($option, $opt, $arg);
1698 OPTION:
1699 while ($option = shift @options) {
1700 if ($option =~ /^-(.)(.*)/) {
1701 $opt = $1;
1702 $arg = $2;
1703 } else {
1704 unshift @options, $option;
1705 last OPTION;
1706 }
1707 if ($opt eq "-" && $arg eq "-") {
1708 shift @options;
1709 last OPTION;
1710 } elsif ($opt eq "o") {
1711 $arg ||= shift @options;
1712 open(STDOUT, ">$arg") or return "open '>$arg': $!\n";
1713 } elsif ($opt eq "n") {
1714 $arg ||= shift @options;
1715 $module_name = $arg;
1716 } elsif ($opt eq "u") {
1717 $arg ||= shift @options;
1718 mark_unused($arg,undef);
1719 } elsif ($opt eq "f") {
1720 $arg ||= shift @options;
1721 my $value = $arg !~ s/^no-//;
1722 $arg =~ s/-/_/g;
1723 my $ref = $optimise{$arg};
1724 if (defined($ref)) {
1725 $$ref = $value;
1726 } else {
1727 warn qq(ignoring unknown optimisation option "$arg"\n);
1728 }
1729 } elsif ($opt eq "O") {
1730 $arg = 1 if $arg eq "";
1731 my $ref;
1732 foreach $ref (values %optimise) {
1733 $$ref = 0;
1734 }
1735 if ($arg >= 2) {
1736 $freetmps_each_loop = 1;
1737 }
1738 if ($arg >= 1) {
1739 $freetmps_each_bblock = 1 unless $freetmps_each_loop;
1740 }
1741 } elsif ($opt eq "m") {
1742 $arg ||= shift @options;
1743 $module = $arg;
1744 mark_unused($arg,undef);
1745 } elsif ($opt eq "p") {
1746 $arg ||= shift @options;
1747 $patchlevel = $arg;
1748 } elsif ($opt eq "D") {
1749 $arg ||= shift @options;
1750 foreach $arg (split(//, $arg)) {
1751 if ($arg eq "o") {
1752 B->debug(1);
1753 } elsif ($arg eq "O") {
1754 $debug_op = 1;
1755 } elsif ($arg eq "s") {
1756 $debug_stack = 1;
1757 } elsif ($arg eq "c") {
1758 $debug_cxstack = 1;
1759 } elsif ($arg eq "p") {
1760 $debug_pad = 1;
1761 } elsif ($arg eq "r") {
1762 $debug_runtime = 1;
1763 } elsif ($arg eq "S") {
1764 $debug_shadow = 1;
1765 } elsif ($arg eq "q") {
1766 $debug_queue = 1;
1767 } elsif ($arg eq "l") {
1768 $debug_lineno = 1;
1769 } elsif ($arg eq "t") {
1770 $debug_timings = 1;
1771 }
1772 }
1773 }
1774 }
1775 init_sections();
1776 $init = B::Section->get("init");
1777 $decl = B::Section->get("decl");
1778
1779 if (@options) {
1780 return sub {
1781 my ($objname, $ppname);
1782 foreach $objname (@options) {
1783 $objname = "main::$objname" unless $objname =~ /::/;
1784 ($ppname = $objname) =~ s/^.*?:://;
1785 eval "cc_obj(qq(pp_sub_$ppname), \\&$objname)";
1786 die "cc_obj(qq(pp_sub_$ppname, \\&$objname) failed: $@" if $@;
1787 return if $errors;
1788 }
1789 output_boilerplate();
1790 print "\n";
1791 output_all($module_name || "init_module");
1792 output_runtime();
1793 }
1794 } else {
1795 return sub { cc_main() };
1796 }
1797}
1798
17991;
1800
1801__END__
1802
1803=head1 NAME
1804
1805B::CC - Perl compiler's optimized C translation backend
1806
1807=head1 SYNOPSIS
1808
1809 perl -MO=CC[,OPTIONS] foo.pl
1810
1811=head1 DESCRIPTION
1812
1813This compiler backend takes Perl source and generates C source code
1814corresponding to the flow of your program. In other words, this
1815backend is somewhat a "real" compiler in the sense that many people
1816think about compilers. Note however that, currently, it is a very
1817poor compiler in that although it generates (mostly, or at least
1818sometimes) correct code, it performs relatively few optimisations.
1819This will change as the compiler develops. The result is that
1820running an executable compiled with this backend may start up more
1821quickly than running the original Perl program (a feature shared
1822by the B<C> compiler backend--see F<B::C>) and may also execute
1823slightly faster. This is by no means a good optimising compiler--yet.
1824
1825=head1 OPTIONS
1826
1827If there are any non-option arguments, they are taken to be
1828names of objects to be saved (probably doesn't work properly yet).
1829Without extra arguments, it saves the main program.
1830
1831=over 4
1832
1833=item B<-ofilename>
1834
1835Output to filename instead of STDOUT
1836
1837=item B<-v>
1838
1839Verbose compilation (currently gives a few compilation statistics).
1840
1841=item B<-->
1842
1843Force end of options
1844
1845=item B<-uPackname>
1846
1847Force apparently unused subs from package Packname to be compiled.
1848This allows programs to use eval "foo()" even when sub foo is never
1849seen to be used at compile time. The down side is that any subs which
1850really are never used also have code generated. This option is
1851necessary, for example, if you have a signal handler foo which you
1852initialise with C<$SIG{BAR} = "foo">. A better fix, though, is just
1853to change it to C<$SIG{BAR} = \&foo>. You can have multiple B<-u>
1854options. The compiler tries to figure out which packages may possibly
1855have subs in which need compiling but the current version doesn't do
1856it very well. In particular, it is confused by nested packages (i.e.
1857of the form C<A::B>) where package C<A> does not contain any subs.
1858
1859=item B<-mModulename>
1860
1861Instead of generating source for a runnable executable, generate
1862source for an XSUB module. The boot_Modulename function (which
1863DynaLoader can look for) does the appropriate initialisation and runs
1864the main part of the Perl source that is being compiled.
1865
1866
1867=item B<-D>
1868
1869Debug options (concatenated or separate flags like C<perl -D>).
1870
1871=item B<-Dr>
1872
1873Writes debugging output to STDERR just as it's about to write to the
1874program's runtime (otherwise writes debugging info as comments in
1875its C output).
1876
1877=item B<-DO>
1878
1879Outputs each OP as it's compiled
1880
1881=item B<-Ds>
1882
1883Outputs the contents of the shadow stack at each OP
1884
1885=item B<-Dp>
1886
1887Outputs the contents of the shadow pad of lexicals as it's loaded for
1888each sub or the main program.
1889
1890=item B<-Dq>
1891
1892Outputs the name of each fake PP function in the queue as it's about
1893to process it.
1894
1895=item B<-Dl>
1896
1897Output the filename and line number of each original line of Perl
1898code as it's processed (C<pp_nextstate>).
1899
1900=item B<-Dt>
1901
1902Outputs timing information of compilation stages.
1903
1904=item B<-f>
1905
1906Force optimisations on or off one at a time.
1907
1908=item B<-ffreetmps-each-bblock>
1909
1910Delays FREETMPS from the end of each statement to the end of the each
1911basic block.
1912
1913=item B<-ffreetmps-each-loop>
1914
1915Delays FREETMPS from the end of each statement to the end of the group
1916of basic blocks forming a loop. At most one of the freetmps-each-*
1917options can be used.
1918
1919=item B<-fomit-taint>
1920
1921Omits generating code for handling perl's tainting mechanism.
1922
1923=item B<-On>
1924
1925Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>.
1926Currently, B<-O1> sets B<-ffreetmps-each-bblock> and B<-O2>
1927sets B<-ffreetmps-each-loop>.
1928
1929=back
1930
1931=head1 EXAMPLES
1932
1933 perl -MO=CC,-O2,-ofoo.c foo.pl
1934 perl cc_harness -o foo foo.c
1935
1936Note that C<cc_harness> lives in the C<B> subdirectory of your perl
1937library directory. The utility called C<perlcc> may also be used to
1938help make use of this compiler.
1939
1940 perl -MO=CC,-mFoo,-oFoo.c Foo.pm
1941 perl cc_harness -shared -c -o Foo.so Foo.c
1942
1943=head1 BUGS
1944
1945Plenty. Current status: experimental.
1946
1947=head1 DIFFERENCES
1948
1949These aren't really bugs but they are constructs which are heavily
1950tied to perl's compile-and-go implementation and with which this
1951compiler backend cannot cope.
1952
1953=head2 Loops
1954
1955Standard perl calculates the target of "next", "last", and "redo"
1956at run-time. The compiler calculates the targets at compile-time.
1957For example, the program
1958
1959 sub skip_on_odd { next NUMBER if $_[0] % 2 }
1960 NUMBER: for ($i = 0; $i < 5; $i++) {
1961 skip_on_odd($i);
1962 print $i;
1963 }
1964
1965produces the output
1966
1967 024
1968
1969with standard perl but gives a compile-time error with the compiler.
1970
1971=head2 Context of ".."
1972
1973The context (scalar or array) of the ".." operator determines whether
1974it behaves as a range or a flip/flop. Standard perl delays until
1975runtime the decision of which context it is in but the compiler needs
1976to know the context at compile-time. For example,
1977
1978 @a = (4,6,1,0,0,1);
1979 sub range { (shift @a)..(shift @a) }
1980 print range();
1981 while (@a) { print scalar(range()) }
1982
1983generates the output
1984
1985 456123E0
1986
1987with standard Perl but gives a compile-time error with compiled Perl.
1988
1989=head2 Arithmetic
1990
1991Compiled Perl programs use native C arithmetic much more frequently
1992than standard perl. Operations on large numbers or on boundary
1993cases may produce different behaviour.
1994
1995=head2 Deprecated features
1996
1997Features of standard perl such as C<$[> which have been deprecated
1998in standard perl since Perl5 was released have not been implemented
1999in the compiler.
2000
2001=head1 AUTHOR
2002
2003Malcolm Beattie, C<[email protected]>
2004
2005=cut
Note: See TracBrowser for help on using the repository browser.