diff options
author | amacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-03-25 12:04:22 +0000 |
---|---|---|
committer | amacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-03-25 12:04:22 +0000 |
commit | fa19b467204927c5b2086633ef9b69d521760c4f (patch) | |
tree | 2807170ca4b3477caead2eefd8812ea0080b4eb3 | |
parent | ad81c4f25672600fbd8549bf4f114df826d6cc3d (diff) | |
download | gcc-fa19b467204927c5b2086633ef9b69d521760c4f.tar.gz |
Thu Mar 25 14:04:54 EST 1999 Andrew MacLeod <amacleod@cygnus.com>
* rtl.texi (RTX_FRAME_RELATED_P): Add documentation.
* rtl.h (struct rtx_def): Update comment for frame_related field.
(set_unique_reg_note): Declare prototype.
* dwarf2out.c (dwarf2out_frame_debug_expr): Split out from
'dwarf2out_frame_debug' to handle only expressions, and process
component parts of a PARALLEL expression.
(dwarf2out_frame_debug): Process insns only, and call
new function 'dwarf2out_frame_debug_expr' for patterns.
* emit-rtl.c (set_unique_reg_note): New function to add a reg note,
but if there is an existingone, deletes it first.
* expmed.c (expand_mult, expand_divmod): Use set_unique_reg_note.
* optabs.c (add_equal_note, expand_binop): Use set_unique_reg_note.
(emit_no_conflict_block, emit_libcall_block): Use set_unique_reg_note.
(expand_fix): Use set_unique_reg_note.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@25977 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/dwarf2out.c | 419 | ||||
-rw-r--r-- | gcc/rtl.h | 3 |
2 files changed, 229 insertions, 193 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. */ diff --git a/gcc/rtl.h b/gcc/rtl.h index 55bd8a978b9..a033733c8e4 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -164,7 +164,7 @@ typedef struct rtx_def In a REG, nonzero means this reg refers to the return value of the current function. */ unsigned integrated : 1; - /* 1 in an INSN if this rtx is related to the call frame, + /* 1 in an INSN or a SET if this rtx is related to the call frame, either changing how we compute the frame address or saving and restoring registers in the prologue and epilogue. 1 in a MEM if the MEM refers to a scalar, rather than a member of @@ -997,6 +997,7 @@ extern rtx gen_mem_addressof PROTO((rtx, union tree_node *)); extern rtx eliminate_constant_term PROTO((rtx, rtx *)); extern rtx expand_complex_abs PROTO((enum machine_mode, rtx, rtx, int)); extern enum machine_mode choose_hard_reg_mode PROTO((int, int)); +extern void set_unique_reg_note PROTO((rtx, enum reg_note, rtx)); /* Functions in rtlanal.c */ |