The attached patch adds decoding of call/return registers to the
disassembler, and also fixes a segfault; both are byproducts of a long
and otherwise fruitless debugging session.  Please let me know what you
think.

                                        -- Bob Rogers
                                           http://rgrjr.dyndns.org/

* src/debug.c:
   + (PDB_disassemble_op):  Add special decoding for the signature used
     in args/returns.  Needs better abstraction, may need better error
     checking.
   + (PDB_disassemble):  Bug fix:  Initialize pline->label, lest the
     caller segfault on output.

Diffs between last version checked in and current workfile(s):

Index: src/debug.c
===================================================================
--- src/debug.c (revision 24244)
+++ src/debug.c (working copy)
@@ -1594,8 +1594,7 @@
             /* If the opcode jumps and this is the last argument,
                that means this is a label */
             if ((j == info->op_count - 1) &&
-                (info->jump & PARROT_JUMP_RELATIVE))
-            {
+                (info->jump & PARROT_JUMP_RELATIVE)) {
                 if (file) {
                     dest[size++] = 'L';
                     i            = PDB_add_label(file, op, op[j]);
@@ -1757,6 +1756,79 @@
             dest[size++] = ',';
     }
 
+    /* Special decoding for the signature used in args/returns.  Such ops have
+       one fixed parameter (the signature vector), plus a varying number of
+       registers/constants.  For each value, we show the register and decode 
its
+       flags. */
+    if (*(op) == PARROT_OP_set_args_pc ||
+            *(op) == PARROT_OP_get_results_pc ||
+            *(op) == PARROT_OP_get_params_pc ||
+            *(op) == PARROT_OP_set_returns_pc) {
+        char buf[1000];
+        PMC * const sig = interp->code->const_table->constants[op[1]]->u.key;
+        int n_values = SIG_ELEMS(sig);
+        const char *regs = "ISPN";
+        /* This is from Call_bits_enum_t (with which it should probably be
+           colocated):
+               ' ' => ignore (this is the reg type, decoded elsewhere)
+               '!' => undefined
+               'C' => constant
+               'F' => :flat or :slurpy
+               'O' => :optional
+               '?' => :opt_flag
+               'N' => named param.
+        */
+        const char *flag_chars = "  !!CF!O?N";
+        int sig_value;
+
+        dest[size++] = '=';
+        dest[size++] = '(';
+        for (j = 0; j < n_values; j++) {
+            unsigned int idx = 0;
+            int sig_value = VTABLE_get_integer_keyed_int(interp, sig, j);
+
+            /* Print the register name, e.g. P37. */
+            if (j)
+                buf[idx++] = ',';
+            buf[idx++] = regs[sig_value & PARROT_ARG_TYPE_MASK];
+            Parrot_snprintf(interp, &buf[idx], sizeof(buf)-idx,
+                            INTVAL_FMT, op[j+2]);
+            idx = strlen(buf);
+
+            /* Add flags, if we have any. */
+            {
+                int flag_idx = 0;
+                int flag_p = 0;
+                int flags = sig_value;
+
+                /* End when we run out of flags, off the end of flag_chars, or
+                   get too close to the end of buf. */
+                while (flags && idx < sizeof(buf)-10) {
+                    char flag_char = flag_chars[flag_idx];
+                    if (! flag_char)
+                        break;
+                    if (flags & 1 && flag_char != ' ') {
+                        if (! flag_p) {
+                            buf[idx++] = '[';
+                            flag_p = 1;
+                        }
+                        buf[idx++] = flag_char;
+                    }
+                    flags >>= 1;
+                    flag_idx++;
+                }
+                if (flag_p)
+                    buf[idx++] = ']';
+            }
+
+            /* Add it to dest. */
+            buf[idx++] = '\0';
+            strcpy(&dest[size], buf);
+            size += strlen(buf);
+        }
+        dest[size++] = ')';
+    }
+
     dest[size] = '\0';
     return ++size;
 }
@@ -1793,6 +1865,7 @@
         PDB_free_file(interp);
 
     pline->number        = 1;
+    pline->label         = NULL;
     pfile->line          = pline;
     pfile->label         = NULL;
     pfile->size          = 0;

End of diffs.

Reply via email to