1package Opcodes;
2
3use 5.006_001;
4use strict;
5
6our($VERSION, @ISA, @EXPORT, @EXPORT_OK);
7
8$VERSION = "0.14";
9
10use Exporter ();
11use XSLoader ();
12
13BEGIN {
14    @ISA = qw(Exporter);
15    @EXPORT =
16      qw(opcodes opname opname2code opflags opaliases
17	 opargs opclass opdesc opname
18	 OA_CLASS_MASK
19	 OA_MARK
20	 OA_FOLDCONST
21	 OA_RETSCALAR
22	 OA_TARGET
23	 OA_RETINTEGER
24	 OA_OTHERINT
25	 OA_DANGEROUS
26	 OA_DEFGV
27	 OA_TARGLEX
28
29	 OA_BASEOP
30	 OA_UNOP
31	 OA_BINOP
32	 OA_LOGOP
33	 OA_LISTOP
34	 OA_PMOP
35	 OA_SVOP
36	 OA_PADOP
37	 OA_PVOP_OR_SVOP
38	 OA_LOOP
39	 OA_COP
40	 OA_BASEOP_OR_UNOP
41	 OA_FILESTATOP
42	 OA_LOOPEXOP
43
44	 OA_SCALAR
45	 OA_LIST
46	 OA_AVREF
47	 OA_HVREF
48	 OA_CVREF
49	 OA_FILEREF
50	 OA_SCALARREF
51	 OA_OPTIONAL
52
53	 OA_NOSTACK
54	 OA_MAYSCALAR
55	 OA_MAYARRAY
56	 OA_MAYVOID
57	 OA_RETFIXED
58	 OA_MAYBRANCH
59	);
60    @EXPORT_OK = qw(ppaddr check argnum maybranch);
61}
62use subs @EXPORT_OK;
63
64sub AUTOLOAD {
65    # 'autoload' constants from the constant() XS function.
66    my $constname;
67    our $AUTOLOAD;
68    ($constname = $AUTOLOAD) =~ s/.*:://;
69    die "&Opcodes::constant not defined" if $constname eq 'constant';
70    my ($error, $val) = constant($constname);
71    if ($error) { die $error; }
72    {
73        no strict 'refs';
74	*$AUTOLOAD = sub { $val };
75    }
76    goto &$AUTOLOAD;
77}
78
79XSLoader::load 'Opcodes', $VERSION;
80
81our @opcodes = opcodes();
82
83sub opname ($) {
84    $opcodes[ $_[0] ]->[1];
85}
86
87sub ppaddr ($) {
88    $opcodes[ $_[0] ]->[2];
89}
90
91sub check ($) {
92    $opcodes[ $_[0] ]->[3];
93}
94
95sub opdesc ($) {
96    Opcode::opdesc( opname( $_[0] ));
97}
98
99sub opargs ($) {
100    $opcodes[ $_[0] ]->[4];
101}
102
103# n no_stack - A handcoded list of ops without any SP handling (Note: stack_base is allowed),
104# i.e. no args + no return values.
105# 'n' 512 is not encoded in opcode.pl. We could add it but then we would have to
106# maintain it in CORE as well as here. Here its is needed for older perls. So
107# keep it this way. Note that enter,entertry,leave indirectly use the stack.
108our %no_stack = map{$_=>1}qw[null unstack scope lineseq
109  next redo goto break continue nextstate dbstate pushmark
110  regcmaybe regcreset];
111# S retval may be scalar. s and i are automatically included
112our %retval_scalar = map{$_=>1}qw[];
113# A retval may be array
114our %retval_array = map{$_=>1}qw[];
115# V retval may be void
116our %retval_void = map{$_=>1}qw[];
117# F fixed retval type (S, A or V)
118our %retval_fixed = map{$_=>1}qw[];
119# N  pp_* may return other than op_next
120our %maybranch = map{$_=>1}
121  # LOGOP's which return op_other
122  qw[once cond_expr and or orassign andassign dor dorassign grepwhile mapwhile substcont
123     enterwhen entergiven range
124    ],
125  # other OPs
126  qw[formline grepstart flip dbstate goto leaveeval
127     break
128     subst entersub
129     return last next redo require entereval entertry continue dump
130    ];
131
132sub opflags ($) {
133    # 0x1ff = 9 bits OCSHIFT
134    my $OCSHIFT = constant('OCSHIFT'); 	# 9
135    my $mask = (2 ** $OCSHIFT) - 1;
136    my $flags =  opargs($_[0]) & $mask; # & 0x1ff
137    # now the extras
138    my $opname = opname($_[0]);
139    #$flags += 16  if $retint{$opname};
140    $flags += 512  if $no_stack{$opname};
141    $flags += 1024 if $retval_scalar{$opname} or $flags & 20; # 4|16
142    $flags += 2048 if $retval_array{$opname};
143    $flags += 4096 if $retval_void{$opname};
144    $flags += 8192 if $retval_fixed{$opname};
145    $flags += 16384 if maybranch($_[0]);
146    return $flags;
147}
148
149# See F<opcode.pl> for $OASHIFT and $OCSHIFT. For flags n 512 we
150# would have to change that.
151sub opclass ($) {
152    my $OCSHIFT = constant('OCSHIFT'); 	# 9
153    my $OASHIFT = constant('OASHIFT');	# 13
154    my $mask = (2 ** ($OASHIFT-$OCSHIFT)) - 1; # 0b1111 4bit 13-9=4 bits
155    $mask = $mask << $OCSHIFT;		# 1e00: 4bit left-shifted by 9
156    (opargs($_[0]) & $mask) >> $OCSHIFT;
157}
158
159sub argnum ($) {
160    #my $ARGSHIFT = 4;
161    #my $ARGBITS = 32;
162    my $OASHIFT = constant('OASHIFT'); # 13
163    # ffffe000 = 32-13 bits left-shifted by 13
164    my $mask = ((2 ** (32-$OASHIFT)) - 1) << $OASHIFT;
165    (opargs($_[0]) & $mask) >> $OASHIFT;
166}
167
168sub opaliases ($) {
169    my $op = shift;
170    my @aliases = ();
171    my $ppaddr = ppaddr($op);
172    for (@opcodes) {
173      push @aliases, ($_->[0])
174        if $_->[2] == $ppaddr and $_->[0] != $op;
175    }
176    @aliases;
177}
178
179sub opname2code ($) {
180    my $name = shift;
181    for (0..$#opcodes) { return $_ if opname($_) eq $name; }
182    return undef;
183}
184
185# All LOGOPs: perl -Mblib -MOpcodes -e'$,=q( );print map {opname $_} grep {opclass($_) == 3} 1..opcodes' =>
186#   regcomp substcont grepwhile mapwhile range and or dor cond_expr andassign orassign dorassign entergiven
187#   enterwhen entertry once
188# All pp which can return other then op_next (inspected pp*.c):
189#   once and cond_expr or defined grepwhile
190#   substcont formline grepstart mapwhile range flip dbstate goto leaveeval enterwhen break subst entersub
191#   return last next redo require entereval entertry continue
192# + aliases: maybranch  perl -MOpcodes -e'$,=q( );print map {opname $_} grep {opflags($_) & 16384} 1..opcodes'
193# => subst substcont defined formline grepstart grepwhile mapwhile range and or dor cond_expr andassign
194#    orassign dorassign dbstate return last next redo dump goto entergiven enterwhen require entereval
195#    entertry once
196sub maybranch ($) {
197    return undef if opclass($_[0]) <= 2;	# NOT if lower than LOGOP
198    my $opname = opname($_[0]);
199    return 1 if $maybranch{$opname};
200    for (opaliases($_[0])) {
201        return 1 if $maybranch{opname($_)};
202    }
203    return undef;
204}
205
206
2071;
208__END__
209
210=head1 NAME
211
212Opcodes - More Opcodes information from opnames.h and opcode.h
213
214=head1 SYNOPSIS
215
216  use Opcodes;
217  print "Empty opcodes are null and ",
218    join ",", map {opname $_}, opaliases(opname2code('null'));
219
220  # All LOGOPs
221  perl -MOpcodes -e'$,=q( );print map {opname $_} grep {opclass($_) == 2} 1..opcodes'
222
223  # Ops which can return other than op->next
224  perl -MOpcodes -e'$,=q( );print map {opname $_} grep {Opcodes::maybranch $_} 1..opcodes'
225
226
227=head1 DESCRIPTION
228
229=head1 Operator Names and Operator Lists
230
231The canonical list of operator names is the contents of the array
232PL_op_name, defined and initialised in file F<opcode.h> of the Perl
233source distribution (and installed into the perl library).
234
235Each operator has both a terse name (its opname) and a more verbose or
236recognisable descriptive name. The opdesc function can be used to
237return a the description for an OP.
238
239=over 8
240
241=item an operator name (opname)
242
243Operator names are typically small lowercase words like enterloop,
244leaveloop, last, next, redo etc. Sometimes they are rather cryptic
245like gv2cv, i_ncmp and ftsvtx.
246
247=item an OP opcode
248
249The opcode information functions all take the integer code, 0..MAX0,
250MAXO being accessed by scalar @opcodes, the length of
251the opcodes array.
252
253=back
254
255
256=head1 Opcode Information
257
258Retrieve information of the Opcodes. All are available for export by the package.
259Functions names starting with "op" are automatically exported.
260
261=over 8
262
263=item opcodes
264
265In a scalar context opcodes returns the number of opcodes in this
266version of perl (361 with perl-5.10).
267
268In a list context it returns a list of all the operators with
269its properties, a list of [ opcode opname ppaddr check opargs ].
270
271=item opname (OP)
272
273Returns the lowercase name without pp_ for the OP,
274an integer between 0 and MAXO.
275
276=item ppaddr (OP)
277
278Returns the address of the ppaddr, which can be used to
279get the aliases for each opcode.
280
281=item check (OP)
282
283Returns the address of the check function.
284
285=item opdesc (OP)
286
287Returns the string description of the OP.
288
289=item opargs (OP)
290
291Returns the opcode args encoded as integer of the opcode.
292See below or F<opcode.pl> for the encoding details.
293
294  opflags 1-128 + opclass 1-13 << 9 + argnum 1-15.. << 13
295
296=item argnum (OP)
297
298Returns the arguments and types encoded as number acccording
299to the following table, 4 bit for each argument.
300
301    'S',  1,		# scalar
302    'L',  2,		# list
303    'A',  3,		# array value
304    'H',  4,		# hash value
305    'C',  5,		# code value
306    'F',  6,		# file value
307    'R',  7,		# scalar reference
308
309  + '?',  8,            # optional
310
311Example:
312
313  argnum(opname2code('bless')) => 145
314  145 = 0b10010001 => S S?
315
316  first 4 bits 0001 => 1st arg is a Scalar,
317  next 4 bits  1001 => (bit 8+1) 2nd arg is an optional Scalar
318
319=item opclass (OP)
320
321Returns the op class as number according to the following table
322from F<opcode.pl>:
323
324    '0',  0,		# baseop
325    '1',  1,		# unop
326    '2',  2,		# binop
327    '|',  3,		# logop
328    '@',  4,		# listop
329    '/',  5,		# pmop
330    '$',  6,		# svop_or_padop
331    '#',  7,		# padop
332    '"',  8,		# pvop_or_svop
333    '{',  9,		# loop
334    ';',  10,		# cop
335    '%',  11,		# baseop_or_unop
336    '-',  12,		# filestatop
337    '}',  13,		# loopexop
338
339=item opflags (OP)
340
341Returns op flags as number according to the following table
342from F<opcode.pl>. In doubt see your perl source.
343I<Warning: There is currently an attempt to change that, but I posted a fix>
344
345    'm' =>  OA_MARK,	 	# needs stack mark
346    'f' =>  OA_FOLDCONST,	# fold constants
347    's' =>  OA_RETSCALAR,	# always produces scalar
348    't' =>  OA_TARGET,		# needs target scalar
349    'T' =>  OA_TARGET | OA_TARGLEX,	# ... which may be lexical
350    'i' =>  OA_RETINTEGER,	# always produces integer (this bit is in question)
351    'I' =>  OA_OTHERINT,	# has corresponding int op
352    'd' =>  OA_DANGEROUS,	# danger, unknown side effects
353    'u' =>  OA_DEFGV,		# defaults to $_
354
355plus not from F<opcode.pl>:
356
357    'n' => OA_NOSTACK,		# nothing on the stack, no args and return
358    'N' => OA_MAYBRANCH		# No next. may return other than PL_op->op_next, maybranch
359
360These not yet:
361
362    'S' =>  OA_MAYSCALAR 	# retval may be scalar
363    'A' =>  OA_MAYARRAY 	# retval may be array
364    'V' =>  OA_MAYVOID 		# retval may be void
365    'F' =>  OA_RETFIXED 	# fixed retval type, either S or A or V
366
367=item OA_* constants
368
369All OA_ flag, class and argnum constants from F<op.h> are exported.
370Addionally new OA_ flags have been created which are needed for L<B::CC>.
371
372=item opaliases (OP)
373
374Returns the opcodes for the aliased opcode functions for the given OP, the ops
375with the same ppaddr.
376
377=item opname2code (OPNAME)
378
379Does a reverse lookup in the opcodes list to get the opcode for the given
380name.
381
382=item maybranch (OP)
383
384Returns if the OP function may return not op->op_next.
385
386Note that not all OP classes which have op->op_other, op->op_first or op->op_last
387(higher then UNOP) are actually returning an other next op than op->op_next.
388
389  opflags(OP) & 16384
390
391=back
392
393=head1 SEE ALSO
394
395L<Opcode> -- The Perl CORE Opcode module for handling sets of Opcodes used by L<Safe>.
396
397L<Safe> -- Opcode and namespace limited execution compartments
398
399L<B::CC> -- The optimizing perl compiler uses this module. L<Jit> also,
400            but only the static information
401
402=head1 TEST REPORTS
403
404CPAN Testers: L<http://cpantesters.org/distro/O/Opcodes>
405
406Travis: L<https://travis-ci.org/rurban/Opcodes.png|https://travis-ci.org/rurban/Opcodes/>
407
408Coveralls: L<https://coveralls.io/repos/rurban/Opcodes/badge.png|https://coveralls.io/r/rurban/Opcodes?branch=master>
409
410=head1 AUTHOR
411
412Reini Urban C<rurban@cpan.org> 2010, 2014
413
414=head1 LICENSE
415
416Copyright 1995, Malcom Beattie.
417Copyright 1996, Tim Bunce.
418Copyright 2010, 2014 Reini Urban.
419All rights reserved.
420
421This program is free software; you can redistribute it and/or
422modify it under the same terms as Perl itself.
423
424=cut
425
426# Local Variables:
427#   mode: cperl
428#   cperl-indent-level: 4
429#   fill-column: 78
430# End:
431# vim: expandtab shiftwidth=4:
432