Merge pull request #2998 from lateralusX/jlorenss/win-x64-full-aot-support
[mono.git] / mono / mini / exceptions-arm.c
index 091122262bb7cadcb4d300cda30b5e1915a09fa2..b036aa7a61f17f107c81766275f3162905d7f2fb 100644 (file)
@@ -111,6 +111,8 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
        ARM_MOV_REG_REG (code, ARMREG_IP, ARMREG_SP);
        ARM_PUSH (code, MONO_ARM_REGSAVE_MASK);
 
+       ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
+
        /* restore all the regs from ctx (in r0), but not sp, the stack pointer */
        ctx_reg = ARMREG_R0;
        ARM_LDR_IMM (code, ARMREG_IP, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, pc));
@@ -121,6 +123,8 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
        ARM_MOV_REG_REG (code, ARMREG_LR, ARMREG_PC);
        ARM_MOV_REG_REG (code, ARMREG_PC, ARMREG_R1);
 
+       ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
+
        /* epilog */
        ARM_POP_NWB (code, 0xff0 | ((1 << ARMREG_SP) | (1 << ARMREG_PC)));
 
@@ -137,6 +141,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
 void
 mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
 {
+       MonoError error;
        MonoContext ctx;
        gboolean rethrow = sp & 1;
 
@@ -152,25 +157,27 @@ mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_
        memcpy (((guint8*)&ctx.regs) + (ARMREG_R4 * sizeof (mgreg_t)), int_regs, 8 * sizeof (mgreg_t));
        memcpy (&ctx.fregs, fp_regs, sizeof (double) * 16);
 
-       if (mono_object_isinst (exc, mono_defaults.exception_class)) {
+       if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) {
                MonoException *mono_ex = (MonoException*)exc;
                if (!rethrow) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                }
        }
+       mono_error_assert_ok (&error);
        mono_handle_exception (&ctx, exc);
        mono_restore_context (&ctx);
        g_assert_not_reached ();
 }
 
 void
-mono_arm_throw_exception_by_token (guint32 type_token, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
+mono_arm_throw_exception_by_token (guint32 ex_token_index, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
 {
+       guint32 ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
        /* Clear thumb bit */
        pc &= ~1;
 
-       mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, type_token), pc, sp, int_regs, fp_regs);
+       mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token), pc, sp, int_regs, fp_regs);
 }
 
 void
@@ -245,9 +252,15 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm
        /* exc is already in place in r0 */
        if (corlib) {
                /* The caller ip is already in R1 */
-               if (llvm)
-                       /* Negate the ip adjustment done in mono_arm_throw_exception */
-                       ARM_ADD_REG_IMM8 (code, ARMREG_R1, ARMREG_R1, 4);
+               if (llvm) {
+                       /*
+                        * The address passed by llvm might point to before the call,
+                        * thus outside the eh range recorded by llvm. Use the return
+                        * address instead.
+                        * FIXME: Do this on more platforms.
+                        */
+                       ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
+               }
        } else {
                ARM_MOV_REG_REG (code, ARMREG_R1, ARMREG_LR); /* caller ip */
        }
@@ -376,19 +389,19 @@ mono_arch_exceptions_init (void)
                        MonoTrampInfo *info = l->data;
 
                        mono_register_jit_icall (info->code, g_strdup (info->name), NULL, TRUE);
-                       mono_tramp_info_register (info);
+                       mono_tramp_info_register (info, NULL);
                }
                g_slist_free (tramps);
        }
 }
 
 /* 
- * mono_arch_find_jit_info:
+ * mono_arch_unwind_frame:
  *
  * See exceptions-amd64.c for docs;
  */
 gboolean
-mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, 
+mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls, 
                                                         MonoJitInfo *ji, MonoContext *ctx, 
                                                         MonoContext *new_ctx, MonoLMF **lmf,
                                                         mgreg_t **save_locations,
@@ -408,7 +421,10 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls,
                guint32 unwind_info_len;
                guint8 *unwind_info;
 
-               frame->type = FRAME_TYPE_MANAGED;
+               if (ji->is_trampoline)
+                       frame->type = FRAME_TYPE_TRAMPOLINE;
+               else
+                       frame->type = FRAME_TYPE_MANAGED;
 
                unwind_info = mono_jinfo_get_unwind_info (ji, &unwind_info_len);
 
@@ -589,8 +605,6 @@ mono_arch_ip_from_context (void *sigctx)
 {
 #ifdef MONO_CROSS_COMPILE
        g_assert_not_reached ();
-#elif defined(__native_client__)
-       g_assert_not_reached ();
 #else
        arm_ucontext *my_uc = sigctx;
        return (void*) UCONTEXT_REG_PC (my_uc);