forked from msys2/MINGW-packages
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes msys2#8046
- Loading branch information
Showing
3 changed files
with
350 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
From 5883d709d2c63a534b959583cb9ef15a2785de9a Mon Sep 17 00:00:00 2001 | ||
From: Liu Hao <[email protected]> | ||
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 <[email protected]> | ||
|
||
2020-10-08 Liu Hao <[email protected]> | ||
|
||
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 <windows.h> | ||
#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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
From 49a714e59194a7c549aa6657676a1b4be4520650 Mon Sep 17 00:00:00 2001 | ||
From: Eric Botcazou <[email protected]> | ||
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 # [email protected] | ||
86CFFCA918CF3AF47147588051E8B148A9999C34 # [email protected] | ||
13975A70E63C361C73AE69EF6EEB81F8981C74C7 # [email protected] | ||
|
@@ -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 | ||
|