From a43f3fadaa3faba2c0fded395f9be0ba9f59c38e Mon Sep 17 00:00:00 2001 From: Astrum-polaris Date: Tue, 13 Apr 2021 11:00:27 +0800 Subject: [PATCH] gcc: Revert 357c435 and 49a714e This commit reverts https://github.com/gcc-mirror/gcc/commit/357c435 and https://github.com/gcc-mirror/gcc/commit/49a714e Reference: https://github.com/msys2/MINGW-packages/issues/8094 --- mingw-w64-gcc/0201-backport-49a714e.patch | 225 ++++++++++++++++++++++ mingw-w64-gcc/0202-backport-2939b35.patch | 40 ++++ mingw-w64-gcc/PKGBUILD | 18 +- 3 files changed, 281 insertions(+), 2 deletions(-) create mode 100644 mingw-w64-gcc/0201-backport-49a714e.patch create mode 100644 mingw-w64-gcc/0202-backport-2939b35.patch diff --git a/mingw-w64-gcc/0201-backport-49a714e.patch b/mingw-w64-gcc/0201-backport-49a714e.patch new file mode 100644 index 0000000000..9eb57be928 --- /dev/null +++ b/mingw-w64-gcc/0201-backport-49a714e.patch @@ -0,0 +1,225 @@ +From 49a714e59194a7c549aa6657676a1b4be4520650 Mon Sep 17 00:00:00 2001 +From: Eric Botcazou +Date: Mon, 1 Mar 2021 07:53:05 +0100 +Subject: [PATCH] Fix wrong result for 1.0/3.0 at -O2 -fno-omit-frame-pointer + -frounding-math + +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 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 discrepancy between cases +where the number of saved general regs is even and cases where it is odd. + +gcc/ + PR target/99234 + * 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. +gcc/testsuite/ + * g++.dg/eh/seh-xmm-unwind.C: New test. +--- + gcc/config/i386/i386.c | 35 +++++--------- + gcc/config/i386/winnt.c | 17 +++++-- + gcc/testsuite/g++.dg/eh/seh-xmm-unwind.C | 61 ++++++++++++++++++++++++ + 3 files changed, 88 insertions(+), 25 deletions(-) + create mode 100644 gcc/testsuite/g++.dg/eh/seh-xmm-unwind.C + +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c +index aedf7873ce5..7b803661366 100644 +--- a/gcc/config/i386/i386.c ++++ b/gcc/config/i386/i386.c +@@ -6190,11 +6190,6 @@ ix86_compute_frame_layout (void) + offset += frame->nregs * UNITS_PER_WORD; + frame->reg_save_offset = offset; + +- /* On SEH target, registers are pushed just before the frame pointer +- location. */ +- if (TARGET_SEH) +- frame->hard_frame_pointer_offset = offset; +- + /* Calculate the size of the va-arg area (not including padding, if any). */ + frame->va_arg_size = ix86_varargs_gpr_size + ix86_varargs_fpr_size; + +@@ -6357,14 +6352,21 @@ ix86_compute_frame_layout (void) + the unwind data structure. */ + if (TARGET_SEH) + { +- HOST_WIDE_INT diff; ++ /* Force the frame pointer to point at or below the lowest register save ++ area, see the SEH code in config/i386/winnt.c for the rationale. */ ++ frame->hard_frame_pointer_offset = frame->sse_reg_save_offset; + +- /* If we can leave the frame pointer where it is, do so. Also, returns ++ /* If we can leave the frame pointer where it is, do so. Also, return + the establisher frame for __builtin_frame_address (0). */ +- diff = frame->stack_pointer_offset - frame->hard_frame_pointer_offset; +- if (diff <= SEH_MAX_FRAME_SIZE +- && (diff > 240 || (diff & 15) != 0) +- && !crtl->accesses_prior_frames) ++ const HOST_WIDE_INT diff ++ = frame->stack_pointer_offset - frame->hard_frame_pointer_offset; ++ if (diff <= 255) ++ { ++ /* The resulting diff will be a multiple of 16 lower than 255, ++ i.e. at most 240 as required by the unwind data structure. */ ++ frame->hard_frame_pointer_offset += (diff & 15); ++ } ++ else if (diff <= SEH_MAX_FRAME_SIZE && !crtl->accesses_prior_frames) + { + /* Ideally we'd determine what portion of the local stack frame + (within the constraint of the lowest 240) is most heavily used. +@@ -8170,17 +8172,6 @@ ix86_expand_prologue (void) + 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 target. */ +- 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); +diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c +index eae3ee2ef9a..201f69e74c4 100644 +--- a/gcc/config/i386/winnt.c ++++ b/gcc/config/i386/winnt.c +@@ -830,9 +830,20 @@ i386_pe_asm_lto_end (void) + + struct seh_frame_state + { +- /* 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. */ ++ /* 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. ++ ++ We do not distinguish these two cases, i.e. we consider that the offsets ++ are always relative to the "current" stack pointer. This means that we ++ need to perform the fixed stack allocation before establishing the frame ++ pointer whenever there are registers to be saved, and this is guaranteed ++ by the prologue provided that we force the frame pointer to point at or ++ below the lowest used register save area, see ix86_compute_frame_layout. ++ ++ This tracks the current stack pointer offset from the CFA. */ + HOST_WIDE_INT sp_offset; + + /* The CFA is located at CFA_REG + CFA_OFFSET. */ +diff --git a/gcc/testsuite/g++.dg/eh/seh-xmm-unwind.C b/gcc/testsuite/g++.dg/eh/seh-xmm-unwind.C +new file mode 100644 +index 00000000000..07fd805b3fd +--- /dev/null ++++ b/gcc/testsuite/g++.dg/eh/seh-xmm-unwind.C +@@ -0,0 +1,61 @@ ++/* PR target/99234 */ ++/* Test SEH unwinding of XMM register saves. */ ++ ++/* { dg-do run { target { x86_64-*-mingw32 && lp64 } } } */ ++ ++extern "C" void abort (void); ++extern "C" void exit (int); ++ ++void ++foo (void) ++{ ++ register __int128 xmm6 asm("xmm6") = 0; ++ register __int128 xmm7 asm("xmm7") = 0; ++ register __int128 xmm8 asm("xmm8") = 0; ++ register __int128 xmm9 asm("xmm9") = 0; ++ register __int128 xmm10 asm("xmm10") = 0; ++ register __int128 xmm11 asm("xmm11") = 0; ++ register __int128 xmm12 asm("xmm12") = 0; ++ register __int128 xmm13 asm("xmm13") = 0; ++ register __int128 xmm14 asm("xmm14") = 0; ++ register __int128 xmm15 asm("xmm15") = 0; ++ ++ __asm__ __volatile__ ("" : "+x" (xmm6), "+x" (xmm7), "+x" (xmm8), "+x" (xmm9), ++ "+x" (xmm10), "+x" (xmm11), "+x" (xmm12), "+x" (xmm13), ++ "+x" (xmm14), "+x" (xmm15)); ++ ++ throw 1; ++} ++ ++int ++main (void) ++{ ++ register __int128 xmm6 asm("xmm6") = 6; ++ register __int128 xmm7 asm("xmm7") = 7; ++ register __int128 xmm8 asm("xmm8") = 8; ++ register __int128 xmm9 asm("xmm9") = 9; ++ register __int128 xmm10 asm("xmm10") = 10; ++ register __int128 xmm11 asm("xmm11") = 11; ++ register __int128 xmm12 asm("xmm12") = 12; ++ register __int128 xmm13 asm("xmm13") = 13; ++ register __int128 xmm14 asm("xmm14") = 14; ++ register __int128 xmm15 asm("xmm15") = 15; ++ ++ __asm__ __volatile__ ("" : "+x" (xmm6), "+x" (xmm7), "+x" (xmm8), "+x" (xmm9), ++ "+x" (xmm10), "+x" (xmm11), "+x" (xmm12), "+x" (xmm13), ++ "+x" (xmm14), "+x" (xmm15)); ++ ++ try { ++ foo (); ++ } catch (...) { ++ __asm__ __volatile__ ("" : "+x" (xmm6), "+x" (xmm7), "+x" (xmm8), "+x" (xmm9), ++ "+x" (xmm10), "+x" (xmm11), "+x" (xmm12), "+x" (xmm13), ++ "+x" (xmm14), "+x" (xmm15)); ++ ++ if (xmm6 != 6 || xmm7 != 7 || xmm8 != 8 || xmm9 != 9 || xmm10 != 10 ++ || xmm11 != 11 || xmm12 != 12 || xmm13 != 13 || xmm14 != 14 || xmm15 != 15) ++ abort (); ++ } ++ ++ exit (0); ++} +-- +2.27.0 + diff --git a/mingw-w64-gcc/0202-backport-2939b35.patch b/mingw-w64-gcc/0202-backport-2939b35.patch new file mode 100644 index 0000000000..d3f57a30cb --- /dev/null +++ b/mingw-w64-gcc/0202-backport-2939b35.patch @@ -0,0 +1,40 @@ +From 2939b358936bb824330888def98ad848dea41483 Mon Sep 17 00:00:00 2001 +From: Eric Botcazou +Date: Wed, 3 Mar 2021 12:25:03 +0100 +Subject: [PATCH] Fix ICE with pathologically large frames + +gcc/ + PR target/99234 + * config/i386/i386.c (ix86_compute_frame_layout): For a SEH target, + point back the hard frame pointer to its default location when the + frame is larger than SEH_MAX_FRAME_SIZE. +--- + gcc/config/i386/i386.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c +index 7b803661366..e23f92b58cc 100644 +--- a/gcc/config/i386/i386.c ++++ b/gcc/config/i386/i386.c +@@ -6357,7 +6357,8 @@ ix86_compute_frame_layout (void) + frame->hard_frame_pointer_offset = frame->sse_reg_save_offset; + + /* If we can leave the frame pointer where it is, do so. Also, return +- the establisher frame for __builtin_frame_address (0). */ ++ the establisher frame for __builtin_frame_address (0) or else if the ++ frame overflows the SEH maximum frame size. */ + const HOST_WIDE_INT diff + = frame->stack_pointer_offset - frame->hard_frame_pointer_offset; + if (diff <= 255) +@@ -6375,6 +6376,8 @@ ix86_compute_frame_layout (void) + frame that is addressable with 8-bit offsets. */ + frame->hard_frame_pointer_offset = frame->stack_pointer_offset - 128; + } ++ else ++ frame->hard_frame_pointer_offset = frame->hfp_save_offset; + } + } + +-- +2.27.0 + diff --git a/mingw-w64-gcc/PKGBUILD b/mingw-w64-gcc/PKGBUILD index fbcea02d87..5ab8cc05f8 100644 --- a/mingw-w64-gcc/PKGBUILD +++ b/mingw-w64-gcc/PKGBUILD @@ -75,7 +75,9 @@ source=("https://ftp.gnu.org/gnu/gcc/${_realname}-${pkgver%%+*}/${_realname}-${p 0140-gcc-8.2.0-diagnostic-color.patch 0150-gcc-10.2.0-libgcc-ldflags.patch 0160-libbacktrace-seh.patch - 0200-ms_printf-improvements.patch) + 0200-ms_printf-improvements.patch + 0201-backport-49a714e.patch + 0202-backport-2939b35.patch) sha256sums=('64f404c1a650f27fc33da242e1f2df54952e3963a49e06e73f6940f3223ac344' 'SKIP' 'bce81824fc89e5e62cca350de4c17a27e27a18a1a1ad5ca3492aec1fc5af3234' @@ -99,7 +101,9 @@ sha256sums=('64f404c1a650f27fc33da242e1f2df54952e3963a49e06e73f6940f3223ac344' '5240a9e731b45c17a164066c7eb193c1fbee9fd8d9a2a5afa2edbcde9510da47' '7f0b4e45d933e18c9d8bd2afcd83e4f52e97e2e25dd41bfa0cba755c70e591c7' '88c1d65e763e631ad49f9a077ed631f4acac9ef4732e2818ccddaefc883b1811' - '146ac7aec004a949e42f7da6ff66351790e56094a85f6dbe28ea583b47c8125d') + '146ac7aec004a949e42f7da6ff66351790e56094a85f6dbe28ea583b47c8125d' + '6bcaf2846ceeafa87912b30ed3e573d75b35bbeafebdaf675e2318b9b0058fbb' + '319b1ffe9dbede0578ffa4fd78fe803bf40ed1e0bc52251fdaaadd869f0dbf2a') validpgpkeys=(F3691687D867B81B51CE07D9BBE43771487328A9 # bpiotrowski@archlinux.org 86CFFCA918CF3AF47147588051E8B148A9999C34 # evangelos@foutrelis.com 13975A70E63C361C73AE69EF6EEB81F8981C74C7 # richard.guenther@gmail.com @@ -168,6 +172,16 @@ prepare() { apply_patch_with_msg \ 0200-ms_printf-improvements.patch + # Fix ICE with pathologically large frames, a fix for 0201 + # Does not fix the crash for Webots introduced by 0201 below + # https://github.com/gcc-mirror/gcc/commit/357c435 + patch -R -p1 -i "${srcdir}/0202-backport-2939b35.patch" + + # Apparently it had some adverse impacts on setjmp and crash Webots at start-up + # https://github.com/msys2/MINGW-packages/issues/8094 + # https://github.com/gcc-mirror/gcc/commit/49a714e + patch -R -p1 -i "${srcdir}/0201-backport-49a714e.patch" + # do not expect ${prefix}/mingw symlink - this should be superceded by # 0005-Windows-Don-t-ignore-native-system-header-dir.patch .. but isn't! sed -i 's/${prefix}\/mingw\//${prefix}\//g' configure