https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106399

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|WAITING                     |NEW
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I can reproduce it, but it was actually wrong-debug before that case.

Consider:
void baz (void) {}
int foo(int a)
{
  int a2 (void)
  {
    a++;
    return a * a;
  }
  baz ();
  int x = a2 ();
  baz ();
  return x;
}

int main ()
{
  return foo (3) - 16;
}

As a is used by nested function, what we actually compile this into (at -O0)
is:
  _3 = __builtin_dwarf_cfa (0);
  FRAME.0.FRAME_BASE.PARENT = _3;
  FRAME.0.a = a_5(D);
  baz ();
  x_9 = a2 (); [static-chain: &FRAME.0]
  baz ();
  _11 = x_9;
  return _11;
Where FRAME.0 is an artificial structure that contains some pointer and the a
parameter.
For -O0, there are 2 copies of a in the foo function's stack.  One is that
holds 
the a_5(D) SSA_NAME, i.e. the value of the argument that was passed to the
function.  And then inside of the FRAME.0 artificial var there is another copy
of it.
Before Eric's change (i.e. GCC 8 and earlier), the former has been declared as
the location holding a in debug info, while after it it is the FRAME.0.a
member.
The former is incorrect, if you put a breakpoint say on the line with second
call to baz () when compiled by GCC 8 and print a, it will print 3, even when a
is actually 4 (a2 has incremented it).
The latter is correct, but it is initialized slightly later.  At -O0 we don't
do (expensive) variable tracking, so we just indicate a single memory location
for the parameter in debug info.  So, unless we there enable the var tracking
too,
we would need to arrange for the breakpoint on foo to be added not just after
the normal prologue, but also after initialization of the FRAME.0 variable.
If you in the debugger stepi a few times or just step, you'll see correct value
of a eventually.
E.g. with current trunk, the foo assembly starts with:
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $48, %rsp
        movl    %edi, -36(%rbp)
        leaq    16(%rbp), %rax
        movq    %rax, -24(%rbp)
        movl    -36(%rbp), %eax
        movl    %eax, -32(%rbp)
        call    baz
and breakpoint on foo is put by the debugger after the movl %edi, -36(%rbp)
instruction, so after the a parameter is stored from %edi register into the
first stack location.  FRAME.0 is at %rbp - 24, so the stores to it are only
completed right before call baz.

Reply via email to