7.2. B:: Modules

There are twelve backend modules to the compiler in the Perl core, and many more besides on CPAN. Here we'll briefly examine those which are particularly helpful to internals hackers or particularly interesting.

7.2.1. B::Concise

B::Concise was written quite recently by Stephen McCamant to provide a generic way of getting concise information about the op tree. It is highly customizable, and can be used to emulate B::Terse and B::Debug. (see below)

Here's the basic output from B::Concise:

	    % perl -MO=Concise -e 'print $a+$b'
1r <@> leave[t1] vKP/REFC ->(end)
1k    <0> enter ->1l
1l    <;> nextstate(main 7 -e:1) v ->1m
1q    <@> print vK ->1r
1m       <0> pushmark s ->1n
1p       <2> add[t1] sK/2 ->1q
-           <1> ex-rv2sv sK/1 ->1o
1n             <$> gvsv(*a) s ->1o
-           <1> ex-rv2sv sK/1 ->1p
1o             <$> gvsv(*b) s ->1p

Each line consists of five main parts:

Note also that, for instance, ops which have been optimized away to a null are left as "ex-...". The exact meanings of the flags and the op classes are given in the B::Concise documentation:

=head2 OP flags abbreviations

    v      OPf_WANT_VOID    Want nothing (void context)
    s      OPf_WANT_SCALAR  Want single value (scalar context)
    l      OPf_WANT_LIST    Want list of any length (list context)
    K      OPf_KIDS         There is a firstborn child.
    P      OPf_PARENS       This operator was parenthesized.
                             (Or block needs explicit scope entry.)
    R      OPf_REF          Certified reference.
                             (Return container, not containee).
    M      OPf_MOD          Will modify (lvalue).
    S      OPf_STACKED      Some arg is arriving on the stack.
    *      OPf_SPECIAL      Do something weird for this op (see op.h)

=head2 OP class abbreviations

    0      OP (aka BASEOP)  An OP with no children
    1      UNOP             An OP with one child
    2      BINOP            An OP with two children
    |      LOGOP            A control branch OP
    @      LISTOP           An OP that could have lots of children
    /      PMOP             An OP with a regular expression
    $      SVOP             An OP with an SV
    "      PVOP             An OP with a string
    {      LOOP             An OP that holds pointers for a loop
    ;      COP              An OP that marks the start of a statement

As with many of the debugging B:: modules, you can use the -exec flag to walk the op tree in execution order, following the chain of op_next's from the start of the tree:

	    % perl -MO=Concise,-exec -e 'print $a+$b'
1k <0> enter 
1l <;> nextstate(main 7 -e:1) v
1m <0> pushmark s
1n <$> gvsv(*a) s
1o <$> gvsv(*b) s
1p <2> add[t1] sK/2
1q <@> print vK
1r <@> leave[t1] vKP/REFC
-e syntax OK
	

Amongst other options, (again, see the documentation) B::Concise supports a -tree option for tree-like ASCII art graphs, and the curious but fun -linenoise option.

7.2.2. B::Debug

B::Debug dumps out all of the information in the op tree; for anything bigger than a trivial program, this is just way too much information. Hence, to sensibly make use of it, it's a good idea to go through with B::Terse or B::Concise first, and find which ops you're interested in, and then grep for them.

Some output from B::Debug looks like this:

LISTOP (0x81121a8)
        op_next         0x0
        op_sibling      0x0
        op_ppaddr       PL_ppaddr[OP_LEAVE]
        op_targ         1
        op_type         178
        op_seq          6433
        op_flags        13
        op_private      64
        op_first        0x81121d0
        op_last         0x8190498
        op_children     3
OP (0x81121d0)
        op_next         0x81904c0
        op_sibling      0x81904c0
        op_ppaddr       PL_ppaddr[OP_ENTER]
        op_targ         0
        op_type         177
        op_seq          6426
        op_flags        0
        op_private      0
As you should know from the ops chapter, this is all the information contained in the op structure: the type of op and its address, the ops related to it, the C function pointer implementing the PP function, the target on the scratchpad this op uses, its type, sequence number, and public and private flags. It also does similar dumps for SVs. You may find the B::Flags module useful for "Englishifying" the flags.

7.2.3. B::Deparse

B::Deparse takes a Perl program and turns it into a Perl program. This doesn't sound very impressive, but it actually does so by decompiling the op tree back into Perl. While this has interesting uses for things like serializing subroutines, it's interesting for internals hackers because it shows us how Perl understands certain constructs. For instance, we can see that logical operators and binary "if" are equivalent:

%  perl -MO=Deparse -e '$a and do {$b}'
if ($a) {
    do {
        $b;
    };
}
-e syntax OK
We can also see, for instance, how the magic that is added by command line switches goes into the op tree:
% perl -MO=Deparse -ane 'print'
LINE: while (defined($_ = <ARGV>)) {
    @F = split(" ", $_, 0);
    print $_;
}
-e syntax OK