This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
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