summaryrefslogtreecommitdiffstats
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r--gcc/dwarf2out.c419
1 files changed, 227 insertions, 192 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index ae38b2099a8..50d6937eb85 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -1186,6 +1186,230 @@ dwarf2out_stack_adjust (insn)
dwarf2out_args_size (label, args_size);
}
+/* A temporary register used in adjusting SP or setting up the store_reg. */
+static unsigned cfa_temp_reg;
+
+/* A temporary value used in adjusting SP or setting up the store_reg. */
+static long cfa_temp_value;
+
+/* Record call frame debugging information for an expression, which either
+ sets SP or FP (adjusting how we calculate the frame address) or saves a
+ register to the stack. */
+
+static void
+dwarf2out_frame_debug_expr (expr, label)
+ rtx expr;
+ char *label;
+{
+ rtx src, dest;
+ long offset;
+
+ /* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of
+ the PARALLEL independantly. The first element is always processed if
+ it is a SET. This is for backward compatability. Other elements
+ are processed only if they are SETs and the RTX_FRAME_RELATED_P
+ flag is set in them. */
+
+ if (GET_CODE (expr) == PARALLEL)
+ {
+ int par_index;
+ int limit = XVECLEN (expr, 0);
+
+ for (par_index = 0; par_index < limit; par_index++)
+ {
+ rtx x = XVECEXP (expr, 0, par_index);
+
+ if (GET_CODE (x) == SET &&
+ (RTX_FRAME_RELATED_P (x) || par_index == 0))
+ dwarf2out_frame_debug_expr (x, label);
+ }
+ return;
+ }
+
+ if (GET_CODE (expr) != SET)
+ abort ();
+
+ src = SET_SRC (expr);
+ dest = SET_DEST (expr);
+
+ switch (GET_CODE (dest))
+ {
+ case REG:
+ /* Update the CFA rule wrt SP or FP. Make sure src is
+ relative to the current CFA register. */
+ switch (GET_CODE (src))
+ {
+ /* Setting FP from SP. */
+ case REG:
+ if (cfa_reg != (unsigned) REGNO (src))
+ abort ();
+ if (REGNO (dest) != STACK_POINTER_REGNUM
+ && !(frame_pointer_needed
+ && REGNO (dest) == HARD_FRAME_POINTER_REGNUM))
+ abort ();
+ cfa_reg = REGNO (dest);
+ break;
+
+ case PLUS:
+ case MINUS:
+ if (dest == stack_pointer_rtx)
+ {
+ /* Adjusting SP. */
+ switch (GET_CODE (XEXP (src, 1)))
+ {
+ case CONST_INT:
+ offset = INTVAL (XEXP (src, 1));
+ break;
+ case REG:
+ if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp_reg)
+ abort ();
+ offset = cfa_temp_value;
+ break;
+ default:
+ abort ();
+ }
+
+ if (XEXP (src, 0) == hard_frame_pointer_rtx)
+ {
+ /* Restoring SP from FP in the epilogue. */
+ if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
+ abort ();
+ cfa_reg = STACK_POINTER_REGNUM;
+ }
+ else if (XEXP (src, 0) != stack_pointer_rtx)
+ abort ();
+
+ if (GET_CODE (src) == PLUS)
+ offset = -offset;
+ if (cfa_reg == STACK_POINTER_REGNUM)
+ cfa_offset += offset;
+ if (cfa_store_reg == STACK_POINTER_REGNUM)
+ cfa_store_offset += offset;
+ }
+ else if (dest == hard_frame_pointer_rtx)
+ {
+ /* Either setting the FP from an offset of the SP,
+ or adjusting the FP */
+ if (! frame_pointer_needed
+ || REGNO (dest) != HARD_FRAME_POINTER_REGNUM)
+ abort ();
+
+ if (XEXP (src, 0) == stack_pointer_rtx
+ && GET_CODE (XEXP (src, 1)) == CONST_INT)
+ {
+ if (cfa_reg != STACK_POINTER_REGNUM)
+ abort ();
+ offset = INTVAL (XEXP (src, 1));
+ if (GET_CODE (src) == PLUS)
+ offset = -offset;
+ cfa_offset += offset;
+ cfa_reg = HARD_FRAME_POINTER_REGNUM;
+ }
+ else if (XEXP (src, 0) == hard_frame_pointer_rtx
+ && GET_CODE (XEXP (src, 1)) == CONST_INT)
+ {
+ if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
+ abort ();
+ offset = INTVAL (XEXP (src, 1));
+ if (GET_CODE (src) == PLUS)
+ offset = -offset;
+ cfa_offset += offset;
+ }
+
+ else
+ abort();
+ }
+ else
+ {
+ if (GET_CODE (src) != PLUS
+ || XEXP (src, 1) != stack_pointer_rtx)
+ abort ();
+ if (GET_CODE (XEXP (src, 0)) != REG
+ || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg)
+ abort ();
+ if (cfa_reg != STACK_POINTER_REGNUM)
+ abort ();
+ cfa_store_reg = REGNO (dest);
+ cfa_store_offset = cfa_offset - cfa_temp_value;
+ }
+ break;
+
+ case CONST_INT:
+ cfa_temp_reg = REGNO (dest);
+ cfa_temp_value = INTVAL (src);
+ break;
+
+ case IOR:
+ if (GET_CODE (XEXP (src, 0)) != REG
+ || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg
+ || (unsigned) REGNO (dest) != cfa_temp_reg
+ || GET_CODE (XEXP (src, 1)) != CONST_INT)
+ abort ();
+ cfa_temp_value |= INTVAL (XEXP (src, 1));
+ break;
+
+ default:
+ abort ();
+ }
+ dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+ break;
+
+ case MEM:
+ /* Saving a register to the stack. Make sure dest is relative to the
+ CFA register. */
+ if (GET_CODE (src) != REG)
+ abort ();
+ switch (GET_CODE (XEXP (dest, 0)))
+ {
+ /* With a push. */
+ case PRE_INC:
+ case PRE_DEC:
+ offset = GET_MODE_SIZE (GET_MODE (dest));
+ if (GET_CODE (XEXP (dest, 0)) == PRE_INC)
+ offset = -offset;
+
+ if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
+ || cfa_store_reg != STACK_POINTER_REGNUM)
+ abort ();
+ cfa_store_offset += offset;
+ if (cfa_reg == STACK_POINTER_REGNUM)
+ cfa_offset = cfa_store_offset;
+
+ offset = -cfa_store_offset;
+ break;
+
+ /* With an offset. */
+ case PLUS:
+ case MINUS:
+ offset = INTVAL (XEXP (XEXP (dest, 0), 1));
+ if (GET_CODE (XEXP (dest, 0)) == MINUS)
+ offset = -offset;
+
+ if (cfa_store_reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
+ abort ();
+ offset -= cfa_store_offset;
+ break;
+
+ /* Without an offset. */
+ case REG:
+ if (cfa_store_reg != (unsigned) REGNO (XEXP (dest, 0)))
+ abort();
+ offset = -cfa_store_offset;
+ break;
+
+ default:
+ abort ();
+ }
+ dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+ dwarf2out_reg_save (label, REGNO (src), offset);
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+
/* Record call frame debugging information for INSN, which either
sets SP or FP (adjusting how we calculate the frame address) or saves a
register to the stack. If INSN is NULL_RTX, initialize our state. */
@@ -1195,12 +1419,7 @@ dwarf2out_frame_debug (insn)
rtx insn;
{
char *label;
- rtx src, dest;
- long offset;
-
- /* A temporary register used in adjusting SP or setting up the store_reg. */
- static unsigned cfa_temp_reg;
- static long cfa_temp_value;
+ rtx src;
if (insn == NULL_RTX)
{
@@ -1227,194 +1446,10 @@ dwarf2out_frame_debug (insn)
src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
if (src)
insn = XEXP (src, 0);
- else
+ else
insn = PATTERN (insn);
- /* Assume that in a PARALLEL prologue insn, only the first elt is
- significant. Currently this is true. */
- if (GET_CODE (insn) == PARALLEL)
- insn = XVECEXP (insn, 0, 0);
- if (GET_CODE (insn) != SET)
- abort ();
-
- src = SET_SRC (insn);
- dest = SET_DEST (insn);
-
- switch (GET_CODE (dest))
- {
- case REG:
- /* Update the CFA rule wrt SP or FP. Make sure src is
- relative to the current CFA register. */
- switch (GET_CODE (src))
- {
- /* Setting FP from SP. */
- case REG:
- if (cfa_reg != (unsigned) REGNO (src))
- abort ();
- if (REGNO (dest) != STACK_POINTER_REGNUM
- && !(frame_pointer_needed
- && REGNO (dest) == HARD_FRAME_POINTER_REGNUM))
- abort ();
- cfa_reg = REGNO (dest);
- break;
-
- case PLUS:
- case MINUS:
- if (dest == stack_pointer_rtx)
- {
- /* Adjusting SP. */
- switch (GET_CODE (XEXP (src, 1)))
- {
- case CONST_INT:
- offset = INTVAL (XEXP (src, 1));
- break;
- case REG:
- if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp_reg)
- abort ();
- offset = cfa_temp_value;
- break;
- default:
- abort ();
- }
-
- if (XEXP (src, 0) == hard_frame_pointer_rtx)
- {
- /* Restoring SP from FP in the epilogue. */
- if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
- abort ();
- cfa_reg = STACK_POINTER_REGNUM;
- }
- else if (XEXP (src, 0) != stack_pointer_rtx)
- abort ();
-
- if (GET_CODE (src) == PLUS)
- offset = -offset;
- if (cfa_reg == STACK_POINTER_REGNUM)
- cfa_offset += offset;
- if (cfa_store_reg == STACK_POINTER_REGNUM)
- cfa_store_offset += offset;
- }
- else if (dest == hard_frame_pointer_rtx)
- {
- /* Either setting the FP from an offset of the SP,
- or adjusting the FP */
- if (! frame_pointer_needed
- || REGNO (dest) != HARD_FRAME_POINTER_REGNUM)
- abort ();
-
- if (XEXP (src, 0) == stack_pointer_rtx
- && GET_CODE (XEXP (src, 1)) == CONST_INT)
- {
- if (cfa_reg != STACK_POINTER_REGNUM)
- abort ();
- offset = INTVAL (XEXP (src, 1));
- if (GET_CODE (src) == PLUS)
- offset = -offset;
- cfa_offset += offset;
- cfa_reg = HARD_FRAME_POINTER_REGNUM;
- }
- else if (XEXP (src, 0) == hard_frame_pointer_rtx
- && GET_CODE (XEXP (src, 1)) == CONST_INT)
- {
- if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
- abort ();
- offset = INTVAL (XEXP (src, 1));
- if (GET_CODE (src) == PLUS)
- offset = -offset;
- cfa_offset += offset;
- }
-
- else
- abort();
- }
- else
- {
- if (GET_CODE (src) != PLUS
- || XEXP (src, 1) != stack_pointer_rtx)
- abort ();
- if (GET_CODE (XEXP (src, 0)) != REG
- || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg)
- abort ();
- if (cfa_reg != STACK_POINTER_REGNUM)
- abort ();
- cfa_store_reg = REGNO (dest);
- cfa_store_offset = cfa_offset - cfa_temp_value;
- }
- break;
-
- case CONST_INT:
- cfa_temp_reg = REGNO (dest);
- cfa_temp_value = INTVAL (src);
- break;
-
- case IOR:
- if (GET_CODE (XEXP (src, 0)) != REG
- || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg
- || (unsigned) REGNO (dest) != cfa_temp_reg
- || GET_CODE (XEXP (src, 1)) != CONST_INT)
- abort ();
- cfa_temp_value |= INTVAL (XEXP (src, 1));
- break;
-
- default:
- abort ();
- }
- dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
- break;
-
- case MEM:
- /* Saving a register to the stack. Make sure dest is relative to the
- CFA register. */
- if (GET_CODE (src) != REG)
- abort ();
- switch (GET_CODE (XEXP (dest, 0)))
- {
- /* With a push. */
- case PRE_INC:
- case PRE_DEC:
- offset = GET_MODE_SIZE (GET_MODE (dest));
- if (GET_CODE (XEXP (dest, 0)) == PRE_INC)
- offset = -offset;
-
- if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
- || cfa_store_reg != STACK_POINTER_REGNUM)
- abort ();
- cfa_store_offset += offset;
- if (cfa_reg == STACK_POINTER_REGNUM)
- cfa_offset = cfa_store_offset;
-
- offset = -cfa_store_offset;
- break;
-
- /* With an offset. */
- case PLUS:
- case MINUS:
- offset = INTVAL (XEXP (XEXP (dest, 0), 1));
- if (GET_CODE (src) == MINUS)
- offset = -offset;
-
- if (cfa_store_reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
- abort ();
- offset -= cfa_store_offset;
- break;
-
- /* Without an offset. */
- case REG:
- if (cfa_store_reg != (unsigned) REGNO (XEXP (dest, 0)))
- abort();
- offset = -cfa_store_offset;
- break;
-
- default:
- abort ();
- }
- dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
- dwarf2out_reg_save (label, REGNO (src), offset);
- break;
-
- default:
- abort ();
- }
+ dwarf2out_frame_debug_expr (insn, label);
}
/* Return the size of an unsigned LEB128 quantity. */
OpenPOWER on IntegriCloud