]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Round out the function call handling opcodes for the interpreter.
authorRhys Weatherley <rweather@southern-storm.com.au>
Tue, 11 May 2004 02:04:17 +0000 (02:04 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Tue, 11 May 2004 02:04:17 +0000 (02:04 +0000)
ChangeLog
include/jit/jit-insn.h
jit/jit-insn.c
jit/jit-interp.cpp
jit/jit-interp.h
jit/jit-opcode.c
jit/jit-rules-interp.c

index a2c9515760b0359103d45c3b888fc90e680ac24b..e81a63c39bbca7307e96ea8c13c765bc37ea0cfc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,10 @@
 
+2004-05-11  Rhys Weatherley  <rweather@southern-storm.com.au>
+
+       * include/jit/jit-insn.h, jit/jit-insn.c, jit/jit-interp.cpp,
+       jit/jit-interp.h, jit/jit-opcode.c, jit/jit-rules-interp.c:
+       round out the function call handling opcodes for the interpreter.
+
 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:
index f667c3f9b62f2eb23dc89199905886a4321b88fe..01b85e8a6e8914279d382a8e28775f7e36329eb3 100644 (file)
@@ -246,6 +246,8 @@ int jit_insn_flush_struct(jit_function_t func, jit_value_t value) JIT_NOTHROW;
 jit_value_t jit_insn_import
        (jit_function_t func, jit_value_t value) JIT_NOTHROW;
 int jit_insn_push(jit_function_t func, jit_value_t value) JIT_NOTHROW;
+int jit_insn_push_ptr
+       (jit_function_t func, jit_value_t value, jit_type_t type) JIT_NOTHROW;
 int jit_insn_pop_stack(jit_function_t func, jit_nint num_items) JIT_NOTHROW;
 int jit_insn_return(jit_function_t func, jit_value_t value) JIT_NOTHROW;
 int jit_insn_return_ptr
index b12e48faa846edbcd53edfce68b6a0513384e02a..731fa1ea9f8b5308b9beadab94d23cc62dc5d28a 100644 (file)
@@ -4994,7 +4994,9 @@ jit_value_t jit_insn_call_indirect
        }
        jit_value_ref(func, value);
        insn->opcode = JIT_OP_CALL_INDIRECT;
+       insn->flags = JIT_INSN_VALUE2_IS_SIGNATURE;
        insn->value1 = value;
+       insn->value2 = (jit_value_t)jit_type_copy(signature);
 
        /* If the function does not return, then end the current block.
           The next block does not have "entered_via_top" set so that
@@ -5593,7 +5595,6 @@ int jit_insn_flush_struct(jit_function_t func, jit_value_t value)
  * @deftypefun jit_value_t jit_insn_import (jit_function_t func, jit_value_t value)
  * Import @code{value} from an outer nested scope into @code{func}.  Returns
  * the effective address of the value for local access via a pointer.
- * If @code{value} is local to @code{func}, then it is returned as-is.
  * Returns NULL if out of memory or the value is not accessible via a
  * parent, grandparent, or other ancestor of @code{func}.
  * @end deftypefun
@@ -5610,11 +5611,11 @@ jit_value_t jit_insn_import(jit_function_t func, jit_value_t value)
                return 0;
        }
 
-       /* If the value is already local, then there is nothing to do */
+       /* If the value is already local, then return the local address */
        value_func = jit_value_get_function(value);
        if(value_func == func)
        {
-               return value;
+               return jit_insn_address_of(func, value);
        }
 
        /* Find the nesting level of the value, where 1 is our parent */
@@ -5695,13 +5696,63 @@ int jit_insn_push(jit_function_t func, jit_value_t value)
                case JIT_TYPE_STRUCT:
                case JIT_TYPE_UNION:
                {
-                       return create_unary_note(func, JIT_OP_PUSH_STRUCT, value);
+                       /* We need the address of the value for "push_struct" */
+                       value = jit_insn_address_of(func, value);
+                       if(!value)
+                       {
+                               return 0;
+                       }
+                       return create_note
+                               (func, JIT_OP_PUSH_STRUCT, value,
+                                jit_value_create_nint_constant
+                                       (func, jit_type_nint, (jit_nint)jit_type_get_size(type)));
                }
                /* Not reached */
        }
        return 1;
 }
 
+/*@
+ * @deftypefun int jit_insn_push_ptr (jit_function_t func, jit_value_t value, jit_type_t type)
+ * Push @code{*value} onto the function call stack, in preparation for a call.
+ * This is normally used for returning @code{struct} and @code{union}
+ * values where you have the effective address of the structure, rather
+ * than the structure's contents, in @code{value}.
+ *
+ * You normally wouldn't call this yourself - it is used internally
+ * by the CPU back ends to set up the stack for a subroutine call.
+ * @end deftypefun
+@*/
+int jit_insn_push_ptr
+       (jit_function_t func, jit_value_t value, jit_type_t type)
+{
+       if(!value || !type)
+       {
+               return 0;
+       }
+       switch(jit_type_normalize(type)->kind)
+       {
+               case JIT_TYPE_STRUCT:
+               case JIT_TYPE_UNION:
+               {
+                       /* Push the structure onto the stack by address */
+                       return create_note
+                               (func, JIT_OP_PUSH_STRUCT, value,
+                                jit_value_create_nint_constant
+                                       (func, jit_type_nint, (jit_nint)jit_type_get_size(type)));
+               }
+               /* Not reached */
+
+               default:
+               {
+                       /* Load the value from the address and push it normally */
+                       return jit_insn_push
+                               (func, jit_insn_load_relative(func, value, 0, type));
+               }
+               /* Not reached */
+       }
+}
+
 /*@
  * @deftypefun int jit_insn_pop_stack (jit_function_t func, jit_nint num_items)
  * Pop @code{num_items} items from the function call stack.  You normally
index 8e463a01f7e4b5802acb46b085da252314eaf460..7f18793bb7cac1674fb09a782e9d0b56839a5c52 100644 (file)
@@ -3294,6 +3294,7 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                 ******************************************************************/
 
                VMCASE(JIT_OP_CALL):
+               VMCASE(JIT_OP_CALL_TAIL):
                {
                        /* Call a function that is under the control of the JIT */
                        call_func = (jit_function_t)VM_NINT_ARG;
@@ -3455,8 +3456,8 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                {
                        /* Return from the current function, with a small structure */
                #if JIT_APPLY_MAX_STRUCT_IN_REG != 0
-                       jit_memcpy(return_area->struct_value, VM_STK_PTR1,
-                                          (unsigned int)VM_STK_NINT0);
+                       jit_memcpy(return_area->struct_value, VM_STK_PTR0,
+                                          (unsigned int)VM_NINT_ARG);
                #endif
                        return;
                }
@@ -3488,19 +3489,46 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                }
                VMBREAK;
 
-               VMCASE(JIT_OP_PUSH_PARENT_LOCALS):
+               VMCASE(JIT_OP_IMPORT_LOCAL):
                {
-                       /* Push the pointer to the parent's local variables */
-                       VM_STK_PTRP = args[0].ptr_value;
-                       VM_MODIFY_PC_AND_STACK(1, -1);
+                       /* Import the address of a local variable from an outer scope */
+                       temparg = VM_NINT_ARG2;
+                       tempptr = args[0].ptr_value;
+                       tempptr2 = args[1].ptr_value;
+                       while(temparg > 1)
+                       {
+                               tempptr = ((jit_item *)tempptr2)[0].ptr_value;
+                               tempptr2 = ((jit_item *)tempptr2)[1].ptr_value;
+                               --temparg;
+                       }
+                       VM_STK_PTRP = ((jit_item *)tempptr) + VM_NINT_ARG;
+                       VM_MODIFY_PC_AND_STACK(3, -1);
                }
                VMBREAK;
 
-               VMCASE(JIT_OP_PUSH_PARENT_ARGS):
+               VMCASE(JIT_OP_IMPORT_ARG):
                {
-                       /* Push the pointer to the parent's argument variables */
-                       VM_STK_PTRP = args[1].ptr_value;
-                       VM_MODIFY_PC_AND_STACK(1, -1);
+                       /* Import the address of an argument from an outer scope */
+                       temparg = VM_NINT_ARG2;
+                       tempptr = args[1].ptr_value;
+                       while(temparg > 1)
+                       {
+                               tempptr = ((jit_item *)tempptr)[1].ptr_value;
+                               --temparg;
+                       }
+                       VM_STK_PTRP = ((jit_item *)tempptr) + VM_NINT_ARG;
+                       VM_MODIFY_PC_AND_STACK(3, -1);
+               }
+               VMBREAK;
+
+               VMCASE(JIT_OP_PUSH_STRUCT):
+               {
+                       /* Push a structure value onto the stack, given a pointer to it */
+                       tempptr = VM_STK_PTR0;
+                       temparg = VM_NINT_ARG;
+                       stacktop -= (JIT_NUM_ITEMS_IN_STRUCT(temparg) - 1);
+                       jit_memcpy(stacktop, tempptr, (unsigned int)temparg);
+                       VM_MODIFY_PC_AND_STACK(2, 0);
                }
                VMBREAK;
 
@@ -4405,7 +4433,6 @@ void _jit_run_function(jit_function_interp *func, jit_item *args,
                VMCASE(JIT_OP_PUSH_FLOAT32):
                VMCASE(JIT_OP_PUSH_FLOAT64):
                VMCASE(JIT_OP_PUSH_NFLOAT):
-               VMCASE(JIT_OP_PUSH_STRUCT):
                VMCASE(JIT_OP_FLUSH_SMALL_STRUCT):
                VMCASE(JIT_OP_END_MARKER):
                VMCASE(JIT_OP_ENTER_CATCH):
index 7a1250625b4a5825e93c086c9a1f2b22f374938e..c23b0a5f8969364498b48ff12a2560d1dadf13ef 100644 (file)
@@ -171,8 +171,8 @@ public:
 /*
  * Nested function call handling.
  */
-#define        JIT_OP_PUSH_PARENT_LOCALS                       (JIT_OP_NUM_OPCODES + 0x0031)
-#define        JIT_OP_PUSH_PARENT_ARGS                         (JIT_OP_NUM_OPCODES + 0x0032)
+#define        JIT_OP_IMPORT_LOCAL                                     (JIT_OP_NUM_OPCODES + 0x0031)
+#define        JIT_OP_IMPORT_ARG                                       (JIT_OP_NUM_OPCODES + 0x0032)
 
 /*
  * Push constant values onto the stack.
@@ -191,7 +191,7 @@ public:
 /*
  * Marker opcode for the end of the interpreter-specific opcodes.
  */
-#define        JIT_OP_END_MARKER                                       (JIT_OP_NUM_OPCODES + 0x0039)
+#define        JIT_OP_END_MARKER                                       (JIT_OP_NUM_OPCODES + 0x003B)
 
 /*
  * Number of interpreter-specific opcodes.
index e3a8d432dea78c974155b7db2bff508d04a44f7e..591ac0d05272a53446b3647565df859974c63228 100644 (file)
@@ -459,7 +459,7 @@ jit_opcode_info_t const jit_opcodes[JIT_OP_NUM_OPCODES] = {
        {"push_float32",                                F_(EMPTY, FLOAT32, EMPTY)},
        {"push_float64",                                F_(EMPTY, FLOAT64, EMPTY)},
        {"push_nfloat",                                 F_(EMPTY, NFLOAT, EMPTY)},
-       {"push_struct",                                 F_(EMPTY, ANY, EMPTY)},
+       {"push_struct",                                 F_(EMPTY, ANY, PTR) | NINT_ARG},
        {"pop_stack",                                   F_(EMPTY, INT, EMPTY) | NINT_ARG},
        {"flush_small_struct",                  F_(EMPTY, ANY, EMPTY)},
 
@@ -588,8 +588,8 @@ jit_opcode_info_t const _jit_interp_opcodes[JIT_OP_NUM_INTERP_OPCODES] = {
        /*
         * Nested function call handling.
         */
-       {"push_parent_locals",                  0},
-       {"push_parent_args",                    0},
+       {"import_local",                                JIT_OPCODE_NINT_ARG_TWO},
+       {"import_arg",                                  JIT_OPCODE_NINT_ARG_TWO},
 
        /*
         * Push constant values onto the stack.
index 91e5e617cf42fb0fbea2955bb6711da37ae37414..f5620b2b6e51e328da38db343c46f8e0db3ee35a 100644 (file)
@@ -375,12 +375,27 @@ int _jit_create_call_setup_insns
         int is_nested, int nested_level, jit_value_t *struct_return)
 {
        jit_type_t type;
+       jit_type_t vtype;
        jit_value_t value;
 
        /* Push all of the arguments in reverse order */
        while(num_args > 0)
        {
                --num_args;
+               type = jit_type_normalize(jit_type_get_param(signature, num_args));
+               if(type->kind == JIT_TYPE_STRUCT || type->kind == JIT_TYPE_UNION)
+               {
+                       /* If the value is a pointer, then we are pushing a structure
+                          argument by pointer rather than by local variable */
+                       vtype = jit_type_normalize(jit_value_get_type(args[num_args]));
+                       if(vtype->kind <= JIT_TYPE_MAX_PRIMITIVE)
+                       {
+                               if(!jit_insn_push_ptr(func, args[num_args], type))
+                               {
+                                       return 0;
+                               }
+                       }
+               }
                if(!jit_insn_push(func, args[num_args]))
                {
                        return 0;
@@ -1056,6 +1071,7 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                /* Not reached */
 
                case JIT_OP_CALL:
+               case JIT_OP_CALL_TAIL:
                {
                        /* Call a function, whose pointer is supplied explicitly */
                        jit_cache_opcode(&(gen->posn), insn->opcode);
@@ -1063,32 +1079,50 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                }
                break;
 
-               case JIT_OP_CALL_EXTERNAL:
+               case JIT_OP_CALL_INDIRECT:
                {
-                       /* Call a native function, whose pointer is supplied explicitly */
+                       /* Call a function, whose pointer is supplied on the stack */
                        if(!jit_type_return_via_pointer
                                        (jit_type_get_return((jit_type_t)(insn->value2))))
                        {
                                jit_cache_opcode(&(gen->posn), JIT_OP_PUSH_RETURN_AREA_PTR);
                        }
+                       reg = _jit_regs_load_to_top(gen, insn->value1, 0, 0);
                        jit_cache_opcode(&(gen->posn), insn->opcode);
                        jit_cache_native(&(gen->posn), (jit_nint)(insn->value2));
-                       jit_cache_native(&(gen->posn), (jit_nint)(insn->dest));
                        jit_cache_native(&(gen->posn), (jit_nint)
                                        (jit_type_num_params((jit_type_t)(insn->value2))));
+                       _jit_regs_free_reg(gen, reg, 1);
+                       adjust_working(gen, -1);
                }
                break;
 
-               case JIT_OP_CALL_INDIRECT:
                case JIT_OP_CALL_VTABLE_PTR:
                {
-                       /* Call a function, whose pointer is supplied on the stack */
-                       _jit_regs_load_to_top(gen, insn->value1, 0, 0);
+                       /* Call a function, whose vtable pointer is supplied on the stack */
+                       reg = _jit_regs_load_to_top(gen, insn->value1, 0, 0);
                        jit_cache_opcode(&(gen->posn), insn->opcode);
+                       _jit_regs_free_reg(gen, reg, 1);
                        adjust_working(gen, -1);
                }
                break;
 
+               case JIT_OP_CALL_EXTERNAL:
+               {
+                       /* Call a native function, whose pointer is supplied explicitly */
+                       if(!jit_type_return_via_pointer
+                                       (jit_type_get_return((jit_type_t)(insn->value2))))
+                       {
+                               jit_cache_opcode(&(gen->posn), JIT_OP_PUSH_RETURN_AREA_PTR);
+                       }
+                       jit_cache_opcode(&(gen->posn), insn->opcode);
+                       jit_cache_native(&(gen->posn), (jit_nint)(insn->value2));
+                       jit_cache_native(&(gen->posn), (jit_nint)(insn->dest));
+                       jit_cache_native(&(gen->posn), (jit_nint)
+                                       (jit_type_num_params((jit_type_t)(insn->value2))));
+               }
+               break;
+
                case JIT_OP_RETURN:
                {
                        /* Return from the current function with no result */
@@ -1115,6 +1149,68 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                }
                break;
 
+               case JIT_OP_RETURN_SMALL_STRUCT:
+               {
+                       /* Return from current function with a small structure result */
+                       if(!_jit_regs_is_top(gen, insn->value1) ||
+                          _jit_regs_num_used(gen, 0) != 1)
+                       {
+                               _jit_regs_spill_all(gen);
+                       }
+                       reg = _jit_regs_load_to_top(gen, insn->value1, 0, 0);
+                       jit_cache_opcode(&(gen->posn), insn->opcode);
+                       jit_cache_native(&(gen->posn),
+                                                        jit_value_get_nint_constant(insn->value2));
+                       _jit_regs_free_reg(gen, reg, 1);
+               }
+               break;
+
+               case JIT_OP_SETUP_FOR_NESTED:
+               {
+                       /* Set up to call a nested child */
+                       jit_cache_opcode(&(gen->posn), insn->opcode);
+                       adjust_working(gen, 2);
+               }
+               break;
+
+               case JIT_OP_SETUP_FOR_SIBLING:
+               {
+                       /* Set up to call a nested sibling */
+                       jit_cache_opcode(&(gen->posn), insn->opcode);
+                       jit_cache_native(&(gen->posn),
+                                                        jit_value_get_nint_constant(insn->value1));
+                       adjust_working(gen, 2);
+               }
+               break;
+
+               case JIT_OP_IMPORT:
+               {
+                       /* Import a local variable from an outer nested scope */
+                       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_IMPORT_LOCAL);
+                               jit_cache_native(&(gen->posn), insn->value1->frame_offset);
+                               jit_cache_native(&(gen->posn),
+                                                                jit_value_get_nint_constant(insn->value2));
+                       }
+                       else
+                       {
+                               jit_cache_opcode(&(gen->posn), JIT_OP_IMPORT_ARG);
+                               jit_cache_native
+                                       (&(gen->posn), -(insn->value1->frame_offset + 1));
+                               jit_cache_native(&(gen->posn),
+                                                                jit_value_get_nint_constant(insn->value2));
+                       }
+                       reg = _jit_regs_new_top(gen, insn->dest, 0);
+                       adjust_working(gen, 1);
+               }
+               break;
+
                case JIT_OP_RETURN_REG:
                {
                        /* Push a function return value back onto the stack */
@@ -1232,14 +1328,30 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
 
                case JIT_OP_PUSH_STRUCT:
                {
-                       /* TODO */
+                       /* Load the pointer value to the top of the stack */
+                       if(!_jit_regs_is_top(gen, insn->value1) ||
+                          _jit_regs_num_used(gen, 0) != 1)
+                       {
+                               _jit_regs_spill_all(gen);
+                       }
+                       reg = _jit_regs_load_to_top
+                               (gen, insn->value1,
+                                (insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
+                                                                JIT_INSN_VALUE1_LIVE)), 0);
+                       _jit_regs_free_reg(gen, reg, 1);
+
+                       /* Push the structure at the designated pointer */
+                       size = jit_value_get_nint_constant(insn->value2);
+                       jit_cache_opcode(&(gen->posn), insn->opcode);
+                       jit_cache_native(&(gen->posn), size);
+                       adjust_working(gen, JIT_NUM_ITEMS_IN_STRUCT(size) - 1);
                }
                break;
 
                case JIT_OP_POP_STACK:
                {
                        /* Pop parameter values from the stack after a function returns */
-                       jit_nint size = jit_value_get_nint_constant(insn->value1);
+                       size = jit_value_get_nint_constant(insn->value1);
                        if(size == 1)
                        {
                                jit_cache_opcode(&(gen->posn), JIT_OP_POP);