Since GCC 8, the -freorder-blocks-and-partition pass can split a function into
hot and cold parts, thus generating 2 CIEs for a single function in DWARF for
exception purposes and doing an equivalent trick for Windows SEH on x86-64.
Now the Windows system unwinder is picky when it comes to the boundary between
an active EH region and the end of the function and, therefore, a nop may need
to be added in specific cases, see e.g. ix86_seh_fixup_eh_fallthru.
I overlooked that when implementing the -freorder-blocks-and-partition support
back in 2018 and this results in e.g. a non-functioning Ada compiler when you
do a profiled bootstrap.
Bootstrapped on x86-64/Windows, applied on all active branches as obvious.
2021-02-11 Eric Botcazou <ebotca...@adacore.com>
* config/i386/winnt.c (i386_pe_seh_unwind_emit): When switching to
the cold section, emit a nop before the directive if the previous
active instruction can throw.
--
Eric Botcazou
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index 962c88e3c1b..adc3f36f13b 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -1231,6 +1231,10 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn)
seh = cfun->machine->seh;
if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
{
+ /* See ix86_seh_fixup_eh_fallthru for the rationale. */
+ rtx_insn *prev = prev_active_insn (insn);
+ if (prev && !insn_nothrow_p (prev))
+ fputs ("\tnop\n", asm_out_file);
fputs ("\t.seh_endproc\n", asm_out_file);
seh->in_cold_section = true;
return;