This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: Comment dwarf2out.c and Fix -O3 -g Error
- To: gcc-patches at gcc dot gnu dot org
- Subject: PATCH: Comment dwarf2out.c and Fix -O3 -g Error
- From: Jeffrey Oldham <oldham at codesourcery dot com>
- Date: Thu, 1 Feb 2001 22:32:07 -0800
- Cc: Jeffrey Oldham <oldham at codesourcery dot com>
- Organization: CodeSourcery LLC
When trying to fix mips-sgi-irix6.5 gcc compilation errors occurring
with "-O3 -fomit-frame-pointer" and "-O3 -g", Mark Mitchell and I
discovered that the generated MIPS prologue code did not match the
assumptions that gcc/dwarf2out.c:dwarf2out_frame_debug_expr() was
making. Thus, I documented the function, making a slight
generalization that resolved the compilation error.
Documentation for RTX_FRAME_RELATED_P was also improved during our
investigations.
This is joint work with Mark Mitchell (mark@codesourcery.com). Thanks
to Jason Merrill (jason@redhat.com) for assistance. All mistakes are,
of course, mine.
2001-02-01 Jeffrey Oldham <oldham@codesourcery.com>
* dwarf2out.c: Added explanation of abbreviations.
(def_cfa_1): Added comments listing DWARF2 instructions.
(cfa_temp_reg): Removed in favor of cfa_temp.
(cfa_temp_value): Removed in favor of cfa_temp.
(cfa_temp): New global variable.
(dwarf2out_frame_debug_expr): Added extensive introductory
comments explaining the function's transformations. Revised to
use cfa_temp. Added some rtx checking. Generalize IOR case.
(dwarf2out_frame_debug): Revised to use cfa_temp.
(output_aranges): Cast as "unsigned" to avoid warning.
* rtl.texi (RTX_FRAME_RELATED_P): Revise entry to emphasize better
explain which instructions must be marked.
Tested on mips-sgi-irix6.5 and i686-pc-linux-gnu
Approved by Mark Mitchell (mark@codesourcery.com)
Thanks,
Jeffrey D. Oldham
oldham@codesourcery.com
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarf2out.c,v
retrieving revision 1.237
diff -c -p -r1.237 dwarf2out.c
*** dwarf2out.c 2001/01/28 01:50:05 1.237
--- dwarf2out.c 2001/02/02 05:51:03
*************** Boston, MA 02111-1307, USA. */
*** 55,60 ****
--- 55,78 ----
#include "md5.h"
#include "tm_p.h"
+ /* DWARF2 Abbreviation Glossary:
+ CFA = Canonical Frame Address
+ stack address identifying a stack call frame; its value is
+ the value of the stack pointer just before the call to the
+ current function
+ CFI = Canonical Frame Instruction
+ information describing entries in a stack call frame, e.g.,
+ CIE and FDE
+ CIE = Common Information Entry
+ information describing information common to one or more FDEs
+ DIE = Debugging Information Entry
+ FDE = Frame Description Entry
+ information describing the stack call frame, in particular,
+ how to restore registers
+
+ DW_CFA_... = DWARF2 CFA call frame instruction
+ DW_TAG_... = DWARF2 DIE tag */
+
/* Decide whether we want to emit frame unwind information for the current
translation unit. */
*************** dwarf2out_def_cfa (label, reg, offset)
*** 855,861 ****
def_cfa_1 (label, &loc);
}
! /* This routine does the actual work. The CFA is now calculated from
the dw_cfa_location structure. */
static void
def_cfa_1 (label, loc_p)
--- 873,879 ----
def_cfa_1 (label, &loc);
}
! /* This routine does the actual work. The CFA is now calculated from
the dw_cfa_location structure. */
static void
def_cfa_1 (label, loc_p)
*************** def_cfa_1 (label, loc_p)
*** 879,884 ****
--- 897,904 ----
{
if (loc.indirect == 0
|| loc.base_offset == old_cfa.base_offset)
+ /* Nothing changed so no need to issue any call frame
+ instructions. */
return;
}
*************** def_cfa_1 (label, loc_p)
*** 886,891 ****
--- 906,914 ----
if (loc.reg == old_cfa.reg && !loc.indirect)
{
+ /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction,
+ indicating the CFA register did not change but the offset
+ did. */
cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset;
}
*************** def_cfa_1 (label, loc_p)
*** 894,899 ****
--- 917,925 ----
else if (loc.offset == old_cfa.offset && old_cfa.reg != (unsigned long) -1
&& !loc.indirect)
{
+ /* Construct a "DW_CFA_def_cfa_register <register>" instruction,
+ indicating the CFA register has changed to <register> but the
+ offset has not changed. */
cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
}
*************** def_cfa_1 (label, loc_p)
*** 901,912 ****
--- 927,944 ----
else if (loc.indirect == 0)
{
+ /* Construct a "DW_CFA_def_cfa <register> <offset>" instruction,
+ indicating the CFA register has changed to <register> with
+ the specified offset. */
cfi->dw_cfi_opc = DW_CFA_def_cfa;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset;
}
else
{
+ /* Construct a DW_CFA_def_cfa_expression instruction to
+ calculate the CFA using a full location expression since no
+ register-offset pair is available. */
struct dw_loc_descr_struct *loc_list;
cfi->dw_cfi_opc = DW_CFA_def_cfa_expression;
loc_list = build_cfa_loc (&loc);
*************** dwarf2out_stack_adjust (insn)
*** 1237,1252 ****
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;
--- 1269,1401 ----
dwarf2out_args_size (label, args_size);
}
! /* A temporary register holding an integral value used in adjusting SP
! or setting up the store_reg. The "offset" field holds the integer
! value, not an offset. */
! dw_cfa_location cfa_temp;
!
! /* Record call frame debugging information for an expression EXPR,
! which either sets SP or FP (adjusting how we calculate the frame
! address) or saves a register to the stack. LABEL indicates the
! address of EXPR.
!
! This function encodes a state machine mapping rtxes to actions on
! cfa, cfa_store, and cfa_temp.reg. We describe these rules so
! users need not read the source code.
!
! Invariants / Summaries of Rules
!
! cfa current register used to calculate the DWARF2 canonical
! frame address register and offset
! cfa_store register used by prologue code to save things to the stack
! cfa_store.offset is the offset from the value of
! cfa_store.reg to the actual CFA
! cfa_temp register holding an integral value. cfa_temp.offset
! stores the value, which will be used to adjust the
! stack pointer.
!
! Rules 1- 4: Setting a register's value to cfa.reg or an expression
! with cfa.reg as the first operand changes the cfa.reg and its
! cfa.offset.
! (For an unknown reason, Rule 4 does not fully obey the
! invariant.)
!
! Rules 6- 9: Set a non-cfa.reg register value to a constant or an
! expression yielding a constant. This sets cfa_temp.reg
! and cfa_temp.offset.
!
! Rule 5: Create a new register cfa_store used to save items to the
! stack.
!
! Rules 10-13: Save a register to the stack. Record the location in
! cfa_store.offset. Define offset as the difference of
! the original location and cfa_store's location.
!
! The Rules
!
! "{a,b}" indicates a choice of a xor b.
! "<reg>:cfa.reg" indicates that <reg> must equal cfa.reg.
!
! Rule 1:
! (set <reg1> <reg2>:cfa.reg)
! effects: cfa.reg = <REG1>
! cfa.offset unchanged
!
! Rule 2:
! (set sp ({minus,plus} {sp,fp}:cfa.reg {<const_int>,<reg>:cfa_temp.reg}))
! effects: cfa.reg = sp if fp used
! cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp
! cfa_store.offset += {+/- <const_int>, cfa_temp.offset}
! if cfa_store.reg==sp
!
! Rule 3:
! (set fp ({minus,plus} <reg>:cfa.reg <const_int>))
! effects: cfa.reg = fp
! cfa_offset += +/- <const_int>
!
! Rule 4:
! (set <reg1> (plus <reg2>:cfa.reg <const_int>))
! constraints: <reg1> != fp
! <reg1> != sp
! effects: cfa.reg = <reg1>
! questions: Where is <const_int> used?
! Should cfa.offset be changed?
!
! Rule 5:
! (set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg))
! constraints: <reg1> != fp
! <reg1> != sp
! effects: cfa_store.reg = <reg1>
! cfa_store.offset = cfa.offset - cfa_temp.offset
!
! Rule 6:
! (set <reg> <const_int>)
! effects: cfa_temp.reg = <reg>
! cfa_temp.offset = <const_int>
!
! Rule 7:
! (set <reg1>:cfa_temp.reg (ior <reg2>:cfa_temp.reg <const_int>))
! effects: cfa_temp.reg = <reg1>
! cfa_temp.offset |= <const_int>
!
! Rule 8:
! (set <reg> (high <exp>))
! effects: none
!
! Rule 9:
! (set <reg> (lo_sum <exp> <const_int>))
! effects: cfa_temp.reg = <reg>
! cfa_temp.offset = <const_int>
!
! Rule 10:
! (set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>)
! effects: cfa_store.offset -= <const_int>
! cfa.offset = cfa_store.offset if cfa.reg == sp
! offset = -cfa_store.offset
! cfa.reg = sp
! cfa.base_offset = offset
!
! Rule 11:
! (set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) <reg>)
! effects: cfa_store.offset += -/+ mode_size(mem)
! cfa.offset = cfa_store.offset if cfa.reg == sp
! offset = -cfa_store.offset
! cfa.reg = sp
! cfa.base_offset = offset
!
! Rule 12:
! (set (mem ({minus,plus} <reg1>:cfa_store <const_int>)) <reg2>)
! effects: cfa_store.offset += -/+ <const_int>
! offset = -cfa_store.offset
! cfa.reg = <reg1
! cfa.base_offset = offset
!
! Rule 13:
! (set (mem <reg1>:cfa_store) <reg2>)
! effects: offset = -cfa_store.offset
! cfa.reg = <reg1>
! cfa.base_offset = offset */
static void
dwarf2out_frame_debug_expr (expr, label)
rtx expr;
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1257,1263 ****
/* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of
the PARALLEL independently. 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. */
--- 1406,1412 ----
/* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of
the PARALLEL independently. The first element is always processed if
! it is a SET. This is for backward compatibility. Other elements
are processed only if they are SETs and the RTX_FRAME_RELATED_P
flag is set in them. */
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1287,1292 ****
--- 1436,1442 ----
switch (GET_CODE (dest))
{
case REG:
+ /* Rule 1 */
/* Update the CFA rule wrt SP or FP. Make sure src is
relative to the current CFA register. */
switch (GET_CODE (src))
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1310,1315 ****
--- 1460,1466 ----
case MINUS:
if (dest == stack_pointer_rtx)
{
+ /* Rule 2 */
/* Adjusting SP. */
switch (GET_CODE (XEXP (src, 1)))
{
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1317,1325 ****
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 ();
--- 1468,1476 ----
offset = INTVAL (XEXP (src, 1));
break;
case REG:
! if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp.reg)
abort ();
! offset = cfa_temp.offset;
break;
default:
abort ();
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1344,1349 ****
--- 1495,1501 ----
}
else if (dest == hard_frame_pointer_rtx)
{
+ /* Rule 3 */
/* Either setting the FP from an offset of the SP,
or adjusting the FP */
if (! frame_pointer_needed)
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1367,1405 ****
if (GET_CODE (src) != PLUS)
abort ();
if (GET_CODE (XEXP (src, 0)) == REG
&& REGNO (XEXP (src, 0)) == cfa.reg
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
/* Setting the FP (or a scratch that will be copied into the FP
later on) from SP + const. */
cfa.reg = REGNO (dest);
else
{
if (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:
--- 1519,1562 ----
if (GET_CODE (src) != PLUS)
abort ();
+ /* Rule 4 */
if (GET_CODE (XEXP (src, 0)) == REG
&& REGNO (XEXP (src, 0)) == cfa.reg
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
/* Setting the FP (or a scratch that will be copied into the FP
later on) from SP + const. */
cfa.reg = REGNO (dest);
+ /* Rule 5 */
else
{
if (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.offset;
}
}
break;
+ /* Rule 6 */
case CONST_INT:
! cfa_temp.reg = REGNO (dest);
! cfa_temp.offset = INTVAL (src);
break;
+ /* Rule 7 */
case IOR:
if (GET_CODE (XEXP (src, 0)) != REG
! || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg
|| GET_CODE (XEXP (src, 1)) != CONST_INT)
abort ();
! if ((unsigned) REGNO (dest) != cfa_temp.reg)
! cfa_temp.reg = REGNO (dest);
! cfa_temp.offset |= INTVAL (XEXP (src, 1));
break;
default:
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1410,1421 ****
/* Skip over HIGH, assuming it will be followed by a LO_SUM, which
will fill in all of the bits. */
case HIGH:
break;
case LO_SUM:
! cfa_temp_reg = REGNO (dest);
! cfa_temp_value = INTVAL (XEXP (src, 1));
break;
case MEM:
--- 1567,1582 ----
/* Skip over HIGH, assuming it will be followed by a LO_SUM, which
will fill in all of the bits. */
+ /* Rule 8 */
case HIGH:
break;
+ /* Rule 9 */
case LO_SUM:
! if (GET_CODE (XEXP (src, 1)) != CONST_INT)
! abort ();
! cfa_temp.reg = REGNO (dest);
! cfa_temp.offset = INTVAL (XEXP (src, 1));
break;
case MEM:
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1426,1431 ****
--- 1587,1593 ----
CFA register. */
switch (GET_CODE (XEXP (dest, 0)))
{
+ /* Rule 10 */
/* With a push. */
case PRE_MODIFY:
/* We can't handle variable size modifications. */
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1442,1447 ****
--- 1604,1610 ----
offset = -cfa_store.offset;
break;
+ /* Rule 11 */
case PRE_INC:
case PRE_DEC:
offset = GET_MODE_SIZE (GET_MODE (dest));
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1458,1466 ****
--- 1621,1632 ----
offset = -cfa_store.offset;
break;
+ /* Rule 12 */
/* With an offset. */
case PLUS:
case MINUS:
+ if (GET_CODE (XEXP (XEXP (dest, 0), 1)) != CONST_INT)
+ abort ();
offset = INTVAL (XEXP (XEXP (dest, 0), 1));
if (GET_CODE (XEXP (dest, 0)) == MINUS)
offset = -offset;
*************** dwarf2out_frame_debug_expr (expr, label)
*** 1470,1475 ****
--- 1636,1642 ----
offset -= cfa_store.offset;
break;
+ /* Rule 13 */
/* Without an offset. */
case REG:
if (cfa_store.reg != (unsigned) REGNO (XEXP (dest, 0)))
*************** dwarf2out_frame_debug (insn)
*** 1543,1550 ****
abort ();
cfa.reg = STACK_POINTER_REGNUM;
cfa_store = cfa;
! cfa_temp_reg = -1;
! cfa_temp_value = 0;
return;
}
--- 1710,1717 ----
abort ();
cfa.reg = STACK_POINTER_REGNUM;
cfa_store = cfa;
! cfa_temp.reg = -1;
! cfa_temp.offset = 0;
return;
}
*************** output_aranges ()
*** 6356,6362 ****
/* Pad using a 2 bytes word so that padding is correct
for any pointer size. */
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, 0);
! for (i = 2; i < DWARF_ARANGES_PAD_SIZE; i += 2)
fprintf (asm_out_file, ",0");
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Pad to %d byte boundary",
--- 6523,6529 ----
/* Pad using a 2 bytes word so that padding is correct
for any pointer size. */
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, 0);
! for (i = 2; i < (unsigned) DWARF_ARANGES_PAD_SIZE; i += 2)
fprintf (asm_out_file, ",0");
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Pad to %d byte boundary",
Index: rtl.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.texi,v
retrieving revision 1.34
diff -c -p -r1.34 rtl.texi
*** rtl.texi 2001/01/22 16:58:08 1.34
--- rtl.texi 2001/02/02 05:51:06
*************** Stored in the @code{integrated} field an
*** 458,467 ****
@findex RTX_FRAME_RELATED_P
@item RTX_FRAME_RELATED_P (@var{x})
! Nonzero in an insn or expression which is part of a function
! prologue and sets the stack pointer, sets the frame pointer, or saves a
! register. This flag is required for exception handling support
! on targets with RTL prologues.
@findex SYMBOL_REF_USED
@cindex @code{used}, in @code{symbol_ref}
--- 458,486 ----
@findex RTX_FRAME_RELATED_P
@item RTX_FRAME_RELATED_P (@var{x})
! Nonzero in an insn or expression which is part of a function prologue
! and sets the stack pointer, sets the frame pointer, or saves a register.
! This flag should also be set on an instruction that sets up a temporary
! register to use in place of the frame pointer.
!
! In particular, on RISC targets where there are limits on the sizes of
! immediate constants, it is sometimes impossible to reach the register
! save area directly from the stack pointer. In that case, a temporary
! register is used that is near enough to the register save area, and the
! Canonical Frame Address, i.e., DWARF2's logical frame pointer, register
! must (temporarily) be changed to be this temporary register. So, the
! instruction that sets this temporary register must be marked as
! @code{RTX_FRAME_RELATED_P}.
!
! If the marked instruction is overly complex (defined in terms of what
! @code{dwarf2out_frame_debug_expr} can handle), you will also have to
! create a @code{REG_FRAME_RELATED_EXPR} note and attach it to the
! instruction. This note should contain a simple expression of the
! computation performed by this instruction, i.e., one that
! @code{dwarf2out_frame_debug_expr} can handle.
!
! This flag is required for exception handling support on targets with RTL
! prologues.
@findex SYMBOL_REF_USED
@cindex @code{used}, in @code{symbol_ref}