S390x)
AC_DEFINE(TARGET_S390X, 1, [...])
;;
+MIPS)
+ AC_DEFINE(TARGET_MIPS, 1, [...])
+ ;;
esac
if test "x$sizeof_register" = "x4"; then
*new_ctx = *ctx;
if (ji != NULL) {
- gint32 address;
+ int i;
gpointer ip = MONO_CONTEXT_GET_IP (ctx);
- gpointer fp = MONO_CONTEXT_GET_BP (ctx);
- guint32 sp;
+ mgreg_t regs [MONO_MAX_IREGS + 1];
+ guint8 *cfa;
+ guint32 unwind_info_len;
+ guint8 *unwind_info;
frame->type = FRAME_TYPE_MANAGED;
- if (*lmf && (fp >= (gpointer)(*lmf)->ebp)) {
+ if (ji->from_aot)
+ unwind_info = mono_aot_get_unwind_info (ji, &unwind_info_len);
+ else
+ unwind_info = mono_get_cached_unwind_info (ji->used_regs, &unwind_info_len);
+
+ for (i = 0; i < MONO_MAX_IREGS; ++i)
+ regs [i] = new_ctx->sc_regs [i];
+
+ mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start,
+ (guint8*)ji->code_start + ji->code_size,
+ ip, regs, MONO_MAX_IREGS,
+ save_locations, MONO_MAX_IREGS, &cfa);
+
+ for (i = 0; i < MONO_MAX_IREGS; ++i)
+ new_ctx->sc_regs [i] = regs [i];
+ new_ctx->sc_pc = regs [mips_ra];
+ new_ctx->sc_regs [mips_sp] = (mgreg_t)cfa;
+
+ if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
/* remove any unused lmf */
*lmf = (*lmf)->previous_lmf;
}
+ /* we substract 8, so that the IP points into the call instruction */
+ MONO_CONTEXT_SET_IP (new_ctx, new_ctx->sc_pc - 8);
+
+#if 0
+
address = (char *)ip - (char *)ji->code_start;
/* Compute the previous stack frame, assuming method
}
/* we substract 8, so that the IP points into the call instruction */
MONO_CONTEXT_SET_IP (new_ctx, new_ctx->sc_regs[mips_ra] - 8);
+#endif
/* Sanity check -- we should have made progress here */
g_assert (MONO_CONTEXT_GET_BP (new_ctx) != MONO_CONTEXT_GET_BP (ctx));
/* lmf_offset is the offset of the LMF from our stack pointer. */
guint32 lmf_offset = cfg->arch.lmf_offset;
#endif
+ int cfa_offset = 0;
if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
tracing = 1;
/* adjust stackframe assignments for spillvars if needed */
mips_adjust_stackframe (cfg);
+ /* Offset between current sp and the CFA */
+ cfa_offset = 0;
+ mono_emit_unwind_op_def_cfa (cfg, code, mips_sp, cfa_offset);
+
/* stack_offset should not be changed here. */
alloc_size = cfg->stack_offset;
cfg->stack_usage = alloc_size;
if (alloc_size) {
g_assert (mips_is_imm16 (-alloc_size));
mips_addiu (code, mips_sp, mips_sp, -alloc_size);
+ cfa_offset = alloc_size;
+ mono_emit_unwind_op_def_cfa_offset (cfg, code, cfa_offset);
}
if ((cfg->flags & MONO_CFG_HAS_CALLS) || ALWAYS_SAVE_RA) {
else {
g_assert_not_reached ();
}
+ /* sp = cfa - cfa_offset, so sp + offset = cfa - cfa_offset + offset */
+ mono_emit_unwind_op_offset (cfg, code, mips_ra, offset - cfa_offset);
}
/* XXX - optimize this later to not save all regs if LMF constructed */
g_assert (pos < (int)(cfg->stack_usage - sizeof(gpointer)));
g_assert (mips_is_imm16(pos));
MIPS_SW (code, i, mips_sp, pos);
+ mono_emit_unwind_op_offset (cfg, code, i, pos - cfa_offset);
pos += SIZEOF_REGISTER;
}
}
#endif
if (cfg->frame_reg != mips_sp) {
MIPS_MOVE (code, cfg->frame_reg, mips_sp);
+ mono_emit_unwind_op_def_cfa (cfg, code, cfg->frame_reg, cfa_offset);
#if SAVE_LMF
if (method->save_lmf) {
int offset = lmf_offset + G_STRUCT_OFFSET(MonoLMF, iregs[cfg->frame_reg]);
}
#endif
if (alloc2_size) {
+ /* The CFA is fp now, so this doesn't need unwind info */
if (mips_is_imm16 (-alloc2_size)) {
mips_addu (code, mips_sp, mips_sp, -alloc2_size);
}
#define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
#define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
#define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
+#define MONO_ARCH_HAVE_XP_UNWIND 1
/* XXX - a mystery, but it works */
#define MONO_GET_CONTEXT \
* This is a platform-independent interface for unwinding through stack frames
* based on the Dwarf unwinding interface.
* See http://dwarfstd.org/Dwarf3.pdf, section "Call Frame Information".
- * Currently, this is only used for emitting unwind info in AOT files.
*/
-/* CFA = Canonical Frame Address */
+/*
+ * CFA = Canonical Frame Address. By convention, this is the value of the stack pointer
+ * prior to the execution of the call instruction in the caller. I.e. on x86, it is
+ * esp + 4 on entry to a function. The value of the CFA does not change during execution
+ * of a function. There are two kinds of unwind directives:
+ * - those that describe how to compute the CFA at a given pc offset inside a function
+ * - those that describe where a given register is saved relative to the CFA.
+ */
/* Unwind ops */
#define NUM_REGS 16
#define DWARF_DATA_ALIGN (-8)
#define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (14))
+#elif defined (TARGET_MIPS)
+/* FIXME: */
+static int map_hw_reg_to_dwarf_reg [32] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31
+};
+#define NUM_REGS 32
+#define DWARF_DATA_ALIGN (-(gint32)sizeof (mgreg_t))
+#define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (mips_ra))
#else
static int map_hw_reg_to_dwarf_reg [16];
#define NUM_REGS 16