This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Fix PR debug/24444: incorrect frame base in IA64 prologues


On Sun, Feb 05, 2006 at 06:16:16PM -0200, Alexandre Oliva wrote:
> That said, if anyone feels we should back out the change, here's one
> that will bring us back to the SP+16 definition of CFA that we used
> before, and adjust the value used to set the CFA location at function
> entry points to match.  I haven't tested it at all, and I don't think
> it's the right way to go, but I thought I'd post right away, while
> this stuff is still hot in my personal cache :-)

Index: gcc/config/ia64/ia64.h
===================================================================
--- gcc/config/ia64/ia64.h      (revision 110597)
+++ gcc/config/ia64/ia64.h      (working copy)
@@ -981,11 +981,9 @@
    On some machines it may depend on the data type of the function.  */
 #define FIRST_PARM_OFFSET(FUNDECL) 0

-/* The CFA is defined as the SP at the call site, so we have to take
-   into account that the first argument pointer is
-   STACK_POINTER_OFFSET bytes off the stack pointer.  */
-#define ARG_POINTER_CFA_OFFSET(FNDECL) \
-  (FIRST_PARM_OFFSET (FNDECL) - STACK_POINTER_OFFSET)
+/* The CFA is past the red zone, not at the entry-point stack
+   pointer.  */
+#define INCOMING_FRAME_SP_OFFSET STACK_POINTER_OFFSET

 /* A C expression whose value is RTL representing the value of the return
    address for the frame COUNT steps up from the current frame, after the

This chunk isn't working properly, the problem is that there
is a
#define INCOMING_FRAME_SP_OFFSET 0
a few lines below this, so we end up with redefinition warnings and
what's worse, incorrect debug info.  So I'm testing ATM folliwng version
(I don't expect to see any regressions in bootstrap/make check, because
even with the incorrect patch where INCOMING_FRAME_SP_OFFSET was 0
and ARG_POINTER_CFA_OFFSET the default definition it bootstrapped/regtested
fine (though guess gdb testsuite would show up a lot of failures).

I don't know what exact testcases you were eyeballing, so I made some of my
own (all compiled with -O2 -g -S -dA):
1)
void bar (int *);
int foo (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k)
{
  k += 24;
  bar (&k);
  return k + 4;
}
In this testcase, r12 is constant through the whole function and K is at
r12+32 (r12+0..r12+15 is the red zone, r12+16 is I, r12+24 is J).
Here, the debug info from rev 110593 (i.e. before your commit) is:
        data1   0x1     // DW_AT_frame_base
        data1   0x5c    // DW_OP_reg12
...
        .ascii "k\0"    // DW_AT_name
        data1   0x1     // DW_AT_decl_file
        data1   0x2     // DW_AT_decl_line
        data4.ua        0xd1    // DW_AT_type
        data1   0x2     // DW_AT_location
        data1   0x91    // DW_OP_fbreg
        .sleb128 32
After your commit it is identical and with the attached patch it is:
        data1   0x2     // DW_AT_frame_base
        data1   0x7c    // DW_OP_breg12
        .sleb128 16
...
        .ascii "k\0"    // DW_AT_name
        data1   0x1     // DW_AT_decl_file
        data1   0x2     // DW_AT_decl_line
        data4.ua        0xd2    // DW_AT_type
        data1   0x2     // DW_AT_location
        data1   0x91    // DW_OP_fbreg
        .sleb128 16
So, while frame_base definition changed by 16 bytes, the reg offset has
been properly adjusted.

2)
void bar (int *, char *);
int foo (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k)
{
  char buf[128];
  k += 24;
  bar (&k, buf);
  return k + 4;
}

Here, r12 changes in:
        .fframe 128
        adds r12 = -128, r12
[.L3:]
Before your commit gcc produced:
        data1   0x1     // DW_AT_frame_base
        data1   0x5c    // DW_OP_reg12
...
        .ascii "k\0"    // DW_AT_name
        data1   0x1     // DW_AT_decl_file
        data1   0x2     // DW_AT_decl_line
        data4.ua        0xe2    // DW_AT_type
        data1   0x3     // DW_AT_location
        data1   0x91    // DW_OP_fbreg
        .sleb128 160
which is correct only after the adds insn above, in the prologue it is
wrong.  After your commit, we have:
        data4.ua        @secrel(.LLST0) // DW_AT_frame_base
...
.LLST0:
        data8.ua        .LFB2-.Ltext0   // Location list begin address (*.LLST0)
        data8.ua        .L3-.Ltext0     // Location list end address (*.LLST0)
        data2.ua        0x1     // Location expression size
        data1   0x5c    // DW_OP_reg12
        data8.ua        .L3-.Ltext0     // Location list begin address (*.LLST0)
        data8.ua        .LFE2-.Ltext0   // Location list end address (*.LLST0)
        data2.ua        0x3     // Location expression size
        data1   0x7c    // DW_OP_breg12
        .sleb128 128
        data8.ua        0x0     // Location list terminator begin (*.LLST0)
        data8.ua        0x0     // Location list terminator end (*.LLST0)
...
        .ascii "k\0"    // DW_AT_name
        data1   0x1     // DW_AT_decl_file
        data1   0x2     // DW_AT_decl_line
        data4.ua        0xe2    // DW_AT_type
        data1   0x2     // DW_AT_location
        data1   0x91    // DW_OP_fbreg
        .sleb128 32
which is correct, k is at r12+32 in the prologue and afterwards at
r12+128+32.  With the patch below we have:
        data4.ua        @secrel(.LLST0) // DW_AT_frame_base
...
.LLST0:
        data8.ua        .LFB2-.Ltext0   // Location list begin address (*.LLST0)
        data8.ua        .L3-.Ltext0     // Location list end address (*.LLST0)
        data2.ua        0x2     // Location expression size
        data1   0x7c    // DW_OP_breg12
        .sleb128 16
        data8.ua        .L3-.Ltext0     // Location list begin address (*.LLST0)
        data8.ua        .LFE2-.Ltext0   // Location list end address (*.LLST0)
        data2.ua        0x3     // Location expression size
        data1   0x7c    // DW_OP_breg12
        .sleb128 144
        data8.ua        0x0     // Location list terminator begin (*.LLST0)
        data8.ua        0x0     // Location list terminator end (*.LLST0)
...
        .ascii "k\0"    // DW_AT_name
        data1   0x1     // DW_AT_decl_file
        data1   0x2     // DW_AT_decl_line
        data4.ua        0xe2    // DW_AT_type
        data1   0x2     // DW_AT_location
        data1   0x91    // DW_OP_fbreg
        .sleb128 16
which is also correct.

3)
void *foo (void)
{
  return __builtin_dwarf_cfa ();
}

This gives
        adds r8 = 16, r12
before your commit or with the patch below and:
        mov r8 = r12
after your commit, without this patch.

So, I believe this patch works correctly, though has the unfortunate
effect that it will make the debug info tiny bit larger
(as describing DW_AT_frame_base in prologue (or in function not changing r12)
can't use the 1 byte DW_OP_reg12, but needs to use 2 byte
DW_OP_breg12, 16).  But, if keeping the meaning of __builtin_dwarf_cfa ()
is important, so be it, this is the price to pay for it.

2006-02-06  Alexandre Oliva  <aoliva@redhat.com>

	PR debug/24444
	* config/ia64/unwind-ia64.c: Revert last change.
	* config/ia64/ia64.h (ARG_POINTER_CFA_OFFSET): Removed.
	(INCOMING_FRAME_SP_OFFSET): Define.

--- gcc/config/ia64/unwind-ia64.c	(revision 110597)
+++ gcc/config/ia64/unwind-ia64.c	(working copy)
@@ -2067,7 +2067,7 @@
 }
 
 /* Fill in CONTEXT for top-of-stack.  The only valid registers at this
-   level will be the return address and the CFA.  */
+   level will be the return address and the CFA.  Note that CFA = SP+16.  */
    
 #define uw_init_context(CONTEXT)					\
   do {									\
@@ -2083,7 +2083,7 @@
 {
   void *rp = __builtin_extract_return_addr (__builtin_return_address (0));
   /* Set psp to the caller's stack pointer.  */
-  void *psp = __builtin_dwarf_cfa ();
+  void *psp = __builtin_dwarf_cfa () - 16;
   _Unwind_FrameState fs;
   unsigned long rnat, tmp1, tmp2;
 
--- gcc/config/ia64/ia64.h	(revision 110597)
+++ gcc/config/ia64/ia64.h	(working copy)
@@ -981,12 +981,6 @@ enum reg_class
    On some machines it may depend on the data type of the function.  */
 #define FIRST_PARM_OFFSET(FUNDECL) 0
 
-/* The CFA is defined as the SP at the call site, so we have to take
-   into account that the first argument pointer is
-   STACK_POINTER_OFFSET bytes off the stack pointer.  */
-#define ARG_POINTER_CFA_OFFSET(FNDECL) \
-  (FIRST_PARM_OFFSET (FNDECL) - STACK_POINTER_OFFSET)
-
 /* A C expression whose value is RTL representing the value of the return
    address for the frame COUNT steps up from the current frame, after the
    prologue.  */
@@ -1022,7 +1016,9 @@ enum reg_class
    beginning of any function, before the prologue.  The top of the frame is
    defined to be the value of the stack pointer in the previous frame, just
    before the call instruction.  */
-#define INCOMING_FRAME_SP_OFFSET 0
+/* The CFA is past the red zone, not at the entry-point stack
+   pointer.  */
+#define INCOMING_FRAME_SP_OFFSET STACK_POINTER_OFFSET
 
 
 /* Register That Address the Stack Frame.  */


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]