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

--- Comment #21 from Pierre-Marie de Rodat <derodat at adacore dot com> ---
(In reply to Eric Botcazou from comment #18)
> I think this is worth investigating though because it's conceptually
> much simpler than adding yet another indirection.  And we should
> concentrate on -O0 (and -Og), we don't really care about what happens
> with aggressive optimization.

Understood and agreed. Nevertheless...

> I guess the question is: can we arrange to have a constant offset
> between the frame base and the FRAME object, "constant" meaning valid
> for every function but possibly target-dependent?

I started to hack into cfgexpand.c and dwarf2out.c, but I realized this
is not possible in the general case. Consider the following example:

    #include <stdlib.h>

    int
    nestee (void)
    {
      int a __attribute__((aligned(64))) = 1234;

      void
      nested (int b)
      {
        a = b;
      }

      nested (2345);
      return a;
    }

    int
    call_nestee (int n)
    {
      int *v = alloca (sizeof (int) * n);
      v[0] = nestee ();
      return v[0];
    }

    int
    main (void)
    {
      call_nestee (1);
      call_nestee (8);
      return 0;
    }

With a GCC 5.0 built from fairly recent sources, I get the following CFA
information:

    00000090 000000000000002c 00000064 FDE cie=00000030
pc=00000000004004ac..00000000004004eb
      DW_CFA_advance_loc: 5 to 00000000004004b1
      DW_CFA_def_cfa: r10 (r10) ofs 0
      DW_CFA_advance_loc: 9 to 00000000004004ba
      DW_CFA_expression: r6 (rbp) (DW_OP_breg6 (rbp): 0)
      DW_CFA_advance_loc: 5 to 00000000004004bf
      DW_CFA_def_cfa_expression (DW_OP_breg6 (rbp): -8; DW_OP_deref)
      DW_CFA_advance_loc: 38 to 00000000004004e5

And now here is what I get under GDB:

    $ gdb -n -q -ex 'b nestee' ./dyn_frame
    Reading symbols from ./dyn_frame...done.
    Breakpoint 1 at 0x4004c3: file dyn_frame.c, line 6.
    (gdb) r
    [...]

    Breakpoint 1, nestee () at dyn_frame.c:6
    6         int a __attribute__((aligned(64))) = 1234;
    (gdb) p $pc
    $1 = (void (*)()) 0x4004c3 <nestee+23>
    (gdb) x/1xg $rbp - 8
    0x7fffffffdf28: 0x00007fffffffdf60
    (gdb) p/x (char *) 0x00007fffffffdf60 - (char *) &a
    $2 = 0xa0

... so for this frame, the CFA and the FRAME object are 0xa0 bytes from
each other. Now let's resume to see the next "nestee" frame:

    (gdb) c
    Continuing.

    Breakpoint 1, nestee () at dyn_frame.c:6
    6         int a __attribute__((aligned(64))) = 1234;
    (gdb) p $pc
    $3 = (void (*)()) 0x4004c3 <nestee+23>
    (gdb) x/1xg $rbp - 8
    0x7fffffffdf28: 0x00007fffffffdf50
    (gdb) p/x (char *) 0x00007fffffffdf50 - (char *) &a
    $4 = 0x90

The offset between the CFA and e FRAME object is now 0x90 bytes. So
because of alignment constraints, I think we cannot assume we can have a
constant offset (even function-dependent).

This offset is dynamic and the only way to compute it is to use the
frame's context: here, nestee's saved registers, which we don't have
access to in DWARF when computing the static link attribute.

Reply via email to