On Jun 21, 2012, at 8:19 PM, Richard Henderson wrote:

> On 2012-06-21 00:48, Tristan Gingold wrote:
>> @@ -9142,9 +9152,12 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
>>     {
>>       HOST_WIDE_INT diff;
>> 
>> -      /* If we can leave the frame pointer where it is, do so.  */
>> +      /* If we can leave the frame pointer where it is, do so.  Also, 
>> returns
>> +     the establisher frame for __builtin_frame_address (0).  */
>>       diff = frame->stack_pointer_offset - frame->hard_frame_pointer_offset;
>> -      if (diff > 240 || (diff & 15) != 0)
>> +      if (diff <= SEH_MAX_FRAME_SIZE
>> +      && (diff > 240 || (diff & 15) != 0)
>> +      && !crtl->accesses_prior_frames)
>>      {
> 
> 
> Can't this result in diff > 240 for access_prior_frames?
> And is thus non-encodable in the unwind info?

This potential issue can only happen when the frame pointer is used.  However, 
just before in ix86_compute_layout, I added:

  /* On SEH target, registers are pushed just before the frame pointer
     location.  */
  if (TARGET_SEH)
    frame->hard_frame_pointer_offset = offset;

And in ix86_expand_prologue:

  if (frame_pointer_needed && !m->fs.fp_valid)
    {
      /* Note: AT&T enter does NOT have reversed args.  Enter is probably
         slower on all targets.  Also sdb doesn't like it.  */
      insn = emit_insn (gen_push (hard_frame_pointer_rtx));
      RTX_FRAME_RELATED_P (insn) = 1;

      /* Push registers now, before setting the frame pointer on SEH.  */
      if (!int_registers_saved
          && TARGET_SEH
          && !frame.save_regs_using_mov)
        {
          ix86_emit_save_regs ();
          int_registers_saved = true;
          gcc_assert (m->fs.sp_offset == frame.reg_save_offset);
        }

      if (m->fs.sp_offset == frame.hard_frame_pointer_offset)
        {
          insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
          RTX_FRAME_RELATED_P (insn) = 1;


So when the frame pointer is set, it is equal to the stack pointer and 
therefore offset is always 0.
(This change is necessary because you cannot push registers once the frame is 
setup.  Otherwise during unwinding they are fetch using %rsp, which cannot be 
correctly computed in presence of alloca/dynamic frames)

FTR (and as you know), the Windows x64 prologue is quite rigid, and should 
follow this pattern:

1) pushes
2a) allocate frame
2b) set frame pointer
4) save regs/xmm

You can swap 2a and 2b.
GCC doesn't mix pushing and saving integer registers, but MS compiler does.

Tristan.



Reply via email to