# Copyright (C) 2001-2004, The Perl Foundation. # $Id: CSwitch.pm 19454 2007-06-29 07:22:39Z paultcochrane $ =head1 NAME Parrot::OpTrans::CSwitch - C Switch Transform =head1 DESCRIPTION C inherits from C to provide a mixture of predereferenced register addressing and a Ced run loop. =head2 Instance Methods =over 4 =cut package Parrot::OpTrans::CSwitch; use strict; use warnings; use Parrot::OpTrans; use base qw( Parrot::OpTrans::CPrederef ); sub new { my $class = shift; my $self = $class->SUPER::new(@_); $self->{split_count} ||= 0; return $self; } =item C The core type is C. =cut sub core_type { return 'PARROT_SWITCH_CORE'; } =item C The prefix is C<'switch_'>. =cut sub core_prefix { return "switch_"; } =item C The suffix is C<'_switch'>. =cut sub suffix { return "_switch"; } =item C Returns the C C<#define> macros required by the ops. =cut sub defines { my ( $self, $pred_def ); $self = shift; $pred_def = $self->SUPER::defines(); my $type = __PACKAGE__; return $pred_def . < $type */ # define opcode_to_prederef(i, op) (op ? \\ (opcode_t*) (op - CONTEXT(i->ctx)->pred_offset) : (opcode_t*)NULL) /* * if we are using CHECK_EVENTS elsewhere this macro should (again) * be in includes/parrot/event.h * * This gives +50 % performance */ #undef CHECK_EVENTS #define CHECK_EVENTS(i, n) \\ interp->task_queue->head ? \\ (opcode_t*)Parrot_do_check_events(i, n) : n END } =item C Transforms the C macro in an ops file into the relevant C code. =cut sub goto_address { my ( $self, $addr ) = @_; #print STDERR "pbcc: map_ret_abs($addr)\n"; if ( $addr eq '0' ) { return "return (0);"; } else { return < Transforms the C macro in an ops file into the relevant C code. =cut sub goto_offset { my ( $self, $offset ) = @_; return "{ cur_opcode += $offset; goto SWITCH_AGAIN; }"; } =item C Transforms the C macro in an ops file into the relevant C code. =cut sub goto_pop { my ($self) = @_; return "{ opcode_t *dest = (opcode_t*)pop_dest(interp); cur_opcode = opcode_to_prederef(interp, dest); goto SWITCH_AGAIN; }"; } =item C Returns the C code prior to the run core function. =cut sub run_core_func_start { my $type = __PACKAGE__; return < $type */ #if defined(__GNUC__) && defined(I386) && defined(PARROT_SWITCH_REGS) register opcode_t * cur_opcode __asm__ ("esi") = cur_op; register char * _reg_base __asm__ ("edi"); #else opcode_t * cur_opcode = cur_op; char * _reg_base; #endif SWITCH_RELOAD: _reg_base = (char*)interp->ctx.bp.regs_i; do { SWITCH_AGAIN: cur_opcode = CHECK_EVENTS(interp, cur_opcode); if (!cur_opcode) break; switch (*(opcode_t*)cur_opcode) { END_C } =item C If defined return code to split e.g. a switch. =cut sub run_core_split { my ($self) = @_; $self->{split_count}++; return < Returns the C code following the run core function. =cut sub run_core_finish { my ( $self, $base ) = @_; my $bs = $base . $self->suffix . '_'; my $c = <= 0 && *(opcode_t*)cur_opcode < (opcode_t)${bs}op_lib.op_count) { *(opcode_t*)cur_opcode = CORE_OPS_wrapper__; continue; } real_exception(interp, NULL, 1, "illegal opcode in switch core\\n"); break; } /* switch */ END_C for ( my $i = 0 ; $i < $self->{split_count} ; $i++ ) { $c .= <core_prefix . "$base */\n\n"; return $c; } =back =head1 SEE ALSO =over 4 =item C =item C =item C =item C =item C =item C =back =cut 1; # Local Variables: # mode: cperl # cperl-indent-level: 4 # fill-column: 100 # End: # vim: expandtab shiftwidth=4: