The included patch requires a new file t/op/exceptions.t, which tests basic exception 
handling, in this case divide-by-zero.
Patch was generated against latest CVS, but it shouldn't matter -that- much.

-Jeff
<[EMAIL PROTECTED]>


diff --recursive -C 2 parrot_cvs/MANIFEST parrot/MANIFEST
*** parrot_cvs/MANIFEST Wed Oct 24 07:36:57 2001
--- parrot/MANIFEST     Wed Oct 24 07:37:22 2001
***************
*** 108,111 ****
--- 108,112 ----
  t/op/basic.t
  t/op/bitwise.t
+ t/op/exception.t
  t/op/integer.t
  t/op/number.t
Only in parrot/: Makefile
diff --recursive -C 2 parrot_cvs/Parrot/Assembler.pm parrot/Parrot/Assembler.pm
*** parrot_cvs/Parrot/Assembler.pm      Wed Oct 24 07:36:57 2001
--- parrot/Parrot/Assembler.pm  Wed Oct 24 07:54:22 2001
***************
*** 110,114 ****
  =cut
  
! my(%type_to_suffix)=('I'=>'i',  'N'=>'n',
                       'S'=>'s',  'P'=>'p',
                       'i'=>'ic', 'n'=>'nc',
--- 110,115 ----
  =cut
  
! my(%type_to_suffix)=('E'=>'e',
!                    'I'=>'i',  'N'=>'n',
                       'S'=>'s',  'P'=>'p',
                       'i'=>'ic', 'n'=>'nc',
***************
*** 923,927 ****
      #
  
!     if      (m/^([INPS])\d+$/) {                       # a register.
        push @arg_t,lc($1);
      } elsif (m/^\[([a-z]+):(\d+)\s*\]$/) {             # string constant
--- 924,928 ----
      #
  
!     if      (m/^([EINPS])\d+$/) {                      # a register.
        push @arg_t,lc($1);
      } elsif (m/^\[([a-z]+):(\d+)\s*\]$/) {             # string constant
***************
*** 945,949 ****
    #
  
!   my @grep_ops = grep($_ =~ /^$opcode(?:_(?:(?:[ins]c?)|p))+$/, keys(%opcodes));
  
    foreach my $op (@grep_ops) {
--- 946,950 ----
    #
  
!   my @grep_ops = grep($_ =~ /^$opcode(?:_(?:(?:[eins]c?)|p))+$/, keys(%opcodes));
  
    foreach my $op (@grep_ops) {
***************
*** 1056,1059 ****
--- 1057,1061 ----
  
  my %rtype_map = (
+   "e" => "E",
    "i" => "I",
    "n" => "N",
***************
*** 1092,1100 ****
      #
  
!     if($rtype eq "I" || $rtype eq "N" || $rtype eq "P" || $rtype eq "S") {
        # its a register argument
  
!       $args[$_] =~ s/^[INPS](\d+)$/$1/i
!         or error("Expected m/[INPS]\\d+/, but got '$args[$_]'!", $file, $line);
  
        error("Register $1 out of range (should be 0-31) in '$opcode'",$file,$line) if 
$1 < 0 or $1 > 31;
--- 1094,1102 ----
      #
  
!     if($rtype eq "E" || $rtype eq "I" || $rtype eq "N" || $rtype eq "P" || $rtype eq 
"S") {
        # its a register argument
  
!       $args[$_] =~ s/^[EINPS](\d+)$/$1/i
!         or error("Expected m/[EINPS]\\d+/, but got '$args[$_]'!", $file, $line);
  
        error("Register $1 out of range (should be 0-31) in '$opcode'",$file,$line) if 
$1 < 0 or $1 > 31;
Only in parrot/Parrot: Config.pm
Only in parrot/Parrot: Types.pm
diff --recursive -C 2 parrot_cvs/Types_pm.in parrot/Types_pm.in
*** parrot_cvs/Types_pm.in      Wed Oct 24 07:36:57 2001
--- parrot/Types_pm.in  Wed Oct 24 07:39:58 2001
***************
*** 35,38 ****
--- 35,39 ----
  
  my %how_to_pack = (
+     E  => $pack_type{op},
      I  => $pack_type{op},
      i  => $pack_type{op},
Only in parrot/classes: intclass.o
diff --recursive -C 2 parrot_cvs/config_h.in parrot/config_h.in
*** parrot_cvs/config_h.in      Wed Oct 24 07:36:57 2001
--- parrot/config_h.in  Wed Oct 24 07:53:11 2001
***************
*** 24,31 ****
--- 24,33 ----
  #define FRAMES_PER_PMC_REG_CHUNK FRAMES_PER_CHUNK
  #define FRAMES_PER_NUM_REG_CHUNK FRAMES_PER_CHUNK
+ #define FRAMES_PER_EXC_REG_CHUNK FRAMES_PER_CHUNK
  #define FRAMES_PER_INT_REG_CHUNK FRAMES_PER_CHUNK
  #define FRAMES_PER_STR_REG_CHUNK FRAMES_PER_CHUNK
  
  #define MASK_STACK_CHUNK_LOW_BITS ${stacklow}
+ #define MASK_EXC_CHUNK_LOW_BITS ${intlow}
  #define MASK_INT_CHUNK_LOW_BITS ${intlow}
  #define MASK_NUM_CHUNK_LOW_BITS ${numlow}
diff --recursive -C 2 parrot_cvs/core.ops parrot/core.ops
*** parrot_cvs/core.ops Wed Oct 24 07:36:57 2001
--- parrot/core.ops     Wed Oct 24 07:56:30 2001
***************
*** 120,123 ****
--- 120,127 ----
  ########################################
  
+ =item B<set>(e, i)
+ 
+ =item B<set>(i, e)
+ 
  =item B<set>(i, i)
  
***************
*** 136,141 ****
  =cut
  
  
! AUTO_OP set(i, i|ic) {
    $1 = $2;
  }
--- 140,148 ----
  =cut
  
+ AUTO_OP set(e, i) {
+   $1 = $2;
+ }
  
! AUTO_OP set(i, e|i|ic) {
    $1 = $2;
  }
***************
*** 684,688 ****
  
  AUTO_OP div(i, i|ic, i|ic) {
!   $1 = $2 / $3;
  }
  
--- 691,701 ----
  
  AUTO_OP div(i, i|ic, i|ic) {
!   INTVAL z = $3;
! 
!   if(z == 0) {
!     interpreter->exc_reg->registers[0] = 1;
!   } else {
!     $1 = $2 / $3;
!   }
  }
  
***************
*** 1504,1507 ****
--- 1517,1522 ----
  ########################################
  
+ =item B<pope>()
+ 
  =item B<popi>()
  
***************
*** 1517,1520 ****
--- 1532,1539 ----
  =cut
  
+ AUTO_OP pope() {
+   Parrot_pop_e(interpreter);
+ }
+ 
  AUTO_OP popi() {
    Parrot_pop_i(interpreter);
***************
*** 1536,1539 ****
--- 1555,1560 ----
  ########################################
  
+ =item B<pushe>()
+ 
  =item B<pushi>()
  
***************
*** 1547,1550 ****
--- 1568,1575 ----
  
  =cut
+ 
+ AUTO_OP pushe() {
+   Parrot_push_e(interpreter);
+ }
  
  AUTO_OP pushi() {
diff --recursive -C 2 parrot_cvs/disassemble.pl parrot/disassemble.pl
*** parrot_cvs/disassemble.pl   Wed Oct 24 07:36:57 2001
--- parrot/disassemble.pl       Wed Oct 24 07:43:50 2001
***************
*** 119,122 ****
--- 119,123 ----
  
  my %rtype_map = (
+   "e" => "E",
    "i" => "I",
    "n" => "N",
***************
*** 187,191 ****
            $offset += $unpack_size;
  
!           if($type =~ m/^[INPS]$/) { # Register
                push @{$pasm{$op_start}[3]}, $type . $arg;
            } elsif($type eq "D") { # destination address
--- 188,192 ----
            $offset += $unpack_size;
  
!           if($type =~ m/^[EINPS]$/) { # Register
                push @{$pasm{$op_start}[3]}, $type . $arg;
            } elsif($type eq "D") { # destination address
Only in parrot/include/parrot: config.h
diff --recursive -C 2 parrot_cvs/include/parrot/interpreter.h 
parrot/include/parrot/interpreter.h
*** parrot_cvs/include/parrot/interpreter.h     Wed Oct 24 07:36:57 2001
--- parrot/include/parrot/interpreter.h Wed Oct 24 07:44:53 2001
***************
*** 19,22 ****
--- 19,23 ----
  
  struct Parrot_Interp {
+     struct EReg *exc_reg;            /* Current top of exception reg stack */
      struct IReg *int_reg;            /* Current top of int reg stack */
      struct NReg *num_reg;            /* Current top of the float reg stack */
***************
*** 24,27 ****
--- 25,29 ----
      struct PReg *pmc_reg;            /* Current top of the PMC stack */
      struct Stack_Entry *stack_top;         /* Current top of the generic stack */
+     struct ERegChunk *exc_reg_base;            /* base of the exc reg stack */
      struct IRegChunk *int_reg_base;            /* base of the int reg stack */
      struct NRegChunk *num_reg_base;            /* Base of the float reg stack */
diff --recursive -C 2 parrot_cvs/include/parrot/op.h parrot/include/parrot/op.h
*** parrot_cvs/include/parrot/op.h      Wed Oct 24 07:36:57 2001
--- parrot/include/parrot/op.h  Wed Oct 24 07:45:18 2001
***************
*** 31,34 ****
--- 31,35 ----
    PARROT_ARG_SC,
  
+   PARROT_ARG_E,
    PARROT_ARG_I,
    PARROT_ARG_N,
diff --recursive -C 2 parrot_cvs/include/parrot/register.h 
parrot/include/parrot/register.h
*** parrot_cvs/include/parrot/register.h        Wed Oct 24 07:36:57 2001
--- parrot/include/parrot/register.h    Wed Oct 24 07:46:50 2001
***************
*** 16,19 ****
--- 16,23 ----
  #include "parrot/parrot.h"
  
+ struct EReg {
+     INTVAL registers[NUM_REGISTERS];
+ };
+ 
  struct IReg {
      INTVAL registers[NUM_REGISTERS];
***************
*** 32,35 ****
--- 36,47 ----
  };
  
+ struct ERegChunk {
+     INTVAL used;
+     INTVAL free;
+     struct ERegChunk *next;
+     struct ERegChunk *prev;
+     struct EReg EReg[FRAMES_PER_CHUNK];
+ };
+ 
  struct IRegChunk {
      INTVAL used;
***************
*** 66,69 ****
--- 78,82 ----
  /* These macros masks off the low bits of a register chunk address,
     since we're guaranteed to be aligned */
+ #define EXC_CHUNK_BASE(x) (void *)(MASK_EXC_CHUNK_LOW_BITS & (ptrcast_t)x)
  #define INT_CHUNK_BASE(x) (void *)(MASK_INT_CHUNK_LOW_BITS & (ptrcast_t)x)
  #define NUM_CHUNK_BASE(x) (void *)(MASK_NUM_CHUNK_LOW_BITS & (ptrcast_t)x)
***************
*** 76,79 ****
--- 89,93 ----
  void Parrot_clear_n(struct Parrot_Interp *);
  
+ void Parrot_push_e(struct Parrot_Interp *);
  void Parrot_push_i(struct Parrot_Interp *);
  void Parrot_push_n(struct Parrot_Interp *);
***************
*** 86,89 ****
--- 100,104 ----
  void Parrot_clone_p(struct Parrot_Interp *);
  
+ void Parrot_pop_e(struct Parrot_Interp *);
  void Parrot_pop_i(struct Parrot_Interp *);
  void Parrot_pop_n(struct Parrot_Interp *);
diff --recursive -C 2 parrot_cvs/interpreter.c parrot/interpreter.c
*** parrot_cvs/interpreter.c    Wed Oct 24 07:36:57 2001
--- parrot/interpreter.c        Wed Oct 24 07:47:56 2001
***************
*** 128,131 ****
--- 128,132 ----
      
      /* Set up the initial register chunks */
+     interpreter->exc_reg_base = mem_allocate_aligned(sizeof(struct ERegChunk));
      interpreter->int_reg_base = mem_allocate_aligned(sizeof(struct IRegChunk));
      interpreter->num_reg_base = mem_allocate_aligned(sizeof(struct NRegChunk));
***************
*** 134,141 ****
--- 135,149 ----
      
      /* Set up the initial register frame pointers */
+     interpreter->exc_reg = &interpreter->exc_reg_base->EReg[0];
      interpreter->int_reg = &interpreter->int_reg_base->IReg[0];
      interpreter->num_reg = &interpreter->num_reg_base->NReg[0];
      interpreter->string_reg = &interpreter->string_reg_base->SReg[0];
      interpreter->pmc_reg = &interpreter->pmc_reg_base->PReg[0];
+     
+     /* Initialize the exception register chunk */
+     interpreter->exc_reg_base->used = 1;
+     interpreter->exc_reg_base->free = FRAMES_PER_EXC_REG_CHUNK - 1;
+     interpreter->exc_reg_base->next = NULL;
+     interpreter->exc_reg_base->prev = NULL;
      
      /* Initialize the integer register chunk */
diff --recursive -C 2 parrot_cvs/ops2c.pl parrot/ops2c.pl
*** parrot_cvs/ops2c.pl Wed Oct 24 07:36:57 2001
--- parrot/ops2c.pl     Wed Oct 24 07:48:19 2001
***************
*** 221,224 ****
--- 221,225 ----
      'op' => "cur_opcode[%ld]",
  
+     'e'  => "interpreter->exc_reg->registers[cur_opcode[%ld]]",
      'i'  => "interpreter->int_reg->registers[cur_opcode[%ld]]",
      'n'  => "interpreter->num_reg->registers[cur_opcode[%ld]]",
diff --recursive -C 2 parrot_cvs/pbc2c.pl parrot/pbc2c.pl
*** parrot_cvs/pbc2c.pl Wed Oct 24 07:36:57 2001
--- parrot/pbc2c.pl     Wed Oct 24 07:48:44 2001
***************
*** 208,211 ****
--- 208,212 ----
  
  my %arg_maps = (
+   'e'  => "interpreter->exc_reg->registers[%ld]",
    'i'  => "interpreter->int_reg->registers[%ld]",
    'n'  => "interpreter->num_reg->registers[%ld]",
diff --recursive -C 2 parrot_cvs/register.c parrot/register.c
*** parrot_cvs/register.c       Wed Oct 24 07:36:57 2001
--- parrot/register.c   Wed Oct 24 07:51:19 2001
***************
*** 13,16 ****
--- 13,42 ----
  #include "parrot/parrot.h"
  
+ /*=for api register Parrot_push_e
+   pushes a new exception register frame on the frame stack
+ */
+ void
+ Parrot_push_e(struct Parrot_Interp *interpreter) {
+     struct ERegChunk *chunk_base;
+     
+     chunk_base = EXC_CHUNK_BASE(interpreter->exc_reg);
+     /* Do we have any slots left in the current chunk? */
+     if (chunk_base->free) {
+         interpreter->exc_reg = &chunk_base->EReg[chunk_base->used++];
+         chunk_base->free--;
+     }
+     /* Nope, so plan B time. Allocate a new chunk of exc register frames */
+     else {
+         struct ERegChunk *new_chunk;
+         new_chunk = mem_allocate_aligned(sizeof(struct ERegChunk));
+         new_chunk->used = 1;
+         new_chunk->free = FRAMES_PER_EXC_REG_CHUNK - 1;
+         new_chunk->next = NULL;
+         new_chunk->prev = chunk_base;
+         chunk_base->next = new_chunk;
+         interpreter->exc_reg = &new_chunk->EReg[0];
+     }
+ }
+ 
  /*=for api register Parrot_push_i
    pushes a new integer register frame on the frame stack
***************
*** 69,72 ****
--- 95,127 ----
                          sizeof(struct IReg));
          interpreter->int_reg = &new_chunk->IReg[0];
+     }
+ }
+ 
+ /*=for api register Parrot_pop_e
+   pops an exception register frame off of the frame stack
+ */
+ void
+ Parrot_pop_e(struct Parrot_Interp *interpreter) {
+     struct ERegChunk *chunk_base;
+     chunk_base = EXC_CHUNK_BASE(interpreter->exc_reg);
+     /* Is there more than one register frame in use? */
+     if (chunk_base->used > 1) {
+         chunk_base->used--;
+         chunk_base->free++;
+         interpreter->exc_reg = &chunk_base->EReg[chunk_base->used - 1];
+     }
+     /* nope. Walk back */
+     else {
+         /* Can we even walk back? */
+         if (chunk_base->prev) {
+             /* Do so. We don't need to adjust used/free, since they're
+                already OK for the "We're full" case */
+             chunk_base = chunk_base->prev;
+             interpreter->exc_reg = &chunk_base->EReg[chunk_base->used - 1];
+         }
+         /* Nope. So pitch a fit */
+         else {
+             INTERNAL_EXCEPTION(NO_REG_FRAMES, "No more E register frames to pop!");
+         }
      }
  }
Only in parrot/t/op: exception.t
Only in parrot/t/op: integer19.out
Only in parrot/t/op: integer19.pasm
Only in parrot/t/op: string1.out
Only in parrot/t/op: string1.pasm
#! perl -w

use Parrot::Test tests => 4;

# Test set operations
output_is(<<'CODE', <<'OUTPUT', "set");
        set I0,5
        set E0,I0
        set I1,E0
        print I1
        print "\n"
        end
CODE
5
OUTPUT

# Test exception stack push
output_is(<<'CODE', <<'OUTPUT', "pushe");
        set I0,5
        set E0,I0
        pushe
        set I1,E0
        print I1
        print "\n"
        end
CODE
0
OUTPUT

# Test exception stack
output_is(<<'CODE', <<'OUTPUT', "set");
        set I0,5
        set I1,-7
        set E0,I0
        pushe
        set E0,I1
        pope
        set I0,E0
        print I0
        print "\n"
        end
CODE
5
OUTPUT

# It would be very embarrassing if these didn't work...
output_is(<<'CODE', <<'OUTPUT', "divide-by-zero exception");
        set I1,5
        div I0,I1,0
        set I2,E0
        print I2
        print "\n"
        end
CODE
1
OUTPUT

Reply via email to