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