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