On Fri, Feb 26, 2021 at 5:14 PM Eric Botcazou <botca...@adacore.com> wrote: > > Hi, > > this wrong-code PR for the C++ compiler on x86-64/Windows is a regression > in GCC 9 and later, but the underlying issue has probably been there since > SEH was implemented and is exposed by this comment in config/i386/winnt.c: > > /* SEH records saves relative to the "current" stack pointer, whether > or not there's a frame pointer in place. This tracks the current > stack pointer offset from the CFA. */ > HOST_WIDE_INT sp_offset; > > That's not what the (current) Microsoft documentation says; instead it says: > > /* SEH records offsets relative to the lowest address of the fixed stack > allocation. If there is no frame pointer, these offsets are from the > stack pointer; if there is a frame pointer, these offsets are from the > value of the stack pointer when the frame pointer was established, i.e. > the frame pointer minus the offset in the .seh_setframe directive. > > That's why the implementation is correct only under the condition that the > frame pointer be established *after* the fixed stack allocation; as a matter > of fact, that's clearly the model underpinning SEH, but is the opposite of > what is done e.g. on Linux. > > However the issue is mostly papered over in practice because: > > 1. SEH forces use_fast_prologue_epilogue to false, which in turns forces > save_regs_using_mov to false, so the general regs are always pushed when they > need to be saved, which eliminates the offset computation for them. > > 2. As soon as a frame is larger than 240 bytes, the frame pointer is fixed > arbitrarily to 128 bytes above the stack pointer, which of course requires > that it be established after the fixed stack allocation. > > So you need a very small frame clobbering one of the call-saved XMM registers > in order to generate wrong SEH unwind info. > > The attached fix makes sure that the frame pointer is always established after > the fixed stack allocation by pointing it at or below the lowest used register > save area, i.e. the SSE save area, and removing the special early saves in the > prologue; the end result is a uniform prologue sequence for SEH whatever the > frame size. And it avoids a weird discrepancy between cases where the number > of saved general regs is even and cases where it is odd. > > Tested on x86_64-w64-mingw32, OK for mainline, 10 and 9 branches? > > > 2021-02-26 Eric Botcazou <ebotca...@adacore.com> > > PR target/99264 > * config/i386/i386.c (ix86_compute_frame_layout): For a SEH target, > point the hard frame pointer to the SSE register save area instead > of the general register save area. Perform only minimal adjustment > for small frames if it is initially not correctly aligned. > (ix86_expand_prologue): Remove early saves for a SEH target. > * config/i386/winnt.c (struct seh_frame_state): Document constraint. > > > 2021-02-26 Eric Botcazou <ebotca...@adacore.com> > > * g++.dg/eh/seh-xmm-unwind.C: New test.
LGTM. Thanks, Uros. > -- > Eric Botcazou