On Jun 19, 2012, at 6:47 PM, Richard Henderson wrote:
> On 2012-06-18 05:22, Tristan Gingold wrote:
>> +/* Output assembly code to get the establisher frame (Windows x64 only).
>> + This corresponds to what will be computed by Windows from Frame Register
>> + and Frame Register Offset fields of the UNWIND_INFO structure. Since
>> + these values are computed very late (by ix86_expand_prologue), we cannot
>> + express this using only RTL. */
>> +
>> +const char *
>> +ix86_output_establisher_frame (rtx target)
>> +{
>> + if (!frame_pointer_needed)
>> + {
>> + /* Note that we have advertized an lea operation. */
>> + output_asm_insn ("lea{q}\t{0(%%rsp), %0|%0, 0[rsp]}", &target);
>> + }
>> + else
>> + {
>> + rtx xops[3];
>> + struct ix86_frame frame;
>> +
>> + /* Recompute the frame layout here. */
>> + ix86_compute_frame_layout (&frame);
>> +
>> + /* Closely follow how the frame pointer is set in
>> + ix86_expand_prologue. */
>> + xops[0] = target;
>> + xops[1] = hard_frame_pointer_rtx;
>> + if (frame.hard_frame_pointer_offset == frame.reg_save_offset)
>> + xops[2] = GEN_INT (0);
>> + else
>> + xops[2] = GEN_INT (-(frame.stack_pointer_offset
>> + - frame.hard_frame_pointer_offset));
>> + output_asm_insn ("lea{q}\t{%a2(%1), %0|%0, %a2[%1]}", xops);
>
> This is what register elimination is for; the value substitution happens
> during reload.
>
> Now, one *could* add a new pseudo-hard-register for this (we support as
> many register eliminations as needed), but before we do that we need to
> decide if we can adjust the soft frame pointer to be the value required.
> If so, you can then rely on the existing __builtin_frame_address. Which
> is a very attractive sounding solution. I'm 99% moving the sfp will work.
One possibly naive question: the current code to expand __builtin_frame_address
is:
/* For a zero count with __builtin_return_address, we don't care what
frame address we return, because target-specific definitions will
override us. Therefore frame pointer elimination is OK, and using
the soft frame pointer is OK.
For a nonzero count, or a zero count with __builtin_frame_address,
we require a stable offset from the current frame pointer to the
previous one, so we must use the hard frame pointer, and
we must disable frame pointer elimination. */
if (count == 0 && fndecl_code == BUILT_IN_RETURN_ADDRESS)
tem = frame_pointer_rtx;
else
{
tem = hard_frame_pointer_rtx;
/* Tell reload not to eliminate the frame pointer. */
crtl->accesses_prior_frames = 1;
}
So whatever we do with the sfp, the builtin will always returns %rbp - which is
not what we expect.
This however opens two tracks:
1) Implement the __builtin_establisher_frame with frame_pointer_rtx
2) If accesses_prior_frames is set, makes %rbp be the establisher frame.
I will pursue the later.
Tristan.