]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Add support for the alloca opcode on X86_64.
authorKlaus Treichel <ktreichel@web.de>
Sat, 31 Oct 2009 14:57:28 +0000 (15:57 +0100)
committerKlaus Treichel <ktreichel@web.de>
Sat, 31 Oct 2009 14:57:28 +0000 (15:57 +0100)
Changes based on a patch from Peter Lobsinger <plobsing@gmail.com>

ChangeLog
jit/jit-rules-x86-64.c
jit/jit-rules-x86-64.h
jit/jit-rules-x86-64.ins

index e765f0f8f925d3b72aa1aef3885f7da4d1063a03..b9231747a238a580f4ff7cdafbd23cd3960da5ab 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,17 @@
        * jit/jit-compile.c (_JIT_RESULT_TO_OBJECT, _JIT_RESULT_FROM_OBJECT):
        Fix compiler warnings on systems where sizeof(int) != sizeof(void *)
 
+       * jit/jit-rules-x86-64.c (fixup_alloca): Added to handle alloca
+       fixups with param area enabled.
+       (_jit_gen_epilog): Generate the epilog differenty if the stackpointer
+       was changed during code generation with param area enabled.
+
+       * jit/jit-rules-x86-64.h: Add the alloca_fixups to the
+       extra_gen_state.
+
+       * jit/jit-rules-x86-64.ins: Add support for JIT_OP_ALLOCA.
+       (alloca support based on a patch from Peter Lobsinger, thanks)
+
 2009-10-30  Aleksey Demakov  <ademakov@gmail.com>
 
        * include/jit/jit-function.h, jit/jit-function.c
index 52ba8ed5d8ac5cc02417770f4c149011a3154638..155d201ace419957447362758354562f9857bde7 100644 (file)
@@ -1327,6 +1327,47 @@ jump_to_epilog(jit_gencode_t gen, unsigned char *inst, jit_block_t block)
        return inst;
 }
 
+/*
+ * fixup a register being alloca'd to by accounting for the param area
+ */
+static unsigned char *
+fixup_alloca(jit_gencode_t gen, unsigned char *inst, int reg)
+{
+#ifdef JIT_USE_PARAM_AREA
+       jit_int fixup;
+       jit_int temp;
+
+       /*
+        * emit the instruction and then replace the imm section of op with
+        * the fixup.
+        * NOTE: We are using the temp variable here to avoid a compiler
+        * warning and the temp value to make sure that an instruction with
+        * a 32 bit immediate is emitted. The temp value in the instruction
+        * will be replaced by the fixup
+        */
+       temp = 1234567;
+       x86_64_add_reg_imm_size(inst, reg, temp, 8);
+
+       /* Make inst pointing to the 32bit immediate in the instruction */
+       inst -= 4;
+
+       /* calculalte the fixup */
+       if (gen->alloca_fixup)
+       {
+               fixup = _JIT_CALC_FIXUP(gen->alloca_fixup, inst);
+       }
+       else
+       {
+               fixup = 0;
+       }
+       gen->alloca_fixup = (void *)inst;
+       x86_imm_emit32(inst, fixup);
+#else /* !JIT_USE_PARAM_AREA */
+       /* alloca fixup is not needed if the param area is not used */
+#endif /* JIT_USE_PARAM_AREA */
+       return inst;
+}
+
 /*
  * Compare a xmm register with an immediate value.
  */
@@ -2469,27 +2510,22 @@ _jit_gen_epilog(jit_gencode_t gen, jit_function_t func)
        }
        gen->epilog_fixup = 0;
 
-       /* Restore the used callee saved registers */
-#ifdef JIT_USE_PARAM_AREA
-       if(func->builder->param_area_size > 0)
+       /* Perform fixups on any alloca calls */
+       fixup = (jit_int *)(gen->alloca_fixup);
+       while (fixup != 0)
        {
-               current_offset = func->builder->param_area_size;
-       }
-       else
-       {
-               current_offset = 0;
-       }
-       for(reg = 0; reg <= 14; ++reg)
-       {
-               if(jit_reg_is_used(gen->touched, reg) &&
-                  (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
+               next = (jit_int *)_JIT_CALC_NEXT_FIXUP(fixup, fixup[0]);
+               fixup[0] = func->builder->param_area_size;
+               if(DEBUG_FIXUPS)
                {
-                       x86_64_mov_reg_membase_size(inst, _jit_reg_info[reg].cpu_reg,
-                                                   X86_64_RSP, current_offset, 8);
-                       current_offset += 8;
+                       fprintf(stderr, "Fixup Param Area Size: %lx, Value: %x\n",
+                                       (jit_nint)fixup, fixup[0]);
                }
+               fixup = next;
        }
-#else /* !JIT_USE_PARAM_AREA */
+       gen->alloca_fixup = 0;
+
+       /* Restore the used callee saved registers */
        if(gen->stack_changed)
        {
                int frame_size = func->builder->frame_size;
@@ -2520,26 +2556,36 @@ _jit_gen_epilog(jit_gencode_t gen, jit_function_t func)
                           (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
                        {
                                x86_64_mov_reg_membase_size(inst, _jit_reg_info[reg].cpu_reg,
-                                                                                       X86_64_RBP, current_offset, 8);
+                                                           X86_64_RBP, current_offset, 8);
                                current_offset += 8;
                        }
                }
        }
        else
        {
+#ifdef JIT_USE_PARAM_AREA
+               if(func->builder->param_area_size > 0)
+               {
+                       current_offset = func->builder->param_area_size;
+               }
+               else
+               {
+                       current_offset = 0;
+               }
+#else /* !JIT_USE_PARAM_AREA */
                current_offset = 0;
+#endif /* !JIT_USE_PARAM_AREA */
                for(reg = 0; reg <= 14; ++reg)
                {
                        if(jit_reg_is_used(gen->touched, reg) &&
                           (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
                        {
                                x86_64_mov_reg_membase_size(inst, _jit_reg_info[reg].cpu_reg,
-                                                                                       X86_64_RSP, current_offset, 8);
+                                                           X86_64_RSP, current_offset, 8);
                                current_offset += 8;
                        }
                }
        }
-#endif /* !JIT_USE_PARAM_AREA */
 
        /* Restore stackpointer and frame register */
        x86_64_mov_reg_reg_size(inst, X86_64_RSP, X86_64_RBP, 8);
index 569d42940a86e23ea1e7ea6da4f8b1847a0e4520..37b896dab2deb5274c786b2bd48c66691cbed6e9 100644 (file)
@@ -109,6 +109,20 @@ extern     "C" {
  */
 #define        JIT_ALIGN_OVERRIDES             1
 
+/*
+ * Extra state information that is added to the "jit_gencode" structure.
+ */
+
+#define jit_extra_gen_state    \
+       void *alloca_fixup
+
+#define jit_extra_gen_init(gen)        \
+       do {    \
+               (gen)->alloca_fixup = 0;        \
+       } while (0)
+
+#define jit_extra_gen_cleanup(gen)     do { ; } while (0)
+
 /*
  * Parameter passing rules.
  */
index cce61185a174fcd217fd4c31787ca894fffa5301..f8a10968be6f63eded075757373e0c32ed484590 100644 (file)
@@ -3167,6 +3167,16 @@ JIT_OP_MEMSET: ternary
                inst = x86_64_call_code(inst, (jit_nint)jit_memset);
        }
 
+JIT_OP_ALLOCA:
+       [reg] -> {
+               x86_64_add_reg_imm_size(inst, $1, 15, 8);
+               x86_64_and_reg_imm_size(inst, $1, ~15, 8);
+               x86_64_sub_reg_reg_size(inst, X86_64_RSP, $1, 8);
+               x86_64_mov_reg_reg_size(inst, $1, X86_64_RSP, 8);
+               inst = fixup_alloca(gen, inst, $1);
+               gen->stack_changed = 1;
+}
+
 JIT_OP_JUMP_TABLE: ternary, branch
        [reg, imm, imm, scratch reg, space("64")] -> {
                unsigned char *patch_jump_table;