/* Dwarf2 Call Frame Information helper routines.
- Copyright (C) 1992-2018 Free Software Foundation, Inc.
+ Copyright (C) 1992-2020 Free Software Foundation, Inc.
This file is part of GCC.
/* The expressions for any register column that is saved. */
cfi_vec reg_save;
+
+ /* True if the register window is saved. */
+ bool window_save;
+
+ /* True if the return address is in a mangled state. */
+ bool ra_mangled;
};
/* The caller's ORIG_REG is saved in SAVED_IN_REG. */
/* True if we've seen different values incoming to beg_true_args_size. */
bool args_size_undefined;
+
+ /* True if we've seen an insn with a REG_ARGS_SIZE note before EH_HEAD. */
+ bool args_size_defined_for_eh;
};
return false;
}
+ if (a->window_save != b->window_save)
+ return false;
+
+ if (a->ra_mangled != b->ra_mangled)
+ return false;
+
return true;
}
if (note == NULL)
return;
+ if (!cur_trace->eh_head)
+ cur_trace->args_size_defined_for_eh = true;
+
args_size = get_args_size (note);
delta = args_size - cur_trace->end_true_args_size;
if (known_eq (delta, 0))
}
/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_WINDOW_SAVE.
- ??? Perhaps we should note in the CIE where windows are saved (instead of
- assuming 0(cfa)) and what registers are in the window. */
+
+ ??? Perhaps we should note in the CIE where windows are saved (instead
+ of assuming 0(cfa)) and what registers are in the window. */
static void
dwarf2out_frame_debug_cfa_window_save (void)
cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
add_cfi (cfi);
+ cur_row->window_save = true;
+}
+
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_TOGGLE_RA_MANGLE.
+ Note: DW_CFA_GNU_window_save dwarf opcode is reused for toggling RA mangle
+ state, this is a target specific operation on AArch64 and can only be used
+ on other targets if they don't use the window save operation otherwise. */
+
+static void
+dwarf2out_frame_debug_cfa_toggle_ra_mangle (void)
+{
+ dw_cfi_ref cfi = new_cfi ();
+
+ cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
+ add_cfi (cfi);
+ cur_row->ra_mangled = !cur_row->ra_mangled;
}
/* Record call frame debugging information for an expression EXPR,
/* Rule 6 */
case CONST_INT:
- case POLY_INT_CST:
+ case CONST_POLY_INT:
cur_trace->cfa_temp.reg = dwf_regno (dest);
cur_trace->cfa_temp.offset = rtx_to_poly_int64 (src);
break;
break;
case REG_CFA_TOGGLE_RA_MANGLE:
+ dwarf2out_frame_debug_cfa_toggle_ra_mangle ();
+ handled_one = true;
+ break;
+
case REG_CFA_WINDOW_SAVE:
- /* We overload both of these operations onto the same DWARF opcode. */
dwarf2out_frame_debug_cfa_window_save ();
handled_one = true;
break;
else if (!cfi_equal_p (r_old, r_new))
add_cfi (r_new);
}
+
+ if (!old_row->window_save && new_row->window_save)
+ {
+ dw_cfi_ref cfi = new_cfi ();
+
+ gcc_assert (!old_row->ra_mangled && !new_row->ra_mangled);
+ cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
+ add_cfi (cfi);
+ }
+
+ if (old_row->ra_mangled != new_row->ra_mangled)
+ {
+ dw_cfi_ref cfi = new_cfi ();
+
+ gcc_assert (!old_row->window_save && !new_row->window_save);
+ /* DW_CFA_GNU_window_save is reused for toggling RA mangle state. */
+ cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
+ add_cfi (cfi);
+ }
}
/* Examine CFI and return true if a cfi label and set_loc is needed
rtx_insn *lab = as_a <rtx_insn *> (XEXP (RTVEC_ELT (vec, i), 0));
maybe_record_trace_start (lab, insn);
}
+
+ /* Handle casesi dispatch insns. */
+ if ((tmp = tablejump_casesi_pattern (insn)) != NULL_RTX)
+ {
+ rtx_insn * lab = label_ref_label (XEXP (SET_SRC (tmp), 2));
+ maybe_record_trace_start (lab, insn);
+ }
}
else if (computed_jump_p (insn))
{
if (ti->switch_sections)
prev_args_size = 0;
+
if (ti->eh_head == NULL)
continue;
- gcc_assert (!ti->args_size_undefined);
- if (maybe_ne (ti->beg_delay_args_size, prev_args_size))
+ /* We require either the incoming args_size values to match or the
+ presence of an insn setting it before the first EH insn. */
+ gcc_assert (!ti->args_size_undefined || ti->args_size_defined_for_eh);
+
+ /* In the latter case, we force the creation of a CFI note. */
+ if (ti->args_size_undefined
+ || maybe_ne (ti->beg_delay_args_size, prev_args_size))
{
/* ??? Search back to previous CFI note. */
add_cfi_insn = PREV_INSN (ti->eh_head);