]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Interpreter code conversion for relative pointer and copy opcodes;
authorRhys Weatherley <rweather@southern-storm.com.au>
Mon, 10 May 2004 03:41:49 +0000 (03:41 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Mon, 10 May 2004 03:41:49 +0000 (03:41 +0000)
fix some bugs in stack-based register allocation.

ChangeLog
jit/jit-reg-alloc.c
jit/jit-reg-alloc.h
jit/jit-rules-interp.c

index de55c3ee922aa2723335f03412a22c9e1f543f32..6b318dcd582b3aa1a2bb15229f6993c461a597bf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,10 @@
 
+2004-05-10  Rhys Weatherley  <rweather@southern-storm.com.au>
+
+       * jit/jit-reg-alloc.c, jit/jit-reg-alloc.h, jit/jit-rules-interp.c:
+       interpreter code conversion for relative pointer and copy opcodes;
+       fix some bugs in stack-based register allocation.
+
 2004-05-08  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * jit/jit-cache.c, jit/jit-cache.h, jit/jit-dump.c, jit/jit-interp.h,
index d2790e57666eb1b7aa6d4c948551cbf788a505a9..d77c00cae35a3589d408950f5f29e174338dab3c 100644 (file)
@@ -210,13 +210,6 @@ static void spill_all_between(jit_gencode_t gen, int first, int last)
                        first_stack_reg = reg;
                }
 
-               /* Skip this register if there is nothing in it */
-               if(gen->contents[reg].num_values == 0 &&
-                  !(gen->contents[reg].used_for_temp))
-               {
-                       continue;
-               }
-
                /* If this is a stack register, then we need to find the
                   register that contains the top-most stack position,
                   because we must spill stack registers from top down.
@@ -224,12 +217,23 @@ static void spill_all_between(jit_gencode_t gen, int first, int last)
                if((_jit_reg_info[reg].flags & JIT_REG_IN_STACK) != 0)
                {
                        real_reg = gen->stack_map[first_stack_reg];
+                       if(real_reg == -1)
+                       {
+                               continue;
+                       }
                }
                else
                {
                        real_reg = reg;
                }
 
+               /* Skip this register if there is nothing in it */
+               if(gen->contents[real_reg].num_values == 0 &&
+                  !(gen->contents[real_reg].used_for_temp))
+               {
+                       continue;
+               }
+
                /* Get the other register in a long pair, if there is one */
                if(gen->contents[real_reg].is_long_start)
                {
@@ -1246,3 +1250,30 @@ int _jit_regs_num_used(jit_gencode_t gen, int type_reg)
        }
        return count;
 }
+
+/*@
+ * @deftypefun int _jit_regs_new_top (jit_gencode_t gen, jit_value_t value, int type_reg)
+ * Record that the top of the stack indicated by @code{type_reg} now
+ * contains @code{value}.  This is slightly different from
+ * @code{_jit_regs_set_value}, in that the register wasn't previously
+ * allocated to a temporary operand value.  Returns the actual stack
+ * register that contains @code{value}.
+ * @end deftypefun
+@*/
+int _jit_regs_new_top(jit_gencode_t gen, jit_value_t value, int type_reg)
+{
+       int reg;
+       
+       /* Create space for the value at the top of the stack */
+       reg = create_stack_reg(gen, type_reg, 1);
+
+       /* Record the "value" is now in this register */
+       value->in_register = 1;
+       value->in_frame = 0;
+       value->reg = reg;
+       gen->contents[reg].values[0] = value;
+       gen->contents[reg].num_values = 1;
+
+       /* Return the allocated register to the caller */
+       return reg;
+}
index e44f28069700c0b892f2ed8c457feac1494f647d..b78adcce33e06a6d9ef4bd52b5b675842313f98a 100644 (file)
@@ -52,6 +52,7 @@ void _jit_regs_load_to_top_three
         jit_value_t value3, int used_again1, int used_again2,
         int used_again3, int type_reg);
 int _jit_regs_num_used(jit_gencode_t gen, int type_reg);
+int _jit_regs_new_top(jit_gencode_t gen, jit_value_t value, int type_reg);
 
 #ifdef __cplusplus
 };
index 7479933fa393e32a8d3ceb24521a4f8292313d59..91e5e617cf42fb0fbea2955bb6711da37ae37414 100644 (file)
@@ -870,6 +870,33 @@ static jit_label_t get_branch_dest(jit_block_t block, jit_insn_t insn)
        return label;
 }
 
+/*
+ * Record that a destination is now in a particular register.
+ */
+static void record_dest(jit_gencode_t gen, jit_insn_t insn, int reg)
+{
+       if(insn->dest)
+       {
+               if((insn->flags & JIT_INSN_DEST_NEXT_USE) != 0)
+               {
+                       /* Record that the destination is in "reg" */
+                       _jit_regs_set_value(gen, reg, insn->dest, 0);
+               }
+               else
+               {
+                       /* No next use, so store to the destination */
+                       _jit_gen_spill_reg(gen, reg, -1, insn->dest);
+                       insn->dest->in_frame = 1;
+                       _jit_regs_free_reg(gen, reg, 1);
+               }
+       }
+       else
+       {
+               /* This is a note, with the result left on the stack */
+               _jit_regs_free_reg(gen, reg, 1);
+       }
+}
+
 /*@
  * @deftypefun void _jit_gen_insn (jit_gencode_t gen, jit_function_t func, jit_block_t block, jit_insn_t insn)
  * Generate native code for the specified @code{insn}.  This function should
@@ -884,6 +911,8 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
        int reg;
        jit_label_t label;
        void **pc;
+       jit_nint offset;
+       jit_nint size;
 
        switch(insn->opcode)
        {
@@ -1135,6 +1164,52 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                }
                break;
 
+               case JIT_OP_COPY_LOAD_SBYTE:
+               case JIT_OP_COPY_LOAD_UBYTE:
+               case JIT_OP_COPY_LOAD_SHORT:
+               case JIT_OP_COPY_LOAD_USHORT:
+               case JIT_OP_COPY_INT:
+               case JIT_OP_COPY_LONG:
+               case JIT_OP_COPY_FLOAT32:
+               case JIT_OP_COPY_FLOAT64:
+               case JIT_OP_COPY_NFLOAT:
+               case JIT_OP_COPY_STRUCT:
+               case JIT_OP_COPY_STORE_BYTE:
+               case JIT_OP_COPY_STORE_SHORT:
+               {
+                       /* Copy a value from one temporary variable to another */
+                       reg = _jit_regs_load_to_top
+                               (gen, insn->value1,
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)), 0);
+                       record_dest(gen, insn, reg);
+               }
+               break;
+
+               case JIT_OP_ADDRESS_OF:
+               {
+                       /* Get the address of a local variable */
+                       if(_jit_regs_num_used(gen, 0) >= JIT_NUM_REGS)
+                       {
+                               _jit_regs_spill_all(gen);
+                       }
+                       _jit_gen_fix_value(insn->value1);
+                       if(insn->value1->frame_offset >= 0)
+                       {
+                               jit_cache_opcode(&(gen->posn), JIT_OP_LDLOCA);
+                               jit_cache_native(&(gen->posn), insn->value1->frame_offset);
+                       }
+                       else
+                       {
+                               jit_cache_opcode(&(gen->posn), JIT_OP_LDARGA);
+                               jit_cache_native
+                                       (&(gen->posn), -(insn->value1->frame_offset + 1));
+                       }
+                       reg = _jit_regs_new_top(gen, insn->dest, 0);
+                       adjust_working(gen, 1);
+               }
+               break;
+
                case JIT_OP_PUSH_INT:
                case JIT_OP_PUSH_LONG:
                case JIT_OP_PUSH_FLOAT32:
@@ -1212,6 +1287,107 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                }
                break;
 
+               case JIT_OP_LOAD_RELATIVE_SBYTE:
+               case JIT_OP_LOAD_RELATIVE_UBYTE:
+               case JIT_OP_LOAD_RELATIVE_SHORT:
+               case JIT_OP_LOAD_RELATIVE_USHORT:
+               case JIT_OP_LOAD_RELATIVE_INT:
+               case JIT_OP_LOAD_RELATIVE_LONG:
+               case JIT_OP_LOAD_RELATIVE_FLOAT32:
+               case JIT_OP_LOAD_RELATIVE_FLOAT64:
+               case JIT_OP_LOAD_RELATIVE_NFLOAT:
+               {
+                       /* Load a value from a relative pointer */
+                       reg = _jit_regs_load_to_top
+                               (gen, insn->value1,
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)), 0);
+                       offset = jit_value_get_nint_constant(insn->value2);
+                       jit_cache_opcode(&(gen->posn), insn->opcode);
+                       jit_cache_native(&(gen->posn), offset);
+                       record_dest(gen, insn, reg);
+               }
+               break;
+
+               case JIT_OP_LOAD_RELATIVE_STRUCT:
+               {
+                       /* Load a structured value from a relative pointer */
+                       reg = _jit_regs_load_to_top
+                               (gen, insn->value1,
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)), 0);
+                       offset = jit_value_get_nint_constant(insn->value2);
+                       size = (jit_nint)jit_type_get_size(jit_value_get_type(insn->dest));
+                       jit_cache_opcode(&(gen->posn), insn->opcode);
+                       jit_cache_native(&(gen->posn), offset);
+                       jit_cache_native(&(gen->posn), size);
+                       size = JIT_NUM_ITEMS_IN_STRUCT(size);
+                       record_dest(gen, insn, reg);
+                       adjust_working(gen, size - 1);
+               }
+               break;
+
+               case JIT_OP_STORE_RELATIVE_BYTE:
+               case JIT_OP_STORE_RELATIVE_SHORT:
+               case JIT_OP_STORE_RELATIVE_INT:
+               case JIT_OP_STORE_RELATIVE_LONG:
+               case JIT_OP_STORE_RELATIVE_FLOAT32:
+               case JIT_OP_STORE_RELATIVE_FLOAT64:
+               case JIT_OP_STORE_RELATIVE_NFLOAT:
+               {
+                       /* Store a value to a relative pointer */
+                       reg = _jit_regs_load_to_top_two
+                               (gen, insn->dest, insn->value1,
+                                (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+                                                                JIT_INSN_DEST_LIVE)),
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)), 0);
+                       offset = jit_value_get_nint_constant(insn->value2);
+                       jit_cache_opcode(&(gen->posn), insn->opcode);
+                       jit_cache_native(&(gen->posn), offset);
+                       _jit_regs_free_reg(gen, reg, 1);
+                       adjust_working(gen, -2);
+               }
+               break;
+
+               case JIT_OP_STORE_RELATIVE_STRUCT:
+               {
+                       /* Store a structured value to a relative pointer */
+                       reg = _jit_regs_load_to_top_two
+                               (gen, insn->dest, insn->value1,
+                                (insn->flags & (JIT_INSN_DEST_NEXT_USE |
+                                                                JIT_INSN_DEST_LIVE)),
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)), 0);
+                       offset = jit_value_get_nint_constant(insn->value2);
+                       size = (jit_nint)jit_type_get_size
+                               (jit_value_get_type(insn->value1));
+                       jit_cache_opcode(&(gen->posn), insn->opcode);
+                       jit_cache_native(&(gen->posn), offset);
+                       jit_cache_native(&(gen->posn), size);
+                       _jit_regs_free_reg(gen, reg, 1);
+                       size = JIT_NUM_ITEMS_IN_STRUCT(size);
+                       adjust_working(gen, -(size + 1));
+               }
+               break;
+
+               case JIT_OP_ADD_RELATIVE:
+               {
+                       /* Add a relative offset to a pointer */
+                       reg = _jit_regs_load_to_top
+                               (gen, insn->value1,
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)), 0);
+                       offset = jit_value_get_nint_constant(insn->value2);
+                       if(offset != 0)
+                       {
+                               jit_cache_opcode(&(gen->posn), insn->opcode);
+                               jit_cache_native(&(gen->posn), offset);
+                       }
+                       record_dest(gen, insn, reg);
+               }
+               break;
+
                default:
                {
                        /* Whatever opcodes are left are ordinary operators,