2010-07-04 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Sun, 4 Jul 2010 00:48:13 +0000 (00:48 -0000)
committerZoltan Varga <vargaz@gmail.com>
Sun, 4 Jul 2010 00:48:13 +0000 (00:48 -0000)
* mini-arm.c: Always use V5 for passing IMT/RGCTX when running under LLVM.

* method-to-ir.c (emit_imt_argument): Fix LLVM support for architectures
without IMT_REG defined (ARM).

* exceptions-arm.c: Add LLVM throw exception trampolines, add xdebug info for
the trampolines.

svn path=/trunk/mono/; revision=159857

mono/mini/ChangeLog
mono/mini/exceptions-arm.c
mono/mini/method-to-ir.c
mono/mini/mini-arm.c
mono/mini/mini-arm.h

index 05aad7673c53fddbce0723fbe6fe1aba0155d2c5..ac786bc34781eb3cbb8ded848e9314aa5a7f6da7 100755 (executable)
@@ -1,3 +1,13 @@
+2010-07-04  Zoltan Varga  <vargaz@gmail.com>
+
+       * mini-arm.c: Always use V5 for passing IMT/RGCTX when running under LLVM.
+
+       * method-to-ir.c (emit_imt_argument): Fix LLVM support for architectures
+       without IMT_REG defined (ARM).
+
+       * exceptions-arm.c: Add LLVM throw exception trampolines, add xdebug info for
+       the trampolines.
+
 2010-07-03  Zoltan Varga  <vargaz@gmail.com>
 
        * mini-llvm.c (process_bb): Disable OP_MEMORY_BARRIER on arm.
index cc51ba9d3f91070d86aa68bebfb1ca6979fca072..99f4bcde25423419cd4b10b826b4ead191b802e0 100644 (file)
@@ -166,7 +166,7 @@ mono_arm_throw_exception_by_token (guint32 type_token, unsigned long eip, unsign
 }
 
 /**
- * arch_get_throw_exception_generic:
+ * get_throw_trampoline:
  *
  * Returns a function pointer which can be used to raise 
  * exceptions. The returned function has the following 
@@ -175,7 +175,7 @@ mono_arm_throw_exception_by_token (guint32 type_token, unsigned long eip, unsign
  *
  */
 static gpointer 
-mono_arch_get_throw_exception_generic (int size, gboolean corlib, gboolean rethrow, MonoTrampInfo **info, gboolean aot)
+get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, const char *tramp_name, MonoTrampInfo **info, gboolean aot)
 {
        guint8 *start;
        guint8 *code;
@@ -184,10 +184,15 @@ mono_arch_get_throw_exception_generic (int size, gboolean corlib, gboolean rethr
 
        code = start = mono_global_codeman_reserve (size);
 
+       mono_add_unwind_op_def_cfa (unwind_ops, code, start, ARMREG_SP, 0);
+
        /* save all the regs on the stack */
        ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_SP);
        ARM_PUSH (code, MONO_ARM_REGSAVE_MASK);
 
+       mono_add_unwind_op_def_cfa (unwind_ops, code, start, ARMREG_SP, 10 * 4);
+       mono_add_unwind_op_offset (unwind_ops, code, start, ARMREG_LR, -4);
+
        /* call throw_exception (exc, ip, sp, int_regs, fp_regs) */
        /* caller sp */
        ARM_ADD_REG_IMM8 (code, ARMREG_R2, ARMREG_SP, 10 * 4); /* 10 saved regs */
@@ -222,8 +227,10 @@ mono_arch_get_throw_exception_generic (int size, gboolean corlib, gboolean rethr
        g_assert ((code - start) < size);
        mono_arch_flush_icache (start, code - start);
 
+       mono_save_trampoline_xdebug_info (tramp_name, start, code - start, unwind_ops);
+
        if (info)
-               *info = mono_tramp_info_create (g_strdup_printf (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_exception" : "throw_exception")), start, code - start, ji, unwind_ops);
+               *info = mono_tramp_info_create (g_strdup_printf (tramp_name), start, code - start, ji, unwind_ops);
 
        return start;
 }
@@ -239,7 +246,7 @@ mono_arch_get_throw_exception_generic (int size, gboolean corlib, gboolean rethr
 gpointer
 mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
 {
-       return mono_arch_get_throw_exception_generic (132, FALSE, TRUE, info, aot);
+       return get_throw_trampoline (132, FALSE, TRUE, "rethrow_exception", info, aot);
 }
 
 /**
@@ -257,7 +264,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
 gpointer 
 mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
 {
-       return mono_arch_get_throw_exception_generic (132, FALSE, FALSE, info, aot);
+       return get_throw_trampoline (132, FALSE, FALSE, "throw_exception", info, aot);
 }
 
 /**
@@ -274,9 +281,30 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
 gpointer 
 mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
 {
-       return mono_arch_get_throw_exception_generic (168, TRUE, FALSE, info, aot);
+       return get_throw_trampoline (168, TRUE, FALSE, "throw_corlib_exception", info, aot);
 }      
 
+void
+mono_arch_exceptions_init (void)
+{
+       guint8 *tramp;
+
+       if (mono_aot_only) {
+       } else {
+               /* LLVM uses the normal trampolines, but with a different name */
+               tramp = get_throw_trampoline (168, TRUE, FALSE, "llvm_throw_corlib_exception", NULL, FALSE);
+               mono_register_jit_icall (tramp, "mono_arch_llvm_throw_corlib_exception", NULL, TRUE);
+
+               tramp = get_throw_trampoline (168, TRUE, FALSE, "llvm_throw_corlib_exception_abs", NULL, FALSE);
+               mono_register_jit_icall (tramp, "mono_arch_llvm_throw_corlib_exception_abs", NULL, TRUE);
+
+               /*
+               tramp = get_throw_trampoline (NULL, FALSE, TRUE, TRUE, TRUE, "mono_llvm_resume_unwind_trampoline", FALSE);
+               mono_register_jit_icall (tramp, "mono_llvm_resume_unwind_trampoline", NULL, TRUE);
+               */
+       }
+}
+
 /* 
  * mono_arch_find_jit_info_ext:
  *
index 22c0c12a3c9ee02957e56de1f2393b2df9b2774f..d3bd36a5abf3bebd43a033b00fa3ce52aec67e66 100644 (file)
@@ -2085,7 +2085,32 @@ static void
 emit_imt_argument (MonoCompile *cfg, MonoCallInst *call, MonoInst *imt_arg)
 {
 #ifdef MONO_ARCH_IMT_REG
-       int method_reg = alloc_preg (cfg);
+       int method_reg;
+#endif
+
+       if (COMPILE_LLVM (cfg)) {
+               method_reg = alloc_preg (cfg);
+
+               if (imt_arg) {
+                       MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, method_reg, imt_arg->dreg);
+               } else if (cfg->compile_aot) {
+                       MONO_EMIT_NEW_AOTCONST (cfg, method_reg, call->method, MONO_PATCH_INFO_METHODCONST);
+               } else {
+                       MonoInst *ins;
+                       MONO_INST_NEW (cfg, ins, OP_PCONST);
+                       ins->inst_p0 = call->method;
+                       ins->dreg = method_reg;
+                       MONO_ADD_INS (cfg->cbb, ins);
+               }
+
+#ifdef ENABLE_LLVM
+               call->imt_arg_reg = method_reg;
+#endif
+               return;
+       }
+
+#ifdef MONO_ARCH_IMT_REG
+       method_reg = alloc_preg (cfg);
 
        if (imt_arg) {
                MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, method_reg, imt_arg->dreg);
@@ -2099,10 +2124,6 @@ emit_imt_argument (MonoCompile *cfg, MonoCallInst *call, MonoInst *imt_arg)
                MONO_ADD_INS (cfg->cbb, ins);
        }
 
-#ifdef ENABLE_LLVM
-       if (COMPILE_LLVM (cfg))
-               call->imt_arg_reg = method_reg;
-#endif
        mono_call_inst_add_outarg_reg (cfg, call, method_reg, MONO_ARCH_IMT_REG, FALSE);
 #else
        mono_arch_emit_imt_argument (cfg, call, imt_arg);
index ef50cd47317f95142f63ead7daaeb9eff26caea3..ebbe90ff8b1b62709c87d800a2734e8dc389df2b 100644 (file)
@@ -607,7 +607,7 @@ mono_arch_get_global_int_regs (MonoCompile *cfg)
        regs = g_list_prepend (regs, GUINT_TO_POINTER (ARMREG_V2));
        regs = g_list_prepend (regs, GUINT_TO_POINTER (ARMREG_V3));
        regs = g_list_prepend (regs, GUINT_TO_POINTER (ARMREG_V4));
-       if (!(cfg->compile_aot || cfg->uses_rgctx_reg))
+       if (!(cfg->compile_aot || cfg->uses_rgctx_reg || COMPILE_LLVM (cfg)))
                /* V5 is reserved for passing the vtable/rgctx/IMT method */
                regs = g_list_prepend (regs, GUINT_TO_POINTER (ARMREG_V5));
        /*regs = g_list_prepend (regs, GUINT_TO_POINTER (ARMREG_V6));*/
@@ -1060,7 +1060,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
                cfg->used_int_regs |= 1 << frame_reg;
        }
 
-       if (cfg->compile_aot || cfg->uses_rgctx_reg)
+       if (cfg->compile_aot || cfg->uses_rgctx_reg || COMPILE_LLVM (cfg))
                /* V5 is reserved for passing the vtable/rgctx/IMT method */
                cfg->used_int_regs |= (1 << ARMREG_V5);
 
@@ -5083,7 +5083,7 @@ mono_arch_emit_imt_argument (MonoCompile *cfg, MonoCallInst *call, MonoInst *imt
 
                        mono_call_inst_add_outarg_reg (cfg, call, method_reg, ARMREG_V5, FALSE);
                }
-       } else if (cfg->generic_context || imt_arg) {
+       } else if (cfg->generic_context || imt_arg || mono_use_llvm) {
 
                /* Always pass in a register for simplicity */
                call->dynamic_imt_arg = TRUE;
@@ -5113,6 +5113,11 @@ mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
 {
        guint32 *code_ptr = (guint32*)code;
        code_ptr -= 2;
+
+       if (mono_use_llvm)
+               /* Passed in V5 */
+               return (MonoMethod*)regs [ARMREG_V5];
+
        /* The IMT value is stored in the code stream right after the LDC instruction. */
        if (!IS_LDR_PC (code_ptr [0])) {
                g_warning ("invalid code stream, instruction before IMT value is not a LDC in %s() (code %p value 0: 0x%x -1: 0x%x -2: 0x%x)", __FUNCTION__, code, code_ptr [2], code_ptr [1], code_ptr [0]);
@@ -5219,9 +5224,14 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        vtable_target = code;
        ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
 
-       /* R0 == 0 means we are called from AOT code. In this case, V5 contains the IMT method */
-       ARM_CMP_REG_IMM8 (code, ARMREG_R0, 0);
-       ARM_MOV_REG_REG_COND (code, ARMREG_R0, ARMREG_V5, ARMCOND_EQ);
+       if (mono_use_llvm) {
+               /* LLVM always passes the IMT method in R5 */
+               ARM_MOV_REG_REG (code, ARMREG_R0, ARMREG_V5);
+       } else {
+               /* R0 == 0 means we are called from AOT code. In this case, V5 contains the IMT method */
+               ARM_CMP_REG_IMM8 (code, ARMREG_R0, 0);
+               ARM_MOV_REG_REG_COND (code, ARMREG_R0, ARMREG_V5, ARMCOND_EQ);
+       }
 
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
index 146d4ee6cef4b2d2e4a447531890444535c34c2a..eaff9887e52c6b8f10cfb03d79ace59ee4a3f154 100644 (file)
@@ -168,6 +168,7 @@ typedef struct MonoCompileArch {
 
 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
 #define MONO_ARCH_HAVE_FIND_JIT_INFO_EXT 1
+#define MONO_ARCH_HAVE_EXCEPTIONS_INIT 1
 
 /* ARM doesn't have too many registers, so we have to use a callee saved one */
 #define MONO_ARCH_RGCTX_REG ARMREG_V5
@@ -183,6 +184,8 @@ typedef struct MonoCompileArch {
 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->ebp))
 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->esp))
 
+#define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) do { (ctx)->regs [0] = (gsize)exc; } while (0)
+
 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do {     \
                MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0));       \
                MONO_CONTEXT_SET_SP ((ctx), __builtin_frame_address (0));       \