Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | # Bytecode.pm |
2 | # | |
3 | # Copyright (c) 1996-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 | # | |
8 | package B::Bytecode; | |
9 | ||
10 | our $VERSION = '1.00'; | |
11 | ||
12 | use strict; | |
13 | use Carp; | |
14 | use B qw(main_cv main_root main_start comppadlist | |
15 | class peekop walkoptree svref_2object cstring walksymtable | |
16 | init_av begin_av end_av | |
17 | SVf_POK SVp_POK SVf_IOK SVp_IOK SVf_NOK SVp_NOK | |
18 | SVf_READONLY GVf_IMPORTED_AV GVf_IMPORTED_CV GVf_IMPORTED_HV | |
19 | GVf_IMPORTED_SV SVTYPEMASK | |
20 | ); | |
21 | use B::Asmdata qw(@optype @specialsv_name); | |
22 | use B::Assembler qw(newasm endasm assemble); | |
23 | ||
24 | my %optype_enum; | |
25 | my $i; | |
26 | for ($i = 0; $i < @optype; $i++) { | |
27 | $optype_enum{$optype[$i]} = $i; | |
28 | } | |
29 | ||
30 | # Following is SVf_POK|SVp_POK | |
31 | # XXX Shouldn't be hardwired | |
32 | sub POK () { SVf_POK|SVp_POK } | |
33 | ||
34 | # Following is SVf_IOK|SVp_IOK | |
35 | # XXX Shouldn't be hardwired | |
36 | sub IOK () { SVf_IOK|SVp_IOK } | |
37 | ||
38 | # Following is SVf_NOK|SVp_NOK | |
39 | # XXX Shouldn't be hardwired | |
40 | sub NOK () { SVf_NOK|SVp_NOK } | |
41 | ||
42 | # nonexistant flags (see B::GV::bytecode for usage) | |
43 | sub GVf_IMPORTED_IO () { 0; } | |
44 | sub GVf_IMPORTED_FORM () { 0; } | |
45 | ||
46 | my ($verbose, $no_assemble, $debug_bc, $debug_cv); | |
47 | my @packages; # list of packages to compile | |
48 | ||
49 | sub asm (@) { # print replacement that knows about assembling | |
50 | if ($no_assemble) { | |
51 | print @_; | |
52 | } else { | |
53 | my $buf = join '', @_; | |
54 | assemble($_) for (split /\n/, $buf); | |
55 | } | |
56 | } | |
57 | ||
58 | sub asmf (@) { # printf replacement that knows about assembling | |
59 | if ($no_assemble) { | |
60 | printf shift(), @_; | |
61 | } else { | |
62 | my $format = shift; | |
63 | my $buf = sprintf $format, @_; | |
64 | assemble($_) for (split /\n/, $buf); | |
65 | } | |
66 | } | |
67 | ||
68 | # Optimisation options. On the command line, use hyphens instead of | |
69 | # underscores for compatibility with gcc-style options. We use | |
70 | # underscores here because they are OK in (strict) barewords. | |
71 | my ($compress_nullops, $omit_seq, $bypass_nullops); | |
72 | my %optimise = (compress_nullops => \$compress_nullops, | |
73 | omit_sequence_numbers => \$omit_seq, | |
74 | bypass_nullops => \$bypass_nullops); | |
75 | ||
76 | my $strip_syntree; # this is left here in case stripping the | |
77 | # syntree ever becomes safe again | |
78 | # -- BKS, June 2000 | |
79 | ||
80 | my $nextix = 0; | |
81 | my %symtable; # maps object addresses to object indices. | |
82 | # Filled in at allocation (newsv/newop) time. | |
83 | ||
84 | my %saved; # maps object addresses (for SVish classes) to "saved yet?" | |
85 | # flag. Set at FOO::bytecode time usually by SV::bytecode. | |
86 | # Manipulated via saved(), mark_saved(), unmark_saved(). | |
87 | ||
88 | my %strtable; # maps shared strings to object indices | |
89 | # Filled in at allocation (pvix) time | |
90 | ||
91 | my $svix = -1; # we keep track of when the sv register contains an element | |
92 | # of the object table to avoid unnecessary repeated | |
93 | # consecutive ldsv instructions. | |
94 | ||
95 | my $opix = -1; # Ditto for the op register. | |
96 | ||
97 | sub ldsv { | |
98 | my $ix = shift; | |
99 | if ($ix != $svix) { | |
100 | asm "ldsv $ix\n"; | |
101 | $svix = $ix; | |
102 | } | |
103 | } | |
104 | ||
105 | sub stsv { | |
106 | my $ix = shift; | |
107 | asm "stsv $ix\n"; | |
108 | $svix = $ix; | |
109 | } | |
110 | ||
111 | sub set_svix { | |
112 | $svix = shift; | |
113 | } | |
114 | ||
115 | sub ldop { | |
116 | my $ix = shift; | |
117 | if ($ix != $opix) { | |
118 | asm "ldop $ix\n"; | |
119 | $opix = $ix; | |
120 | } | |
121 | } | |
122 | ||
123 | sub stop { | |
124 | my $ix = shift; | |
125 | asm "stop $ix\n"; | |
126 | $opix = $ix; | |
127 | } | |
128 | ||
129 | sub set_opix { | |
130 | $opix = shift; | |
131 | } | |
132 | ||
133 | sub pvstring { | |
134 | my $str = shift; | |
135 | if (defined($str)) { | |
136 | return cstring($str . "\0"); | |
137 | } else { | |
138 | return '""'; | |
139 | } | |
140 | } | |
141 | ||
142 | sub nv { | |
143 | # print full precision | |
144 | my $str = sprintf "%.40f", $_[0]; | |
145 | $str =~ s/0+$//; # remove trailing zeros | |
146 | $str =~ s/\.$/.0/; | |
147 | return $str; | |
148 | } | |
149 | ||
150 | sub saved { $saved{${$_[0]}} } | |
151 | sub mark_saved { $saved{${$_[0]}} = 1 } | |
152 | sub unmark_saved { $saved{${$_[0]}} = 0 } | |
153 | ||
154 | sub debug { $debug_bc = shift } | |
155 | ||
156 | sub pvix { # save a shared PV (mainly for COPs) | |
157 | return $strtable{$_[0]} if defined($strtable{$_[0]}); | |
158 | asmf "newpv %s\n", pvstring($_[0]); | |
159 | my $ix = $nextix++; | |
160 | $strtable{$_[0]} = $ix; | |
161 | asmf "stpv %d\n", $ix; | |
162 | return $ix; | |
163 | } | |
164 | ||
165 | sub B::OBJECT::nyi { | |
166 | my $obj = shift; | |
167 | warn sprintf("bytecode save method for %s (0x%x) not yet implemented\n", | |
168 | class($obj), $$obj); | |
169 | } | |
170 | ||
171 | # | |
172 | # objix may stomp on the op register (for op objects) | |
173 | # or the sv register (for SV objects) | |
174 | # | |
175 | sub B::OBJECT::objix { | |
176 | my $obj = shift; | |
177 | my $ix = $symtable{$$obj}; | |
178 | if (defined($ix)) { | |
179 | return $ix; | |
180 | } else { | |
181 | $obj->newix($nextix); | |
182 | return $symtable{$$obj} = $nextix++; | |
183 | } | |
184 | } | |
185 | ||
186 | sub B::SV::newix { | |
187 | my ($sv, $ix) = @_; | |
188 | asmf "newsv %d\t# %s\n", $sv->FLAGS & SVTYPEMASK, class($sv); | |
189 | stsv($ix); | |
190 | } | |
191 | ||
192 | sub B::GV::newix { | |
193 | my ($gv, $ix) = @_; | |
194 | my $gvname = $gv->NAME; | |
195 | my $name = cstring($gv->STASH->NAME . "::" . $gvname); | |
196 | asm "gv_fetchpv $name\n"; | |
197 | stsv($ix); | |
198 | } | |
199 | ||
200 | sub B::HV::newix { | |
201 | my ($hv, $ix) = @_; | |
202 | my $name = $hv->NAME; | |
203 | if ($name) { | |
204 | # It's a stash | |
205 | asmf "gv_stashpv %s\n", cstring($name); | |
206 | stsv($ix); | |
207 | } else { | |
208 | # It's an ordinary HV. Fall back to ordinary newix method | |
209 | $hv->B::SV::newix($ix); | |
210 | } | |
211 | } | |
212 | ||
213 | sub B::SPECIAL::newix { | |
214 | my ($sv, $ix) = @_; | |
215 | # Special case. $$sv is not the address of the SV but an | |
216 | # index into svspecialsv_list. | |
217 | asmf "ldspecsv $$sv\t# %s\n", $specialsv_name[$$sv]; | |
218 | stsv($ix); | |
219 | } | |
220 | ||
221 | sub B::OP::newix { | |
222 | my ($op, $ix) = @_; | |
223 | my $class = class($op); | |
224 | my $typenum = $optype_enum{$class}; | |
225 | croak("OP::newix: can't understand class $class") unless defined($typenum); | |
226 | asm "newop $typenum\t# $class\n"; | |
227 | stop($ix); | |
228 | } | |
229 | ||
230 | sub B::OP::walkoptree_debug { | |
231 | my $op = shift; | |
232 | warn(sprintf("walkoptree: %s\n", peekop($op))); | |
233 | } | |
234 | ||
235 | sub B::OP::bytecode { | |
236 | my $op = shift; | |
237 | my $next = $op->next; | |
238 | my $nextix; | |
239 | my $sibix = $op->sibling->objix unless $strip_syntree; | |
240 | my $ix = $op->objix; | |
241 | my $type = $op->type; | |
242 | ||
243 | if ($bypass_nullops) { | |
244 | $next = $next->next while $$next && $next->type == 0; | |
245 | } | |
246 | $nextix = $next->objix; | |
247 | ||
248 | asmf "# %s\n", peekop($op) if $debug_bc; | |
249 | ldop($ix); | |
250 | asm "op_next $nextix\n"; | |
251 | asm "op_sibling $sibix\n" unless $strip_syntree; | |
252 | asmf "op_type %s\t# %d\n", "pp_" . $op->name, $type; | |
253 | asmf("op_seq %d\n", $op->seq) unless $omit_seq; | |
254 | if ($type || !$compress_nullops) { | |
255 | asmf "op_targ %d\nop_flags 0x%x\nop_private 0x%x\n", | |
256 | $op->targ, $op->flags, $op->private; | |
257 | } | |
258 | } | |
259 | ||
260 | sub B::UNOP::bytecode { | |
261 | my $op = shift; | |
262 | my $firstix = $op->first->objix unless $strip_syntree; | |
263 | $op->B::OP::bytecode; | |
264 | if (($op->type || !$compress_nullops) && !$strip_syntree) { | |
265 | asm "op_first $firstix\n"; | |
266 | } | |
267 | } | |
268 | ||
269 | sub B::LOGOP::bytecode { | |
270 | my $op = shift; | |
271 | my $otherix = $op->other->objix; | |
272 | $op->B::UNOP::bytecode; | |
273 | asm "op_other $otherix\n"; | |
274 | } | |
275 | ||
276 | sub B::SVOP::bytecode { | |
277 | my $op = shift; | |
278 | my $sv = $op->sv; | |
279 | my $svix = $sv->objix; | |
280 | $op->B::OP::bytecode; | |
281 | asm "op_sv $svix\n"; | |
282 | $sv->bytecode; | |
283 | } | |
284 | ||
285 | sub B::PADOP::bytecode { | |
286 | my $op = shift; | |
287 | my $padix = $op->padix; | |
288 | $op->B::OP::bytecode; | |
289 | asm "op_padix $padix\n"; | |
290 | } | |
291 | ||
292 | sub B::PVOP::bytecode { | |
293 | my $op = shift; | |
294 | my $pv = $op->pv; | |
295 | $op->B::OP::bytecode; | |
296 | # | |
297 | # This would be easy except that OP_TRANS uses a PVOP to store an | |
298 | # endian-dependent array of 256 shorts instead of a plain string. | |
299 | # | |
300 | if ($op->name eq "trans") { | |
301 | my @shorts = unpack("s256", $pv); # assembler handles endianness | |
302 | asm "op_pv_tr ", join(",", @shorts), "\n"; | |
303 | } else { | |
304 | asmf "newpv %s\nop_pv\n", pvstring($pv); | |
305 | } | |
306 | } | |
307 | ||
308 | sub B::BINOP::bytecode { | |
309 | my $op = shift; | |
310 | my $lastix = $op->last->objix unless $strip_syntree; | |
311 | $op->B::UNOP::bytecode; | |
312 | if (($op->type || !$compress_nullops) && !$strip_syntree) { | |
313 | asm "op_last $lastix\n"; | |
314 | } | |
315 | } | |
316 | ||
317 | sub B::LOOP::bytecode { | |
318 | my $op = shift; | |
319 | my $redoopix = $op->redoop->objix; | |
320 | my $nextopix = $op->nextop->objix; | |
321 | my $lastopix = $op->lastop->objix; | |
322 | $op->B::LISTOP::bytecode; | |
323 | asm "op_redoop $redoopix\nop_nextop $nextopix\nop_lastop $lastopix\n"; | |
324 | } | |
325 | ||
326 | sub B::COP::bytecode { | |
327 | my $op = shift; | |
328 | my $file = $op->file; | |
329 | my $line = $op->line; | |
330 | if ($debug_bc) { # do this early to aid debugging | |
331 | asmf "# line %s:%d\n", $file, $line; | |
332 | } | |
333 | my $stashpv = $op->stashpv; | |
334 | my $warnings = $op->warnings; | |
335 | my $warningsix = $warnings->objix; | |
336 | my $labelix = pvix($op->label); | |
337 | my $stashix = pvix($stashpv); | |
338 | my $fileix = pvix($file); | |
339 | $warnings->bytecode; | |
340 | $op->B::OP::bytecode; | |
341 | asmf <<"EOT", $labelix, $stashix, $op->cop_seq, $fileix, $op->arybase; | |
342 | cop_label %d | |
343 | cop_stashpv %d | |
344 | cop_seq %d | |
345 | cop_file %d | |
346 | cop_arybase %d | |
347 | cop_line $line | |
348 | cop_warnings $warningsix | |
349 | EOT | |
350 | } | |
351 | ||
352 | sub B::PMOP::bytecode { | |
353 | my $op = shift; | |
354 | my $replroot = $op->pmreplroot; | |
355 | my $replrootix = $replroot->objix; | |
356 | my $replstartix = $op->pmreplstart->objix; | |
357 | my $opname = $op->name; | |
358 | # pmnext is corrupt in some PMOPs (see misc.t for example) | |
359 | #my $pmnextix = $op->pmnext->objix; | |
360 | ||
361 | if ($$replroot) { | |
362 | # OP_PUSHRE (a mutated version of OP_MATCH for the regexp | |
363 | # argument to a split) stores a GV in op_pmreplroot instead | |
364 | # of a substitution syntax tree. We don't want to walk that... | |
365 | if ($opname eq "pushre") { | |
366 | $replroot->bytecode; | |
367 | } else { | |
368 | walkoptree($replroot, "bytecode"); | |
369 | } | |
370 | } | |
371 | $op->B::LISTOP::bytecode; | |
372 | if ($opname eq "pushre") { | |
373 | asmf "op_pmreplrootgv $replrootix\n"; | |
374 | } else { | |
375 | asm "op_pmreplroot $replrootix\nop_pmreplstart $replstartix\n"; | |
376 | } | |
377 | my $re = pvstring($op->precomp); | |
378 | # op_pmnext omitted since a perl bug means it's sometime corrupt | |
379 | asmf <<"EOT", $op->pmflags, $op->pmpermflags; | |
380 | op_pmflags 0x%x | |
381 | op_pmpermflags 0x%x | |
382 | newpv $re | |
383 | pregcomp | |
384 | EOT | |
385 | } | |
386 | ||
387 | sub B::SV::bytecode { | |
388 | my $sv = shift; | |
389 | return if saved($sv); | |
390 | my $ix = $sv->objix; | |
391 | my $refcnt = $sv->REFCNT; | |
392 | my $flags = sprintf("0x%x", $sv->FLAGS); | |
393 | ldsv($ix); | |
394 | asm "sv_refcnt $refcnt\nsv_flags $flags\n"; | |
395 | mark_saved($sv); | |
396 | } | |
397 | ||
398 | sub B::PV::bytecode { | |
399 | my $sv = shift; | |
400 | return if saved($sv); | |
401 | $sv->B::SV::bytecode; | |
402 | asmf("newpv %s\nxpv\n", pvstring($sv->PV)) if $sv->FLAGS & POK; | |
403 | } | |
404 | ||
405 | sub B::IV::bytecode { | |
406 | my $sv = shift; | |
407 | return if saved($sv); | |
408 | my $iv = $sv->IVX; | |
409 | $sv->B::SV::bytecode; | |
410 | asmf "%s $iv\n", $sv->needs64bits ? "xiv64" : "xiv32" if $sv->FLAGS & IOK; # could be PVNV | |
411 | } | |
412 | ||
413 | sub B::NV::bytecode { | |
414 | my $sv = shift; | |
415 | return if saved($sv); | |
416 | $sv->B::SV::bytecode; | |
417 | asmf "xnv %s\n", nv($sv->NVX); | |
418 | } | |
419 | ||
420 | sub B::RV::bytecode { | |
421 | my $sv = shift; | |
422 | return if saved($sv); | |
423 | my $rv = $sv->RV; | |
424 | my $rvix = $rv->objix; | |
425 | $rv->bytecode; | |
426 | $sv->B::SV::bytecode; | |
427 | asm "xrv $rvix\n"; | |
428 | } | |
429 | ||
430 | sub B::PVIV::bytecode { | |
431 | my $sv = shift; | |
432 | return if saved($sv); | |
433 | my $iv = $sv->IVX; | |
434 | $sv->B::PV::bytecode; | |
435 | asmf "%s $iv\n", $sv->needs64bits ? "xiv64" : "xiv32"; | |
436 | } | |
437 | ||
438 | sub B::PVNV::bytecode { | |
439 | my $sv = shift; | |
440 | my $flag = shift || 0; | |
441 | # The $flag argument is passed through PVMG::bytecode by BM::bytecode | |
442 | # and AV::bytecode and indicates special handling. $flag = 1 is used by | |
443 | # BM::bytecode and means that we should ensure we save the whole B-M | |
444 | # table. It consists of 257 bytes (256 char array plus a final \0) | |
445 | # which follow the ordinary PV+\0 and the 257 bytes are *not* reflected | |
446 | # in SvCUR. $flag = 2 is used by AV::bytecode and means that we only | |
447 | # call SV::bytecode instead of saving PV and calling NV::bytecode since | |
448 | # PV/NV/IV stuff is different for AVs. | |
449 | return if saved($sv); | |
450 | if ($flag == 2) { | |
451 | $sv->B::SV::bytecode; | |
452 | } else { | |
453 | my $pv = $sv->PV; | |
454 | $sv->B::IV::bytecode; | |
455 | asmf "xnv %s\n", nv($sv->NVX); | |
456 | if ($flag == 1) { | |
457 | $pv .= "\0" . $sv->TABLE; | |
458 | asmf "newpv %s\npv_cur %d\nxpv\n", pvstring($pv),length($pv)-257; | |
459 | } else { | |
460 | asmf("newpv %s\nxpv\n", pvstring($pv)) if $sv->FLAGS & POK; | |
461 | } | |
462 | } | |
463 | } | |
464 | ||
465 | sub B::PVMG::bytecode { | |
466 | my ($sv, $flag) = @_; | |
467 | # See B::PVNV::bytecode for an explanation of $flag. | |
468 | return if saved($sv); | |
469 | # XXX We assume SvSTASH is already saved and don't save it later ourselves | |
470 | my $stashix = $sv->SvSTASH->objix; | |
471 | my @mgchain = $sv->MAGIC; | |
472 | my (@mgobjix, $mg); | |
473 | # | |
474 | # We need to traverse the magic chain and get objix for each OBJ | |
475 | # field *before* we do B::PVNV::bytecode since objix overwrites | |
476 | # the sv register. However, we need to write the magic-saving | |
477 | # bytecode *after* B::PVNV::bytecode since sv isn't initialised | |
478 | # to refer to $sv until then. | |
479 | # | |
480 | @mgobjix = map($_->OBJ->objix, @mgchain); | |
481 | $sv->B::PVNV::bytecode($flag); | |
482 | asm "xmg_stash $stashix\n"; | |
483 | foreach $mg (@mgchain) { | |
484 | asmf "sv_magic %s\nmg_obj %d\nnewpv %s\nmg_pv\n", | |
485 | cstring($mg->TYPE), shift(@mgobjix), pvstring($mg->PTR); | |
486 | } | |
487 | } | |
488 | ||
489 | sub B::PVLV::bytecode { | |
490 | my $sv = shift; | |
491 | return if saved($sv); | |
492 | $sv->B::PVMG::bytecode; | |
493 | asmf <<'EOT', $sv->TARGOFF, $sv->TARGLEN, cstring($sv->TYPE); | |
494 | xlv_targoff %d | |
495 | xlv_targlen %d | |
496 | xlv_type %s | |
497 | EOT | |
498 | } | |
499 | ||
500 | sub B::BM::bytecode { | |
501 | my $sv = shift; | |
502 | return if saved($sv); | |
503 | # See PVNV::bytecode for an explanation of what the argument does | |
504 | $sv->B::PVMG::bytecode(1); | |
505 | asmf "xbm_useful %d\nxbm_previous %d\nxbm_rare %d\n", | |
506 | $sv->USEFUL, $sv->PREVIOUS, $sv->RARE; | |
507 | } | |
508 | ||
509 | sub empty_gv { # is a GV empty except for imported stuff? | |
510 | my $gv = shift; | |
511 | ||
512 | return 0 if ($gv->SV->FLAGS & SVTYPEMASK); # sv not SVt_NULL | |
513 | my @subfield_names = qw(AV HV CV FORM IO); | |
514 | @subfield_names = grep {; | |
515 | no strict 'refs'; | |
516 | !($gv->GvFLAGS & ${\"GVf_IMPORTED_$_"}->()) && ${$gv->$_()}; | |
517 | } @subfield_names; | |
518 | return scalar @subfield_names; | |
519 | } | |
520 | ||
521 | sub B::GV::bytecode { | |
522 | my $gv = shift; | |
523 | return if saved($gv); | |
524 | return unless grep { $_ eq $gv->STASH->NAME; } @packages; | |
525 | return if $gv->NAME =~ m/^\(/; # ignore overloads - they'll be rebuilt | |
526 | my $ix = $gv->objix; | |
527 | mark_saved($gv); | |
528 | ldsv($ix); | |
529 | asmf <<"EOT", $gv->FLAGS, $gv->GvFLAGS; | |
530 | sv_flags 0x%x | |
531 | xgv_flags 0x%x | |
532 | EOT | |
533 | my $refcnt = $gv->REFCNT; | |
534 | asmf("sv_refcnt_add %d\n", $refcnt - 1) if $refcnt > 1; | |
535 | return if $gv->is_empty; | |
536 | asmf <<"EOT", $gv->LINE, pvix($gv->FILE); | |
537 | gp_line %d | |
538 | gp_file %d | |
539 | EOT | |
540 | my $gvname = $gv->NAME; | |
541 | my $name = cstring($gv->STASH->NAME . "::" . $gvname); | |
542 | my $egv = $gv->EGV; | |
543 | my $egvix = $egv->objix; | |
544 | my $gvrefcnt = $gv->GvREFCNT; | |
545 | asmf("gp_refcnt_add %d\n", $gvrefcnt - 1) if $gvrefcnt > 1; | |
546 | if ($gvrefcnt > 1 && $ix != $egvix) { | |
547 | asm "gp_share $egvix\n"; | |
548 | } else { | |
549 | if ($gvname !~ /^([^A-Za-z]|STDIN|STDOUT|STDERR|ARGV|SIG|ENV)$/) { | |
550 | my $i; | |
551 | my @subfield_names = qw(SV AV HV CV FORM IO); | |
552 | @subfield_names = grep {; | |
553 | no strict 'refs'; | |
554 | !($gv->GvFLAGS & ${\"GVf_IMPORTED_$_"}->()); | |
555 | } @subfield_names; | |
556 | my @subfields = map($gv->$_(), @subfield_names); | |
557 | my @ixes = map($_->objix, @subfields); | |
558 | # Reset sv register for $gv | |
559 | ldsv($ix); | |
560 | for ($i = 0; $i < @ixes; $i++) { | |
561 | asmf "gp_%s %d\n", lc($subfield_names[$i]), $ixes[$i]; | |
562 | } | |
563 | # Now save all the subfields | |
564 | my $sv; | |
565 | foreach $sv (@subfields) { | |
566 | $sv->bytecode; | |
567 | } | |
568 | } | |
569 | } | |
570 | } | |
571 | ||
572 | sub B::HV::bytecode { | |
573 | my $hv = shift; | |
574 | return if saved($hv); | |
575 | mark_saved($hv); | |
576 | my $name = $hv->NAME; | |
577 | my $ix = $hv->objix; | |
578 | if (!$name) { | |
579 | # It's an ordinary HV. Stashes have NAME set and need no further | |
580 | # saving beyond the gv_stashpv that $hv->objix already ensures. | |
581 | my @contents = $hv->ARRAY; | |
582 | my ($i, @ixes); | |
583 | for ($i = 1; $i < @contents; $i += 2) { | |
584 | push(@ixes, $contents[$i]->objix); | |
585 | } | |
586 | for ($i = 1; $i < @contents; $i += 2) { | |
587 | $contents[$i]->bytecode; | |
588 | } | |
589 | ldsv($ix); | |
590 | for ($i = 0; $i < @contents; $i += 2) { | |
591 | asmf("newpv %s\nhv_store %d\n", | |
592 | pvstring($contents[$i]), $ixes[$i / 2]); | |
593 | } | |
594 | asmf "sv_refcnt %d\nsv_flags 0x%x\n", $hv->REFCNT, $hv->FLAGS; | |
595 | } | |
596 | } | |
597 | ||
598 | sub B::AV::bytecode { | |
599 | my $av = shift; | |
600 | return if saved($av); | |
601 | my $ix = $av->objix; | |
602 | my $fill = $av->FILL; | |
603 | my $max = $av->MAX; | |
604 | my (@array, @ixes); | |
605 | if ($fill > -1) { | |
606 | @array = $av->ARRAY; | |
607 | @ixes = map($_->objix, @array); | |
608 | my $sv; | |
609 | foreach $sv (@array) { | |
610 | $sv->bytecode; | |
611 | } | |
612 | } | |
613 | # See PVNV::bytecode for the meaning of the flag argument of 2. | |
614 | $av->B::PVMG::bytecode(2); | |
615 | # Recover sv register and set AvMAX and AvFILL to -1 (since we | |
616 | # create an AV with NEWSV and SvUPGRADE rather than doing newAV | |
617 | # which is what sets AvMAX and AvFILL. | |
618 | ldsv($ix); | |
619 | asmf "sv_flags 0x%x\n", $av->FLAGS & ~SVf_READONLY; # SvREADONLY_off($av) in case PADCONST | |
620 | asmf "xav_flags 0x%x\nxav_max -1\nxav_fill -1\n", $av->AvFLAGS; | |
621 | if ($fill > -1) { | |
622 | my $elix; | |
623 | foreach $elix (@ixes) { | |
624 | asm "av_push $elix\n"; | |
625 | } | |
626 | } else { | |
627 | if ($max > -1) { | |
628 | asm "av_extend $max\n"; | |
629 | } | |
630 | } | |
631 | asmf "sv_flags 0x%x\n", $av->FLAGS; # restore flags from above | |
632 | } | |
633 | ||
634 | sub B::CV::bytecode { | |
635 | my $cv = shift; | |
636 | return if saved($cv); | |
637 | return if ${$cv->GV} && ($cv->GV->GvFLAGS & GVf_IMPORTED_CV); | |
638 | my $fileix = pvix($cv->FILE); | |
639 | my $ix = $cv->objix; | |
640 | $cv->B::PVMG::bytecode; | |
641 | my $i; | |
642 | my @subfield_names = qw(ROOT START STASH GV PADLIST OUTSIDE); | |
643 | my @subfields = map($cv->$_(), @subfield_names); | |
644 | my @ixes = map($_->objix, @subfields); | |
645 | # Save OP tree from CvROOT (first element of @subfields) | |
646 | my $root = shift @subfields; | |
647 | if ($$root) { | |
648 | walkoptree($root, "bytecode"); | |
649 | } | |
650 | # Reset sv register for $cv (since above ->objix calls stomped on it) | |
651 | ldsv($ix); | |
652 | for ($i = 0; $i < @ixes; $i++) { | |
653 | asmf "xcv_%s %d\n", lc($subfield_names[$i]), $ixes[$i]; | |
654 | } | |
655 | asmf "xcv_depth %d\nxcv_flags 0x%x\n", $cv->DEPTH, $cv->CvFLAGS; | |
656 | asmf "xcv_file %d\n", $fileix; | |
657 | # Now save all the subfields (except for CvROOT which was handled | |
658 | # above) and CvSTART (now the initial element of @subfields). | |
659 | shift @subfields; # bye-bye CvSTART | |
660 | my $sv; | |
661 | foreach $sv (@subfields) { | |
662 | $sv->bytecode; | |
663 | } | |
664 | } | |
665 | ||
666 | sub B::IO::bytecode { | |
667 | my $io = shift; | |
668 | return if saved($io); | |
669 | my $ix = $io->objix; | |
670 | my $top_gv = $io->TOP_GV; | |
671 | my $top_gvix = $top_gv->objix; | |
672 | my $fmt_gv = $io->FMT_GV; | |
673 | my $fmt_gvix = $fmt_gv->objix; | |
674 | my $bottom_gv = $io->BOTTOM_GV; | |
675 | my $bottom_gvix = $bottom_gv->objix; | |
676 | ||
677 | $io->B::PVMG::bytecode; | |
678 | ldsv($ix); | |
679 | asm "xio_top_gv $top_gvix\n"; | |
680 | asm "xio_fmt_gv $fmt_gvix\n"; | |
681 | asm "xio_bottom_gv $bottom_gvix\n"; | |
682 | my $field; | |
683 | foreach $field (qw(TOP_NAME FMT_NAME BOTTOM_NAME)) { | |
684 | asmf "newpv %s\nxio_%s\n", pvstring($io->$field()), lc($field); | |
685 | } | |
686 | foreach $field (qw(LINES PAGE PAGE_LEN LINES_LEFT SUBPROCESS)) { | |
687 | asmf "xio_%s %d\n", lc($field), $io->$field(); | |
688 | } | |
689 | asmf "xio_type %s\nxio_flags 0x%x\n", cstring($io->IoTYPE), $io->IoFLAGS; | |
690 | $top_gv->bytecode; | |
691 | $fmt_gv->bytecode; | |
692 | $bottom_gv->bytecode; | |
693 | } | |
694 | ||
695 | sub B::SPECIAL::bytecode { | |
696 | # nothing extra needs doing | |
697 | } | |
698 | ||
699 | sub bytecompile_object { | |
700 | for my $sv (@_) { | |
701 | svref_2object($sv)->bytecode; | |
702 | } | |
703 | } | |
704 | ||
705 | sub B::GV::bytecodecv { | |
706 | my $gv = shift; | |
707 | my $cv = $gv->CV; | |
708 | if ($$cv && !saved($cv) && !($gv->FLAGS & GVf_IMPORTED_CV)) { | |
709 | if ($debug_cv) { | |
710 | warn sprintf("saving extra CV &%s::%s (0x%x) from GV 0x%x\n", | |
711 | $gv->STASH->NAME, $gv->NAME, $$cv, $$gv); | |
712 | } | |
713 | $gv->bytecode; | |
714 | } | |
715 | } | |
716 | ||
717 | sub save_call_queues { | |
718 | if (begin_av()->isa("B::AV")) { # this is just to save 'use Foo;' calls | |
719 | for my $cv (begin_av()->ARRAY) { | |
720 | next unless grep { $_ eq $cv->STASH->NAME; } @packages; | |
721 | my $op = $cv->START; | |
722 | OPLOOP: | |
723 | while ($$op) { | |
724 | if ($op->name eq 'require') { # save any BEGIN that does a require | |
725 | $cv->bytecode; | |
726 | asmf "push_begin %d\n", $cv->objix; | |
727 | last OPLOOP; | |
728 | } | |
729 | $op = $op->next; | |
730 | } | |
731 | } | |
732 | } | |
733 | if (init_av()->isa("B::AV")) { | |
734 | for my $cv (init_av()->ARRAY) { | |
735 | next unless grep { $_ eq $cv->STASH->NAME; } @packages; | |
736 | $cv->bytecode; | |
737 | asmf "push_init %d\n", $cv->objix; | |
738 | } | |
739 | } | |
740 | if (end_av()->isa("B::AV")) { | |
741 | for my $cv (end_av()->ARRAY) { | |
742 | next unless grep { $_ eq $cv->STASH->NAME; } @packages; | |
743 | $cv->bytecode; | |
744 | asmf "push_end %d\n", $cv->objix; | |
745 | } | |
746 | } | |
747 | } | |
748 | ||
749 | sub symwalk { | |
750 | no strict 'refs'; | |
751 | my $ok = 1 if grep { (my $name = $_[0]) =~ s/::$//; $_ eq $name;} @packages; | |
752 | if (grep { /^$_[0]/; } @packages) { | |
753 | walksymtable(\%{"$_[0]"}, "bytecodecv", \&symwalk, $_[0]); | |
754 | } | |
755 | warn "considering $_[0] ... " . ($ok ? "accepted\n" : "rejected\n") | |
756 | if $debug_bc; | |
757 | $ok; | |
758 | } | |
759 | ||
760 | sub bytecompile_main { | |
761 | my $curpad = (comppadlist->ARRAY)[1]; | |
762 | my $curpadix = $curpad->objix; | |
763 | $curpad->bytecode; | |
764 | save_call_queues(); | |
765 | walkoptree(main_root, "bytecode") unless ref(main_root) eq "B::NULL"; | |
766 | warn "done main program, now walking symbol table\n" if $debug_bc; | |
767 | if (@packages) { | |
768 | no strict qw(refs); | |
769 | walksymtable(\%{"main::"}, "bytecodecv", \&symwalk); | |
770 | } else { | |
771 | die "No packages requested for compilation!\n"; | |
772 | } | |
773 | asmf "main_root %d\n", main_root->objix; | |
774 | asmf "main_start %d\n", main_start->objix; | |
775 | asmf "curpad $curpadix\n"; | |
776 | # XXX Do min_intro_pending and max_intro_pending matter? | |
777 | } | |
778 | ||
779 | sub compile { | |
780 | my @options = @_; | |
781 | my ($option, $opt, $arg); | |
782 | open(OUT, ">&STDOUT"); | |
783 | binmode OUT; | |
784 | select OUT; | |
785 | OPTION: | |
786 | while ($option = shift @options) { | |
787 | if ($option =~ /^-(.)(.*)/) { | |
788 | $opt = $1; | |
789 | $arg = $2; | |
790 | } else { | |
791 | unshift @options, $option; | |
792 | last OPTION; | |
793 | } | |
794 | if ($opt eq "-" && $arg eq "-") { | |
795 | shift @options; | |
796 | last OPTION; | |
797 | } elsif ($opt eq "o") { | |
798 | $arg ||= shift @options; | |
799 | open(OUT, ">$arg") or return "$arg: $!\n"; | |
800 | binmode OUT; | |
801 | } elsif ($opt eq "a") { | |
802 | $arg ||= shift @options; | |
803 | open(OUT, ">>$arg") or return "$arg: $!\n"; | |
804 | binmode OUT; | |
805 | } elsif ($opt eq "D") { | |
806 | $arg ||= shift @options; | |
807 | foreach $arg (split(//, $arg)) { | |
808 | if ($arg eq "b") { | |
809 | $| = 1; | |
810 | debug(1); | |
811 | } elsif ($arg eq "o") { | |
812 | B->debug(1); | |
813 | } elsif ($arg eq "a") { | |
814 | B::Assembler::debug(1); | |
815 | } elsif ($arg eq "C") { | |
816 | $debug_cv = 1; | |
817 | } | |
818 | } | |
819 | } elsif ($opt eq "v") { | |
820 | $verbose = 1; | |
821 | } elsif ($opt eq "S") { | |
822 | $no_assemble = 1; | |
823 | } elsif ($opt eq "f") { | |
824 | $arg ||= shift @options; | |
825 | my $value = $arg !~ s/^no-//; | |
826 | $arg =~ s/-/_/g; | |
827 | my $ref = $optimise{$arg}; | |
828 | if (defined($ref)) { | |
829 | $$ref = $value; | |
830 | } else { | |
831 | warn qq(ignoring unknown optimisation option "$arg"\n); | |
832 | } | |
833 | } elsif ($opt eq "O") { | |
834 | $arg = 1 if $arg eq ""; | |
835 | my $ref; | |
836 | foreach $ref (values %optimise) { | |
837 | $$ref = 0; | |
838 | } | |
839 | if ($arg >= 2) { | |
840 | $bypass_nullops = 1; | |
841 | } | |
842 | if ($arg >= 1) { | |
843 | $compress_nullops = 1; | |
844 | $omit_seq = 1; | |
845 | } | |
846 | } elsif ($opt eq "u") { | |
847 | $arg ||= shift @options; | |
848 | push @packages, $arg; | |
849 | } else { | |
850 | warn qq(ignoring unknown option "$opt$arg"\n); | |
851 | } | |
852 | } | |
853 | if (! @packages) { | |
854 | warn "No package specified for compilation, assuming main::\n"; | |
855 | @packages = qw(main); | |
856 | } | |
857 | if (@options) { | |
858 | die "Extraneous options left on B::Bytecode commandline: @options\n"; | |
859 | } else { | |
860 | return sub { | |
861 | newasm(\&apr) unless $no_assemble; | |
862 | bytecompile_main(); | |
863 | endasm() unless $no_assemble; | |
864 | }; | |
865 | } | |
866 | } | |
867 | ||
868 | sub apr { print @_; } | |
869 | ||
870 | 1; | |
871 | ||
872 | __END__ | |
873 | ||
874 | =head1 NAME | |
875 | ||
876 | B::Bytecode - Perl compiler's bytecode backend | |
877 | ||
878 | =head1 SYNOPSIS | |
879 | ||
880 | perl -MO=Bytecode[,OPTIONS] foo.pl | |
881 | ||
882 | =head1 DESCRIPTION | |
883 | ||
884 | This compiler backend takes Perl source and generates a | |
885 | platform-independent bytecode encapsulating code to load the | |
886 | internal structures perl uses to run your program. When the | |
887 | generated bytecode is loaded in, your program is ready to run, | |
888 | reducing the time which perl would have taken to load and parse | |
889 | your program into its internal semi-compiled form. That means that | |
890 | compiling with this backend will not help improve the runtime | |
891 | execution speed of your program but may improve the start-up time. | |
892 | Depending on the environment in which your program runs this may | |
893 | or may not be a help. | |
894 | ||
895 | The resulting bytecode can be run with a special byteperl executable | |
896 | or (for non-main programs) be loaded via the C<byteload_fh> function | |
897 | in the F<B> module. | |
898 | ||
899 | =head1 OPTIONS | |
900 | ||
901 | If there are any non-option arguments, they are taken to be names of | |
902 | objects to be saved (probably doesn't work properly yet). Without | |
903 | extra arguments, it saves the main program. | |
904 | ||
905 | =over 4 | |
906 | ||
907 | =item B<-ofilename> | |
908 | ||
909 | Output to filename instead of STDOUT. | |
910 | ||
911 | =item B<-afilename> | |
912 | ||
913 | Append output to filename. | |
914 | ||
915 | =item B<--> | |
916 | ||
917 | Force end of options. | |
918 | ||
919 | =item B<-f> | |
920 | ||
921 | Force optimisations on or off one at a time. Each can be preceded | |
922 | by B<no-> to turn the option off (e.g. B<-fno-compress-nullops>). | |
923 | ||
924 | =item B<-fcompress-nullops> | |
925 | ||
926 | Only fills in the necessary fields of ops which have | |
927 | been optimised away by perl's internal compiler. | |
928 | ||
929 | =item B<-fomit-sequence-numbers> | |
930 | ||
931 | Leaves out code to fill in the op_seq field of all ops | |
932 | which is only used by perl's internal compiler. | |
933 | ||
934 | =item B<-fbypass-nullops> | |
935 | ||
936 | If op->op_next ever points to a NULLOP, replaces the op_next field | |
937 | with the first non-NULLOP in the path of execution. | |
938 | ||
939 | =item B<-On> | |
940 | ||
941 | Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>. | |
942 | B<-O1> sets B<-fcompress-nullops> B<-fomit-sequence numbers>. | |
943 | B<-O2> adds B<-fbypass-nullops>. | |
944 | ||
945 | =item B<-D> | |
946 | ||
947 | Debug options (concatenated or separate flags like C<perl -D>). | |
948 | ||
949 | =item B<-Do> | |
950 | ||
951 | Prints each OP as it's processed. | |
952 | ||
953 | =item B<-Db> | |
954 | ||
955 | Print debugging information about bytecompiler progress. | |
956 | ||
957 | =item B<-Da> | |
958 | ||
959 | Tells the (bytecode) assembler to include source assembler lines | |
960 | in its output as bytecode comments. | |
961 | ||
962 | =item B<-DC> | |
963 | ||
964 | Prints each CV taken from the final symbol tree walk. | |
965 | ||
966 | =item B<-S> | |
967 | ||
968 | Output (bytecode) assembler source rather than piping it | |
969 | through the assembler and outputting bytecode. | |
970 | ||
971 | =item B<-upackage> | |
972 | ||
973 | Stores package in the output. | |
974 | ||
975 | =back | |
976 | ||
977 | =head1 EXAMPLES | |
978 | ||
979 | perl -MO=Bytecode,-O6,-ofoo.plc,-umain foo.pl | |
980 | ||
981 | perl -MO=Bytecode,-S,-umain foo.pl > foo.S | |
982 | assemble foo.S > foo.plc | |
983 | ||
984 | Note that C<assemble> lives in the C<B> subdirectory of your perl | |
985 | library directory. The utility called perlcc may also be used to | |
986 | help make use of this compiler. | |
987 | ||
988 | perl -MO=Bytecode,-uFoo,-oFoo.pmc Foo.pm | |
989 | ||
990 | =head1 BUGS | |
991 | ||
992 | Output is still huge and there are still occasional crashes during | |
993 | either compilation or ByteLoading. Current status: experimental. | |
994 | ||
995 | =head1 AUTHORS | |
996 | ||
997 | Malcolm Beattie, C<mbeattie@sable.ox.ac.uk> | |
998 | Benjamin Stuhl, C<sho_pi@hotmail.com> | |
999 | ||
1000 | =cut |