This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: update dwarf2 asm unwind info [hppa64-*-* failures]
- From: Richard Henderson <rth at twiddle dot net>
- To: John David Anglin <dave at hiauly1 dot hia dot nrc dot ca>
- Cc: sje at cup dot hp dot com, gcc-patches at gcc dot gnu dot org, dave dot anglin at nrc-cnrc dot gc dot ca, binutils-patches at gcc dot gnu dot org
- Date: Sun, 24 Aug 2008 11:34:17 -0700
- Subject: Re: update dwarf2 asm unwind info [hppa64-*-* failures]
- References: <20080823201219.5B05B431A@hiauly1.hia.nrc.ca>
John David Anglin wrote:
As can be seen, gas is dividing DWARF2_CIE_DATA_ALIGNMENT when the
offset is negative. GCC is also dividing by the data alignment.
So, which is wrong?
Gcc is wrong. Here's a patch to avoid doing the division twice.
r~
--- dwarf2out.c (revision 139547)
+++ dwarf2out.c (local)
@@ -776,23 +776,16 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_loc
switch (cfi->dw_cfi_opc)
{
case DW_CFA_def_cfa_offset:
- loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset;
- break;
case DW_CFA_def_cfa_offset_sf:
- loc->offset
- = cfi->dw_cfi_oprnd1.dw_cfi_offset * DWARF_CIE_DATA_ALIGNMENT;
+ loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset;
break;
case DW_CFA_def_cfa_register:
loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
break;
case DW_CFA_def_cfa:
- loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
- loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset;
- break;
case DW_CFA_def_cfa_sf:
loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
- loc->offset
- = cfi->dw_cfi_oprnd2.dw_cfi_offset * DWARF_CIE_DATA_ALIGNMENT;
+ loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset;
break;
case DW_CFA_def_cfa_expression:
get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc);
@@ -891,20 +884,14 @@ def_cfa_1 (const char *label, dw_cfa_loc
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. */
+ the CFA register did not change but the offset did. The data
+ factoring for DW_CFA_def_cfa_offset_sf happens in output_cfi, or
+ in the assembler via the .cfi_def_cfa_offset directive. */
if (loc.offset < 0)
- {
- HOST_WIDE_INT f_offset = loc.offset / DWARF_CIE_DATA_ALIGNMENT;
- gcc_assert (f_offset * DWARF_CIE_DATA_ALIGNMENT == loc.offset);
-
- cfi->dw_cfi_opc = DW_CFA_def_cfa_offset_sf;
- cfi->dw_cfi_oprnd1.dw_cfi_offset = f_offset;
- }
+ cfi->dw_cfi_opc = DW_CFA_def_cfa_offset_sf;
else
- {
- cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
- cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset;
- }
+ cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
+ cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset;
}
#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */
@@ -924,22 +911,15 @@ def_cfa_1 (const char *label, dw_cfa_loc
{
/* Construct a "DW_CFA_def_cfa <register> <offset>" instruction,
indicating the CFA register has changed to <register> with
- the specified offset. */
+ the specified offset. The data factoring for DW_CFA_def_cfa_sf
+ happens in output_cfi, or in the assembler via the .cfi_def_cfa
+ directive. */
if (loc.offset < 0)
- {
- HOST_WIDE_INT f_offset = loc.offset / DWARF_CIE_DATA_ALIGNMENT;
- gcc_assert (f_offset * DWARF_CIE_DATA_ALIGNMENT == loc.offset);
-
- cfi->dw_cfi_opc = DW_CFA_def_cfa_sf;
- cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
- cfi->dw_cfi_oprnd2.dw_cfi_offset = f_offset;
- }
+ cfi->dw_cfi_opc = DW_CFA_def_cfa_sf;
else
- {
- 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;
- }
+ 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
{
@@ -2552,6 +2532,8 @@ static void
output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
{
unsigned long r;
+ HOST_WIDE_INT off;
+
if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
dw2_asm_output_data (1, (cfi->dw_cfi_opc
| (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)),
@@ -2622,12 +2604,20 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref f
break;
case DW_CFA_offset_extended_sf:
- case DW_CFA_def_cfa_sf:
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
dw2_asm_output_data_uleb128 (r, NULL);
dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
break;
+ case DW_CFA_def_cfa_sf:
+ r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
+ dw2_asm_output_data_uleb128 (r, NULL);
+
+ off = cfi->dw_cfi_oprnd2.dw_cfi_offset;
+ gcc_assert (off % DWARF_CIE_DATA_ALIGNMENT == 0);
+ dw2_asm_output_data_sleb128 (off / DWARF_CIE_DATA_ALIGNMENT, NULL);
+ break;
+
case DW_CFA_restore_extended:
case DW_CFA_undefined:
case DW_CFA_same_value:
@@ -2649,7 +2639,9 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref f
break;
case DW_CFA_def_cfa_offset_sf:
- dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
+ off = cfi->dw_cfi_oprnd1.dw_cfi_offset;
+ gcc_assert (off % DWARF_CIE_DATA_ALIGNMENT == 0);
+ dw2_asm_output_data_sleb128 (off / DWARF_CIE_DATA_ALIGNMENT, NULL);
break;
case DW_CFA_GNU_window_save: