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.