fix various C-backend shenanigans
[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;
5712119f 272 $svopsect->add(sprintf("s\\_%x, s\\_%x, %s,$handle_VC_problem %u, %u, %u, 0x%x, 0x%x, Nullsv",
a798dbf2 273 ${$op->next}, ${$op->sibling}, $op->ppaddr,
274 $op->targ, $op->type, $op_seq, $op->flags,
5712119f 275 $op->private));
276 $init->add(sprintf("svop_list[%d].op_sv = %s;", $svopsect->index, "(SV*)$svsym"));
a798dbf2 277 savesym($op, sprintf("(OP*)&svop_list[%d]", $svopsect->index));
278}
279
7934575e 280sub B::PADOP::save {
a798dbf2 281 my ($op, $level) = @_;
2c0b28dd 282 my $sym = objsym($op);
283 return $sym if defined $sym;
7934575e 284 $padopsect->add(sprintf("s\\_%x, s\\_%x, %s,$handle_VC_problem %u, %u, %u, 0x%x, 0x%x, Nullgv",
a798dbf2 285 ${$op->next}, ${$op->sibling}, $op->ppaddr,
286 $op->targ, $op->type, $op_seq, $op->flags,
287 $op->private));
7934575e 288 $init->add(sprintf("padop_list[%d].op_padix = %ld;",
289 $padopsect->index, $op->padix));
290 savesym($op, sprintf("(OP*)&padop_list[%d]", $padopsect->index));
a798dbf2 291}
292
293sub B::COP::save {
294 my ($op, $level) = @_;
2c0b28dd 295 my $sym = objsym($op);
296 return $sym if defined $sym;
57843af0 297 warn sprintf("COP: line %d file %s\n", $op->line, $op->file)
a798dbf2 298 if $debug_cops;
f0cd5c3a 299 $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 300 ${$op->next}, ${$op->sibling}, $op->ppaddr,
301 $op->targ, $op->type, $op_seq, $op->flags,
302 $op->private, cstring($op->label), $op->cop_seq,
303 $op->arybase, $op->line));
304 my $copix = $copsect->index;
57843af0 305 $init->add(sprintf("CopFILE_set(&cop_list[%d], %s);", $copix, cstring($op->file)),
562d31b8 306 sprintf("CopSTASHPV_set(&cop_list[%d], %s);", $copix, cstring($op->stashpv)));
a798dbf2 307 savesym($op, "(OP*)&cop_list[$copix]");
308}
309
310sub B::PMOP::save {
311 my ($op, $level) = @_;
2c0b28dd 312 my $sym = objsym($op);
313 return $sym if defined $sym;
a798dbf2 314 my $replroot = $op->pmreplroot;
315 my $replstart = $op->pmreplstart;
316 my $replrootfield = sprintf("s\\_%x", $$replroot);
317 my $replstartfield = sprintf("s\\_%x", $$replstart);
318 my $gvsym;
319 my $ppaddr = $op->ppaddr;
320 if ($$replroot) {
321 # OP_PUSHRE (a mutated version of OP_MATCH for the regexp
322 # argument to a split) stores a GV in op_pmreplroot instead
323 # of a substitution syntax tree. We don't want to walk that...
3f872cb9 324 if ($op->name eq "pushre") {
a798dbf2 325 $gvsym = $replroot->save;
326# warn "PMOP::save saving a pp_pushre with GV $gvsym\n"; # debug
327 $replrootfield = 0;
328 } else {
329 $replstartfield = saveoptree("*ignore*", $replroot, $replstart);
330 }
331 }
332 # pmnext handling is broken in perl itself, I think. Bad op_pmnext
333 # fields aren't noticed in perl's runtime (unless you try reset) but we
334 # segfault when trying to dereference it to find op->op_pmnext->op_type
f0cd5c3a 335 $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 336 ${$op->next}, ${$op->sibling}, $ppaddr, $op->targ,
337 $op->type, $op_seq, $op->flags, $op->private,
338 ${$op->first}, ${$op->last}, $op->children,
339 $replrootfield, $replstartfield,
340 $op->pmflags, $op->pmpermflags,));
341 my $pm = sprintf("pmop_list[%d]", $pmopsect->index);
342 my $re = $op->precomp;
343 if (defined($re)) {
344 my $resym = sprintf("re%d", $re_index++);
345 $decl->add(sprintf("static char *$resym = %s;", cstring($re)));
346 $init->add(sprintf("$pm.op_pmregexp = pregcomp($resym, $resym + %u, &$pm);",
347 length($re)));
348 }
349 if ($gvsym) {
350 $init->add("$pm.op_pmreplroot = (OP*)$gvsym;");
351 }
352 savesym($op, sprintf("(OP*)&pmop_list[%d]", $pmopsect->index));
353}
354
355sub B::SPECIAL::save {
356 my ($sv) = @_;
357 # special case: $$sv is not the address but an index into specialsv_list
358# warn "SPECIAL::save specialsv $$sv\n"; # debug
359 my $sym = $specialsv_name[$$sv];
360 if (!defined($sym)) {
361 confess "unknown specialsv index $$sv passed to B::SPECIAL::save";
362 }
363 return $sym;
364}
365
366sub B::OBJECT::save {}
367
368sub B::NULL::save {
369 my ($sv) = @_;
370 my $sym = objsym($sv);
371 return $sym if defined $sym;
372# warn "Saving SVt_NULL SV\n"; # debug
373 # debug
374 #if ($$sv == 0) {
375 # warn "NULL::save for sv = 0 called from @{[(caller(1))[3]]}\n";
376 #}
932e9ff9 377 $svsect->add(sprintf("0, %u, 0x%x", $sv->REFCNT , $sv->FLAGS));
a798dbf2 378 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
379}
380
381sub B::IV::save {
382 my ($sv) = @_;
383 my $sym = objsym($sv);
384 return $sym if defined $sym;
385 $xpvivsect->add(sprintf("0, 0, 0, %d", $sv->IVX));
386 $svsect->add(sprintf("&xpviv_list[%d], %lu, 0x%x",
932e9ff9 387 $xpvivsect->index, $sv->REFCNT , $sv->FLAGS));
a798dbf2 388 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
389}
390
391sub B::NV::save {
392 my ($sv) = @_;
393 my $sym = objsym($sv);
394 return $sym if defined $sym;
56eca212 395 my $val= $sv->NVX;
396 $val .= '.00' if $val =~ /^-?\d+$/;
397 $xpvnvsect->add(sprintf("0, 0, 0, %d, %s", $sv->IVX, $val));
a798dbf2 398 $svsect->add(sprintf("&xpvnv_list[%d], %lu, 0x%x",
932e9ff9 399 $xpvnvsect->index, $sv->REFCNT , $sv->FLAGS));
a798dbf2 400 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
401}
402
403sub B::PVLV::save {
404 my ($sv) = @_;
405 my $sym = objsym($sv);
406 return $sym if defined $sym;
407 my $pv = $sv->PV;
408 my $len = length($pv);
409 my ($pvsym, $pvmax) = savepv($pv);
410 my ($lvtarg, $lvtarg_sym);
411 $xpvlvsect->add(sprintf("%s, %u, %u, %d, %g, 0, 0, %u, %u, 0, %s",
412 $pvsym, $len, $pvmax, $sv->IVX, $sv->NVX,
413 $sv->TARGOFF, $sv->TARGLEN, cchar($sv->TYPE)));
414 $svsect->add(sprintf("&xpvlv_list[%d], %lu, 0x%x",
932e9ff9 415 $xpvlvsect->index, $sv->REFCNT , $sv->FLAGS));
a798dbf2 416 if (!$pv_copy_on_grow) {
417 $init->add(sprintf("xpvlv_list[%d].xpv_pv = savepvn(%s, %u);",
418 $xpvlvsect->index, cstring($pv), $len));
419 }
420 $sv->save_magic;
421 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
422}
423
424sub B::PVIV::save {
425 my ($sv) = @_;
426 my $sym = objsym($sv);
427 return $sym if defined $sym;
428 my $pv = $sv->PV;
429 my $len = length($pv);
430 my ($pvsym, $pvmax) = savepv($pv);
431 $xpvivsect->add(sprintf("%s, %u, %u, %d", $pvsym, $len, $pvmax, $sv->IVX));
432 $svsect->add(sprintf("&xpviv_list[%d], %u, 0x%x",
932e9ff9 433 $xpvivsect->index, $sv->REFCNT , $sv->FLAGS));
a798dbf2 434 if (!$pv_copy_on_grow) {
435 $init->add(sprintf("xpviv_list[%d].xpv_pv = savepvn(%s, %u);",
436 $xpvivsect->index, cstring($pv), $len));
437 }
438 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
439}
440
441sub B::PVNV::save {
442 my ($sv) = @_;
443 my $sym = objsym($sv);
444 return $sym if defined $sym;
66a2622e 445 my $pv = $sv->PV;
446 $pv = '' unless defined $pv;
a798dbf2 447 my $len = length($pv);
448 my ($pvsym, $pvmax) = savepv($pv);
56eca212 449 my $val= $sv->NVX;
450 $val .= '.00' if $val =~ /^-?\d+$/;
a798dbf2 451 $xpvnvsect->add(sprintf("%s, %u, %u, %d, %s",
56eca212 452 $pvsym, $len, $pvmax, $sv->IVX, $val));
a798dbf2 453 $svsect->add(sprintf("&xpvnv_list[%d], %lu, 0x%x",
932e9ff9 454 $xpvnvsect->index, $sv->REFCNT , $sv->FLAGS));
a798dbf2 455 if (!$pv_copy_on_grow) {
456 $init->add(sprintf("xpvnv_list[%d].xpv_pv = savepvn(%s,%u);",
457 $xpvnvsect->index, cstring($pv), $len));
458 }
459 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
460}
461
462sub B::BM::save {
463 my ($sv) = @_;
464 my $sym = objsym($sv);
465 return $sym if defined $sym;
466 my $pv = $sv->PV . "\0" . $sv->TABLE;
467 my $len = length($pv);
468 $xpvbmsect->add(sprintf("0, %u, %u, %d, %s, 0, 0, %d, %u, 0x%x",
469 $len, $len + 258, $sv->IVX, $sv->NVX,
470 $sv->USEFUL, $sv->PREVIOUS, $sv->RARE));
471 $svsect->add(sprintf("&xpvbm_list[%d], %lu, 0x%x",
932e9ff9 472 $xpvbmsect->index, $sv->REFCNT , $sv->FLAGS));
a798dbf2 473 $sv->save_magic;
474 $init->add(sprintf("xpvbm_list[%d].xpv_pv = savepvn(%s, %u);",
475 $xpvbmsect->index, cstring($pv), $len),
476 sprintf("xpvbm_list[%d].xpv_cur = %u;",
477 $xpvbmsect->index, $len - 257));
478 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
479}
480
481sub B::PV::save {
482 my ($sv) = @_;
483 my $sym = objsym($sv);
484 return $sym if defined $sym;
485 my $pv = $sv->PV;
486 my $len = length($pv);
487 my ($pvsym, $pvmax) = savepv($pv);
488 $xpvsect->add(sprintf("%s, %u, %u", $pvsym, $len, $pvmax));
489 $svsect->add(sprintf("&xpv_list[%d], %lu, 0x%x",
932e9ff9 490 $xpvsect->index, $sv->REFCNT , $sv->FLAGS));
a798dbf2 491 if (!$pv_copy_on_grow) {
492 $init->add(sprintf("xpv_list[%d].xpv_pv = savepvn(%s, %u);",
493 $xpvsect->index, cstring($pv), $len));
494 }
495 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
496}
497
498sub B::PVMG::save {
499 my ($sv) = @_;
500 my $sym = objsym($sv);
501 return $sym if defined $sym;
502 my $pv = $sv->PV;
503 my $len = length($pv);
504 my ($pvsym, $pvmax) = savepv($pv);
505 $xpvmgsect->add(sprintf("%s, %u, %u, %d, %s, 0, 0",
506 $pvsym, $len, $pvmax, $sv->IVX, $sv->NVX));
507 $svsect->add(sprintf("&xpvmg_list[%d], %lu, 0x%x",
932e9ff9 508 $xpvmgsect->index, $sv->REFCNT , $sv->FLAGS));
a798dbf2 509 if (!$pv_copy_on_grow) {
510 $init->add(sprintf("xpvmg_list[%d].xpv_pv = savepvn(%s, %u);",
511 $xpvmgsect->index, cstring($pv), $len));
512 }
513 $sym = savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
514 $sv->save_magic;
515 return $sym;
516}
517
518sub B::PVMG::save_magic {
519 my ($sv) = @_;
520 #warn sprintf("saving magic for %s (0x%x)\n", class($sv), $$sv); # debug
521 my $stash = $sv->SvSTASH;
56eca212 522 $stash->save;
a798dbf2 523 if ($$stash) {
524 warn sprintf("xmg_stash = %s (0x%x)\n", $stash->NAME, $$stash)
525 if $debug_mg;
526 # XXX Hope stash is already going to be saved.
527 $init->add(sprintf("SvSTASH(s\\_%x) = s\\_%x;", $$sv, $$stash));
528 }
529 my @mgchain = $sv->MAGIC;
88b39979 530 my ($mg, $type, $obj, $ptr,$len,$ptrsv);
a798dbf2 531 foreach $mg (@mgchain) {
532 $type = $mg->TYPE;
533 $obj = $mg->OBJ;
534 $ptr = $mg->PTR;
88b39979 535 $len=$mg->LENGTH;
a798dbf2 536 if ($debug_mg) {
537 warn sprintf("magic %s (0x%x), obj %s (0x%x), type %s, ptr %s\n",
538 class($sv), $$sv, class($obj), $$obj,
539 cchar($type), cstring($ptr));
540 }
56eca212 541 $obj->save;
88b39979 542 if ($len == HEf_SVKEY){
543 #The pointer is an SV*
544 $ptrsv=svref_2object($ptr)->save;
5ab5c7a4 545 $init->add(sprintf("sv_magic((SV*)s\\_%x, (SV*)s\\_%x, %s,(char *) %s, %d);",
88b39979 546 $$sv, $$obj, cchar($type),$ptrsv,$len));
547 }else{
548 $init->add(sprintf("sv_magic((SV*)s\\_%x, (SV*)s\\_%x, %s, %s, %d);",
a798dbf2 549 $$sv, $$obj, cchar($type),cstring($ptr),$len));
88b39979 550 }
a798dbf2 551 }
552}
553
554sub B::RV::save {
555 my ($sv) = @_;
556 my $sym = objsym($sv);
557 return $sym if defined $sym;
66a2622e 558 my $rv = $sv->RV->save;
559 $rv =~ s/^\([AGHS]V\s*\*\)\s*(\&sv_list.*)$/$1/;
560 $xrvsect->add($rv);
a798dbf2 561 $svsect->add(sprintf("&xrv_list[%d], %lu, 0x%x",
932e9ff9 562 $xrvsect->index, $sv->REFCNT , $sv->FLAGS));
a798dbf2 563 return savesym($sv, sprintf("&sv_list[%d]", $svsect->index));
564}
565
566sub try_autoload {
567 my ($cvstashname, $cvname) = @_;
568 warn sprintf("No definition for sub %s::%s\n", $cvstashname, $cvname);
569 # Handle AutoLoader classes explicitly. Any more general AUTOLOAD
570 # use should be handled by the class itself.
571 no strict 'refs';
572 my $isa = \@{"$cvstashname\::ISA"};
573 if (grep($_ eq "AutoLoader", @$isa)) {
574 warn "Forcing immediate load of sub derived from AutoLoader\n";
575 # Tweaked version of AutoLoader::AUTOLOAD
576 my $dir = $cvstashname;
577 $dir =~ s(::)(/)g;
578 eval { require "auto/$dir/$cvname.al" };
579 if ($@) {
580 warn qq(failed require "auto/$dir/$cvname.al": $@\n);
581 return 0;
582 } else {
583 return 1;
584 }
585 }
586}
e9a14d94 587sub Dummy_initxs{};
a798dbf2 588sub B::CV::save {
589 my ($cv) = @_;
590 my $sym = objsym($cv);
591 if (defined($sym)) {
592# warn sprintf("CV 0x%x already saved as $sym\n", $$cv); # debug
593 return $sym;
594 }
595 # Reserve a place in svsect and xpvcvsect and record indices
af765ed9 596 my $gv = $cv->GV;
6771324e 597 my ($cvname, $cvstashname);
598 if ($$gv){
599 $cvname = $gv->NAME;
600 $cvstashname = $gv->STASH->NAME;
601 }
af765ed9 602 my $root = $cv->ROOT;
603 my $cvxsub = $cv->XSUB;
e9a14d94 604 #INIT is removed from the symbol table, so this call must come
605 # from PL_initav->save. Re-bootstrapping will push INIT back in
606 # so nullop should be sent.
607 if ($cvxsub && ($cvname ne "INIT")) {
af765ed9 608 my $egv = $gv->EGV;
609 my $stashname = $egv->STASH->NAME;
be6f3502 610 if ($cvname eq "bootstrap")
611 {
b195d487 612 my $file = $gv->FILE;
be6f3502 613 $decl->add("/* bootstrap $file */");
614 warn "Bootstrap $stashname $file\n";
615 $xsub{$stashname}='Dynamic';
616 # $xsub{$stashname}='Static' unless $xsub{$stashname};
a0e9c8c7 617 return qq/NULL/;
be6f3502 618 }
a0e9c8c7 619 warn sprintf("stub for XSUB $cvstashname\:\:$cvname CV 0x%x\n", $$cv) if $debug_cv;
be6f3502 620 return qq/(perl_get_cv("$stashname\:\:$cvname",TRUE))/;
e9a14d94 621 }
622 if ($cvxsub && $cvname eq "INIT") {
623 no strict 'refs';
624 return svref_2object(\&Dummy_initxs)->save;
af765ed9 625 }
a798dbf2 626 my $sv_ix = $svsect->index + 1;
627 $svsect->add("svix$sv_ix");
628 my $xpvcv_ix = $xpvcvsect->index + 1;
629 $xpvcvsect->add("xpvcvix$xpvcv_ix");
630 # Save symbol now so that GvCV() doesn't recurse back to us via CvGV()
631 $sym = savesym($cv, "&sv_list[$sv_ix]");
a0e9c8c7 632 warn sprintf("saving $cvstashname\:\:$cvname CV 0x%x as $sym\n", $$cv) if $debug_cv;
a798dbf2 633 if (!$$root && !$cvxsub) {
634 if (try_autoload($cvstashname, $cvname)) {
635 # Recalculate root and xsub
636 $root = $cv->ROOT;
637 $cvxsub = $cv->XSUB;
638 if ($$root || $cvxsub) {
639 warn "Successful forced autoload\n";
640 }
641 }
642 }
643 my $startfield = 0;
644 my $padlist = $cv->PADLIST;
645 my $pv = $cv->PV;
646 my $xsub = 0;
647 my $xsubany = "Nullany";
648 if ($$root) {
649 warn sprintf("saving op tree for CV 0x%x, root = 0x%x\n",
650 $$cv, $$root) if $debug_cv;
651 my $ppname = "";
652 if ($$gv) {
653 my $stashname = $gv->STASH->NAME;
654 my $gvname = $gv->NAME;
655 if ($gvname ne "__ANON__") {
656 $ppname = (${$gv->FORM} == $$cv) ? "pp_form_" : "pp_sub_";
657 $ppname .= ($stashname eq "main") ?
658 $gvname : "$stashname\::$gvname";
659 $ppname =~ s/::/__/g;
44887cfa 660 if ($gvname eq "INIT"){
661 $ppname .= "_$initsub_index";
662 $initsub_index++;
663 }
a798dbf2 664 }
665 }
666 if (!$ppname) {
667 $ppname = "pp_anonsub_$anonsub_index";
668 $anonsub_index++;
669 }
670 $startfield = saveoptree($ppname, $root, $cv->START, $padlist->ARRAY);
671 warn sprintf("done saving op tree for CV 0x%x, name %s, root 0x%x\n",
672 $$cv, $ppname, $$root) if $debug_cv;
673 if ($$padlist) {
674 warn sprintf("saving PADLIST 0x%x for CV 0x%x\n",
675 $$padlist, $$cv) if $debug_cv;
676 $padlist->save;
677 warn sprintf("done saving PADLIST 0x%x for CV 0x%x\n",
678 $$padlist, $$cv) if $debug_cv;
679 }
680 }
a798dbf2 681 else {
682 warn sprintf("No definition for sub %s::%s (unable to autoload)\n",
683 $cvstashname, $cvname); # debug
66a2622e 684 }
685 $pv = '' unless defined $pv; # Avoid use of undef warnings
5712119f 686 $symsect->add(sprintf("xpvcvix%d\t%s, %u, 0, %d, %s, 0, Nullhv, Nullhv, %s, s\\_%x, $xsub, $xsubany, Nullgv, \"\", %d, s\\_%x, (CV*)s\\_%x, 0x%x",
a798dbf2 687 $xpvcv_ix, cstring($pv), length($pv), $cv->IVX,
688 $cv->NVX, $startfield, ${$cv->ROOT}, $cv->DEPTH,
5cfd8ad4 689 $$padlist, ${$cv->OUTSIDE}, $cv->CvFLAGS));
690
691 if (${$cv->OUTSIDE} == ${main_cv()}){
692 $init->add(sprintf("CvOUTSIDE(s\\_%x)=PL_main_cv;",$$cv));
358b5eb8 693 $init->add(sprintf("SvREFCNT_inc(PL_main_cv);"));
5cfd8ad4 694 }
695
a798dbf2 696 if ($$gv) {
697 $gv->save;
698 $init->add(sprintf("CvGV(s\\_%x) = s\\_%x;",$$cv,$$gv));
699 warn sprintf("done saving GV 0x%x for CV 0x%x\n",
700 $$gv, $$cv) if $debug_cv;
701 }
57843af0 702 $init->add(sprintf("CvFILE($sym) = %s;", cstring($cv->FILE)));
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;
57843af0 1014 char * xcv_file;
b195d487 1015 long xcv_depth; /* >= 2 indicates recursive call */
a798dbf2 1016 AV * xcv_padlist;
1017 CV * xcv_outside;
1018#ifdef USE_THREADS
1019 perl_mutex *xcv_mutexp;
1020 struct perl_thread *xcv_owner; /* current owner thread */
1021#endif /* USE_THREADS */
1022 U8 xcv_flags;
1023} XPVCV_or_similar;
1024#define ANYINIT(i) i
1025#else
1026#define XPVCV_or_similar XPVCV
1027#define ANYINIT(i) {i}
1028#endif /* BROKEN_UNION_INIT */
1029#define Nullany ANYINIT(0)
1030
1031#define UNUSED 0
1032#define sym_0 0
1033
1034EOT
1035 print "static GV *gv_list[$gv_index];\n" if $gv_index;
1036 print "\n";
1037}
1038
1039
1040sub output_boilerplate {
1041 print <<'EOT';
1042#include "EXTERN.h"
1043#include "perl.h"
a798dbf2 1044
1045/* Workaround for mapstart: the only op which needs a different ppaddr */
3f872cb9 1046#undef Perl_pp_mapstart
1047#define Perl_pp_mapstart Perl_pp_grepstart
511dd457 1048#define XS_DynaLoader_boot_DynaLoader boot_DynaLoader
5712119f 1049EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
a798dbf2 1050
5712119f 1051static void xs_init (pTHX);
1052static void dl_init (pTHX);
a798dbf2 1053static PerlInterpreter *my_perl;
1054EOT
1055}
1056
1057sub output_main {
1058 print <<'EOT';
1059int
a798dbf2 1060main(int argc, char **argv, char **env)
a798dbf2 1061{
1062 int exitstatus;
1063 int i;
1064 char **fakeargv;
1065
5712119f 1066 PERL_SYS_INIT3(&argc,&argv,&env);
a798dbf2 1067
81009501 1068 if (!PL_do_undump) {
a798dbf2 1069 my_perl = perl_alloc();
1070 if (!my_perl)
1071 exit(1);
1072 perl_construct( my_perl );
5712119f 1073 PL_perl_destruct_level = 0;
a798dbf2 1074 }
1075
1076#ifdef CSH
81009501 1077 if (!PL_cshlen)
1078 PL_cshlen = strlen(PL_cshname);
a798dbf2 1079#endif
1080
1081#ifdef ALLOW_PERL_OPTIONS
1082#define EXTRA_OPTIONS 2
1083#else
1084#define EXTRA_OPTIONS 3
1085#endif /* ALLOW_PERL_OPTIONS */
1086 New(666, fakeargv, argc + EXTRA_OPTIONS + 1, char *);
1087 fakeargv[0] = argv[0];
1088 fakeargv[1] = "-e";
1089 fakeargv[2] = "";
1090#ifndef ALLOW_PERL_OPTIONS
1091 fakeargv[3] = "--";
1092#endif /* ALLOW_PERL_OPTIONS */
1093 for (i = 1; i < argc; i++)
1094 fakeargv[i + EXTRA_OPTIONS] = argv[i];
1095 fakeargv[argc + EXTRA_OPTIONS] = 0;
1096
1097 exitstatus = perl_parse(my_perl, xs_init, argc + EXTRA_OPTIONS,
1098 fakeargv, NULL);
1099 if (exitstatus)
1100 exit( exitstatus );
1101
1102 sv_setpv(GvSV(gv_fetchpv("0", TRUE, SVt_PV)), argv[0]);
81009501 1103 PL_main_cv = PL_compcv;
1104 PL_compcv = 0;
a798dbf2 1105
1106 exitstatus = perl_init();
1107 if (exitstatus)
1108 exit( exitstatus );
5712119f 1109 dl_init(aTHX);
a798dbf2 1110
1111 exitstatus = perl_run( my_perl );
1112
1113 perl_destruct( my_perl );
1114 perl_free( my_perl );
1115
5712119f 1116 PERL_SYS_TERM();
1117
a798dbf2 1118 exit( exitstatus );
1119}
1120
511dd457 1121/* yanked from perl.c */
a798dbf2 1122static void
5712119f 1123xs_init(pTHX)
a798dbf2 1124{
511dd457 1125 char *file = __FILE__;
af765ed9 1126 dTARG;
1127 djSP;
a798dbf2 1128EOT
af765ed9 1129 print "\n#ifdef USE_DYNAMIC_LOADING";
1130 print qq/\n\tnewXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);/;
1131 print "\n#endif\n" ;
a0e9c8c7 1132 # delete $xsub{'DynaLoader'};
af765ed9 1133 delete $xsub{'UNIVERSAL'};
be6f3502 1134 print("/* bootstrapping code*/\n\tSAVETMPS;\n");
af765ed9 1135 print("\ttarg=sv_newmortal();\n");
a0e9c8c7 1136 print "#ifdef DYNALOADER_BOOTSTRAP\n";
1137 print "\tPUSHMARK(sp);\n";
1138 print qq/\tXPUSHp("DynaLoader",strlen("DynaLoader"));\n/;
1139 print qq/\tPUTBACK;\n/;
5712119f 1140 print "\tboot_DynaLoader(aTHX_ NULL);\n";
a0e9c8c7 1141 print qq/\tSPAGAIN;\n/;
1142 print "#endif\n";
1143 foreach my $stashname (keys %xsub){
be6f3502 1144 if ($xsub{$stashname} ne 'Dynamic') {
1145 my $stashxsub=$stashname;
1146 $stashxsub =~ s/::/__/g;
1147 print "\tPUSHMARK(sp);\n";
a0e9c8c7 1148 print qq/\tXPUSHp("$stashname",strlen("$stashname"));\n/;
1149 print qq/\tPUTBACK;\n/;
5712119f 1150 print "\tboot_$stashxsub(aTHX_ NULL);\n";
a0e9c8c7 1151 print qq/\tSPAGAIN;\n/;
be6f3502 1152 }
1153 }
1154 print("\tFREETMPS;\n/* end bootstrapping code */\n");
a0e9c8c7 1155 print "}\n";
be6f3502 1156
1157print <<'EOT';
1158static void
5712119f 1159dl_init(pTHX)
be6f3502 1160{
1161 char *file = __FILE__;
1162 dTARG;
1163 djSP;
1164EOT
1165 print("/* Dynamicboot strapping code*/\n\tSAVETMPS;\n");
1166 print("\ttarg=sv_newmortal();\n");
1167 foreach my $stashname (@DynaLoader::dl_modules) {
1168 warn "Loaded $stashname\n";
1169 if (exists($xsub{$stashname}) && $xsub{$stashname} eq 'Dynamic') {
1170 my $stashxsub=$stashname;
1171 $stashxsub =~ s/::/__/g;
1172 print "\tPUSHMARK(sp);\n";
a0e9c8c7 1173 print qq/\tXPUSHp("$stashname",/,length($stashname),qq/);\n/;
be6f3502 1174 print qq/\tPUTBACK;\n/;
af765ed9 1175 print "#ifdef DYNALOADER_BOOTSTRAP\n";
1176 warn "bootstrapping $stashname added to xs_init\n";
be6f3502 1177 print qq/\tperl_call_method("bootstrap",G_DISCARD);\n/;
af765ed9 1178 print "\n#else\n";
5712119f 1179 print "\tboot_$stashxsub(aTHX_ NULL);\n";
be6f3502 1180 print "#endif\n";
1181 print qq/\tSPAGAIN;\n/;
1182 }
af765ed9 1183 }
be6f3502 1184 print("\tFREETMPS;\n/* end Dynamic bootstrapping code */\n");
a0e9c8c7 1185 print "}\n";
af765ed9 1186}
a798dbf2 1187sub dump_symtable {
1188 # For debugging
1189 my ($sym, $val);
1190 warn "----Symbol table:\n";
1191 while (($sym, $val) = each %symtable) {
1192 warn "$sym => $val\n";
1193 }
1194 warn "---End of symbol table\n";
1195}
1196
1197sub save_object {
1198 my $sv;
1199 foreach $sv (@_) {
1200 svref_2object($sv)->save;
1201 }
338a6d08 1202}
1203
1204sub Dummy_BootStrap { }
a798dbf2 1205
66a2622e 1206sub B::GV::savecv
1207{
1208 my $gv = shift;
1209 my $package=$gv->STASH->NAME;
1210 my $name = $gv->NAME;
1211 my $cv = $gv->CV;
7cf11ee8 1212 my $sv = $gv->SV;
1213 my $av = $gv->AV;
1214 my $hv = $gv->HV;
7cf11ee8 1215
66a2622e 1216 # We may be looking at this package just because it is a branch in the
1217 # symbol table which is on the path to a package which we need to save
7cf11ee8 1218 # e.g. this is 'Getopt' and we need to save 'Getopt::Long'
66a2622e 1219 #
7cf11ee8 1220 return unless ($unused_sub_packages{$package});
be6f3502 1221 return unless ($$cv || $$av || $$sv || $$hv);
1222 $gv->save;
66a2622e 1223}
5ed82aed 1224
66a2622e 1225sub mark_package
1226{
1227 my $package = shift;
1228 unless ($unused_sub_packages{$package})
1229 {
1230 no strict 'refs';
1231 $unused_sub_packages{$package} = 1;
6771324e 1232 if (defined @{$package.'::ISA'})
66a2622e 1233 {
1234 foreach my $isa (@{$package.'::ISA'})
1235 {
1236 if ($isa eq 'DynaLoader')
1237 {
1238 unless (defined(&{$package.'::bootstrap'}))
1239 {
1240 warn "Forcing bootstrap of $package\n";
1241 eval { $package->bootstrap };
1242 }
1243 }
a0e9c8c7 1244# else
66a2622e 1245 {
1246 unless ($unused_sub_packages{$isa})
1247 {
1248 warn "$isa saved (it is in $package\'s \@ISA)\n";
1249 mark_package($isa);
1250 }
1251 }
1252 }
1253 }
1254 }
1255 return 1;
1256}
1257
1258sub should_save
1259{
1260 no strict qw(vars refs);
1261 my $package = shift;
1262 $package =~ s/::$//;
1263 return $unused_sub_packages{$package} = 0 if ($package =~ /::::/); # skip ::::ISA::CACHE etc.
cf86991c 1264 # warn "Considering $package\n";#debug
66a2622e 1265 foreach my $u (grep($unused_sub_packages{$_},keys %unused_sub_packages))
1266 {
1267 # If this package is a prefix to something we are saving, traverse it
1268 # but do not mark it for saving if it is not already
1269 # e.g. to get to Getopt::Long we need to traverse Getopt but need
1270 # not save Getopt
1271 return 1 if ($u =~ /^$package\:\:/);
1272 }
1273 if (exists $unused_sub_packages{$package})
1274 {
cf86991c 1275 # warn "Cached $package is ".$unused_sub_packages{$package}."\n";
cfa4c8ee 1276 delete_unsaved_hashINC($package) unless $unused_sub_packages{$package} ;
1277 return $unused_sub_packages{$package};
66a2622e 1278 }
1279 # Omit the packages which we use (and which cause grief
1280 # because of fancy "goto &$AUTOLOAD" stuff).
1281 # XXX Surely there must be a nicer way to do this.
1282 if ($package eq "FileHandle" || $package eq "Config" ||
cf86991c 1283 $package eq "SelectSaver" || $package =~/^(B|IO)::/)
66a2622e 1284 {
cfa4c8ee 1285 delete_unsaved_hashINC($package);
66a2622e 1286 return $unused_sub_packages{$package} = 0;
1287 }
1288 # Now see if current package looks like an OO class this is probably too strong.
1289 foreach my $m (qw(new DESTROY TIESCALAR TIEARRAY TIEHASH TIEHANDLE))
1290 {
1291 if ($package->can($m))
1292 {
1293 warn "$package has method $m: saving package\n";#debug
1294 return mark_package($package);
1295 }
1296 }
cfa4c8ee 1297 delete_unsaved_hashINC($package);
66a2622e 1298 return $unused_sub_packages{$package} = 0;
a798dbf2 1299}
cfa4c8ee 1300sub delete_unsaved_hashINC{
1301 my $packname=shift;
1302 $packname =~ s/\:\:/\//g;
1303 $packname .= '.pm';
59c10aa2 1304# warn "deleting $packname" if $INC{$packname} ;# debug
cfa4c8ee 1305 delete $INC{$packname};
1306}
66a2622e 1307sub walkpackages
1308{
1309 my ($symref, $recurse, $prefix) = @_;
1310 my $sym;
1311 my $ref;
1312 no strict 'vars';
1313 local(*glob);
1314 $prefix = '' unless defined $prefix;
1315 while (($sym, $ref) = each %$symref)
1316 {
1317 *glob = $ref;
1318 if ($sym =~ /::$/)
1319 {
1320 $sym = $prefix . $sym;
1321 if ($sym ne "main::" && &$recurse($sym))
1322 {
1323 walkpackages(\%glob, $recurse, $sym);
1324 }
1325 }
1326 }
1327}
338a6d08 1328
1329
66a2622e 1330sub save_unused_subs
1331{
1332 no strict qw(refs);
a9b6343a 1333 &descend_marked_unused;
66a2622e 1334 warn "Prescan\n";
1335 walkpackages(\%{"main::"}, sub { should_save($_[0]); return 1 });
1336 warn "Saving methods\n";
1337 walksymtable(\%{"main::"}, "savecv", \&should_save);
a798dbf2 1338}
1339
0cc1d052 1340sub save_context
1341{
1342 my $curpad_nam = (comppadlist->ARRAY)[0]->save;
1343 my $curpad_sym = (comppadlist->ARRAY)[1]->save;
1344 my $inc_hv = svref_2object(\%INC)->save;
1345 my $inc_av = svref_2object(\@INC)->save;
56eca212 1346 my $amagic_generate= amagic_generation;
0cc1d052 1347 $init->add( "PL_curpad = AvARRAY($curpad_sym);",
1348 "GvHV(PL_incgv) = $inc_hv;",
1349 "GvAV(PL_incgv) = $inc_av;",
1350 "av_store(CvPADLIST(PL_main_cv),0,SvREFCNT_inc($curpad_nam));",
56eca212 1351 "av_store(CvPADLIST(PL_main_cv),1,SvREFCNT_inc($curpad_sym));",
1352 "PL_amagic_generation= $amagic_generate;" );
0cc1d052 1353}
1354
a9b6343a 1355sub descend_marked_unused {
1356 foreach my $pack (keys %unused_sub_packages)
1357 {
1358 mark_package($pack);
1359 }
1360}
73544139 1361
a798dbf2 1362sub save_main {
66a2622e 1363 warn "Starting compile\n";
66a2622e 1364 warn "Walking tree\n";
73544139 1365 seek(STDOUT,0,0); #exclude print statements in BEGIN{} into output
a798dbf2 1366 walkoptree(main_root, "save");
1367 warn "done main optree, walking symtable for extras\n" if $debug_cv;
66a2622e 1368 save_unused_subs();
0cc1d052 1369 my $init_av = init_av->save;
81009501 1370 $init->add(sprintf("PL_main_root = s\\_%x;", ${main_root()}),
1371 sprintf("PL_main_start = s\\_%x;", ${main_start()}),
5ab5c7a4 1372 "PL_initav = (AV *) $init_av;");
0cc1d052 1373 save_context();
5ed82aed 1374 warn "Writing output\n";
a798dbf2 1375 output_boilerplate();
1376 print "\n";
1377 output_all("perl_init");
1378 print "\n";
1379 output_main();
1380}
1381
1382sub init_sections {
1383 my @sections = (init => \$init, decl => \$decl, sym => \$symsect,
1384 binop => \$binopsect, condop => \$condopsect,
7934575e 1385 cop => \$copsect, padop => \$padopsect,
a798dbf2 1386 listop => \$listopsect, logop => \$logopsect,
1387 loop => \$loopsect, op => \$opsect, pmop => \$pmopsect,
1388 pvop => \$pvopsect, svop => \$svopsect, unop => \$unopsect,
1389 sv => \$svsect, xpv => \$xpvsect, xpvav => \$xpvavsect,
1390 xpvhv => \$xpvhvsect, xpvcv => \$xpvcvsect,
1391 xpviv => \$xpvivsect, xpvnv => \$xpvnvsect,
1392 xpvmg => \$xpvmgsect, xpvlv => \$xpvlvsect,
1393 xrv => \$xrvsect, xpvbm => \$xpvbmsect,
af765ed9 1394 xpvio => \$xpviosect);
a798dbf2 1395 my ($name, $sectref);
1396 while (($name, $sectref) = splice(@sections, 0, 2)) {
66a2622e 1397 $$sectref = new B::C::Section $name, \%symtable, 0;
a798dbf2 1398 }
0cc1d052 1399}
1400
1401sub mark_unused
1402{
1403 my ($arg,$val) = @_;
1404 $unused_sub_packages{$arg} = $val;
a798dbf2 1405}
1406
1407sub compile {
1408 my @options = @_;
1409 my ($option, $opt, $arg);
1410 OPTION:
1411 while ($option = shift @options) {
1412 if ($option =~ /^-(.)(.*)/) {
1413 $opt = $1;
1414 $arg = $2;
1415 } else {
1416 unshift @options, $option;
1417 last OPTION;
1418 }
1419 if ($opt eq "-" && $arg eq "-") {
1420 shift @options;
1421 last OPTION;
1422 }
1423 if ($opt eq "w") {
1424 $warn_undefined_syms = 1;
1425 } elsif ($opt eq "D") {
1426 $arg ||= shift @options;
1427 foreach $arg (split(//, $arg)) {
1428 if ($arg eq "o") {
1429 B->debug(1);
1430 } elsif ($arg eq "c") {
1431 $debug_cops = 1;
1432 } elsif ($arg eq "A") {
1433 $debug_av = 1;
1434 } elsif ($arg eq "C") {
1435 $debug_cv = 1;
1436 } elsif ($arg eq "M") {
1437 $debug_mg = 1;
1438 } else {
1439 warn "ignoring unknown debug option: $arg\n";
1440 }
1441 }
1442 } elsif ($opt eq "o") {
1443 $arg ||= shift @options;
1444 open(STDOUT, ">$arg") or return "$arg: $!\n";
1445 } elsif ($opt eq "v") {
1446 $verbose = 1;
1447 } elsif ($opt eq "u") {
1448 $arg ||= shift @options;
0cc1d052 1449 mark_unused($arg,undef);
a798dbf2 1450 } elsif ($opt eq "f") {
1451 $arg ||= shift @options;
1452 if ($arg eq "cog") {
1453 $pv_copy_on_grow = 1;
1454 } elsif ($arg eq "no-cog") {
1455 $pv_copy_on_grow = 0;
1456 }
1457 } elsif ($opt eq "O") {
1458 $arg = 1 if $arg eq "";
1459 $pv_copy_on_grow = 0;
1460 if ($arg >= 1) {
1461 # Optimisations for -O1
1462 $pv_copy_on_grow = 1;
1463 }
1464 }
1465 }
1466 init_sections();
1467 if (@options) {
1468 return sub {
1469 my $objname;
1470 foreach $objname (@options) {
1471 eval "save_object(\\$objname)";
1472 }
1473 output_all();
1474 }
1475 } else {
1476 return sub { save_main() };
1477 }
1478}
1479
14801;
7f20e9dd 1481
1482__END__
1483
1484=head1 NAME
1485
1486B::C - Perl compiler's C backend
1487
1488=head1 SYNOPSIS
1489
1490 perl -MO=C[,OPTIONS] foo.pl
1491
1492=head1 DESCRIPTION
1493
1a52ab62 1494This compiler backend takes Perl source and generates C source code
1495corresponding to the internal structures that perl uses to run
1496your program. When the generated C source is compiled and run, it
1497cuts out the time which perl would have taken to load and parse
1498your program into its internal semi-compiled form. That means that
1499compiling with this backend will not help improve the runtime
1500execution speed of your program but may improve the start-up time.
1501Depending on the environment in which your program runs this may be
1502either a help or a hindrance.
1503
1504=head1 OPTIONS
1505
1506If there are any non-option arguments, they are taken to be
1507names of objects to be saved (probably doesn't work properly yet).
1508Without extra arguments, it saves the main program.
1509
1510=over 4
1511
1512=item B<-ofilename>
1513
1514Output to filename instead of STDOUT
1515
1516=item B<-v>
1517
1518Verbose compilation (currently gives a few compilation statistics).
1519
1520=item B<-->
1521
1522Force end of options
1523
1524=item B<-uPackname>
1525
1526Force apparently unused subs from package Packname to be compiled.
1527This allows programs to use eval "foo()" even when sub foo is never
1528seen to be used at compile time. The down side is that any subs which
1529really are never used also have code generated. This option is
1530necessary, for example, if you have a signal handler foo which you
1531initialise with C<$SIG{BAR} = "foo">. A better fix, though, is just
1532to change it to C<$SIG{BAR} = \&foo>. You can have multiple B<-u>
1533options. The compiler tries to figure out which packages may possibly
1534have subs in which need compiling but the current version doesn't do
1535it very well. In particular, it is confused by nested packages (i.e.
1536of the form C<A::B>) where package C<A> does not contain any subs.
1537
1538=item B<-D>
1539
1540Debug options (concatenated or separate flags like C<perl -D>).
1541
1542=item B<-Do>
1543
1544OPs, prints each OP as it's processed
1545
1546=item B<-Dc>
1547
1548COPs, prints COPs as processed (incl. file & line num)
1549
1550=item B<-DA>
1551
1552prints AV information on saving
1553
1554=item B<-DC>
1555
1556prints CV information on saving
1557
1558=item B<-DM>
1559
1560prints MAGIC information on saving
1561
1562=item B<-f>
1563
1564Force optimisations on or off one at a time.
1565
1566=item B<-fcog>
1567
1568Copy-on-grow: PVs declared and initialised statically.
1569
1570=item B<-fno-cog>
1571
1572No copy-on-grow.
1573
1574=item B<-On>
1575
1576Optimisation level (n = 0, 1, 2, ...). B<-O> means B<-O1>. Currently,
1577B<-O1> and higher set B<-fcog>.
1578
1579=head1 EXAMPLES
1580
1581 perl -MO=C,-ofoo.c foo.pl
1582 perl cc_harness -o foo foo.c
1583
1584Note that C<cc_harness> lives in the C<B> subdirectory of your perl
1585library directory. The utility called C<perlcc> may also be used to
1586help make use of this compiler.
1587
1588 perl -MO=C,-v,-DcA bar.pl > /dev/null
1589
1590=head1 BUGS
1591
1592Plenty. Current status: experimental.
7f20e9dd 1593
1594=head1 AUTHOR
1595
1596Malcolm Beattie, C<mbeattie@sable.ox.ac.uk>
1597
1598=cut