fix bugs in do_sv_dump() from Devel::Peek integration
[p5sagit/p5-mst-13.2.git] / ext / B / B / C.pm
CommitLineData
a798dbf2 1# C.pm
2#
1a52ab62 3# Copyright (c) 1996, 1997, 1998 Malcolm Beattie
a798dbf2 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#
66a2622e 8package B::C::Section;
9use B ();
10use base B::Section;
11
12sub new
13{
14 my $class = shift;
15 my $o = $class->SUPER::new(@_);
16 push(@$o,[]);
17 return $o;
18}
19
20sub add
21{
22 my $section = shift;
23 push(@{$section->[-1]},@_);
24}
25
26sub index
27{
28 my $section = shift;
29 return scalar(@{$section->[-1]})-1;
30}
31
32sub output
33{
34 my ($section, $fh, $format) = @_;
35 my $sym = $section->symtable || {};
36 my $default = $section->default;
37 foreach (@{$section->[-1]})
38 {
39 s{(s\\_[0-9a-f]+)}{ exists($sym->{$1}) ? $sym->{$1} : $default; }ge;
40 printf $fh $format, $_;
41 }
42}
43
a798dbf2 44package B::C;
45use Exporter ();
46@ISA = qw(Exporter);
0cc1d052 47@EXPORT_OK = qw(output_all output_boilerplate output_main mark_unused
48 init_sections set_callback save_unused_subs objsym save_context);
a798dbf2 49
50use B qw(minus_c sv_undef walkoptree walksymtable main_root main_start peekop
51 class cstring cchar svref_2object compile_stats comppadlist hash
b874ff32 52 threadsv_names main_cv init_av opnumber
53 AVf_REAL HEf_SVKEY);
a798dbf2 54use B::Asmdata qw(@specialsv_name);
55
56use FileHandle;
57use Carp;
58use strict;
59
60my $hv_index = 0;
61my $gv_index = 0;
62my $re_index = 0;
63my $pv_index = 0;
64my $anonsub_index = 0;
44887cfa 65my $initsub_index = 0;
a798dbf2 66
67my %symtable;
68my $warn_undefined_syms;
69my $verbose;
66a2622e 70my %unused_sub_packages;
a798dbf2 71my $nullop_count;
66a2622e 72my $pv_copy_on_grow = 0;
a798dbf2 73my ($debug_cops, $debug_av, $debug_cv, $debug_mg);
74
75my @threadsv_names;
76BEGIN {
77 @threadsv_names = threadsv_names();
78}
79
80# Code sections
66a2622e 81my ($init, $decl, $symsect, $binopsect, $condopsect, $copsect,
a798dbf2 82 $gvopsect, $listopsect, $logopsect, $loopsect, $opsect, $pmopsect,
83 $pvopsect, $svopsect, $unopsect, $svsect, $xpvsect, $xpvavsect,
84 $xpvhvsect, $xpvcvsect, $xpvivsect, $xpvnvsect, $xpvmgsect, $xpvlvsect,
31d7d75a 85 $xrvsect, $xpvbmsect, $xpviosect, $bootstrap);
a798dbf2 86
87sub walk_and_save_optree;
88my $saveoptree_callback = \&walk_and_save_optree;
89sub set_callback { $saveoptree_callback = shift }
90sub saveoptree { &$saveoptree_callback(@_) }
91
92sub walk_and_save_optree {
93 my ($name, $root, $start) = @_;
94 walkoptree($root, "save");
95 return objsym($start);
96}
97
98# Current workaround/fix for op_free() trying to free statically
99# defined OPs is to set op_seq = -1 and check for that in op_free().
100# Instead of hardwiring -1 in place of $op->seq, we use $op_seq
101# so that it can be changed back easily if necessary. In fact, to
102# stop compilers from moaning about a U16 being initialised with an
103# uncast -1 (the printf format is %d so we can't tweak it), we have
104# to "know" that op_seq is a U16 and use 65535. Ugh.
105my $op_seq = 65535;
106
0cc1d052 107# Look this up here so we can do just a number compare
108# rather than looking up the name of every BASEOP in B::OP
109my $OP_THREADSV = opnumber('threadsv');
a798dbf2 110
111sub savesym {
112 my ($obj, $value) = @_;
113 my $sym = sprintf("s\\_%x", $$obj);
114 $symtable{$sym} = $value;
115}
116
117sub objsym {
118 my $obj = shift;
119 return $symtable{sprintf("s\\_%x", $$obj)};
120}
121
122sub getsym {
123 my $sym = shift;
124 my $value;
125
126 return 0 if $sym eq "sym_0"; # special case
127 $value = $symtable{$sym};
128 if (defined($value)) {
129 return $value;
130 } else {
131 warn "warning: undefined symbol $sym\n" if $warn_undefined_syms;
132 return "UNUSED";
133 }
134}
135
136sub savepv {
66a2622e 137 my $pv = shift;
138 $pv = '' unless defined $pv; # Is this sane ?
a798dbf2 139 my $pvsym = 0;
140 my $pvmax = 0;
66a2622e 141 if ($pv_copy_on_grow) {
a798dbf2 142 my $cstring = cstring($pv);
143 if ($cstring ne "0") { # sic
144 $pvsym = sprintf("pv%d", $pv_index++);
145 $decl->add(sprintf("static char %s[] = %s;", $pvsym, $cstring));
146 }
147 } else {
148 $pvmax = length($pv) + 1;
149 }
150 return ($pvsym, $pvmax);
151}
152
153sub B::OP::save {
154 my ($op, $level) = @_;
155 my $type = $op->type;
156 $nullop_count++ unless $type;
0cc1d052 157 if ($type == $OP_THREADSV) {
a798dbf2 158 # saves looking up ppaddr but it's a bit naughty to hard code this
159 $init->add(sprintf("(void)find_threadsv(%s);",
160 cstring($threadsv_names[$op->targ])));
161 }
162 $opsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x",
163 ${$op->next}, ${$op->sibling}, $op->ppaddr, $op->targ,
164 $type, $op_seq, $op->flags, $op->private));
165 savesym($op, sprintf("&op_list[%d]", $opsect->index));
166}
167
168sub B::FAKEOP::new {
169 my ($class, %objdata) = @_;
170 bless \%objdata, $class;
171}
172
173sub B::FAKEOP::save {
174 my ($op, $level) = @_;
175 $opsect->add(sprintf("%s, %s, %s, %u, %u, %u, 0x%x, 0x%x",
176 $op->next, $op->sibling, $op->ppaddr, $op->targ,
177 $op->type, $op_seq, $op->flags, $op->private));
178 return sprintf("&op_list[%d]", $opsect->index);
179}
180
181sub B::FAKEOP::next { $_[0]->{"next"} || 0 }
182sub B::FAKEOP::type { $_[0]->{type} || 0}
183sub B::FAKEOP::sibling { $_[0]->{sibling} || 0 }
184sub B::FAKEOP::ppaddr { $_[0]->{ppaddr} || 0 }
185sub B::FAKEOP::targ { $_[0]->{targ} || 0 }
186sub B::FAKEOP::flags { $_[0]->{flags} || 0 }
187sub B::FAKEOP::private { $_[0]->{private} || 0 }
188
189sub B::UNOP::save {
190 my ($op, $level) = @_;
191 $unopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x",
192 ${$op->next}, ${$op->sibling}, $op->ppaddr,
193 $op->targ, $op->type, $op_seq, $op->flags,
194 $op->private, ${$op->first}));
195 savesym($op, sprintf("(OP*)&unop_list[%d]", $unopsect->index));
196}
197
198sub B::BINOP::save {
199 my ($op, $level) = @_;
200 $binopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x",
201 ${$op->next}, ${$op->sibling}, $op->ppaddr,
202 $op->targ, $op->type, $op_seq, $op->flags,
203 $op->private, ${$op->first}, ${$op->last}));
204 savesym($op, sprintf("(OP*)&binop_list[%d]", $binopsect->index));
205}
206
207sub B::LISTOP::save {
208 my ($op, $level) = @_;
209 $listopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, %u",
210 ${$op->next}, ${$op->sibling}, $op->ppaddr,
211 $op->targ, $op->type, $op_seq, $op->flags,
212 $op->private, ${$op->first}, ${$op->last},
213 $op->children));
214 savesym($op, sprintf("(OP*)&listop_list[%d]", $listopsect->index));
215}
216
217sub B::LOGOP::save {
218 my ($op, $level) = @_;
219 $logopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x",
220 ${$op->next}, ${$op->sibling}, $op->ppaddr,
221 $op->targ, $op->type, $op_seq, $op->flags,
222 $op->private, ${$op->first}, ${$op->other}));
223 savesym($op, sprintf("(OP*)&logop_list[%d]", $logopsect->index));
224}
225
226sub B::CONDOP::save {
227 my ($op, $level) = @_;
228 $condopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, s\\_%x",
229 ${$op->next}, ${$op->sibling}, $op->ppaddr,
230 $op->targ, $op->type, $op_seq, $op->flags,
231 $op->private, ${$op->first}, ${$op->true},
232 ${$op->false}));
233 savesym($op, sprintf("(OP*)&condop_list[%d]", $condopsect->index));
234}
235
236sub B::LOOP::save {
237 my ($op, $level) = @_;
238 #warn sprintf("LOOP: redoop %s, nextop %s, lastop %s\n",
239 # peekop($op->redoop), peekop($op->nextop),
240 # peekop($op->lastop)); # debug
241 $loopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, %u, s\\_%x, s\\_%x, s\\_%x",
242 ${$op->next}, ${$op->sibling}, $op->ppaddr,
243 $op->targ, $op->type, $op_seq, $op->flags,
244 $op->private, ${$op->first}, ${$op->last},
245 $op->children, ${$op->redoop}, ${$op->nextop},
246 ${$op->lastop}));
247 savesym($op, sprintf("(OP*)&loop_list[%d]", $loopsect->index));
248}
249
250sub B::PVOP::save {
251 my ($op, $level) = @_;
252 $pvopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, %s",
253 ${$op->next}, ${$op->sibling}, $op->ppaddr,
254 $op->targ, $op->type, $op_seq, $op->flags,
255 $op->private, cstring($op->pv)));
256 savesym($op, sprintf("(OP*)&pvop_list[%d]", $pvopsect->index));
257}
258
259sub B::SVOP::save {
260 my ($op, $level) = @_;
261 my $svsym = $op->sv->save;
262 $svopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, %s",
263 ${$op->next}, ${$op->sibling}, $op->ppaddr,
264 $op->targ, $op->type, $op_seq, $op->flags,
265 $op->private, "(SV*)$svsym"));
266 savesym($op, sprintf("(OP*)&svop_list[%d]", $svopsect->index));
267}
268
269sub B::GVOP::save {
270 my ($op, $level) = @_;
271 my $gvsym = $op->gv->save;
272 $gvopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, Nullgv",
273 ${$op->next}, ${$op->sibling}, $op->ppaddr,
274 $op->targ, $op->type, $op_seq, $op->flags,
275 $op->private));
276 $init->add(sprintf("gvop_list[%d].op_gv = %s;", $gvopsect->index, $gvsym));
277 savesym($op, sprintf("(OP*)&gvop_list[%d]", $gvopsect->index));
278}
279
280sub B::COP::save {
281 my ($op, $level) = @_;
282 my $gvsym = $op->filegv->save;
283 my $stashsym = $op->stash->save;
284 warn sprintf("COP: line %d file %s\n", $op->line, $op->filegv->SV->PV)
285 if $debug_cops;
286 $copsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, %s, Nullhv, Nullgv, %u, %d, %u",
287 ${$op->next}, ${$op->sibling}, $op->ppaddr,
288 $op->targ, $op->type, $op_seq, $op->flags,
289 $op->private, cstring($op->label), $op->cop_seq,
290 $op->arybase, $op->line));
291 my $copix = $copsect->index;
292 $init->add(sprintf("cop_list[%d].cop_filegv = %s;", $copix, $gvsym),
293 sprintf("cop_list[%d].cop_stash = %s;", $copix, $stashsym));
294 savesym($op, "(OP*)&cop_list[$copix]");
295}
296
297sub B::PMOP::save {
298 my ($op, $level) = @_;
299 my $replroot = $op->pmreplroot;
300 my $replstart = $op->pmreplstart;
301 my $replrootfield = sprintf("s\\_%x", $$replroot);
302 my $replstartfield = sprintf("s\\_%x", $$replstart);
303 my $gvsym;
304 my $ppaddr = $op->ppaddr;
305 if ($$replroot) {
306 # OP_PUSHRE (a mutated version of OP_MATCH for the regexp
307 # argument to a split) stores a GV in op_pmreplroot instead
308 # of a substitution syntax tree. We don't want to walk that...
309 if ($ppaddr eq "pp_pushre") {
310 $gvsym = $replroot->save;
311# warn "PMOP::save saving a pp_pushre with GV $gvsym\n"; # debug
312 $replrootfield = 0;
313 } else {
314 $replstartfield = saveoptree("*ignore*", $replroot, $replstart);
315 }
316 }
317 # pmnext handling is broken in perl itself, I think. Bad op_pmnext
318 # fields aren't noticed in perl's runtime (unless you try reset) but we
319 # segfault when trying to dereference it to find op->op_pmnext->op_type
320 $pmopsect->add(sprintf("s\\_%x, s\\_%x, %s, %u, %u, %u, 0x%x, 0x%x, s\\_%x, s\\_%x, %u, %s, %s, 0, 0, 0x%x, 0x%x",
321 ${$op->next}, ${$op->sibling}, $ppaddr, $op->targ,
322 $op->type, $op_seq, $op->flags, $op->private,
323 ${$op->first}, ${$op->last}, $op->children,
324 $replrootfield, $replstartfield,
325 $op->pmflags, $op->pmpermflags,));
326 my $pm = sprintf("pmop_list[%d]", $pmopsect->index);
327 my $re = $op->precomp;
328 if (defined($re)) {
329 my $resym = sprintf("re%d", $re_index++);
330 $decl->add(sprintf("static char *$resym = %s;", cstring($re)));
331 $init->add(sprintf("$pm.op_pmregexp = pregcomp($resym, $resym + %u, &$pm);",
332 length($re)));
333 }
334 if ($gvsym) {
335 $init->add("$pm.op_pmreplroot = (OP*)$gvsym;");
336 }
337 savesym($op, sprintf("(OP*)&pmop_list[%d]", $pmopsect->index));
338}
339
340sub B::SPECIAL::save {
341 my ($sv) = @_;
342 # special case: $$sv is not the address but an index into specialsv_list
343# warn "SPECIAL::save specialsv $$sv\n"; # debug
344 my $sym = $specialsv_name[$$sv];
345 if (!defined($sym)) {
346 confess "unknown specialsv index $$sv passed to B::SPECIAL::save";
347 }
348 return $sym;
349}
350
351sub B::OBJECT::save {}
352
353sub B::NULL::save {
354 my ($sv) = @_;
355 my $sym = objsym($sv);
356 return $sym if defined $sym;
357# warn "Saving SVt_NULL SV\n"; # debug
358 # debug
359 #if ($$sv == 0) {
360 # warn "NULL::save for sv = 0 called from @{[(caller(1))[3]]}\n";
361 #}
362 $svsect->add(sprintf("0, %u, 0x%x", $sv->REFCNT + 1, $sv->FLAGS));
363 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
364}
365
366sub B::IV::save {
367 my ($sv) = @_;
368 my $sym = objsym($sv);
369 return $sym if defined $sym;
370 $xpvivsect->add(sprintf("0, 0, 0, %d", $sv->IVX));
371 $svsect->add(sprintf("&xpviv_list[%d], %lu, 0x%x",
372 $xpvivsect->index, $sv->REFCNT + 1, $sv->FLAGS));
373 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
374}
375
376sub B::NV::save {
377 my ($sv) = @_;
378 my $sym = objsym($sv);
379 return $sym if defined $sym;
380 $xpvnvsect->add(sprintf("0, 0, 0, %d, %s", $sv->IVX, $sv->NVX));
381 $svsect->add(sprintf("&xpvnv_list[%d], %lu, 0x%x",
382 $xpvnvsect->index, $sv->REFCNT + 1, $sv->FLAGS));
383 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
384}
385
386sub B::PVLV::save {
387 my ($sv) = @_;
388 my $sym = objsym($sv);
389 return $sym if defined $sym;
390 my $pv = $sv->PV;
391 my $len = length($pv);
392 my ($pvsym, $pvmax) = savepv($pv);
393 my ($lvtarg, $lvtarg_sym);
394 $xpvlvsect->add(sprintf("%s, %u, %u, %d, %g, 0, 0, %u, %u, 0, %s",
395 $pvsym, $len, $pvmax, $sv->IVX, $sv->NVX,
396 $sv->TARGOFF, $sv->TARGLEN, cchar($sv->TYPE)));
397 $svsect->add(sprintf("&xpvlv_list[%d], %lu, 0x%x",
398 $xpvlvsect->index, $sv->REFCNT + 1, $sv->FLAGS));
399 if (!$pv_copy_on_grow) {
400 $init->add(sprintf("xpvlv_list[%d].xpv_pv = savepvn(%s, %u);",
401 $xpvlvsect->index, cstring($pv), $len));
402 }
403 $sv->save_magic;
404 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
405}
406
407sub B::PVIV::save {
408 my ($sv) = @_;
409 my $sym = objsym($sv);
410 return $sym if defined $sym;
411 my $pv = $sv->PV;
412 my $len = length($pv);
413 my ($pvsym, $pvmax) = savepv($pv);
414 $xpvivsect->add(sprintf("%s, %u, %u, %d", $pvsym, $len, $pvmax, $sv->IVX));
415 $svsect->add(sprintf("&xpviv_list[%d], %u, 0x%x",
416 $xpvivsect->index, $sv->REFCNT + 1, $sv->FLAGS));
417 if (!$pv_copy_on_grow) {
418 $init->add(sprintf("xpviv_list[%d].xpv_pv = savepvn(%s, %u);",
419 $xpvivsect->index, cstring($pv), $len));
420 }
421 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
422}
423
424sub B::PVNV::save {
425 my ($sv) = @_;
426 my $sym = objsym($sv);
427 return $sym if defined $sym;
66a2622e 428 my $pv = $sv->PV;
429 $pv = '' unless defined $pv;
a798dbf2 430 my $len = length($pv);
431 my ($pvsym, $pvmax) = savepv($pv);
432 $xpvnvsect->add(sprintf("%s, %u, %u, %d, %s",
433 $pvsym, $len, $pvmax, $sv->IVX, $sv->NVX));
434 $svsect->add(sprintf("&xpvnv_list[%d], %lu, 0x%x",
435 $xpvnvsect->index, $sv->REFCNT + 1, $sv->FLAGS));
436 if (!$pv_copy_on_grow) {
437 $init->add(sprintf("xpvnv_list[%d].xpv_pv = savepvn(%s,%u);",
438 $xpvnvsect->index, cstring($pv), $len));
439 }
440 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
441}
442
443sub B::BM::save {
444 my ($sv) = @_;
445 my $sym = objsym($sv);
446 return $sym if defined $sym;
447 my $pv = $sv->PV . "\0" . $sv->TABLE;
448 my $len = length($pv);
449 $xpvbmsect->add(sprintf("0, %u, %u, %d, %s, 0, 0, %d, %u, 0x%x",
450 $len, $len + 258, $sv->IVX, $sv->NVX,
451 $sv->USEFUL, $sv->PREVIOUS, $sv->RARE));
452 $svsect->add(sprintf("&xpvbm_list[%d], %lu, 0x%x",
453 $xpvbmsect->index, $sv->REFCNT + 1, $sv->FLAGS));
454 $sv->save_magic;
455 $init->add(sprintf("xpvbm_list[%d].xpv_pv = savepvn(%s, %u);",
456 $xpvbmsect->index, cstring($pv), $len),
457 sprintf("xpvbm_list[%d].xpv_cur = %u;",
458 $xpvbmsect->index, $len - 257));
459 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
460}
461
462sub B::PV::save {
463 my ($sv) = @_;
464 my $sym = objsym($sv);
465 return $sym if defined $sym;
466 my $pv = $sv->PV;
467 my $len = length($pv);
468 my ($pvsym, $pvmax) = savepv($pv);
469 $xpvsect->add(sprintf("%s, %u, %u", $pvsym, $len, $pvmax));
470 $svsect->add(sprintf("&xpv_list[%d], %lu, 0x%x",
471 $xpvsect->index, $sv->REFCNT + 1, $sv->FLAGS));
472 if (!$pv_copy_on_grow) {
473 $init->add(sprintf("xpv_list[%d].xpv_pv = savepvn(%s, %u);",
474 $xpvsect->index, cstring($pv), $len));
475 }
476 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
477}
478
479sub B::PVMG::save {
480 my ($sv) = @_;
481 my $sym = objsym($sv);
482 return $sym if defined $sym;
483 my $pv = $sv->PV;
484 my $len = length($pv);
485 my ($pvsym, $pvmax) = savepv($pv);
486 $xpvmgsect->add(sprintf("%s, %u, %u, %d, %s, 0, 0",
487 $pvsym, $len, $pvmax, $sv->IVX, $sv->NVX));
488 $svsect->add(sprintf("&xpvmg_list[%d], %lu, 0x%x",
489 $xpvmgsect->index, $sv->REFCNT + 1, $sv->FLAGS));
490 if (!$pv_copy_on_grow) {
491 $init->add(sprintf("xpvmg_list[%d].xpv_pv = savepvn(%s, %u);",
492 $xpvmgsect->index, cstring($pv), $len));
493 }
494 $sym = savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
495 $sv->save_magic;
496 return $sym;
497}
498
499sub B::PVMG::save_magic {
500 my ($sv) = @_;
501 #warn sprintf("saving magic for %s (0x%x)\n", class($sv), $$sv); # debug
502 my $stash = $sv->SvSTASH;
503 if ($$stash) {
504 warn sprintf("xmg_stash = %s (0x%x)\n", $stash->NAME, $$stash)
505 if $debug_mg;
506 # XXX Hope stash is already going to be saved.
507 $init->add(sprintf("SvSTASH(s\\_%x) = s\\_%x;", $$sv, $$stash));
508 }
509 my @mgchain = $sv->MAGIC;
88b39979 510 my ($mg, $type, $obj, $ptr,$len,$ptrsv);
a798dbf2 511 foreach $mg (@mgchain) {
512 $type = $mg->TYPE;
513 $obj = $mg->OBJ;
514 $ptr = $mg->PTR;
88b39979 515 $len=$mg->LENGTH;
a798dbf2 516 if ($debug_mg) {
517 warn sprintf("magic %s (0x%x), obj %s (0x%x), type %s, ptr %s\n",
518 class($sv), $$sv, class($obj), $$obj,
519 cchar($type), cstring($ptr));
520 }
88b39979 521 if ($len == HEf_SVKEY){
522 #The pointer is an SV*
523 $ptrsv=svref_2object($ptr)->save;
524 $init->add(sprintf("sv_magic((SV*)s\\_%x, (SV*)s\\_%x, %s, %s, %d);",
525 $$sv, $$obj, cchar($type),$ptrsv,$len));
526 }else{
527 $init->add(sprintf("sv_magic((SV*)s\\_%x, (SV*)s\\_%x, %s, %s, %d);",
a798dbf2 528 $$sv, $$obj, cchar($type),cstring($ptr),$len));
88b39979 529 }
a798dbf2 530 }
531}
532
533sub B::RV::save {
534 my ($sv) = @_;
535 my $sym = objsym($sv);
536 return $sym if defined $sym;
66a2622e 537 my $rv = $sv->RV->save;
538 $rv =~ s/^\([AGHS]V\s*\*\)\s*(\&sv_list.*)$/$1/;
539 $xrvsect->add($rv);
a798dbf2 540 $svsect->add(sprintf("&xrv_list[%d], %lu, 0x%x",
541 $xrvsect->index, $sv->REFCNT + 1, $sv->FLAGS));
542 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
543}
544
545sub try_autoload {
546 my ($cvstashname, $cvname) = @_;
547 warn sprintf("No definition for sub %s::%s\n", $cvstashname, $cvname);
548 # Handle AutoLoader classes explicitly. Any more general AUTOLOAD
549 # use should be handled by the class itself.
550 no strict 'refs';
551 my $isa = \@{"$cvstashname\::ISA"};
552 if (grep($_ eq "AutoLoader", @$isa)) {
553 warn "Forcing immediate load of sub derived from AutoLoader\n";
554 # Tweaked version of AutoLoader::AUTOLOAD
555 my $dir = $cvstashname;
556 $dir =~ s(::)(/)g;
557 eval { require "auto/$dir/$cvname.al" };
558 if ($@) {
559 warn qq(failed require "auto/$dir/$cvname.al": $@\n);
560 return 0;
561 } else {
562 return 1;
563 }
564 }
565}
566
567sub B::CV::save {
568 my ($cv) = @_;
569 my $sym = objsym($cv);
570 if (defined($sym)) {
571# warn sprintf("CV 0x%x already saved as $sym\n", $$cv); # debug
572 return $sym;
573 }
574 # Reserve a place in svsect and xpvcvsect and record indices
575 my $sv_ix = $svsect->index + 1;
576 $svsect->add("svix$sv_ix");
577 my $xpvcv_ix = $xpvcvsect->index + 1;
578 $xpvcvsect->add("xpvcvix$xpvcv_ix");
579 # Save symbol now so that GvCV() doesn't recurse back to us via CvGV()
580 $sym = savesym($cv, "&sv_list[$sv_ix]");
581 warn sprintf("saving CV 0x%x as $sym\n", $$cv) if $debug_cv;
582 my $gv = $cv->GV;
583 my $cvstashname = $gv->STASH->NAME;
584 my $cvname = $gv->NAME;
585 my $root = $cv->ROOT;
586 my $cvxsub = $cv->XSUB;
587 if (!$$root && !$cvxsub) {
588 if (try_autoload($cvstashname, $cvname)) {
589 # Recalculate root and xsub
590 $root = $cv->ROOT;
591 $cvxsub = $cv->XSUB;
592 if ($$root || $cvxsub) {
593 warn "Successful forced autoload\n";
594 }
595 }
596 }
597 my $startfield = 0;
598 my $padlist = $cv->PADLIST;
599 my $pv = $cv->PV;
600 my $xsub = 0;
601 my $xsubany = "Nullany";
602 if ($$root) {
603 warn sprintf("saving op tree for CV 0x%x, root = 0x%x\n",
604 $$cv, $$root) if $debug_cv;
605 my $ppname = "";
606 if ($$gv) {
607 my $stashname = $gv->STASH->NAME;
608 my $gvname = $gv->NAME;
609 if ($gvname ne "__ANON__") {
610 $ppname = (${$gv->FORM} == $$cv) ? "pp_form_" : "pp_sub_";
611 $ppname .= ($stashname eq "main") ?
612 $gvname : "$stashname\::$gvname";
613 $ppname =~ s/::/__/g;
44887cfa 614 if ($gvname eq "INIT"){
615 $ppname .= "_$initsub_index";
616 $initsub_index++;
617 }
a798dbf2 618 }
619 }
620 if (!$ppname) {
621 $ppname = "pp_anonsub_$anonsub_index";
622 $anonsub_index++;
623 }
624 $startfield = saveoptree($ppname, $root, $cv->START, $padlist->ARRAY);
625 warn sprintf("done saving op tree for CV 0x%x, name %s, root 0x%x\n",
626 $$cv, $ppname, $$root) if $debug_cv;
627 if ($$padlist) {
628 warn sprintf("saving PADLIST 0x%x for CV 0x%x\n",
629 $$padlist, $$cv) if $debug_cv;
630 $padlist->save;
631 warn sprintf("done saving PADLIST 0x%x for CV 0x%x\n",
632 $$padlist, $$cv) if $debug_cv;
633 }
634 }
635 elsif ($cvxsub) {
636 $xsubany = sprintf("ANYINIT((void*)0x%x)", $cv->XSUBANY);
637 # Try to find out canonical name of XSUB function from EGV.
638 # XXX Doesn't work for XSUBs with PREFIX set (or anyone who
639 # calls newXS() manually with weird arguments).
640 my $egv = $gv->EGV;
641 my $stashname = $egv->STASH->NAME;
642 $stashname =~ s/::/__/g;
643 $xsub = sprintf("XS_%s_%s", $stashname, $egv->NAME);
644 $decl->add("void $xsub _((CV*));");
645 }
646 else {
647 warn sprintf("No definition for sub %s::%s (unable to autoload)\n",
648 $cvstashname, $cvname); # debug
66a2622e 649 }
650 $pv = '' unless defined $pv; # Avoid use of undef warnings
5cfd8ad4 651 $symsect->add(sprintf("xpvcvix%d\t%s, %u, 0, %d, %s, 0, Nullhv, Nullhv, %s, s\\_%x, $xsub, $xsubany, Nullgv, Nullgv, %d, s\\_%x, (CV*)s\\_%x, 0x%x",
a798dbf2 652 $xpvcv_ix, cstring($pv), length($pv), $cv->IVX,
653 $cv->NVX, $startfield, ${$cv->ROOT}, $cv->DEPTH,
5cfd8ad4 654 $$padlist, ${$cv->OUTSIDE}, $cv->CvFLAGS));
655
656 if (${$cv->OUTSIDE} == ${main_cv()}){
657 $init->add(sprintf("CvOUTSIDE(s\\_%x)=PL_main_cv;",$$cv));
658 }
659
a798dbf2 660 if ($$gv) {
661 $gv->save;
662 $init->add(sprintf("CvGV(s\\_%x) = s\\_%x;",$$cv,$$gv));
663 warn sprintf("done saving GV 0x%x for CV 0x%x\n",
664 $$gv, $$cv) if $debug_cv;
665 }
666 my $filegv = $cv->FILEGV;
667 if ($$filegv) {
668 $filegv->save;
669 $init->add(sprintf("CvFILEGV(s\\_%x) = s\\_%x;", $$cv, $$filegv));
670 warn sprintf("done saving FILEGV 0x%x for CV 0x%x\n",
671 $$filegv, $$cv) if $debug_cv;
672 }
673 my $stash = $cv->STASH;
674 if ($$stash) {
675 $stash->save;
676 $init->add(sprintf("CvSTASH(s\\_%x) = s\\_%x;", $$cv, $$stash));
677 warn sprintf("done saving STASH 0x%x for CV 0x%x\n",
678 $$stash, $$cv) if $debug_cv;
679 }
680 $symsect->add(sprintf("svix%d\t(XPVCV*)&xpvcv_list[%u], %lu, 0x%x",
681 $sv_ix, $xpvcv_ix, $cv->REFCNT + 1, $cv->FLAGS));
682 return $sym;
683}
684
685sub B::GV::save {
7cf11ee8 686 my ($gv,$skip_cv) = @_;
a798dbf2 687 my $sym = objsym($gv);
688 if (defined($sym)) {
689 #warn sprintf("GV 0x%x already saved as $sym\n", $$gv); # debug
690 return $sym;
691 } else {
692 my $ix = $gv_index++;
693 $sym = savesym($gv, "gv_list[$ix]");
694 #warn sprintf("Saving GV 0x%x as $sym\n", $$gv); # debug
695 }
696 my $gvname = $gv->NAME;
697 my $name = cstring($gv->STASH->NAME . "::" . $gvname);
698 #warn "GV name is $name\n"; # debug
699 my $egv = $gv->EGV;
700 my $egvsym;
701 if ($$gv != $$egv) {
702 #warn(sprintf("EGV name is %s, saving it now\n",
703 # $egv->STASH->NAME . "::" . $egv->NAME)); # debug
704 $egvsym = $egv->save;
705 }
706 $init->add(qq[$sym = gv_fetchpv($name, TRUE, SVt_PV);],
707 sprintf("SvFLAGS($sym) = 0x%x;", $gv->FLAGS),
708 sprintf("GvFLAGS($sym) = 0x%x;", $gv->GvFLAGS),
709 sprintf("GvLINE($sym) = %u;", $gv->LINE));
710 # Shouldn't need to do save_magic since gv_fetchpv handles that
711 #$gv->save_magic;
712 my $refcnt = $gv->REFCNT + 1;
713 $init->add(sprintf("SvREFCNT($sym) += %u;", $refcnt - 1)) if $refcnt > 1;
714 my $gvrefcnt = $gv->GvREFCNT;
715 if ($gvrefcnt > 1) {
716 $init->add(sprintf("GvREFCNT($sym) += %u;", $gvrefcnt - 1));
717 }
718 if (defined($egvsym)) {
719 # Shared glob *foo = *bar
720 $init->add("gp_free($sym);",
721 "GvGP($sym) = GvGP($egvsym);");
722 } elsif ($gvname !~ /^([^A-Za-z]|STDIN|STDOUT|STDERR|ARGV|SIG|ENV)$/) {
723 # Don't save subfields of special GVs (*_, *1, *# and so on)
724# warn "GV::save saving subfields\n"; # debug
725 my $gvsv = $gv->SV;
726 if ($$gvsv) {
727 $init->add(sprintf("GvSV($sym) = s\\_%x;", $$gvsv));
728# warn "GV::save \$$name\n"; # debug
729 $gvsv->save;
730 }
731 my $gvav = $gv->AV;
732 if ($$gvav) {
733 $init->add(sprintf("GvAV($sym) = s\\_%x;", $$gvav));
734# warn "GV::save \@$name\n"; # debug
735 $gvav->save;
736 }
737 my $gvhv = $gv->HV;
738 if ($$gvhv) {
739 $init->add(sprintf("GvHV($sym) = s\\_%x;", $$gvhv));
740# warn "GV::save \%$name\n"; # debug
741 $gvhv->save;
742 }
743 my $gvcv = $gv->CV;
7cf11ee8 744 if ($$gvcv && !$skip_cv) {
a798dbf2 745 $init->add(sprintf("GvCV($sym) = (CV*)s\\_%x;", $$gvcv));
746# warn "GV::save &$name\n"; # debug
747 $gvcv->save;
748 }
749 my $gvfilegv = $gv->FILEGV;
750 if ($$gvfilegv) {
5ed82aed 751 $init->add(sprintf("GvFILEGV($sym) = (GV*)s\\_%x;",$$gvfilegv));
a798dbf2 752# warn "GV::save GvFILEGV(*$name)\n"; # debug
753 $gvfilegv->save;
754 }
755 my $gvform = $gv->FORM;
756 if ($$gvform) {
757 $init->add(sprintf("GvFORM($sym) = (CV*)s\\_%x;", $$gvform));
758# warn "GV::save GvFORM(*$name)\n"; # debug
759 $gvform->save;
760 }
761 my $gvio = $gv->IO;
762 if ($$gvio) {
763 $init->add(sprintf("GvIOp($sym) = s\\_%x;", $$gvio));
764# warn "GV::save GvIO(*$name)\n"; # debug
765 $gvio->save;
766 }
767 }
768 return $sym;
769}
770sub B::AV::save {
771 my ($av) = @_;
772 my $sym = objsym($av);
773 return $sym if defined $sym;
774 my $avflags = $av->AvFLAGS;
775 $xpvavsect->add(sprintf("0, -1, -1, 0, 0.0, 0, Nullhv, 0, 0, 0x%x",
776 $avflags));
777 $svsect->add(sprintf("&xpvav_list[%d], %lu, 0x%x",
778 $xpvavsect->index, $av->REFCNT + 1, $av->FLAGS));
779 my $sv_list_index = $svsect->index;
780 my $fill = $av->FILL;
781 $av->save_magic;
782 warn sprintf("saving AV 0x%x FILL=$fill AvFLAGS=0x%x", $$av, $avflags)
783 if $debug_av;
784 # XXX AVf_REAL is wrong test: need to save comppadlist but not stack
785 #if ($fill > -1 && ($avflags & AVf_REAL)) {
786 if ($fill > -1) {
787 my @array = $av->ARRAY;
788 if ($debug_av) {
789 my $el;
790 my $i = 0;
791 foreach $el (@array) {
792 warn sprintf("AV 0x%x[%d] = %s 0x%x\n",
793 $$av, $i++, class($el), $$el);
794 }
795 }
796 my @names = map($_->save, @array);
797 # XXX Better ways to write loop?
798 # Perhaps svp[0] = ...; svp[1] = ...; svp[2] = ...;
799 # Perhaps I32 i = 0; svp[i++] = ...; svp[i++] = ...; svp[i++] = ...;
800 $init->add("{",
801 "\tSV **svp;",
802 "\tAV *av = (AV*)&sv_list[$sv_list_index];",
803 "\tav_extend(av, $fill);",
804 "\tsvp = AvARRAY(av);",
805 map("\t*svp++ = (SV*)$_;", @names),
806 "\tAvFILLp(av) = $fill;",
807 "}");
808 } else {
809 my $max = $av->MAX;
810 $init->add("av_extend((AV*)&sv_list[$sv_list_index], $max);")
811 if $max > -1;
812 }
813 return savesym($av, "(AV*)&sv_list[$sv_list_index]");
814}
815
816sub B::HV::save {
817 my ($hv) = @_;
818 my $sym = objsym($hv);
819 return $sym if defined $sym;
820 my $name = $hv->NAME;
821 if ($name) {
822 # It's a stash
823
824 # A perl bug means HvPMROOT isn't altered when a PMOP is freed. Usually
825 # the only symptom is that sv_reset tries to reset the PMf_USED flag of
826 # a trashed op but we look at the trashed op_type and segfault.
827 #my $adpmroot = ${$hv->PMROOT};
828 my $adpmroot = 0;
829 $decl->add("static HV *hv$hv_index;");
830 # XXX Beware of weird package names containing double-quotes, \n, ...?
831 $init->add(qq[hv$hv_index = gv_stashpv("$name", TRUE);]);
832 if ($adpmroot) {
833 $init->add(sprintf("HvPMROOT(hv$hv_index) = (PMOP*)s\\_%x;",
834 $adpmroot));
835 }
836 $sym = savesym($hv, "hv$hv_index");
837 $hv_index++;
838 return $sym;
839 }
840 # It's just an ordinary HV
841 $xpvhvsect->add(sprintf("0, 0, %d, 0, 0.0, 0, Nullhv, %d, 0, 0, 0",
842 $hv->MAX, $hv->RITER));
843 $svsect->add(sprintf("&xpvhv_list[%d], %lu, 0x%x",
844 $xpvhvsect->index, $hv->REFCNT + 1, $hv->FLAGS));
845 my $sv_list_index = $svsect->index;
846 my @contents = $hv->ARRAY;
847 if (@contents) {
848 my $i;
849 for ($i = 1; $i < @contents; $i += 2) {
850 $contents[$i] = $contents[$i]->save;
851 }
852 $init->add("{", "\tHV *hv = (HV*)&sv_list[$sv_list_index];");
853 while (@contents) {
854 my ($key, $value) = splice(@contents, 0, 2);
855 $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
856 cstring($key),length($key),$value, hash($key)));
cf86991c 857# $init->add(sprintf("\thv_store(hv, %s, %u, %s, %s);",
858# cstring($key),length($key),$value, 0));
a798dbf2 859 }
860 $init->add("}");
861 }
862 return savesym($hv, "(HV*)&sv_list[$sv_list_index]");
863}
864
865sub B::IO::save {
866 my ($io) = @_;
867 my $sym = objsym($io);
868 return $sym if defined $sym;
869 my $pv = $io->PV;
66a2622e 870 $pv = '' unless defined $pv;
a798dbf2 871 my $len = length($pv);
872 $xpviosect->add(sprintf("0, %u, %u, %d, %s, 0, 0, 0, 0, 0, %d, %d, %d, %d, %s, Nullgv, %s, Nullgv, %s, Nullgv, %d, %s, 0x%x",
873 $len, $len+1, $io->IVX, $io->NVX, $io->LINES,
874 $io->PAGE, $io->PAGE_LEN, $io->LINES_LEFT,
875 cstring($io->TOP_NAME), cstring($io->FMT_NAME),
876 cstring($io->BOTTOM_NAME), $io->SUBPROCESS,
877 cchar($io->IoTYPE), $io->IoFLAGS));
878 $svsect->add(sprintf("&xpvio_list[%d], %lu, 0x%x",
879 $xpviosect->index, $io->REFCNT + 1, $io->FLAGS));
880 $sym = savesym($io, sprintf("(IO*)&sv_list[%d]", $svsect->index));
881 my ($field, $fsym);
882 foreach $field (qw(TOP_GV FMT_GV BOTTOM_GV)) {
883 $fsym = $io->$field();
884 if ($$fsym) {
885 $init->add(sprintf("Io$field($sym) = (GV*)s\\_%x;", $$fsym));
886 $fsym->save;
887 }
888 }
889 $io->save_magic;
890 return $sym;
891}
892
893sub B::SV::save {
894 my $sv = shift;
895 # This is where we catch an honest-to-goodness Nullsv (which gets
896 # blessed into B::SV explicitly) and any stray erroneous SVs.
897 return 0 unless $$sv;
898 confess sprintf("cannot save that type of SV: %s (0x%x)\n",
899 class($sv), $$sv);
900}
901
902sub output_all {
903 my $init_name = shift;
904 my $section;
905 my @sections = ($opsect, $unopsect, $binopsect, $logopsect, $condopsect,
906 $listopsect, $pmopsect, $svopsect, $gvopsect, $pvopsect,
66a2622e 907 $loopsect, $copsect, $svsect, $xpvsect,
a798dbf2 908 $xpvavsect, $xpvhvsect, $xpvcvsect, $xpvivsect, $xpvnvsect,
909 $xpvmgsect, $xpvlvsect, $xrvsect, $xpvbmsect, $xpviosect);
31d7d75a 910 $bootstrap->output(\*STDOUT, "/* bootstrap %s */\n");
a798dbf2 911 $symsect->output(\*STDOUT, "#define %s\n");
912 print "\n";
913 output_declarations();
914 foreach $section (@sections) {
915 my $lines = $section->index + 1;
916 if ($lines) {
917 my $name = $section->name;
918 my $typename = ($name eq "xpvcv") ? "XPVCV_or_similar" : uc($name);
919 print "Static $typename ${name}_list[$lines];\n";
920 }
921 }
922 $decl->output(\*STDOUT, "%s\n");
923 print "\n";
924 foreach $section (@sections) {
925 my $lines = $section->index + 1;
926 if ($lines) {
927 my $name = $section->name;
928 my $typename = ($name eq "xpvcv") ? "XPVCV_or_similar" : uc($name);
929 printf "static %s %s_list[%u] = {\n", $typename, $name, $lines;
930 $section->output(\*STDOUT, "\t{ %s },\n");
931 print "};\n\n";
932 }
933 }
934
935 print <<"EOT";
936static int $init_name()
937{
938 dTHR;
939EOT
940 $init->output(\*STDOUT, "\t%s\n");
941 print "\treturn 0;\n}\n";
942 if ($verbose) {
943 warn compile_stats();
944 warn "NULLOP count: $nullop_count\n";
945 }
946}
947
948sub output_declarations {
949 print <<'EOT';
950#ifdef BROKEN_STATIC_REDECL
951#define Static extern
952#else
953#define Static static
954#endif /* BROKEN_STATIC_REDECL */
955
956#ifdef BROKEN_UNION_INIT
957/*
958 * Cribbed from cv.h with ANY (a union) replaced by void*.
959 * Some pre-Standard compilers can't cope with initialising unions. Ho hum.
960 */
961typedef struct {
962 char * xpv_pv; /* pointer to malloced string */
963 STRLEN xpv_cur; /* length of xp_pv as a C string */
964 STRLEN xpv_len; /* allocated size */
965 IV xof_off; /* integer value */
966 double xnv_nv; /* numeric value, if any */
967 MAGIC* xmg_magic; /* magic for scalar array */
968 HV* xmg_stash; /* class package */
969
970 HV * xcv_stash;
971 OP * xcv_start;
972 OP * xcv_root;
973 void (*xcv_xsub) _((CV*));
974 void * xcv_xsubany;
975 GV * xcv_gv;
976 GV * xcv_filegv;
977 long xcv_depth; /* >= 2 indicates recursive call */
978 AV * xcv_padlist;
979 CV * xcv_outside;
980#ifdef USE_THREADS
981 perl_mutex *xcv_mutexp;
982 struct perl_thread *xcv_owner; /* current owner thread */
983#endif /* USE_THREADS */
984 U8 xcv_flags;
985} XPVCV_or_similar;
986#define ANYINIT(i) i
987#else
988#define XPVCV_or_similar XPVCV
989#define ANYINIT(i) {i}
990#endif /* BROKEN_UNION_INIT */
991#define Nullany ANYINIT(0)
992
993#define UNUSED 0
994#define sym_0 0
995
996EOT
997 print "static GV *gv_list[$gv_index];\n" if $gv_index;
998 print "\n";
999}
1000
1001
1002sub output_boilerplate {
1003 print <<'EOT';
1004#include "EXTERN.h"
1005#include "perl.h"
1006#ifndef PATCHLEVEL
1007#include "patchlevel.h"
1008#endif
1009
1010/* Workaround for mapstart: the only op which needs a different ppaddr */
1011#undef pp_mapstart
1012#define pp_mapstart pp_grepstart
1013
1014static void xs_init _((void));
1015static PerlInterpreter *my_perl;
1016EOT
1017}
1018
1019sub output_main {
1020 print <<'EOT';
1021int
1022#ifndef CAN_PROTOTYPE
1023main(argc, argv, env)
1024int argc;
1025char **argv;
1026char **env;
1027#else /* def(CAN_PROTOTYPE) */
1028main(int argc, char **argv, char **env)
1029#endif /* def(CAN_PROTOTYPE) */
1030{
1031 int exitstatus;
1032 int i;
1033 char **fakeargv;
1034
1035 PERL_SYS_INIT(&argc,&argv);
1036
1037 perl_init_i18nl10n(1);
1038
81009501 1039 if (!PL_do_undump) {
a798dbf2 1040 my_perl = perl_alloc();
1041 if (!my_perl)
1042 exit(1);
1043 perl_construct( my_perl );
1044 }
1045
1046#ifdef CSH
81009501 1047 if (!PL_cshlen)
1048 PL_cshlen = strlen(PL_cshname);
a798dbf2 1049#endif
1050
1051#ifdef ALLOW_PERL_OPTIONS
1052#define EXTRA_OPTIONS 2
1053#else
1054#define EXTRA_OPTIONS 3
1055#endif /* ALLOW_PERL_OPTIONS */
1056 New(666, fakeargv, argc + EXTRA_OPTIONS + 1, char *);
1057 fakeargv[0] = argv[0];
1058 fakeargv[1] = "-e";
1059 fakeargv[2] = "";
1060#ifndef ALLOW_PERL_OPTIONS
1061 fakeargv[3] = "--";
1062#endif /* ALLOW_PERL_OPTIONS */
1063 for (i = 1; i < argc; i++)
1064 fakeargv[i + EXTRA_OPTIONS] = argv[i];
1065 fakeargv[argc + EXTRA_OPTIONS] = 0;
1066
1067 exitstatus = perl_parse(my_perl, xs_init, argc + EXTRA_OPTIONS,
1068 fakeargv, NULL);
1069 if (exitstatus)
1070 exit( exitstatus );
1071
1072 sv_setpv(GvSV(gv_fetchpv("0", TRUE, SVt_PV)), argv[0]);
81009501 1073 PL_main_cv = PL_compcv;
1074 PL_compcv = 0;
a798dbf2 1075
1076 exitstatus = perl_init();
1077 if (exitstatus)
1078 exit( exitstatus );
1079
1080 exitstatus = perl_run( my_perl );
1081
1082 perl_destruct( my_perl );
1083 perl_free( my_perl );
1084
1085 exit( exitstatus );
1086}
1087
1088static void
1089xs_init()
1090{
1091}
1092EOT
1093}
1094
1095sub dump_symtable {
1096 # For debugging
1097 my ($sym, $val);
1098 warn "----Symbol table:\n";
1099 while (($sym, $val) = each %symtable) {
1100 warn "$sym => $val\n";
1101 }
1102 warn "---End of symbol table\n";
1103}
1104
1105sub save_object {
1106 my $sv;
1107 foreach $sv (@_) {
1108 svref_2object($sv)->save;
1109 }
338a6d08 1110}
1111
1112sub Dummy_BootStrap { }
a798dbf2 1113
66a2622e 1114sub B::GV::savecv
1115{
1116 my $gv = shift;
1117 my $package=$gv->STASH->NAME;
1118 my $name = $gv->NAME;
1119 my $cv = $gv->CV;
7cf11ee8 1120 my $sv = $gv->SV;
1121 my $av = $gv->AV;
1122 my $hv = $gv->HV;
1123 my $skip_cv = 0;
1124
66a2622e 1125 # We may be looking at this package just because it is a branch in the
1126 # symbol table which is on the path to a package which we need to save
7cf11ee8 1127 # e.g. this is 'Getopt' and we need to save 'Getopt::Long'
66a2622e 1128 #
7cf11ee8 1129 return unless ($unused_sub_packages{$package});
66a2622e 1130 if ($$cv)
1131 {
1132 if ($name eq "bootstrap" && $cv->XSUB)
1133 {
7cf11ee8 1134 my $file = $cv->FILEGV->SV->PV;
1135 $bootstrap->add($file);
66a2622e 1136 my $name = $gv->STASH->NAME.'::'.$name;
1137 no strict 'refs';
1138 *{$name} = \&Dummy_BootStrap;
1139 $cv = $gv->CV;
a798dbf2 1140 }
66a2622e 1141 warn sprintf("saving extra CV &%s::%s (0x%x) from GV 0x%x\n",
1142 $package, $name, $$cv, $$gv) if ($debug_cv);
7cf11ee8 1143 }
1144 else
66a2622e 1145 {
7cf11ee8 1146 return unless ($$av || $$sv || $$hv)
66a2622e 1147 }
7cf11ee8 1148 $gv->save($skip_cv);
66a2622e 1149}
5ed82aed 1150
66a2622e 1151sub mark_package
1152{
1153 my $package = shift;
1154 unless ($unused_sub_packages{$package})
1155 {
1156 no strict 'refs';
1157 $unused_sub_packages{$package} = 1;
1158 if (defined(@{$package.'::ISA'}))
1159 {
1160 foreach my $isa (@{$package.'::ISA'})
1161 {
1162 if ($isa eq 'DynaLoader')
1163 {
1164 unless (defined(&{$package.'::bootstrap'}))
1165 {
1166 warn "Forcing bootstrap of $package\n";
1167 eval { $package->bootstrap };
1168 }
1169 }
1170 else
1171 {
1172 unless ($unused_sub_packages{$isa})
1173 {
1174 warn "$isa saved (it is in $package\'s \@ISA)\n";
1175 mark_package($isa);
1176 }
1177 }
1178 }
1179 }
1180 }
1181 return 1;
1182}
1183
1184sub should_save
1185{
1186 no strict qw(vars refs);
1187 my $package = shift;
1188 $package =~ s/::$//;
1189 return $unused_sub_packages{$package} = 0 if ($package =~ /::::/); # skip ::::ISA::CACHE etc.
cf86991c 1190 # warn "Considering $package\n";#debug
66a2622e 1191 foreach my $u (grep($unused_sub_packages{$_},keys %unused_sub_packages))
1192 {
1193 # If this package is a prefix to something we are saving, traverse it
1194 # but do not mark it for saving if it is not already
1195 # e.g. to get to Getopt::Long we need to traverse Getopt but need
1196 # not save Getopt
1197 return 1 if ($u =~ /^$package\:\:/);
1198 }
1199 if (exists $unused_sub_packages{$package})
1200 {
cf86991c 1201 # warn "Cached $package is ".$unused_sub_packages{$package}."\n";
66a2622e 1202 return $unused_sub_packages{$package}
1203 }
1204 # Omit the packages which we use (and which cause grief
1205 # because of fancy "goto &$AUTOLOAD" stuff).
1206 # XXX Surely there must be a nicer way to do this.
1207 if ($package eq "FileHandle" || $package eq "Config" ||
cf86991c 1208 $package eq "SelectSaver" || $package =~/^(B|IO)::/)
66a2622e 1209 {
1210 return $unused_sub_packages{$package} = 0;
1211 }
1212 # Now see if current package looks like an OO class this is probably too strong.
1213 foreach my $m (qw(new DESTROY TIESCALAR TIEARRAY TIEHASH TIEHANDLE))
1214 {
1215 if ($package->can($m))
1216 {
1217 warn "$package has method $m: saving package\n";#debug
1218 return mark_package($package);
1219 }
1220 }
1221 return $unused_sub_packages{$package} = 0;
a798dbf2 1222}
1223
66a2622e 1224sub walkpackages
1225{
1226 my ($symref, $recurse, $prefix) = @_;
1227 my $sym;
1228 my $ref;
1229 no strict 'vars';
1230 local(*glob);
1231 $prefix = '' unless defined $prefix;
1232 while (($sym, $ref) = each %$symref)
1233 {
1234 *glob = $ref;
1235 if ($sym =~ /::$/)
1236 {
1237 $sym = $prefix . $sym;
1238 if ($sym ne "main::" && &$recurse($sym))
1239 {
1240 walkpackages(\%glob, $recurse, $sym);
1241 }
1242 }
1243 }
1244}
338a6d08 1245
1246
66a2622e 1247sub save_unused_subs
1248{
1249 no strict qw(refs);
a9b6343a 1250 &descend_marked_unused;
66a2622e 1251 warn "Prescan\n";
1252 walkpackages(\%{"main::"}, sub { should_save($_[0]); return 1 });
1253 warn "Saving methods\n";
1254 walksymtable(\%{"main::"}, "savecv", \&should_save);
a798dbf2 1255}
1256
0cc1d052 1257sub save_context
1258{
1259 my $curpad_nam = (comppadlist->ARRAY)[0]->save;
1260 my $curpad_sym = (comppadlist->ARRAY)[1]->save;
1261 my $inc_hv = svref_2object(\%INC)->save;
1262 my $inc_av = svref_2object(\@INC)->save;
1263 $init->add( "PL_curpad = AvARRAY($curpad_sym);",
1264 "GvHV(PL_incgv) = $inc_hv;",
1265 "GvAV(PL_incgv) = $inc_av;",
1266 "av_store(CvPADLIST(PL_main_cv),0,SvREFCNT_inc($curpad_nam));",
1267 "av_store(CvPADLIST(PL_main_cv),1,SvREFCNT_inc($curpad_sym));");
1268}
1269
a9b6343a 1270sub descend_marked_unused {
1271 foreach my $pack (keys %unused_sub_packages)
1272 {
1273 mark_package($pack);
1274 }
1275}
1276
73544139 1277sub descend_marked_unused {
1278 foreach my $pack (keys %unused_sub_packages)
1279 {
1280 mark_package($pack);
1281 }
1282}
1283
a798dbf2 1284sub save_main {
66a2622e 1285 warn "Starting compile\n";
66a2622e 1286 warn "Walking tree\n";
73544139 1287 seek(STDOUT,0,0); #exclude print statements in BEGIN{} into output
a798dbf2 1288 walkoptree(main_root, "save");
1289 warn "done main optree, walking symtable for extras\n" if $debug_cv;
66a2622e 1290 save_unused_subs();
0cc1d052 1291 my $init_av = init_av->save;
81009501 1292 $init->add(sprintf("PL_main_root = s\\_%x;", ${main_root()}),
1293 sprintf("PL_main_start = s\\_%x;", ${main_start()}),
0cc1d052 1294 "PL_initav = $init_av;");
1295 save_context();
5ed82aed 1296 warn "Writing output\n";
a798dbf2 1297 output_boilerplate();
1298 print "\n";
1299 output_all("perl_init");
1300 print "\n";
1301 output_main();
1302}
1303
1304sub init_sections {
1305 my @sections = (init => \$init, decl => \$decl, sym => \$symsect,
1306 binop => \$binopsect, condop => \$condopsect,
66a2622e 1307 cop => \$copsect, gvop => \$gvopsect,
a798dbf2 1308 listop => \$listopsect, logop => \$logopsect,
1309 loop => \$loopsect, op => \$opsect, pmop => \$pmopsect,
1310 pvop => \$pvopsect, svop => \$svopsect, unop => \$unopsect,
1311 sv => \$svsect, xpv => \$xpvsect, xpvav => \$xpvavsect,
1312 xpvhv => \$xpvhvsect, xpvcv => \$xpvcvsect,
1313 xpviv => \$xpvivsect, xpvnv => \$xpvnvsect,
1314 xpvmg => \$xpvmgsect, xpvlv => \$xpvlvsect,
1315 xrv => \$xrvsect, xpvbm => \$xpvbmsect,
31d7d75a 1316 xpvio => \$xpviosect, bootstrap => \$bootstrap);
a798dbf2 1317 my ($name, $sectref);
1318 while (($name, $sectref) = splice(@sections, 0, 2)) {
66a2622e 1319 $$sectref = new B::C::Section $name, \%symtable, 0;
a798dbf2 1320 }
0cc1d052 1321}
1322
1323sub mark_unused
1324{
1325 my ($arg,$val) = @_;
1326 $unused_sub_packages{$arg} = $val;
a798dbf2 1327}
1328
1329sub compile {
1330 my @options = @_;
1331 my ($option, $opt, $arg);
1332 OPTION:
1333 while ($option = shift @options) {
1334 if ($option =~ /^-(.)(.*)/) {
1335 $opt = $1;
1336 $arg = $2;
1337 } else {
1338 unshift @options, $option;
1339 last OPTION;
1340 }
1341 if ($opt eq "-" && $arg eq "-") {
1342 shift @options;
1343 last OPTION;
1344 }
1345 if ($opt eq "w") {
1346 $warn_undefined_syms = 1;
1347 } elsif ($opt eq "D") {
1348 $arg ||= shift @options;
1349 foreach $arg (split(//, $arg)) {
1350 if ($arg eq "o") {
1351 B->debug(1);
1352 } elsif ($arg eq "c") {
1353 $debug_cops = 1;
1354 } elsif ($arg eq "A") {
1355 $debug_av = 1;
1356 } elsif ($arg eq "C") {
1357 $debug_cv = 1;
1358 } elsif ($arg eq "M") {
1359 $debug_mg = 1;
1360 } else {
1361 warn "ignoring unknown debug option: $arg\n";
1362 }
1363 }
1364 } elsif ($opt eq "o") {
1365 $arg ||= shift @options;
1366 open(STDOUT, ">$arg") or return "$arg: $!\n";
1367 } elsif ($opt eq "v") {
1368 $verbose = 1;
1369 } elsif ($opt eq "u") {
1370 $arg ||= shift @options;
0cc1d052 1371 mark_unused($arg,undef);
a798dbf2 1372 } elsif ($opt eq "f") {
1373 $arg ||= shift @options;
1374 if ($arg eq "cog") {
1375 $pv_copy_on_grow = 1;
1376 } elsif ($arg eq "no-cog") {
1377 $pv_copy_on_grow = 0;
1378 }
1379 } elsif ($opt eq "O") {
1380 $arg = 1 if $arg eq "";
1381 $pv_copy_on_grow = 0;
1382 if ($arg >= 1) {
1383 # Optimisations for -O1
1384 $pv_copy_on_grow = 1;
1385 }
1386 }
1387 }
1388 init_sections();
1389 if (@options) {
1390 return sub {
1391 my $objname;
1392 foreach $objname (@options) {
1393 eval "save_object(\\$objname)";
1394 }
1395 output_all();
1396 }
1397 } else {
1398 return sub { save_main() };
1399 }
1400}
1401
14021;
7f20e9dd 1403
1404__END__
1405
1406=head1 NAME
1407
1408B::C - Perl compiler's C backend
1409
1410=head1 SYNOPSIS
1411
1412 perl -MO=C[,OPTIONS] foo.pl
1413
1414=head1 DESCRIPTION
1415
1a52ab62 1416This compiler backend takes Perl source and generates C source code
1417corresponding to the internal structures that perl uses to run
1418your program. When the generated C source is compiled and run, it
1419cuts out the time which perl would have taken to load and parse
1420your program into its internal semi-compiled form. That means that
1421compiling with this backend will not help improve the runtime
1422execution speed of your program but may improve the start-up time.
1423Depending on the environment in which your program runs this may be
1424either a help or a hindrance.
1425
1426=head1 OPTIONS
1427
1428If there are any non-option arguments, they are taken to be
1429names of objects to be saved (probably doesn't work properly yet).
1430Without extra arguments, it saves the main program.
1431
1432=over 4
1433
1434=item B<-ofilename>
1435
1436Output to filename instead of STDOUT
1437
1438=item B<-v>
1439
1440Verbose compilation (currently gives a few compilation statistics).
1441
1442=item B<-->
1443
1444Force end of options
1445
1446=item B<-uPackname>
1447
1448Force apparently unused subs from package Packname to be compiled.
1449This allows programs to use eval "foo()" even when sub foo is never
1450seen to be used at compile time. The down side is that any subs which
1451really are never used also have code generated. This option is
1452necessary, for example, if you have a signal handler foo which you
1453initialise with C<$SIG{BAR} = "foo">. A better fix, though, is just
1454to change it to C<$SIG{BAR} = \&foo>. You can have multiple B<-u>
1455options. The compiler tries to figure out which packages may possibly
1456have subs in which need compiling but the current version doesn't do
1457it very well. In particular, it is confused by nested packages (i.e.
1458of the form C<A::B>) where package C<A> does not contain any subs.
1459
1460=item B<-D>
1461
1462Debug options (concatenated or separate flags like C<perl -D>).
1463
1464=item B<-Do>
1465
1466OPs, prints each OP as it's processed
1467
1468=item B<-Dc>
1469
1470COPs, prints COPs as processed (incl. file & line num)
1471
1472=item B<-DA>
1473
1474prints AV information on saving
1475
1476=item B<-DC>
1477
1478prints CV information on saving
1479
1480=item B<-DM>
1481
1482prints MAGIC information on saving
1483
1484=item B<-f>
1485
1486Force optimisations on or off one at a time.
1487
1488=item B<-fcog>
1489
1490Copy-on-grow: PVs declared and initialised statically.
1491
1492=item B<-fno-cog>
1493
1494No copy-on-grow.
1495
1496=item B<-On>
1497
1498Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>. Currently,
1499B<-O1> and higher set B<-fcog>.
1500
1501=head1 EXAMPLES
1502
1503 perl -MO=C,-ofoo.c foo.pl
1504 perl cc_harness -o foo foo.c
1505
1506Note that C<cc_harness> lives in the C<B> subdirectory of your perl
1507library directory. The utility called C<perlcc> may also be used to
1508help make use of this compiler.
1509
1510 perl -MO=C,-v,-DcA bar.pl > /dev/null
1511
1512=head1 BUGS
1513
1514Plenty. Current status: experimental.
7f20e9dd 1515
1516=head1 AUTHOR
1517
1518Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
1519
1520=cut