@@ -1235,7 +1235,7 @@ dwarf2out_frame_debug_cfa_register (rtx set)
reg_save (sregno, dregno, 0);
}
-/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_EXPRESSION note. */
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_EXPRESSION note. */
static void
dwarf2out_frame_debug_cfa_expression (rtx set)
@@ -1267,6 +1267,29 @@ dwarf2out_frame_debug_cfa_expression (rtx set)
update_row_reg_save (cur_row, regno, cfi);
}
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_VAL_EXPRESSION
+ note. */
+
+static void
+dwarf2out_frame_debug_cfa_val_expression (rtx set)
+{
+ rtx dest = SET_DEST (set);
+ gcc_assert (REG_P (dest));
+
+ rtx span = targetm.dwarf_register_span (dest);
+ gcc_assert (!span);
+
+ rtx src = SET_SRC (set);
+ dw_cfi_ref cfi = new_cfi ();
+ cfi->dw_cfi_opc = DW_CFA_val_expression;
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = dwf_regno (dest);
+ cfi->dw_cfi_oprnd2.dw_cfi_loc
+ = mem_loc_descriptor (src, GET_MODE (src),
+ GET_MODE (dest), VAR_INIT_STATUS_INITIALIZED);
+ add_cfi (cfi);
+ update_row_reg_save (cur_row, dwf_regno (dest), cfi);
+}
+
/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note. */
static void
@@ -2033,10 +2056,16 @@ dwarf2out_frame_debug (rtx_insn *insn)
break;
case REG_CFA_EXPRESSION:
+ case REG_CFA_VAL_EXPRESSION:
n = XEXP (note, 0);
if (n == NULL)
n = single_set (insn);
- dwarf2out_frame_debug_cfa_expression (n);
+
+ if (REG_NOTE_KIND (note) == REG_CFA_EXPRESSION)
+ dwarf2out_frame_debug_cfa_expression (n);
+ else
+ dwarf2out_frame_debug_cfa_val_expression (n);
+
handled_one = true;
break;
@@ -3015,7 +3044,8 @@ output_cfa_loc (dw_cfi_ref cfi, int for_eh)
dw_loc_descr_ref loc;
unsigned long size;
- if (cfi->dw_cfi_opc == DW_CFA_expression)
+ if (cfi->dw_cfi_opc == DW_CFA_expression
+ || cfi->dw_cfi_opc == DW_CFA_val_expression)
{
unsigned r =
DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
@@ -3041,7 +3071,8 @@ output_cfa_loc_raw (dw_cfi_ref cfi)
dw_loc_descr_ref loc;
unsigned long size;
- if (cfi->dw_cfi_opc == DW_CFA_expression)
+ if (cfi->dw_cfi_opc == DW_CFA_expression
+ || cfi->dw_cfi_opc == DW_CFA_val_expression)
{
unsigned r =
DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
@@ -3188,6 +3219,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
case DW_CFA_def_cfa_expression:
case DW_CFA_expression:
+ case DW_CFA_val_expression:
output_cfa_loc (cfi, for_eh);
break;
@@ -3302,16 +3334,13 @@ output_cfi_directive (FILE *f, dw_cfi_ref cfi)
break;
case DW_CFA_def_cfa_expression:
- if (f != asm_out_file)
- {
- fprintf (f, "\t.cfi_def_cfa_expression ...\n");
- break;
- }
- /* FALLTHRU */
case DW_CFA_expression:
+ case DW_CFA_val_expression:
if (f != asm_out_file)
{
- fprintf (f, "\t.cfi_cfa_expression ...\n");
+ fprintf (f, "\t.cfi_%scfa_%sexpression ...\n",
+ cfi->dw_cfi_opc == DW_CFA_def_cfa_expression ? "def_" : "",
+ cfi->dw_cfi_opc == DW_CFA_val_expression ? "val_" : "");
break;
}
fprintf (f, "\t.cfi_escape %#x,", cfi->dw_cfi_opc);
@@ -518,6 +518,7 @@ dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi)
case DW_CFA_def_cfa_register:
case DW_CFA_register:
case DW_CFA_expression:
+ case DW_CFA_val_expression:
return dw_cfi_oprnd_reg_num;
case DW_CFA_def_cfa_offset:
@@ -551,6 +552,7 @@ dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi)
return dw_cfi_oprnd_reg_num;
case DW_CFA_expression:
+ case DW_CFA_val_expression:
return dw_cfi_oprnd_loc;
default:
@@ -14236,6 +14238,58 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
resolve_one_addr (&rtl);
goto symref;
+ /* RTL sequences inside PARALLEL are raw expression representation.
+
+ mem_loc_descriptor can be used to build generic DWARF expressions for
+ DW_CFA_expression and DW_CFA_val_expression where the expression may can
+ not be represented using normal RTL sequences. In this case, group all
+ expression operations (DW_OP_*) inside a PARALLEL. For those DW_OP which
+ doesn't have RTL mapping, wrap it using UNSPEC. The logic for parsing
+ PARALLEL sequences is:
+
+ foreach elem inside PARALLEL
+ if (elem is UNSPEC)
+ dw_op = XINT (elem, 1) (DWARF operation is kept as UNSPEC number)
+ oprnd1 = XVECEXP (elem, 0, 0)
+ oprnd2 = XVECEXP (elem, 0, 1)
+ else
+ call mem_loc_descriptor */
+ case PARALLEL:
+ {
+ int index = 0;
+ dw_loc_descr_ref exp_result = NULL;
+
+ for (; index < XVECLEN (rtl, 0); index++)
+ {
+ rtx elem = XVECEXP (rtl, 0, index);
+ if (GET_CODE (elem) == UNSPEC)
+ {
+ /* Each DWARF operation UNSPEC contain two operands, if
+ one operand is not used for the operation, const0_rtx is
+ passed. */
+ gcc_assert (XVECLEN (elem, 0) == 2);
+
+ HOST_WIDE_INT dw_op = XINT (elem, 1);
+ HOST_WIDE_INT oprnd1 = INTVAL (XVECEXP (elem, 0, 0));
+ HOST_WIDE_INT oprnd2 = INTVAL (XVECEXP (elem, 0, 1));
+ exp_result =
+ new_loc_descr ((enum dwarf_location_atom) dw_op, oprnd1,
+ oprnd2);
+ }
+ else
+ exp_result =
+ mem_loc_descriptor (elem, mode, mem_mode,
+ VAR_INIT_STATUS_INITIALIZED);
+
+ if (!mem_loc_result)
+ mem_loc_result = exp_result;
+ else
+ add_loc_descr (&mem_loc_result, exp_result);
+ }
+
+ break;
+ }
+
default:
if (flag_checking)
{
@@ -149,6 +149,11 @@ REG_NOTE (CFA_REGISTER)
store of a register to an arbitrary (non-validated) memory address. */
REG_NOTE (CFA_EXPRESSION)
+/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
+ for FRAME_RELATED_EXPR intuition. The DWARF expression computes the value of
+ the given register. */
+REG_NOTE (CFA_VAL_EXPRESSION)
+
/* Attached to insns that are RTX_FRAME_RELATED_P, with the information
that this is a restore operation, i.e. will result in DW_CFA_restore
or the like. Either the attached rtx, or the destination of the insn's