Commit b664de3a by Andrew Macleod

rtl.texi (RTX_FRAME_RELATED_P): Add documentation.

 
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.

From-SVN: r25977
parent 2b4b3e5f
...@@ -1186,6 +1186,230 @@ dwarf2out_stack_adjust (insn) ...@@ -1186,6 +1186,230 @@ dwarf2out_stack_adjust (insn)
dwarf2out_args_size (label, args_size); 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 /* Record call frame debugging information for INSN, which either
sets SP or FP (adjusting how we calculate the frame address) or saves a 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. */ register to the stack. If INSN is NULL_RTX, initialize our state. */
...@@ -1195,12 +1419,7 @@ dwarf2out_frame_debug (insn) ...@@ -1195,12 +1419,7 @@ dwarf2out_frame_debug (insn)
rtx insn; rtx insn;
{ {
char *label; char *label;
rtx src, dest; rtx src;
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;
if (insn == NULL_RTX) if (insn == NULL_RTX)
{ {
...@@ -1227,194 +1446,10 @@ dwarf2out_frame_debug (insn) ...@@ -1227,194 +1446,10 @@ dwarf2out_frame_debug (insn)
src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
if (src) if (src)
insn = XEXP (src, 0); insn = XEXP (src, 0);
else else
insn = PATTERN (insn); insn = PATTERN (insn);
/* Assume that in a PARALLEL prologue insn, only the first elt is dwarf2out_frame_debug_expr (insn, label);
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 ();
}
} }
/* Return the size of an unsigned LEB128 quantity. */ /* Return the size of an unsigned LEB128 quantity. */
......
...@@ -164,7 +164,7 @@ typedef struct rtx_def ...@@ -164,7 +164,7 @@ typedef struct rtx_def
In a REG, nonzero means this reg refers to the return value In a REG, nonzero means this reg refers to the return value
of the current function. */ of the current function. */
unsigned integrated : 1; 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 either changing how we compute the frame address or saving and
restoring registers in the prologue and epilogue. restoring registers in the prologue and epilogue.
1 in a MEM if the MEM refers to a scalar, rather than a member of 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 *)); ...@@ -997,6 +997,7 @@ extern rtx gen_mem_addressof PROTO((rtx, union tree_node *));
extern rtx eliminate_constant_term PROTO((rtx, rtx *)); extern rtx eliminate_constant_term PROTO((rtx, rtx *));
extern rtx expand_complex_abs PROTO((enum machine_mode, rtx, rtx, int)); extern rtx expand_complex_abs PROTO((enum machine_mode, rtx, rtx, int));
extern enum machine_mode choose_hard_reg_mode PROTO((int, 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 */ /* Functions in rtlanal.c */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment