Mercurial > hg > CbC > CbC_gcc
diff gcc/config/i386/winnt.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/config/i386/winnt.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/config/i386/winnt.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,6 +1,6 @@ /* Subroutines for insn-output.c for Windows NT. Contributed by Douglas Rupp (drupp@cs.washington.edu) - Copyright (C) 1995-2017 Free Software Foundation, Inc. + Copyright (C) 1995-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -18,6 +18,8 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +#define IN_TARGET_CODE 1 + #include "config.h" #include "system.h" #include "coretypes.h" @@ -34,6 +36,7 @@ #include "emit-rtl.h" #include "cgraph.h" #include "lto-streamer.h" +#include "except.h" #include "output.h" #include "varasm.h" #include "lto-section-names.h" @@ -805,6 +808,23 @@ } } +/* Kludge because of missing PE-COFF support for early LTO debug. */ + +static enum debug_info_levels saved_debug_info_level; + +void +i386_pe_asm_lto_start (void) +{ + saved_debug_info_level = debug_info_level; + debug_info_level = DINFO_LEVEL_NONE; +} + +void +i386_pe_asm_lto_end (void) +{ + debug_info_level = saved_debug_info_level; +} + /* x64 Structured Exception Handling unwind info. */ @@ -818,6 +838,15 @@ /* The CFA is located at CFA_REG + CFA_OFFSET. */ HOST_WIDE_INT cfa_offset; rtx cfa_reg; + + /* The offset wrt the CFA where register N has been saved. */ + HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER]; + + /* True if we are past the end of the epilogue. */ + bool after_prologue; + + /* True if we are in the cold section. */ + bool in_cold_section; }; /* Set up data structures beginning output for SEH. */ @@ -848,9 +877,105 @@ fputc ('\n', f); } +/* Emit an assembler directive for the end of the prologue. */ + void i386_pe_seh_end_prologue (FILE *f) { + if (!TARGET_SEH) + return; + if (cfun->is_thunk) + return; + cfun->machine->seh->after_prologue = true; + fputs ("\t.seh_endprologue\n", f); +} + +/* Emit assembler directives to reconstruct the SEH state. */ + +void +i386_pe_seh_cold_init (FILE *f, const char *name) +{ + struct seh_frame_state *seh; + HOST_WIDE_INT alloc_offset, offset; + + if (!TARGET_SEH) + return; + if (cfun->is_thunk) + return; + seh = cfun->machine->seh; + + fputs ("\t.seh_proc\t", f); + assemble_name (f, name); + fputc ('\n', f); + + /* In the normal case, the frame pointer is near the bottom of the frame + so we can do the full stack allocation and set it afterwards. There + is an exception when the function accesses prior frames so, in this + case, we need to pre-allocate a small chunk before setting it. */ + if (crtl->accesses_prior_frames) + alloc_offset = seh->cfa_offset; + else + alloc_offset = seh->sp_offset; + + offset = alloc_offset - INCOMING_FRAME_SP_OFFSET; + if (offset > 0 && offset < SEH_MAX_FRAME_SIZE) + fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset); + + for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + if (seh->reg_offset[regno] > 0 && seh->reg_offset[regno] <= alloc_offset) + { + if (SSE_REGNO_P (regno)) + fputs ("\t.seh_savexmm\t", f); + else if (GENERAL_REGNO_P (regno)) + fputs ("\t.seh_savereg\t", f); + else + gcc_unreachable (); + print_reg (gen_rtx_REG (DImode, regno), 0, f); + fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", + alloc_offset - seh->reg_offset[regno]); + } + + if (seh->cfa_reg != stack_pointer_rtx) + { + offset = alloc_offset - seh->cfa_offset; + + gcc_assert ((offset & 15) == 0); + gcc_assert (IN_RANGE (offset, 0, 240)); + + fputs ("\t.seh_setframe\t", f); + print_reg (seh->cfa_reg, 0, f); + fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", offset); + } + + if (crtl->accesses_prior_frames) + { + offset = seh->sp_offset - alloc_offset; + if (offset > 0 && offset < SEH_MAX_FRAME_SIZE) + fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset); + + for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + if (seh->reg_offset[regno] > alloc_offset) + { + if (SSE_REGNO_P (regno)) + fputs ("\t.seh_savexmm\t", f); + else if (GENERAL_REGNO_P (regno)) + fputs ("\t.seh_savereg\t", f); + else + gcc_unreachable (); + print_reg (gen_rtx_REG (DImode, regno), 0, f); + fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", + seh->sp_offset - seh->reg_offset[regno]); + } + } + + fputs ("\t.seh_endprologue\n", f); +} + +/* Emit an assembler directive for the end of the function. */ + +static void +i386_pe_seh_fini (FILE *f, bool cold) +{ struct seh_frame_state *seh; if (!TARGET_SEH) @@ -858,20 +983,10 @@ if (cfun->is_thunk) return; seh = cfun->machine->seh; - + if (cold != seh->in_cold_section) + return; XDELETE (seh); cfun->machine->seh = NULL; - - fputs ("\t.seh_endprologue\n", f); -} - -static void -i386_pe_seh_fini (FILE *f) -{ - if (!TARGET_SEH) - return; - if (cfun->is_thunk) - return; fputs ("\t.seh_endproc\n", f); } @@ -880,11 +995,12 @@ static void seh_emit_push (FILE *f, struct seh_frame_state *seh, rtx reg) { - unsigned int regno = REGNO (reg); + const unsigned int regno = REGNO (reg); gcc_checking_assert (GENERAL_REGNO_P (regno)); seh->sp_offset += UNITS_PER_WORD; + seh->reg_offset[regno] = seh->sp_offset; if (seh->cfa_reg == stack_pointer_rtx) seh->cfa_offset += UNITS_PER_WORD; @@ -899,9 +1015,11 @@ seh_emit_save (FILE *f, struct seh_frame_state *seh, rtx reg, HOST_WIDE_INT cfa_offset) { - unsigned int regno = REGNO (reg); + const unsigned int regno = REGNO (reg); HOST_WIDE_INT offset; + seh->reg_offset[regno] = cfa_offset; + /* Negative save offsets are of course not supported, since that would be a store below the stack pointer and thus clobberable. */ gcc_assert (seh->sp_offset >= cfa_offset); @@ -1110,13 +1228,19 @@ if (!TARGET_SEH) return; - /* We free the SEH data once done with the prologue. Ignore those - RTX_FRAME_RELATED_P insns that are associated with the epilogue. */ seh = cfun->machine->seh; - if (seh == NULL) + if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS) + { + fputs ("\t.seh_endproc\n", asm_out_file); + seh->in_cold_section = true; + return; + } + + if (NOTE_P (insn) || !RTX_FRAME_RELATED_P (insn)) return; - if (NOTE_P (insn) || !RTX_FRAME_RELATED_P (insn)) + /* Skip RTX_FRAME_RELATED_P insns that are associated with the epilogue. */ + if (seh->after_prologue) return; for (note = REG_NOTES (insn); note ; note = XEXP (note, 1)) @@ -1215,8 +1339,7 @@ i386_pe_start_function (FILE *f, const char *name, tree decl) { i386_pe_maybe_record_exported_symbol (decl, name, 0); - if (write_symbols != SDB_DEBUG) - i386_pe_declare_function_type (f, name, TREE_PUBLIC (decl)); + i386_pe_declare_function_type (f, name, TREE_PUBLIC (decl)); /* In case section was altered by debugging output. */ if (decl != NULL_TREE) switch_to_section (function_section (decl)); @@ -1226,8 +1349,13 @@ void i386_pe_end_function (FILE *f, const char *, tree) { - i386_pe_seh_fini (f); + i386_pe_seh_fini (f, false); } +void +i386_pe_end_cold_function (FILE *f, const char *, tree) +{ + i386_pe_seh_fini (f, true); +} #include "gt-winnt.h"