diff --git a/mingw-w64-gcc/0200-backport-7fc0f78.patch b/mingw-w64-gcc/0200-backport-7fc0f78.patch new file mode 100644 index 0000000000000..469e2dc42dd26 --- /dev/null +++ b/mingw-w64-gcc/0200-backport-7fc0f78.patch @@ -0,0 +1,110 @@ +From 5883d709d2c63a534b959583cb9ef15a2785de9a Mon Sep 17 00:00:00 2001 +From: Liu Hao +Date: Thu, 8 Oct 2020 10:26:13 +0800 +Subject: [PATCH] libsupc++: Make the destructor parameter to + `__cxa_thread_atexit()` use the `__thiscall` calling convention for + i686-w64-mingw32 + +The mingw-w64 implementations of `__cxa_thread_atexit()` and `__cxa_atexit()` have been +using `__thiscall` since two years ago. Using the default calling convention (which is +`__cdecl`) causes crashes as explained in PR83562. + +Calling conventions have no effect on x86_64-w64-mingw32. + +Reference: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83562 +Reference: https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/crt/cxa_thread_atexit.c +Reference: https://sourceforge.net/p/mingw-w64/mingw-w64/ci/f3e0fbb40cbc9f8821db8bd8a0c4dae8ff671e9f/ +Reference: https://github.com/msys2/MINGW-packages/issues/7071 +Signed-off-by: Liu Hao + + 2020-10-08 Liu Hao + + libstdc++-v3: + * libsupc++/cxxabi.h: (__cxa_atexit): mark with _GLIBCXX_CDTOR_CALLABI + (__cxa_thread_atexit): ditto + * libsupc++/atexit_thread.cc: (__cxa_atexit): mark with + _GLIBCXX_CDTOR_CALLABI + (__cxa_thread_atexit): ditto + (elt): ditto +--- + libstdc++-v3/libsupc++/atexit_thread.cc | 14 ++++++++++---- + libstdc++-v3/libsupc++/cxxabi.h | 8 ++++++++ + 2 files changed, 18 insertions(+), 4 deletions(-) + +diff --git a/libstdc++-v3/libsupc++/atexit_thread.cc b/libstdc++-v3/libsupc++/atexit_thread.cc +index e97644f8cd4..4f7f982ac6b 100644 +--- a/libstdc++-v3/libsupc++/atexit_thread.cc ++++ b/libstdc++-v3/libsupc++/atexit_thread.cc +@@ -30,16 +30,21 @@ + #include + #endif + ++// Simplify it a little for this file. ++#ifndef _GLIBCXX_CDTOR_CALLABI ++# define _GLIBCXX_CDTOR_CALLABI ++#endif ++ + #if _GLIBCXX_HAVE___CXA_THREAD_ATEXIT + + // Libc provides __cxa_thread_atexit definition. + + #elif _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL + +-extern "C" int __cxa_thread_atexit_impl (void (*func) (void *), ++extern "C" int __cxa_thread_atexit_impl (void (_GLIBCXX_CDTOR_CALLABI *func) (void *), + void *arg, void *d); + extern "C" int +-__cxxabiv1::__cxa_thread_atexit (void (*dtor)(void *), ++__cxxabiv1::__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *), + void *obj, void *dso_handle) + _GLIBCXX_NOTHROW + { +@@ -52,7 +57,7 @@ namespace { + // One element in a singly-linked stack of cleanups. + struct elt + { +- void (*destructor)(void *); ++ void (_GLIBCXX_CDTOR_CALLABI *destructor)(void *); + void *object; + elt *next; + #ifdef _GLIBCXX_THREAD_ATEXIT_WIN32 +@@ -116,7 +121,8 @@ namespace { + } + + extern "C" int +-__cxxabiv1::__cxa_thread_atexit (void (*dtor)(void *), void *obj, void */*dso_handle*/) ++__cxxabiv1::__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *), ++ void *obj, void */*dso_handle*/) + _GLIBCXX_NOTHROW + { + // Do this initialization once. +diff --git a/libstdc++-v3/libsupc++/cxxabi.h b/libstdc++-v3/libsupc++/cxxabi.h +index 50298205daa..e6244c7f5ac 100644 +--- a/libstdc++-v3/libsupc++/cxxabi.h ++++ b/libstdc++-v3/libsupc++/cxxabi.h +@@ -125,14 +125,22 @@ namespace __cxxabiv1 + + // DSO destruction. + int ++#ifdef _GLIBCXX_CDTOR_CALLABI ++ __cxa_atexit(void (_GLIBCXX_CDTOR_CALLABI *)(void*), void*, void*) _GLIBCXX_NOTHROW; ++#else + __cxa_atexit(void (*)(void*), void*, void*) _GLIBCXX_NOTHROW; ++#endif + + int + __cxa_finalize(void*); + + // TLS destruction. + int ++#ifdef _GLIBCXX_CDTOR_CALLABI ++ __cxa_thread_atexit(void (_GLIBCXX_CDTOR_CALLABI *)(void*), void*, void *) _GLIBCXX_NOTHROW; ++#else + __cxa_thread_atexit(void (*)(void*), void*, void *) _GLIBCXX_NOTHROW; ++#endif + + // Pure virtual functions. + void +-- +2.30.1 + diff --git a/mingw-w64-gcc/0201-backport-49a714e.patch b/mingw-w64-gcc/0201-backport-49a714e.patch new file mode 100644 index 0000000000000..9eb57be9280f7 --- /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/PKGBUILD b/mingw-w64-gcc/PKGBUILD index 77f998733eef3..d03c937d79b64 100644 --- a/mingw-w64-gcc/PKGBUILD +++ b/mingw-w64-gcc/PKGBUILD @@ -24,7 +24,7 @@ pkgver=10.2.0 #_majorver=${pkgver:0:1} #_sourcedir=${_realname}-${_majorver}-${_snapshot} _sourcedir=${_realname}-${pkgver} -pkgrel=6 +pkgrel=7 pkgdesc="GCC for the MinGW-w64" arch=('any') url="https://gcc.gnu.org" @@ -70,7 +70,9 @@ source=("https://ftp.gnu.org/gnu/gcc/${_realname}-${pkgver%%+*}/${_realname}-${p 0130-libstdc++-in-out.patch 0140-gcc-8.2.0-diagnostic-color.patch 0150-gcc-10.2.0-libgcc-ldflags.patch - 0160-libbacktrace-seh.patch) + 0160-libbacktrace-seh.patch + 0200-backport-7fc0f78.patch + 0201-backport-49a714e.patch) sha256sums=('b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c' 'SKIP' 'bce81824fc89e5e62cca350de4c17a27e27a18a1a1ad5ca3492aec1fc5af3234' @@ -94,7 +96,9 @@ sha256sums=('b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c' '055289699c4222ef0b8125abdc8c9ceeff0712876c86e6d552a056fbacc14284' '5240a9e731b45c17a164066c7eb193c1fbee9fd8d9a2a5afa2edbcde9510da47' '7f0b4e45d933e18c9d8bd2afcd83e4f52e97e2e25dd41bfa0cba755c70e591c7' - '88c1d65e763e631ad49f9a077ed631f4acac9ef4732e2818ccddaefc883b1811') + '88c1d65e763e631ad49f9a077ed631f4acac9ef4732e2818ccddaefc883b1811' + '90b0f1aae2e2f9d75520569e8fbb31a9bac507136dd103a966f063d28e2094b8' + '6bcaf2846ceeafa87912b30ed3e573d75b35bbeafebdaf675e2318b9b0058fbb') validpgpkeys=(F3691687D867B81B51CE07D9BBE43771487328A9 # bpiotrowski@archlinux.org 86CFFCA918CF3AF47147588051E8B148A9999C34 # evangelos@foutrelis.com 13975A70E63C361C73AE69EF6EEB81F8981C74C7 # richard.guenther@gmail.com @@ -160,6 +164,14 @@ prepare() { apply_patch_with_msg \ 0160-libbacktrace-seh.patch + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83562 + apply_patch_with_msg \ + 0200-backport-7fc0f78.patch + + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99234 + apply_patch_with_msg \ + 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