On Wed, Feb 13, 2002 at 10:43:38PM -0500, Jason Gloudon wrote:
> The type changes in struct Packfile break the pointer math used in a few places
> to calculate the address of the end of the loaded byte code. This causes
> segfaults in build_asm in jit.c when using -j. It also breaks the bounds
> checking on opcode address in runops_slow_core.
> 
> The patch adds the necessary cast to correct the code_end calculations.

Personally, I think it makes much more sense to have everything
outside of the packfile think in terms of opcode_t*, not char*. The
following untested but straightforward patch eliminates all typecasts
from the relevant chunks of code. And adds them back in to pdump.c, at
the points where it really is meant to be converting a char* array to
an opcode_t* array.

Oh, oops. Except it collided with my previously submitted but
unapplied patch to fix the parsing of complex control-flow macros like
goto ADDRESS(( branch ? expr OFFSET($2) : expr NEXT() )). I did that
one to fix something with the jit, I seem to recall. Well, they're
rolled together here, let me know if you want me to split them apart.
The casting patch is all the files in this patch except Op.pm, and
contains only the macro redefinitions in C.pm and CPrederef.pm.

Index: pdump.c
===================================================================
RCS file: /home/perlcvs/parrot/pdump.c,v
retrieving revision 1.8
diff -a -u -r1.8 pdump.c
--- pdump.c     1 Jan 2002 19:49:11 -0000       1.8
+++ pdump.c     14 Feb 2002 19:09:22 -0000
@@ -16,7 +16,7 @@
 main(int argc, char **argv) {
     struct stat       file_stat;
     int               fd;
-    char *            packed;
+    opcode_t *        packed;
     size_t            packed_size;
     struct PackFile * pf;
     struct Parrot_Interp *interpreter = make_interpreter(0);
@@ -43,7 +43,7 @@
     packed_size = file_stat.st_size;
 
 #ifndef HAS_HEADER_SYSMMAN
-    packed = mem_sys_allocate(packed_size);
+    packed = (opcode_t *) mem_sys_allocate(packed_size);
 
     if (!packed) {
         printf("Can't allocate, code %i\n", errno);
@@ -52,7 +52,7 @@
 
     read(fd, (void*)packed, packed_size);
 #else
-    packed = mmap(0, packed_size, PROT_READ, MAP_SHARED, fd, (off_t)0);
+    packed = (opcode_t *) mmap(0, packed_size, PROT_READ, MAP_SHARED, fd, (off_t)0);
 
     if (!packed) {
         printf("Can't mmap, code %i\n", errno);
Index: interpreter.c
===================================================================
RCS file: /home/perlcvs/parrot/interpreter.c,v
retrieving revision 1.69
diff -a -u -r1.69 interpreter.c
--- interpreter.c       14 Feb 2002 05:53:58 -0000      1.69
+++ interpreter.c       14 Feb 2002 19:09:24 -0000
@@ -61,14 +61,14 @@
 runops_generic (opcode_t * (*core)(struct Parrot_Interp *, opcode_t *), 
                 struct Parrot_Interp *interpreter, opcode_t * pc) {
     opcode_t * code_start;
-    UINTVAL    code_size;
+    UINTVAL    code_size; /* in opcodes */
     opcode_t * code_end;
 
     check_fingerprint(interpreter);
 
-    code_start = (opcode_t *)interpreter->code->byte_code;
-    code_size  = interpreter->code->byte_code_size;
-    code_end   = (opcode_t *)((char *)interpreter->code->byte_code + code_size);
+    code_start = interpreter->code->byte_code;
+    code_size  = interpreter->code->byte_code_size / sizeof(opcode_t);
+    code_end   = interpreter->code->byte_code + code_size;
 
     pc = core(interpreter, pc);
 
@@ -286,15 +286,15 @@
 runops_jit (struct Parrot_Interp *interpreter, opcode_t * pc) {
 #ifdef HAS_JIT
     opcode_t * code_start;
-    UINTVAL    code_size;
+    UINTVAL    code_size; /* in opcodes */
     opcode_t * code_end;
     jit_f      jit_code;
 
     check_fingerprint(interpreter);
 
-    code_start = (opcode_t *)interpreter->code->byte_code;
-    code_size  = interpreter->code->byte_code_size;
-    code_end   = (opcode_t *)((char *)interpreter->code->byte_code + code_size);
+    code_start = interpreter->code->byte_code;
+    code_size  = interpreter->code->byte_code_size / sizeof(opcode_t);
+    code_end   = interpreter->code->byte_code + code_size;
 
     jit_code = build_asm(interpreter, pc, code_start, code_end);
 #ifdef ALPHA
@@ -337,15 +337,15 @@
 runops_prederef (struct Parrot_Interp *interpreter, opcode_t * pc, 
                  void ** pc_prederef) {
     opcode_t * code_start;
-    UINTVAL    code_size;
+    UINTVAL    code_size; /* in opcodes */
     opcode_t * code_end;
     void **    code_start_prederef;
 
     check_fingerprint(interpreter);
 
-    code_start = (opcode_t *)interpreter->code->byte_code;
-    code_size  = interpreter->code->byte_code_size;
-    code_end   = (opcode_t *)((char *)interpreter->code->byte_code + code_size);
+    code_start = interpreter->code->byte_code;
+    code_size  = interpreter->code->byte_code_size / sizeof(opcode_t);
+    code_end   = interpreter->code->byte_code + code_size;
 
     code_start_prederef = pc_prederef;
 
Index: runops_cores.c
===================================================================
RCS file: /home/perlcvs/parrot/runops_cores.c,v
retrieving revision 1.12
diff -a -u -r1.12 runops_cores.c
--- runops_cores.c      14 Feb 2002 05:53:58 -0000      1.12
+++ runops_cores.c      14 Feb 2002 19:09:24 -0000
@@ -42,14 +42,14 @@
 opcode_t *
 runops_slow_core (struct Parrot_Interp *interpreter, opcode_t * pc) {
     opcode_t * code_start;
-    INTVAL     code_size;
+    INTVAL     code_size; /* in opcodes */
     opcode_t * code_end;
     opcode_t * lastpc = NULL;
     FLOATVAL starttime = 0;
 
-    code_start = (opcode_t *)interpreter->code->byte_code;
-    code_size  = interpreter->code->byte_code_size;
-    code_end   = (opcode_t *)((char *)interpreter->code->byte_code + code_size);
+    code_start = interpreter->code->byte_code;
+    code_size  = interpreter->code->byte_code_size / sizeof(opcode_t);
+    code_end   = interpreter->code->byte_code + code_size;
 
     if (interpreter->flags & PARROT_TRACE_FLAG) {
       trace_op(interpreter, code_start, code_end, pc);
Index: lib/Parrot/Op.pm
===================================================================
RCS file: /home/perlcvs/parrot/lib/Parrot/Op.pm,v
retrieving revision 1.6
diff -a -u -r1.6 Op.pm
--- lib/Parrot/Op.pm    30 Jan 2002 23:19:46 -0000      1.6
+++ lib/Parrot/Op.pm    14 Feb 2002 19:09:24 -0000
@@ -162,6 +162,45 @@
   return $body;
 }
 
+sub _substitute {
+  my $self = shift;
+  local $_ = shift;
+  my $trans = shift;
+
+  s/{{([a-z]+)\@([^{]*?)}}/ $trans->access_arg($1, $2, $self); /me;
+  s/{{\@([^{]*?)}}/   $trans->access_arg($self->arg_type($1), $1, $self); /me;
+
+  s/{{=0,=([^{]*?)}}/   $trans->restart_address($1) . "; {{=0}}"; /me;
+  s/{{=0,\+=([^{]*?)}}/ $trans->restart_offset($1)  . "; {{=0}}"; /me;
+  s/{{=0,-=([^{]*?)}}/  $trans->restart_offset(-$1) . "; {{=0}}"; /me;
+
+  s/{{=\*}}/            $trans->goto_pop();       /me;
+
+  s/{{\+=([^{]*?)}}/    $trans->goto_offset($1);  /me;
+  s/{{-=([^{]*?)}}/     $trans->goto_offset(-$1); /me;
+  s/{{=([^*][^{]*?)}}/  $trans->goto_address($1); /me;
+
+  s/{{\^\+([^{]*?)}}/   $trans->expr_offset($1);  /me;
+  s/{{\^-([^{]*?)}}/    $trans->expr_offset(-$1); /me;
+  s/{{\^([^{]*?)}}/     $trans->expr_address($1); /me;
+
+  return $_;
+}
+
+# Correctly handle nested substitions for {{...}} by making sure the ...
+# never contains '{', and repeating over the whole string until no more
+# substitutions can be made.
+sub rewrite_body {
+    my ($self, $body, $trans) = @_;
+
+    while (1) {
+        my $new_body = $self->_substitute($body, $trans);
+        last if $body eq $new_body;
+        $body = $new_body;
+    }
+
+    return $body;
+}
 
 #
 # source()
@@ -170,27 +209,7 @@
 sub source
 {
   my ($self, $trans) = @_;
-
-  my $full_body = $self->full_body;
-
-  $full_body =~ s/{{([a-z]+)\@(.*?)}}/ $trans->access_arg($1, $2, $self); /mge;
-  $full_body =~ s/{{\@(.*?)}}/ $trans->access_arg($self->arg_type($1), $1, $self); 
/mge;
-
-  $full_body =~ s/{{=0,=(.*?)}}/   $trans->restart_address($1) . "; " . 
$trans->goto_address(0); /mge;
-  $full_body =~ s/{{=0,\+=(.*?)}}/ $trans->restart_offset($1)  . "; " . 
$trans->goto_address(0); /mge;
-  $full_body =~ s/{{=0,-=(.*?)}}/  $trans->restart_offset(-$1) . "; " . 
$trans->goto_address(0); /mge;
-
-  $full_body =~ s/{{=\*}}/      $trans->goto_pop();       /mge; # NOTE: MUST BE FIRST
-
-  $full_body =~ s/{{\+=(.*?)}}/ $trans->goto_offset($1);  /mge;
-  $full_body =~ s/{{-=(.*?)}}/  $trans->goto_offset(-$1); /mge;
-  $full_body =~ s/{{=(.*?)}}/   $trans->goto_address($1); /mge;
-
-  $full_body =~ s/{{\^\+(.*?)}}/ $trans->expr_offset($1);  /mge;
-  $full_body =~ s/{{\^-(.*?)}}/  $trans->expr_offset(-$1); /mge;
-  $full_body =~ s/{{\^(.*?)}}/   $trans->expr_address($1); /mge;
-
-  return $full_body;
+  return $self->rewrite_body($self->full_body, $trans);
 }
 
 
Index: lib/Parrot/OpsFile.pm
===================================================================
RCS file: /home/perlcvs/parrot/lib/Parrot/OpsFile.pm,v
retrieving revision 1.16
diff -a -u -r1.16 OpsFile.pm
--- lib/Parrot/OpsFile.pm       30 Jan 2002 23:19:46 -0000      1.16
+++ lib/Parrot/OpsFile.pm       14 Feb 2002 19:09:25 -0000
@@ -283,24 +283,24 @@
 
       $jumps ||= $body =~ s/\bgoto\s+OFFSET\(\( (.*?) \)\)/{{+=$1}}/mg;
       $jumps ||= $body =~ s/\bgoto\s+ADDRESS\(\( (.*?) \)\)/{{=$1}}/mg;
-      $body =~ s/\bexpr\s+OFFSET\(\( (.*?) \)\)/{{^+$1}}/mg;
-      $body =~ s/\bexpr\s+ADDRESS\(\( (.*?) \)\)/{{^$1}}/mg;
+                 $body =~ s/\bexpr\s+OFFSET\(\( (.*?) \)\)/{{^+$1}}/mg;
+                 $body =~ s/\bexpr\s+ADDRESS\(\( (.*?) \)\)/{{^$1}}/mg;
 
       $jumps ||= $body =~ s/\bgoto\s+OFFSET\((.*?)\)/{{+=$1}}/mg;
-      $body =~ s/\bgoto\s+NEXT\(\)/{{+=$op_size}}/mg;
+                 $body =~ s/\bgoto\s+NEXT\(\)/{{+=$op_size}}/mg;
       $jumps ||= $body =~ s/\bgoto\s+ADDRESS\((.*?)\)/{{=$1}}/mg;
       $jumps ||= $body =~ s/\bgoto\s+POP\(\)/{{=*}}/mg;
-      $body =~ s/\bexpr\s+OFFSET\((.*?)\)/{{^+$1}}/mg;
-      $body =~ s/\bexpr\s+NEXT\(\)/{{^+$op_size}}/mg;
-      $body =~ s/\bexpr\s+ADDRESS\((.*?)\)/{{^$1}}/mg;
-      $body =~ s/\bexpr\s+POP\(\)/{{^*}}/mg;
+                 $body =~ s/\bexpr\s+OFFSET\((.*?)\)/{{^+$1}}/mg;
+                 $body =~ s/\bexpr\s+NEXT\(\)/{{^+$op_size}}/mg;
+                 $body =~ s/\bexpr\s+ADDRESS\((.*?)\)/{{^$1}}/mg;
+                 $body =~ s/\bexpr\s+POP\(\)/{{^*}}/mg;
 
-      $body =~ s/\bHALT\(\)/{{=0}}/mg;
+                 $body =~ s/\bHALT\(\)/{{=0}}/mg;
 
       $jumps ||= $body =~ s/\brestart\s+OFFSET\((.*?)\)/{{=0,+=$1}}/mg;
-      $body =~ s/\brestart\s+NEXT\(\)/{{=0,+=$op_size}}/mg;
+                 $body =~ s/\brestart\s+NEXT\(\)/{{=0,+=$op_size}}/mg;
 
-      $body =~ s/\$(\d+)/{{\@$1}}/mg;
+                 $body =~ s/\$(\d+)/{{\@$1}}/mg;
 
       $op->body(qq{#line $line "$file"\n}.$body);
 
@@ -388,15 +388,10 @@
     s/goto\s+POP\(\)/{{=*}}/mg;
     s/HALT\(\)/{{=0}}/mg;
 
-    #borrowed from Parrot::Op
-    s/{{=\*}}/      $trans->goto_pop();       /mge;
-    s/{{=(.*?)}}/   $trans->goto_address($1); /mge;
-    s/{{\+=(.*?)}}/ $trans->goto_offset($1);  /mge;
-    s/{{-=(.*?)}}/  $trans->goto_offset(-$1); /mge;
-    s/{{\^\*}}/     $trans->expr_pop();       /mge;
-    s/{{\^(.*?)}}/  $trans->expr_address($1); /mge;
-    s/{{\^\+(.*?)}}/$trans->expr_offset($1);  /mge;
-    s/{{\^-(.*?)}}/ $trans->expr_offset(-$1); /mge;
+    # FIXME: This ought to throw errors when attempting to rewrite $n
+    # argument accesses and other things that make no sense in the
+    # preamble.
+    $_ = Parrot::Op->rewrite_body($_, $trans);
   }
 
   return $_;
Index: lib/Parrot/OpTrans/C.pm
===================================================================
RCS file: /home/perlcvs/parrot/lib/Parrot/OpTrans/C.pm,v
retrieving revision 1.4
diff -a -u -r1.4 C.pm
--- lib/Parrot/OpTrans/C.pm     28 Jan 2002 06:03:20 -0000      1.4
+++ lib/Parrot/OpTrans/C.pm     14 Feb 2002 19:09:25 -0000
@@ -21,7 +21,7 @@
 sub defines
 {
   return <<END;
-#define REL_PC     ((size_t)(cur_opcode - (opcode_t *)interpreter->code->byte_code))
+#define REL_PC     ((size_t)(cur_opcode - interpreter->code->byte_code))
 #define CUR_OPCODE cur_opcode
 END
 }
Index: lib/Parrot/OpTrans/CPrederef.pm
===================================================================
RCS file: /home/perlcvs/parrot/lib/Parrot/OpTrans/CPrederef.pm,v
retrieving revision 1.5
diff -a -u -r1.5 CPrederef.pm
--- lib/Parrot/OpTrans/CPrederef.pm     15 Jan 2002 16:10:46 -0000      1.5
+++ lib/Parrot/OpTrans/CPrederef.pm     14 Feb 2002 19:09:26 -0000
@@ -23,7 +23,26 @@
 {
   return <<END;
 #define REL_PC ((size_t)(cur_opcode - interpreter->prederef_code))
-#define CUR_OPCODE (((opcode_t *)interpreter->code->byte_code) + REL_PC)
+#define CUR_OPCODE (interpreter->code->byte_code + REL_PC)
+
+static inline opcode_t* prederef_to_opcode(struct Parrot_Interp* interpreter,
+                                           void** prederef_addr)
+{
+    ssize_t offset_in_ops;
+    if (prederef_addr == NULL) return NULL;
+    offset_in_ops = prederef_addr - interpreter->prederef_code;
+    return interpreter->code->byte_code + offset_in_ops;
+}
+
+static inline void** opcode_to_prederef(struct Parrot_Interp* interpreter,
+                                        opcode_t* opcode_addr)
+{
+    ssize_t offset_in_ops;
+    if (opcode_addr == NULL) return NULL;
+    offset_in_ops = opcode_addr - interpreter->code->byte_code;
+    return interpreter->prederef_code + offset_in_ops;
+}
+
 END
 }
 
@@ -48,7 +67,18 @@
 sub expr_pop
 {
   my ($self) = @_;
-  return "(((opcode_t *)pop_dest(interpreter) - (opcode_t 
*)interpreter->code->byte_code) + interpreter->prederef_code)";
+  return "opcode_to_prederef(interpreter, pop_dest(interpreter))";
+}
+
+# expr_address
+#
+# Same logic as expr_pop
+#
+
+sub expr_address
+{
+  my ($self, $addr) = @_;
+  return "opcode_to_prederef(interpreter, $addr)";
 }
 
 # expr_offset and goto_offset

Reply via email to