This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Missing test file. (Not very useful since Module::Signature
[perl5.git] / ext / B / B / Bytecode.pm
CommitLineData
1df34986
AE
1# B::Bytecode.pm
2# Copyright (c) 2003 Enache Adrian. All rights reserved.
3# This module is free software; you can redistribute and/or modify
4# it under the same terms as Perl itself.
5
6# Based on the original Bytecode.pm module written by Malcolm Beattie.
059a8bb7 7
1df34986 8package B::Bytecode;
28b605d8 9
a798dbf2 10use strict;
1df34986
AE
11use Config;
12use B qw(class main_cv main_root main_start cstring comppadlist
13 defstash curstash begin_av init_av end_av inc_gv warnhook diehook
14 dowarn SVt_PVGV SVt_PVHV OPf_SPECIAL OPf_STACKED OPf_MOD
15 OPpLVAL_INTRO SVf_FAKE SVf_READONLY);
16use B::Asmdata qw(@specialsv_name);
17use B::Assembler qw(asm newasm endasm);
18no warnings; # XXX
19
20#################################################
21
22my $ithreads = $Config{'useithreads'} eq 'define';
23my ($varix, $opix, $savebegins);
24my %strtab = (0,0);
25my %svtab = (0,0);
26my %optab = (0,0);
27my %spectab = (0,0);
28my %walked;
29my @cloop;
30my $tix = 1;
31sub asm;
32sub nice ($) { }
33my %files;
34
35#################################################
059a8bb7 36
1df34986
AE
37sub pvstring {
38 my $pv = shift;
39 defined($pv) ? cstring ($pv."\0") : "\"\"";
059a8bb7 40}
a798dbf2 41
1df34986
AE
42sub pvix {
43 my $str = pvstring shift;
44 my $ix = $strtab{$str};
45 defined($ix) ? $ix : do {
46 asm "newpv", $str;
47 asm "stpv", $strtab{$str} = $tix;
48 $tix++;
a798dbf2
MB
49 }
50}
51
1df34986
AE
52sub B::OP::ix {
53 my $op = shift;
54 my $ix = $optab{$$op};
55 defined($ix) ? $ix : do {
56 nice '['.$op->name.']';
566ece03
JH
57 asm "newopx", $op->size | $op->type <<7;
58 $optab{$$op} = $opix = $ix = $tix++;
1df34986
AE
59 $op->bsave($ix);
60 $ix;
a798dbf2
MB
61 }
62}
63
1df34986
AE
64sub B::SPECIAL::ix {
65 my $spec = shift;
66 my $ix = $spectab{$$spec};
67 defined($ix) ? $ix : do {
68 nice '['.$specialsv_name[$$spec].']';
566ece03
JH
69 asm "ldspecsvx", $$spec;
70 $spectab{$$spec} = $varix = $tix++;
1df34986 71 }
a798dbf2
MB
72}
73
1df34986
AE
74sub B::SV::ix {
75 my $sv = shift;
76 my $ix = $svtab{$$sv};
77 defined($ix) ? $ix : do {
78 nice '['.class($sv).']';
566ece03
JH
79 asm "newsvx", $sv->FLAGS;
80 $svtab{$$sv} = $varix = $ix = $tix++;
1df34986
AE
81 $sv->bsave($ix);
82 $ix;
83 }
84}
85
86sub B::GV::ix {
87 my ($gv,$desired) = @_;
88 my $ix = $svtab{$$gv};
89 defined($ix) ? $ix : do {
90 if ($gv->GP) {
91 my ($svix, $avix, $hvix, $cvix, $ioix, $formix);
92 nice "[GV]";
93 my $name = $gv->STASH->NAME . "::" . $gv->NAME;
566ece03
JH
94 asm "gv_fetchpvx", cstring $name;
95 $svtab{$$gv} = $varix = $ix = $tix++;
1df34986
AE
96 asm "sv_flags", $gv->FLAGS;
97 asm "sv_refcnt", $gv->REFCNT;
98 asm "xgv_flags", $gv->GvFLAGS;
99
100 asm "gp_refcnt", $gv->GvREFCNT;
101 asm "load_glob", $ix if $name eq "CORE::GLOBAL::glob";
102 return $ix
103 unless $desired || desired $gv;
104 $svix = $gv->SV->ix;
105 $avix = $gv->AV->ix;
106 $hvix = $gv->HV->ix;
107
566ece03 108 # XXX {{{{
1df34986
AE
109 my $cv = $gv->CV;
110 $cvix = $$cv && defined $files{$cv->FILE} ? $cv->ix : 0;
111 my $form = $gv->FORM;
112 $formix = $$form && defined $files{$form->FILE} ? $form->ix : 0;
113
566ece03
JH
114 $ioix = $name !~ /STDOUT$/ ? $gv->IO->ix : 0;
115 # }}}} XXX
1df34986
AE
116
117 nice "-GV-",
118 asm "ldsv", $varix = $ix unless $ix == $varix;
119 asm "gp_sv", $svix;
120 asm "gp_av", $avix;
121 asm "gp_hv", $hvix;
122 asm "gp_cv", $cvix;
123 asm "gp_io", $ioix;
124 asm "gp_cvgen", $gv->CVGEN;
125 asm "gp_form", $formix;
126 asm "gp_file", pvix $gv->FILE;
127 asm "gp_line", $gv->LINE;
128 asm "formfeed", $svix if $name eq "main::\cL";
129 } else {
130 nice "[GV]";
566ece03
JH
131 asm "newsvx", $gv->FLAGS;
132 $svtab{$$gv} = $varix = $ix = $tix++;
1df34986
AE
133 my $stashix = $gv->STASH->ix;
134 $gv->B::PVMG::bsave($ix);
135 asm "xgv_flags", $gv->GvFLAGS;
136 asm "xgv_stash", $stashix;
137 }
138 $ix;
139 }
a798dbf2
MB
140}
141
1df34986
AE
142sub B::HV::ix {
143 my $hv = shift;
144 my $ix = $svtab{$$hv};
145 defined($ix) ? $ix : do {
146 my ($ix,$i,@array);
147 my $name = $hv->NAME;
148 if ($name) {
149 nice "[STASH]";
566ece03
JH
150 asm "gv_stashpvx", cstring $name;
151 asm "sv_flags", $hv->FLAGS;
152 $svtab{$$hv} = $varix = $ix = $tix++;
1df34986
AE
153 asm "xhv_name", pvix $name;
154 # my $pmrootix = $hv->PMROOT->ix; # XXX
155 asm "ldsv", $varix = $ix unless $ix == $varix;
156 # asm "xhv_pmroot", $pmrootix; # XXX
157 } else {
158 nice "[HV]";
566ece03
JH
159 asm "newsvx", $hv->FLAGS;
160 $svtab{$$hv} = $varix = $ix = $tix++;
1df34986
AE
161 my $stashix = $hv->SvSTASH->ix;
162 for (@array = $hv->ARRAY) {
163 next if $i = not $i;
164 $_ = $_->ix;
165 }
166 nice "-HV-",
167 asm "ldsv", $varix = $ix unless $ix == $varix;
168 ($i = not $i) ? asm ("newpv", pvstring $_) : asm("hv_store", $_)
169 for @array;
170 asm "xnv", $hv->NVX;
171 asm "xmg_stash", $stashix;
172 }
173 asm "sv_refcnt", $hv->REFCNT;
1df34986 174 $ix;
a798dbf2
MB
175 }
176}
177
1df34986
AE
178sub B::NULL::ix {
179 my $sv = shift;
180 $$sv ? $sv->B::SV::ix : 0;
059a8bb7
JH
181}
182
1df34986 183sub B::NULL::opwalk { 0 }
a798dbf2 184
1df34986 185#################################################
a798dbf2 186
1df34986
AE
187sub B::NULL::bsave {
188 my ($sv,$ix) = @_;
059a8bb7 189
1df34986
AE
190 nice '-'.class($sv).'-',
191 asm "ldsv", $varix = $ix unless $ix == $varix;
192 asm "sv_refcnt", $sv->REFCNT;
a798dbf2
MB
193}
194
1df34986
AE
195sub B::SV::bsave;
196 *B::SV::bsave = *B::NULL::bsave;
a798dbf2 197
1df34986
AE
198sub B::RV::bsave {
199 my ($sv,$ix) = @_;
200 my $rvix = $sv->RV->ix;
201 $sv->B::NULL::bsave($ix);
202 asm "xrv", $rvix;
a798dbf2
MB
203}
204
1df34986
AE
205sub B::PV::bsave {
206 my ($sv,$ix) = @_;
207 $sv->B::NULL::bsave($ix);
208 asm "newpv", pvstring $sv->PVBM;
209 asm "xpv";
a798dbf2
MB
210}
211
1df34986
AE
212sub B::IV::bsave {
213 my ($sv,$ix) = @_;
214 $sv->B::NULL::bsave($ix);
215 asm "xiv", $sv->IVX;
a798dbf2
MB
216}
217
1df34986
AE
218sub B::NV::bsave {
219 my ($sv,$ix) = @_;
220 $sv->B::NULL::bsave($ix);
221 asm "xnv", sprintf "%.40g", $sv->NVX;
a798dbf2
MB
222}
223
1df34986
AE
224sub B::PVIV::bsave {
225 my ($sv,$ix) = @_;
226 $sv->POK ?
227 $sv->B::PV::bsave($ix):
228 $sv->ROK ?
229 $sv->B::RV::bsave($ix):
230 $sv->B::NULL::bsave($ix);
231 asm "xiv", !$ithreads && $sv->FLAGS & (SVf_FAKE|SVf_READONLY) ?
232 "0 but true" : $sv->IVX;
a798dbf2
MB
233}
234
1df34986
AE
235sub B::PVNV::bsave {
236 my ($sv,$ix) = @_;
237 $sv->B::PVIV::bsave($ix);
238 asm "xnv", sprintf "%.40g", $sv->NVX;
a798dbf2
MB
239}
240
1df34986
AE
241sub B::PVMG::domagic {
242 my ($sv,$ix) = @_;
243 nice '-MAGICAL-';
244 my @mglist = $sv->MAGIC;
245 my (@mgix, @namix);
246 for (@mglist) {
247 push @mgix, $_->OBJ->ix;
248 push @namix, $_->PTR->ix if $_->LENGTH == B::HEf_SVKEY;
a798dbf2 249 }
a798dbf2 250
1df34986
AE
251 nice '-'.class($sv).'-',
252 asm "ldsv", $varix = $ix unless $ix == $varix;
253 for (@mglist) {
254 asm "sv_magic", cstring $_->TYPE;
255 asm "mg_obj", shift @mgix;
256 my $length = $_->LENGTH;
257 if ($length == B::HEf_SVKEY) {
258 asm "mg_namex", shift @namix;
259 } elsif ($length) {
260 asm "newpv", pvstring $_->PTR;
261 asm "mg_name";
262 }
a798dbf2
MB
263 }
264}
265
1df34986
AE
266sub B::PVMG::bsave {
267 my ($sv,$ix) = @_;
268 my $stashix = $sv->SvSTASH->ix;
269 $sv->B::PVNV::bsave($ix);
270 asm "xmg_stash", $stashix;
271 $sv->domagic($ix) if $sv->MAGICAL;
272}
273
274sub B::PVLV::bsave {
275 my ($sv,$ix) = @_;
276 my $targix = $sv->TARG->ix;
277 $sv->B::PVMG::bsave($ix);
278 asm "xlv_targ", $targix;
279 asm "xlv_targoff", $sv->TARGOFF;
280 asm "xlv_targlen", $sv->TARGLEN;
281 asm "xlv_type", $sv->TYPE;
282
283}
284
285sub B::BM::bsave {
286 my ($sv,$ix) = @_;
287 $sv->B::PVMG::bsave($ix);
288 asm "xpv_cur", $sv->CUR;
289 asm "xbm_useful", $sv->USEFUL;
290 asm "xbm_previous", $sv->PREVIOUS;
291 asm "xbm_rare", $sv->RARE;
292}
293
294sub B::IO::bsave {
295 my ($io,$ix) = @_;
296 my $topix = $io->TOP_GV->ix;
297 my $fmtix = $io->FMT_GV->ix;
298 my $bottomix = $io->BOTTOM_GV->ix;
299 $io->B::PVMG::bsave($ix);
300 asm "xio_lines", $io->LINES;
301 asm "xio_page", $io->PAGE;
302 asm "xio_page_len", $io->PAGE_LEN;
303 asm "xio_lines_left", $io->LINES_LEFT;
304 asm "xio_top_name", pvix $io->TOP_NAME;
305 asm "xio_top_gv", $topix;
306 asm "xio_fmt_name", pvix $io->FMT_NAME;
307 asm "xio_fmt_gv", $fmtix;
308 asm "xio_bottom_name", pvix $io->BOTTOM_NAME;
309 asm "xio_bottom_gv", $bottomix;
310 asm "xio_subprocess", $io->SUBPROCESS;
311 asm "xio_type", ord $io->IoTYPE;
312 # asm "xio_flags", ord($io->IoFLAGS) & ~32; # XXX XXX
313}
314
315sub B::CV::bsave {
316 my ($cv,$ix) = @_;
317 my $stashix = $cv->STASH->ix;
1df34986
AE
318 my $gvix = $cv->GV->ix;
319 my $padlistix = $cv->PADLIST->ix;
320 my $outsideix = $cv->OUTSIDE->ix;
321 my $constix = $cv->CONST ? $cv->XSUBANY->ix : 0;
566ece03
JH
322 my $startix = $cv->START->opwalk;
323 my $rootix = $cv->ROOT->ix;
1df34986
AE
324
325 $cv->B::PVMG::bsave($ix);
326 asm "xcv_stash", $stashix;
327 asm "xcv_start", $startix;
328 asm "xcv_root", $rootix;
329 asm "xcv_xsubany", $constix;
330 asm "xcv_gv", $gvix;
331 asm "xcv_file", pvix $cv->FILE if $cv->FILE; # XXX AD
332 asm "xcv_padlist", $padlistix;
333 asm "xcv_outside", $outsideix;
334 asm "xcv_flags", $cv->CvFLAGS;
335 asm "xcv_outside_seq", $cv->OUTSIDE_SEQ;
336 asm "xcv_depth", $cv->DEPTH;
337}
338
339sub B::FM::bsave {
340 my ($form,$ix) = @_;
341
342 $form->B::CV::bsave($ix);
343 asm "xfm_lines", $form->LINES;
344}
345
346sub B::AV::bsave {
347 my ($av,$ix) = @_;
348 return $av->B::PVMG::bsave($ix) if $av->MAGICAL;
349 my @array = $av->ARRAY;
350 $_ = $_->ix for @array;
351 my $stashix = $av->SvSTASH->ix;
352
353 nice "-AV-",
354 asm "ldsv", $varix = $ix unless $ix == $varix;
355 asm "av_extend", $av->MAX;
356 asm "av_pushx", $_ for @array;
357 asm "sv_refcnt", $av->REFCNT;
1df34986
AE
358 asm "xav_flags", $av->AvFLAGS;
359 asm "xmg_stash", $stashix;
360}
361
362sub B::GV::desired {
363 my $gv = shift;
364 my ($cv, $form);
365 $files{$gv->FILE} && $gv->LINE
366 || ${$cv = $gv->CV} && $files{$cv->FILE}
367 || ${$form = $gv->FORM} && $files{$form->FILE}
a798dbf2
MB
368}
369
1df34986
AE
370sub B::HV::bwalk {
371 my $hv = shift;
372 return if $walked{$$hv}++;
373 my %stash = $hv->ARRAY;
374 while (my($k,$v) = each %stash) {
375 if ($v->SvTYPE == SVt_PVGV) {
376 my $hash = $v->HV;
377 if ($$hash && $hash->NAME) {
378 $hash->bwalk;
379 }
380 $v->ix(1) if desired $v;
381 } else {
382 nice "[prototype]";
566ece03
JH
383 asm "gv_fetchpvx", cstring $hv->NAME . "::$k";
384 $svtab{$$v} = $varix = $tix;
1df34986 385 $v->bsave($tix++);
566ece03 386 asm "sv_flags", $v->FLAGS;
1df34986
AE
387 }
388 }
a798dbf2
MB
389}
390
1df34986 391######################################################
a798dbf2 392
a798dbf2 393
1df34986
AE
394sub B::OP::bsave_thin {
395 my ($op, $ix) = @_;
396 my $next = $op->next;
397 my $nextix = $optab{$$next};
398 $nextix = 0, push @cloop, $op unless defined $nextix;
399 if ($ix != $opix) {
400 nice '-'.$op->name.'-',
401 asm "ldop", $opix = $ix;
a798dbf2 402 }
1df34986
AE
403 asm "op_next", $nextix;
404 asm "op_targ", $op->targ if $op->type; # tricky
405 asm "op_flags", $op->flags;
406 asm "op_private", $op->private;
a798dbf2
MB
407}
408
1df34986
AE
409sub B::OP::bsave;
410 *B::OP::bsave = *B::OP::bsave_thin;
a798dbf2 411
1df34986
AE
412sub B::UNOP::bsave {
413 my ($op, $ix) = @_;
414 my $name = $op->name;
415 my $flags = $op->flags;
416 my $first = $op->first;
417 my $firstix =
418 $name =~ /fl[io]p/
419 # that's just neat
566ece03 420 || (!$ithreads && $name eq 'regcomp')
1df34986
AE
421 # trick for /$a/o in pp_regcomp
422 || $name eq 'rv2sv'
423 && $op->flags & OPf_MOD
424 && $op->private & OPpLVAL_INTRO
425 # change #18774 made my life hard
426 ? $first->ix
427 : 0;
428
429 $op->B::OP::bsave($ix);
430 asm "op_first", $firstix;
431}
432
566ece03
JH
433sub B::BINOP::bsave {
434 my ($op, $ix) = @_;
435 if ($op->name eq 'aassign' && $op->private & B::OPpASSIGN_HASH()) {
436 my $last = $op->last;
437 my $lastix = do {
438 local *B::OP::bsave = *B::OP::bsave_fat;
439 local *B::UNOP::bsave = *B::UNOP::bsave_fat;
440 $last->ix;
441 };
442 asm "ldop", $lastix unless $lastix == $opix;
443 asm "op_targ", $last->targ;
444 $op->B::OP::bsave($ix);
445 asm "op_last", $lastix;
446 } else {
447 $op->B::OP::bsave($ix);
448 }
449}
450
451# not needed if no pseudohashes
452
453*B::BINOP::bsave = *B::OP::bsave if $] >= 5.009;
1df34986
AE
454
455# deal with sort / formline
456
457sub B::LISTOP::bsave {
458 my ($op, $ix) = @_;
459 my $name = $op->name;
460 if ($name eq 'sort' && $op->flags & (OPf_SPECIAL|OPf_STACKED)) {
461 my $first = $op->first;
462 my $firstix = $first->ix;
463 my $firstsiblix = do {
464 local *B::UNOP::bsave = *B::UNOP::bsave_fat;
465 local *B::LISTOP::bsave = *B::UNOP::bsave_fat;
466 $first->sibling->ix;
467 };
468 asm "ldop", $firstix unless $firstix == $opix;
469 asm "op_sibling", $firstsiblix;
470 $op->B::OP::bsave($ix);
471 asm "op_first", $firstix;
472 } elsif ($name eq 'formline') {
473 $op->B::UNOP::bsave_fat($ix);
a798dbf2 474 } else {
1df34986 475 $op->B::OP::bsave($ix);
a798dbf2 476 }
a798dbf2
MB
477}
478
1df34986 479# fat versions
a798dbf2 480
1df34986
AE
481sub B::OP::bsave_fat {
482 my ($op, $ix) = @_;
483 my $siblix = $op->sibling->ix;
a798dbf2 484
1df34986
AE
485 $op->B::OP::bsave_thin($ix);
486 asm "op_sibling", $siblix;
487 # asm "op_seq", -1; XXX don't allocate OPs piece by piece
a798dbf2
MB
488}
489
1df34986
AE
490sub B::UNOP::bsave_fat {
491 my ($op,$ix) = @_;
492 my $firstix = $op->first->ix;
a798dbf2 493
1df34986
AE
494 $op->B::OP::bsave($ix);
495 asm "op_first", $firstix;
a798dbf2
MB
496}
497
1df34986
AE
498sub B::BINOP::bsave_fat {
499 my ($op,$ix) = @_;
500 my $last = $op->last;
501 my $lastix = $op->last->ix;
502 if ($] < 5.009 && $op->name eq 'aassign' && $last->name eq 'null') {
503 asm "ldop", $lastix unless $lastix == $opix;
504 asm "op_targ", $last->targ;
a798dbf2 505 }
a798dbf2 506
1df34986
AE
507 $op->B::UNOP::bsave($ix);
508 asm "op_last", $lastix;
a798dbf2
MB
509}
510
1df34986
AE
511sub B::LOGOP::bsave {
512 my ($op,$ix) = @_;
513 my $otherix = $op->other->ix;
a798dbf2 514
1df34986
AE
515 $op->B::UNOP::bsave($ix);
516 asm "op_other", $otherix;
a798dbf2
MB
517}
518
1df34986
AE
519sub B::PMOP::bsave {
520 my ($op,$ix) = @_;
521 my ($rrop, $rrarg, $rstart);
059a8bb7 522
1df34986 523 # my $pmnextix = $op->pmnext->ix; # XXX
059a8bb7 524
1df34986
AE
525 if ($ithreads) {
526 if ($op->name eq 'subst') {
527 $rrop = "op_pmreplroot";
528 $rrarg = $op->pmreplroot->ix;
529 $rstart = $op->pmreplstart->ix;
530 } elsif ($op->name eq 'pushre') {
531 $rrop = "op_pmreplrootpo";
532 $rrarg = $op->pmreplroot;
a798dbf2 533 }
1df34986
AE
534 $op->B::BINOP::bsave($ix);
535 asm "op_pmstashpv", pvix $op->pmstashpv;
536 } else {
537 $rrop = "op_pmreplrootgv";
538 $rrarg = $op->pmreplroot->ix;
539 $rstart = $op->pmreplstart->ix if $op->name eq 'subst';
540 my $stashix = $op->pmstash->ix;
541 $op->B::BINOP::bsave($ix);
542 asm "op_pmstash", $stashix;
a798dbf2 543 }
1df34986
AE
544
545 asm $rrop, $rrarg if $rrop;
546 asm "op_pmreplstart", $rstart if $rstart;
547
548 asm "op_pmflags", $op->pmflags;
549 asm "op_pmpermflags", $op->pmpermflags;
550 asm "op_pmdynflags", $op->pmdynflags;
551 # asm "op_pmnext", $pmnextix; # XXX
552 asm "newpv", pvstring $op->precomp;
553 asm "pregcomp";
a798dbf2
MB
554}
555
1df34986
AE
556sub B::SVOP::bsave {
557 my ($op,$ix) = @_;
558 my $svix = $op->sv->ix;
559
560 $op->B::OP::bsave($ix);
561 asm "op_sv", $svix;
a798dbf2
MB
562}
563
1df34986
AE
564sub B::PADOP::bsave {
565 my ($op,$ix) = @_;
566
567 $op->B::OP::bsave($ix);
568 asm "op_padix", $op->padix;
a798dbf2
MB
569}
570
1df34986
AE
571sub B::PVOP::bsave {
572 my ($op,$ix) = @_;
573 $op->B::OP::bsave($ix);
574 return unless my $pv = $op->pv;
575
576 if ($op->name eq 'trans') {
577 asm "op_pv_tr", join ',', length($pv)/2, unpack("s*", $pv);
578 } else {
579 asm "newpv", pvstring $pv;
580 asm "op_pv";
a798dbf2 581 }
a798dbf2
MB
582}
583
1df34986
AE
584sub B::LOOP::bsave {
585 my ($op,$ix) = @_;
586 my $nextix = $op->nextop->ix;
587 my $lastix = $op->lastop->ix;
588 my $redoix = $op->redoop->ix;
589
590 $op->B::BINOP::bsave($ix);
591 asm "op_redoop", $redoix;
592 asm "op_nextop", $nextix;
593 asm "op_lastop", $lastix;
a798dbf2
MB
594}
595
1df34986
AE
596sub B::COP::bsave {
597 my ($cop,$ix) = @_;
598 my $warnix = $cop->warnings->ix;
599 my $ioix = $cop->io->ix;
600 if ($ithreads) {
601 $cop->B::OP::bsave($ix);
602 asm "cop_stashpv", pvix $cop->stashpv;
603 asm "cop_file", pvix $cop->file;
604 } else {
605 my $stashix = $cop->stash->ix;
606 my $fileix = $cop->filegv->ix(1);
607 $cop->B::OP::bsave($ix);
608 asm "cop_stash", $stashix;
609 asm "cop_filegv", $fileix;
a798dbf2 610 }
1df34986
AE
611 asm "cop_label", pvix $cop->label if $cop->label; # XXX AD
612 asm "cop_seq", $cop->cop_seq;
613 asm "cop_arybase", $cop->arybase;
614 asm "cop_line", $cop->line;
615 asm "cop_warnings", $warnix;
616 asm "cop_io", $ioix;
a798dbf2
MB
617}
618
1df34986
AE
619sub B::OP::opwalk {
620 my $op = shift;
621 my $ix = $optab{$$op};
622 defined($ix) ? $ix : do {
623 my $ix;
624 my @oplist = $op->oplist;
625 push @cloop, undef;
626 $ix = $_->ix while $_ = pop @oplist;
627 while ($_ = pop @cloop) {
628 asm "ldop", $optab{$$_};
629 asm "op_next", $optab{${$_->next}};
a798dbf2 630 }
1df34986 631 $ix;
a798dbf2
MB
632 }
633}
634
1df34986
AE
635#################################################
636
637sub save_cq {
638 my $av;
639 if (($av=begin_av)->isa("B::AV")) {
640 if ($savebegins) {
641 for ($av->ARRAY) {
642 next unless $_->FILE eq $0;
643 asm "push_begin", $_->ix;
644 }
645 } else {
646 for ($av->ARRAY) {
647 next unless $_->FILE eq $0;
566ece03 648 # XXX BEGIN { goto A while 1; A: }
1df34986 649 for (my $op = $_->START; $$op; $op = $op->next) {
566ece03
JH
650 next unless $op->name eq 'require' ||
651 # this kludge needed for tests
652 $op->name eq 'gv' && do {
653 my $gv = class($op) eq 'SVOP' ?
654 $op->gv :
655 (($_->PADLIST->ARRAY)[1]->ARRAY)[$op->padix];
656 $$gv && $gv->NAME =~ /use_ok|plan/
657 };
1df34986
AE
658 asm "push_begin", $_->ix;
659 last;
059a8bb7 660 }
059a8bb7
JH
661 }
662 }
a798dbf2 663 }
1df34986
AE
664 if (($av=init_av)->isa("B::AV")) {
665 for ($av->ARRAY) {
666 next unless $_->FILE eq $0;
667 asm "push_init", $_->ix;
059a8bb7
JH
668 }
669 }
1df34986
AE
670 if (($av=end_av)->isa("B::AV")) {
671 for ($av->ARRAY) {
672 next unless $_->FILE eq $0;
673 asm "push_end", $_->ix;
059a8bb7 674 }
a798dbf2
MB
675 }
676}
677
a798dbf2 678sub compile {
566ece03 679 my ($head, $scan, $T_inhinc, $keep_syn);
1df34986
AE
680 my $cwd = '';
681 $files{$0} = 1;
682 sub keep_syn {
683 $keep_syn = 1;
684 *B::OP::bsave = *B::OP::bsave_fat;
685 *B::UNOP::bsave = *B::UNOP::bsave_fat;
686 *B::BINOP::bsave = *B::BINOP::bsave_fat;
687 *B::LISTOP::bsave = *B::LISTOP::bsave_fat;
688 }
689 sub bwarn { print STDERR "Bytecode.pm: @_\n" }
690
691 for (@_) {
692 if (/^-S/) {
693 *newasm = *endasm = sub { };
694 *asm = sub { print " @_\n" };
695 *nice = sub ($) { print "\n@_\n" };
696 } elsif (/^-H/) {
697 require ByteLoader;
698 $head = "#! $^X\nuse ByteLoader $ByteLoader::VERSION;\n";
699 } elsif (/^-k/) {
700 keep_syn;
701 } elsif (/^-o(.*)$/) {
566ece03 702 open STDOUT, ">$1" or die "open $1: $!";
1df34986
AE
703 } elsif (/^-f(.*)$/) {
704 $files{$1} = 1;
566ece03
JH
705 } elsif (/^-s(.*)$/) {
706 $scan = length($1) ? $1 : $0;
1df34986
AE
707 } elsif (/^-b/) {
708 $savebegins = 1;
566ece03
JH
709 # this is here for the testsuite
710 } elsif (/^-TI/) {
1df34986 711 $T_inhinc = 1;
566ece03
JH
712 } elsif (/^-TF(.*)/) {
713 my $thatfile = $1;
714 *B::COP::file = sub { $thatfile };
a798dbf2 715 } else {
1df34986 716 bwarn "Ignoring '$_' option";
a798dbf2 717 }
1df34986
AE
718 }
719 if ($scan) {
566ece03
JH
720 my $f;
721 open $f, $scan
722 or bwarn("cannot rescan '$_'"), next;
723 while (<$f>) {
724 /^#\s*line\s+\d+\s+("?)(.*)\1/ and $files{$2} = 1;
725 /^#/ and next;
726 if (/\bgoto\b/ && !$keep_syn) {
727 bwarn "keeping the syntax tree: \"goto\" op found";
728 keep_syn;
a798dbf2 729 }
1df34986 730 }
566ece03 731 close $f;
1df34986
AE
732 }
733 binmode STDOUT;
734 return sub {
735 print $head if $head;
736 newasm sub { print @_ };
737
738 defstash->bwalk;
739 asm "main_start", main_start->opwalk;
740 asm "main_root", main_root->ix;
741 asm "main_cv", main_cv->ix;
742 asm "curpad", (comppadlist->ARRAY)[1]->ix;
743
744 asm "signal", cstring "__WARN__" # XXX
745 if warnhook->ix;
746 asm "incav", inc_gv->AV->ix if $T_inhinc;
747 save_cq;
748 asm "incav", inc_gv->AV->ix if $T_inhinc;
749 asm "dowarn", dowarn;
750
751 {
752 no strict 'refs';
753 nice "<DATA>";
754 my $dh = *{defstash->NAME."::DATA"};
755 local undef $/;
756 if (length (my $data = <$dh>)) {
757 asm "data", ord 'D';
758 print $data;
a798dbf2 759 } else {
1df34986 760 asm "ret";
a798dbf2 761 }
a798dbf2 762 }
1df34986
AE
763
764 endasm;
a798dbf2
MB
765 }
766}
767
7681;
566ece03
JH
769
770=head1 NAME
771
772B::Bytecode - Perl compiler's bytecode backend
773
774=head1 SYNOPSIS
775
776B<perl -MO=Bytecode>[B<,-H>][B<,-o>I<script.plc>] I<script.pl>
777
778=head1 DESCRIPTION
779
780Compiles a Perl script into a bytecode format that could be loaded
781later by the ByteLoader module and executed as a regular Perl script.
782
783=head1 EXAMPLE
784
785 $ perl -MO=Bytecode,-H,-ohi -e 'print "hi!\n"'
786 $ perl hi
787 hi!
788
789=head1 OPTIONS
790
791=over 4
792
793=item B<-b>
794
795Save all the BEGIN blocks. Normally only BEGIN blocks that C<require>
796other files (ex. C<use Foo;>) are saved.
797
798=item B<-H>
799
800prepend a C<use ByteLoader VERSION;> line to the produced bytecode.
801
802=item B<-k>
803
804keep the syntax tree - it is stripped by default.
805
806=item B<-o>I<outfile>
807
808put the bytecode in <outfile> instead of dumping it to STDOUT.
809
810=item B<-s>
811
812scan the script for C<# line ..> directives and for <goto LABEL>
813expressions. When gotos are found keep the syntax tree.
814
815=back
816
817=head1 KNOWN BUGS
818
819=over 4
820
821=item *
822
823C<BEGIN { goto A: while 1; A: }> won't even compile.
824
825=item *
826
827C<?...?> and C<reset> do not work as expected.
828
829=item *
830
831variables in C<(?{ ... })> constructs are not properly scoped.
832
833=item *
834
835scripts that use source filters will fail miserably.
836
837=back
838
839=head1 NOTICE
840
841There are also undocumented bugs and options.
842
843THIS CODE IS HIGHLY EXPERIMENTAL. USE AT YOUR OWN RISK.
844
845=head1 AUTHORS
846
847Originally written by Malcolm Beattie <mbeattie@sable.ox.ac.uk> and
848modified by Benjamin Stuhl <sho_pi@hotmail.com>.
849
850Rewritten by Enache Adrian <enache@rdslink.ro>, 2003 a.d.
851
852=cut