NAME
B::CC - Perl compiler's optimized C translation backend
SYNOPSIS
perl -MO=CC[,OPTIONS] foo.pl
DESCRIPTION
This compiler backend takes Perl source and generates C source code corresponding to the flow of your program with unrolled ops and optimised stack handling and lexicals variable types. In other words, this backend is somewhat a "real" compiler in the sense that many people think about compilers. Note however that, currently, it is a very poor compiler in that although it generates (mostly, or at least sometimes) correct code, it performs relatively few optimisations. This will change as the compiler and the types develops. The result is that running an executable compiled with this backend may start up more quickly than running the original Perl program (a feature shared by the C compiler backend--see B::C) and may also execute slightly faster. This is by no means a good optimising compiler--yet.
OPTIONS
If there are any non-option arguments, they are taken to be names of objects to be saved (probably doesn't work properly yet). Without extra arguments, it saves the main program.
- -ofilename
-
Output to filename instead of STDOUT
- -v
-
Verbose compilation (prints a few compilation stages).
- --
-
Force end of options
- -uPackname
-
Force apparently unused subs from package Packname to be compiled. This allows programs to use eval "foo()" even when sub foo is never seen to be used at compile time. The down side is that any subs which really are never used also have code generated. This option is necessary, for example, if you have a signal handler foo which you initialise with
$SIG{BAR} = "foo"
. A better fix, though, is just to change it to$SIG{BAR} = \&foo
. You can have multiple -u options. The compiler tries to figure out which packages may possibly have subs in which need compiling but the current version doesn't do it very well. In particular, it is confused by nested packages (i.e. of the formA::B
) where packageA
does not contain any subs. - -mModulename
-
Instead of generating source for a runnable executable, generate source for an XSUB module. The boot_Modulename function (which DynaLoader can look for) does the appropriate initialisation and runs the main part of the Perl source that is being compiled.
- -nInitname
-
Provide a different init name for additional objects added via cmdline.
- -strict
-
With a DEBUGGING perl compile-time errors for range and flip without compile-time context are only warnings. With
-strict
these warnings are fatal, otherwise only run-time errors occur. - -On
-
Optimisation level (n = 0, 1, 2). -O means -O1.
The following B::C optimisations are applied automatically:
optimize_warn_sv save_data_fh av-init2|av_init save_sig destruct pv_copy_on_grow
-O1 sets -ffreetmps-each-bblock.
-O2 adds -ffreetmps-each-loop and -fno-destruct from B::C.
-fomit-taint and -fslow-signals must be set explicitly.
- -f
OPTIM
-
Force optimisations on or off one at a time. Unknown optimizations are passed down to B::C.
- -ffreetmps-each-bblock
-
Delays FREETMPS from the end of each statement to the end of the each basic block.
Enabled with -O1.
- -ffreetmps-each-loop
-
Delays FREETMPS from the end of each statement to the end of the group of basic blocks forming a loop. At most one of the freetmps-each-* options can be used.
Enabled with -O2.
- -fno-inline-ops
-
Do not inline calls to certain small pp ops.
Most of the inlinable ops were already inlined. Turns off inlining for some new ops.
AUTOMATICALLY inlined:
pp_null pp_stub pp_unstack pp_and pp_andassign pp_or pp_orassign pp_cond_expr pp_padsv pp_const pp_nextstate pp_dbstate pp_rv2gv pp_sort pp_gv pp_gvsv pp_aelemfast pp_ncmp pp_add pp_subtract pp_multiply pp_divide pp_modulo pp_left_shift pp_right_shift pp_i_add pp_i_subtract pp_i_multiply pp_i_divide pp_i_modulo pp_eq pp_ne pp_lt pp_gt pp_le pp_ge pp_i_eq pp_i_ne pp_i_lt pp_i_gt pp_i_le pp_i_ge pp_scmp pp_slt pp_sgt pp_sle pp_sge pp_seq pp_sne pp_sassign pp_preinc pp_pushmark pp_list pp_entersub pp_formline pp_goto pp_enterwrite pp_leavesub pp_leavewrite pp_entergiven pp_leavegiven pp_entereval pp_dofile pp_require pp_entertry pp_leavetry pp_grepstart pp_mapstart pp_grepwhile pp_mapwhile pp_return pp_range pp_flip pp_flop pp_enterloop pp_enteriter pp_leaveloop pp_next pp_redo pp_last pp_subst pp_substcont
DONE with -finline-ops:
pp_enter pp_reset pp_regcreset pp_stringify
TODO with -finline-ops:
pp_anoncode pp_wantarray pp_srefgen pp_refgen pp_ref pp_trans pp_schop pp_chop pp_schomp pp_chomp pp_not pp_sprintf pp_anonlist pp_shift pp_once pp_lock pp_rcatline pp_close pp_time pp_alarm pp_av2arylen: no lvalue, pp_length: no magic
- -fomit-taint
-
Omits generating code for handling perl's tainting mechanism.
- -fslow-signals
-
Add PERL_ASYNC_CHECK after every op as in the old Perl runloop before 5.13.
perl "Safe signals" check the state of incoming signals after every op. See http://perldoc.perl.org/perlipc.html#Deferred-Signals-(Safe-Signals) We trade safety for more speed and delay the execution of non-IO signals (IO signals are already handled in PerlIO) from after every single Perl op to the same ops as used in 5.14.
Only with -fslow-signals we get the old slow and safe behaviour.
- -fno-name-magic
-
With the default
-fname-magic
we infer the SCALAR type for specially named locals vars and most ops use C vars then, not the perl vars. Arithmetic and comparison is inlined. Scalar magic is bypassed.With
-fno-name-magic
do not infer a local variable type from its name:B<_i> suffix for int, B<_d> for double, B<_ir> for register int
See the experimental
-ftype-attr
type attributes. Currently supported are int and double only. See </load_pad>. - -ftype-attr (DOES NOT WORK YET)
-
Experimentally support type attributes for int and double, SCALAR only so far. For most ops new C vars are used then, not the fat perl vars. Very awkward to use until the basic type classes are supported from within core or use types.
Enabled with -O2. See TYPES and </load_pad>.
- -D
-
Debug options (concatenated or separate flags like
perl -D
). Verbose debugging options are crucial, because the interactive debugger Od adds a lot of ballast to the resulting code. - -Dr
-
Writes debugging output to STDERR just as it's about to write to the program's runtime (otherwise writes debugging info as comments in its C output).
- -DO
-
Outputs each OP as it's compiled
- -Ds
-
Outputs the contents of the shadow stack at each OP
- -Dp
-
Outputs the contents of the shadow pad of lexicals as it's loaded for each sub or the main program.
- -Dq
-
Outputs the name of each fake PP function in the queue as it's about to process it.
- -Dl
-
Output the filename and line number of each original line of Perl code as it's processed (
pp_nextstate
). - -Dt
-
Outputs timing information of compilation stages.
- -DF
-
Add Flags info to the code.
NOTABLE FUNCTIONS
cc_queue
Creates a new ccpp optree.
Initialised by saveoptree_callback in B::C, replaces B::C::walk_and_save_optree. Called by every CV::save
if ROOT. blocksort also creates its block closure with cc_queue.
save_or_restore_lexical_state
The compiler tracks state of lexical variables in @pad to generate optimised code. But multiple execution paths lead to the entry point of a basic block. The state of the first execution path is saved and all other execution paths are restored to the state of the first one.
Missing flags are regenerated by loading values.
Added flags must are removed; otherwise the compiler would be too optimistic, hence generating code which doesn't match state of the other execution paths.
load_pad
Load pad takes (the elements of) a PADLIST as arguments and loads up @pad with Stackobj-derived objects which represent those lexicals.
If/when perl itself can generate type information (my int $foo; my $foo : int)
then we'll take advantage of that here. Until then, we'll use the "-fno-name-magic" in -fname-magic hack to tell the compiler when we want a lexical to be a particular type or to be a register.
label
We not only mark named labels in C as such - with prefix "label_".
We also have to mark each known (back jumps) and yet unknown branch targets (forward jumps) for compile-time generated branch points, with the "lab_" prefix.
EXAMPLES
perl -MO=CC,-O2,-ofoo.c foo.pl
perl cc_harness -o foo foo.c
Note that cc_harness
lives in the B
subdirectory of your perl library directory. The utility called perlcc
may also be used to help make use of this compiler.
# create a shared XS module
perl -MO=CC,-mFoo,-oFoo.c Foo.pm
perl cc_harness -shared -c -o Foo.so Foo.c
# side-effects just for the types and attributes
perl -MB::CC -e'my int $i:unsigned; ...'
TYPES
Implemented type classes are int and double. Planned is string also. Implemented are only SCALAR types yet.
Implemented are infered types via the names of locals, with '_i', '_d' suffix and an optional 'r' suffix for register allocation.
C<my ($i_i, $j_ir, $num_d);>
Planned type attributes are int, double, string, unsigned, register, temporary, ro and readonly.
The attributes are perl attributes, and int|double|string are either compiler classes or hints for more allowed types.
C<my int $i :double;> declares a NV with SVf_IOK. Same as C<my $i:int:double;>
C<my int $i;> declares an IV. Same as C<my $i:int;>
C<my int $i :string;> declares a PVIV. Same as C<my $i:int:string;>
C<my int @array :unsigned = (0..4);> will be used as c var in faster arithmetic and cmp.
With :readonly or :ro even more.
C<my string %hash : readonly = (foo => any, bar => any);> declare string keys only
and may be generated as read-only perfect hash.
unsigned is valid for int only and declares an UV.
register denotes optionally a short and hot life-time.
temporary are usually generated internally, nameless lexicals. They are more aggressivly destroyed and ignored.
ro and readonly throw a compile-time error on write access and may optimize the internal structure of the variable. We don't need to write back the variable to perl (lexical write_back).
STATUS
OK (classes only):
my int $i;
my double $d;
NOT YET OK (attributes):
my int $i :register;
my $i :int;
my $const :int:ro;
my $uv :int:unsigned;
ISSUES
This does not work with pure perl, unless you use B::CC
or implement the classes and attribute type stubs in your code, sub Mypkg::MODIFY_SCALAR_ATTRIBUTES {}
and sub Mypkg::FETCH_SCALAR_ATTRIBUTES {}
. (TODO: empty should be enough to be detected by the compiler.)
Compiled code pulls in the magic MODIFY_SCALAR_ATTRIBUTES and FETCH_SCALAR_ATTRIBUTES functions, even if they are used at compile time only.
Using attributes adds an import block to your code.
Only our variable attributes are checked at compile-time, my variables attributes at run-time only, which is too late for the compiler.
Perl attributes suck. Nobody thought of the compiler then.
FUTURE
We should be able to support types on ARRAY and HASH.
my int @array; # array of ints, faster magic-less access esp. in inlined arithmetic and cmp.
my string @array : readonly = qw(foo bar); # compile-time error on write. no lexical write_back
my int $hash = {1 => any, 2 => bla}; # int keys (also on hashrefs), typechecked on write
my string %hash1 : readonly = (foo => any); # string keys only => gperf, compile-time error on write
Hash value types defaults to full SVs as values, only the keys are typed.
We should be also able to add type attributes for functions and methods, i.e. for argument and return types. No idea for specs yet.
BUGS
Plenty. Current status: experimental.
DIFFERENCES
These aren't really bugs but they are constructs which are heavily tied to perl's compile-and-go implementation and with which this compiler backend cannot cope.
Loops
Standard perl calculates the target of "next", "last", and "redo" at run-time. The compiler calculates the targets at compile-time. For example, the program
sub skip_on_odd { next NUMBER if $_[0] % 2 }
NUMBER: for ($i = 0; $i < 5; $i++) {
skip_on_odd($i);
print $i;
}
produces the output
024
with standard perl but gives a compile-time error with the compiler.
Context of ".."
The context (scalar or array) of the ".." operator determines whether it behaves as a range or a flip/flop. Standard perl delays until runtime the decision of which context it is in but the compiler needs to know the context at compile-time. For example,
@a = (4,6,1,0,0,1);
sub range { (shift @a)..(shift @a) }
print range();
while (@a) { print scalar(range()) }
generates the output
456123E0
with standard Perl but gives a run-time warning with compiled Perl.
If the option -strict is used it gives a compile-time error.
Arithmetic
Compiled Perl programs use native C arithmetic much more frequently than standard perl. Operations on large numbers or on boundary cases may produce different behaviour.
Deprecated features
Features of standard perl such as $[
which have been deprecated in standard perl since Perl5 was released have not been implemented in the compiler.
AUTHORS
Malcolm Beattie MICB at cpan.org
(1996-1998, retired), Vishal Bhatia <vishal at deja.com> I(1999), Gurusamy Sarathy <gsar@cpan.org> I(1998-2001), Reini Urban perl-compiler@googlegroups.com
I(2008-), Heinz Knutzen heinz.knutzen at gmx.de
I(2010)