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;

Reply via email to