comparison 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
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
1 /* Subroutines for insn-output.c for Windows NT. 1 /* Subroutines for insn-output.c for Windows NT.
2 Contributed by Douglas Rupp (drupp@cs.washington.edu) 2 Contributed by Douglas Rupp (drupp@cs.washington.edu)
3 Copyright (C) 1995-2017 Free Software Foundation, Inc. 3 Copyright (C) 1995-2018 Free Software Foundation, Inc.
4 4
5 This file is part of GCC. 5 This file is part of GCC.
6 6
7 GCC is free software; you can redistribute it and/or modify it under 7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free 8 the terms of the GNU General Public License as published by the Free
15 for more details. 15 for more details.
16 16
17 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see 18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */ 19 <http://www.gnu.org/licenses/>. */
20
21 #define IN_TARGET_CODE 1
20 22
21 #include "config.h" 23 #include "config.h"
22 #include "system.h" 24 #include "system.h"
23 #include "coretypes.h" 25 #include "coretypes.h"
24 #include "target.h" 26 #include "target.h"
32 #include "stringpool.h" 34 #include "stringpool.h"
33 #include "attribs.h" 35 #include "attribs.h"
34 #include "emit-rtl.h" 36 #include "emit-rtl.h"
35 #include "cgraph.h" 37 #include "cgraph.h"
36 #include "lto-streamer.h" 38 #include "lto-streamer.h"
39 #include "except.h"
37 #include "output.h" 40 #include "output.h"
38 #include "varasm.h" 41 #include "varasm.h"
39 #include "lto-section-names.h" 42 #include "lto-section-names.h"
40 43
41 /* i386/PE specific attribute support. 44 /* i386/PE specific attribute support.
803 fprintf (asm_out_file, "%s:\n\t.quad\t%s\n", oname, name); 806 fprintf (asm_out_file, "%s:\n\t.quad\t%s\n", oname, name);
804 } 807 }
805 } 808 }
806 } 809 }
807 810
811 /* Kludge because of missing PE-COFF support for early LTO debug. */
812
813 static enum debug_info_levels saved_debug_info_level;
814
815 void
816 i386_pe_asm_lto_start (void)
817 {
818 saved_debug_info_level = debug_info_level;
819 debug_info_level = DINFO_LEVEL_NONE;
820 }
821
822 void
823 i386_pe_asm_lto_end (void)
824 {
825 debug_info_level = saved_debug_info_level;
826 }
827
808 828
809 /* x64 Structured Exception Handling unwind info. */ 829 /* x64 Structured Exception Handling unwind info. */
810 830
811 struct seh_frame_state 831 struct seh_frame_state
812 { 832 {
816 HOST_WIDE_INT sp_offset; 836 HOST_WIDE_INT sp_offset;
817 837
818 /* The CFA is located at CFA_REG + CFA_OFFSET. */ 838 /* The CFA is located at CFA_REG + CFA_OFFSET. */
819 HOST_WIDE_INT cfa_offset; 839 HOST_WIDE_INT cfa_offset;
820 rtx cfa_reg; 840 rtx cfa_reg;
841
842 /* The offset wrt the CFA where register N has been saved. */
843 HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
844
845 /* True if we are past the end of the epilogue. */
846 bool after_prologue;
847
848 /* True if we are in the cold section. */
849 bool in_cold_section;
821 }; 850 };
822 851
823 /* Set up data structures beginning output for SEH. */ 852 /* Set up data structures beginning output for SEH. */
824 853
825 void 854 void
846 fputs ("\t.seh_proc\t", f); 875 fputs ("\t.seh_proc\t", f);
847 assemble_name (f, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (cfun->decl))); 876 assemble_name (f, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (cfun->decl)));
848 fputc ('\n', f); 877 fputc ('\n', f);
849 } 878 }
850 879
880 /* Emit an assembler directive for the end of the prologue. */
881
851 void 882 void
852 i386_pe_seh_end_prologue (FILE *f) 883 i386_pe_seh_end_prologue (FILE *f)
853 { 884 {
885 if (!TARGET_SEH)
886 return;
887 if (cfun->is_thunk)
888 return;
889 cfun->machine->seh->after_prologue = true;
890 fputs ("\t.seh_endprologue\n", f);
891 }
892
893 /* Emit assembler directives to reconstruct the SEH state. */
894
895 void
896 i386_pe_seh_cold_init (FILE *f, const char *name)
897 {
854 struct seh_frame_state *seh; 898 struct seh_frame_state *seh;
899 HOST_WIDE_INT alloc_offset, offset;
855 900
856 if (!TARGET_SEH) 901 if (!TARGET_SEH)
857 return; 902 return;
858 if (cfun->is_thunk) 903 if (cfun->is_thunk)
859 return; 904 return;
860 seh = cfun->machine->seh; 905 seh = cfun->machine->seh;
861 906
907 fputs ("\t.seh_proc\t", f);
908 assemble_name (f, name);
909 fputc ('\n', f);
910
911 /* In the normal case, the frame pointer is near the bottom of the frame
912 so we can do the full stack allocation and set it afterwards. There
913 is an exception when the function accesses prior frames so, in this
914 case, we need to pre-allocate a small chunk before setting it. */
915 if (crtl->accesses_prior_frames)
916 alloc_offset = seh->cfa_offset;
917 else
918 alloc_offset = seh->sp_offset;
919
920 offset = alloc_offset - INCOMING_FRAME_SP_OFFSET;
921 if (offset > 0 && offset < SEH_MAX_FRAME_SIZE)
922 fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset);
923
924 for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
925 if (seh->reg_offset[regno] > 0 && seh->reg_offset[regno] <= alloc_offset)
926 {
927 if (SSE_REGNO_P (regno))
928 fputs ("\t.seh_savexmm\t", f);
929 else if (GENERAL_REGNO_P (regno))
930 fputs ("\t.seh_savereg\t", f);
931 else
932 gcc_unreachable ();
933 print_reg (gen_rtx_REG (DImode, regno), 0, f);
934 fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n",
935 alloc_offset - seh->reg_offset[regno]);
936 }
937
938 if (seh->cfa_reg != stack_pointer_rtx)
939 {
940 offset = alloc_offset - seh->cfa_offset;
941
942 gcc_assert ((offset & 15) == 0);
943 gcc_assert (IN_RANGE (offset, 0, 240));
944
945 fputs ("\t.seh_setframe\t", f);
946 print_reg (seh->cfa_reg, 0, f);
947 fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", offset);
948 }
949
950 if (crtl->accesses_prior_frames)
951 {
952 offset = seh->sp_offset - alloc_offset;
953 if (offset > 0 && offset < SEH_MAX_FRAME_SIZE)
954 fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset);
955
956 for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
957 if (seh->reg_offset[regno] > alloc_offset)
958 {
959 if (SSE_REGNO_P (regno))
960 fputs ("\t.seh_savexmm\t", f);
961 else if (GENERAL_REGNO_P (regno))
962 fputs ("\t.seh_savereg\t", f);
963 else
964 gcc_unreachable ();
965 print_reg (gen_rtx_REG (DImode, regno), 0, f);
966 fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n",
967 seh->sp_offset - seh->reg_offset[regno]);
968 }
969 }
970
971 fputs ("\t.seh_endprologue\n", f);
972 }
973
974 /* Emit an assembler directive for the end of the function. */
975
976 static void
977 i386_pe_seh_fini (FILE *f, bool cold)
978 {
979 struct seh_frame_state *seh;
980
981 if (!TARGET_SEH)
982 return;
983 if (cfun->is_thunk)
984 return;
985 seh = cfun->machine->seh;
986 if (cold != seh->in_cold_section)
987 return;
862 XDELETE (seh); 988 XDELETE (seh);
863 cfun->machine->seh = NULL; 989 cfun->machine->seh = NULL;
864
865 fputs ("\t.seh_endprologue\n", f);
866 }
867
868 static void
869 i386_pe_seh_fini (FILE *f)
870 {
871 if (!TARGET_SEH)
872 return;
873 if (cfun->is_thunk)
874 return;
875 fputs ("\t.seh_endproc\n", f); 990 fputs ("\t.seh_endproc\n", f);
876 } 991 }
877 992
878 /* Emit an assembler directive to save REG via a PUSH. */ 993 /* Emit an assembler directive to save REG via a PUSH. */
879 994
880 static void 995 static void
881 seh_emit_push (FILE *f, struct seh_frame_state *seh, rtx reg) 996 seh_emit_push (FILE *f, struct seh_frame_state *seh, rtx reg)
882 { 997 {
883 unsigned int regno = REGNO (reg); 998 const unsigned int regno = REGNO (reg);
884 999
885 gcc_checking_assert (GENERAL_REGNO_P (regno)); 1000 gcc_checking_assert (GENERAL_REGNO_P (regno));
886 1001
887 seh->sp_offset += UNITS_PER_WORD; 1002 seh->sp_offset += UNITS_PER_WORD;
1003 seh->reg_offset[regno] = seh->sp_offset;
888 if (seh->cfa_reg == stack_pointer_rtx) 1004 if (seh->cfa_reg == stack_pointer_rtx)
889 seh->cfa_offset += UNITS_PER_WORD; 1005 seh->cfa_offset += UNITS_PER_WORD;
890 1006
891 fputs ("\t.seh_pushreg\t", f); 1007 fputs ("\t.seh_pushreg\t", f);
892 print_reg (reg, 0, f); 1008 print_reg (reg, 0, f);
897 1013
898 static void 1014 static void
899 seh_emit_save (FILE *f, struct seh_frame_state *seh, 1015 seh_emit_save (FILE *f, struct seh_frame_state *seh,
900 rtx reg, HOST_WIDE_INT cfa_offset) 1016 rtx reg, HOST_WIDE_INT cfa_offset)
901 { 1017 {
902 unsigned int regno = REGNO (reg); 1018 const unsigned int regno = REGNO (reg);
903 HOST_WIDE_INT offset; 1019 HOST_WIDE_INT offset;
1020
1021 seh->reg_offset[regno] = cfa_offset;
904 1022
905 /* Negative save offsets are of course not supported, since that 1023 /* Negative save offsets are of course not supported, since that
906 would be a store below the stack pointer and thus clobberable. */ 1024 would be a store below the stack pointer and thus clobberable. */
907 gcc_assert (seh->sp_offset >= cfa_offset); 1025 gcc_assert (seh->sp_offset >= cfa_offset);
908 offset = seh->sp_offset - cfa_offset; 1026 offset = seh->sp_offset - cfa_offset;
1108 struct seh_frame_state *seh; 1226 struct seh_frame_state *seh;
1109 1227
1110 if (!TARGET_SEH) 1228 if (!TARGET_SEH)
1111 return; 1229 return;
1112 1230
1113 /* We free the SEH data once done with the prologue. Ignore those
1114 RTX_FRAME_RELATED_P insns that are associated with the epilogue. */
1115 seh = cfun->machine->seh; 1231 seh = cfun->machine->seh;
1116 if (seh == NULL) 1232 if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
1117 return; 1233 {
1234 fputs ("\t.seh_endproc\n", asm_out_file);
1235 seh->in_cold_section = true;
1236 return;
1237 }
1118 1238
1119 if (NOTE_P (insn) || !RTX_FRAME_RELATED_P (insn)) 1239 if (NOTE_P (insn) || !RTX_FRAME_RELATED_P (insn))
1240 return;
1241
1242 /* Skip RTX_FRAME_RELATED_P insns that are associated with the epilogue. */
1243 if (seh->after_prologue)
1120 return; 1244 return;
1121 1245
1122 for (note = REG_NOTES (insn); note ; note = XEXP (note, 1)) 1246 for (note = REG_NOTES (insn); note ; note = XEXP (note, 1))
1123 { 1247 {
1124 switch (REG_NOTE_KIND (note)) 1248 switch (REG_NOTE_KIND (note))
1213 1337
1214 void 1338 void
1215 i386_pe_start_function (FILE *f, const char *name, tree decl) 1339 i386_pe_start_function (FILE *f, const char *name, tree decl)
1216 { 1340 {
1217 i386_pe_maybe_record_exported_symbol (decl, name, 0); 1341 i386_pe_maybe_record_exported_symbol (decl, name, 0);
1218 if (write_symbols != SDB_DEBUG) 1342 i386_pe_declare_function_type (f, name, TREE_PUBLIC (decl));
1219 i386_pe_declare_function_type (f, name, TREE_PUBLIC (decl));
1220 /* In case section was altered by debugging output. */ 1343 /* In case section was altered by debugging output. */
1221 if (decl != NULL_TREE) 1344 if (decl != NULL_TREE)
1222 switch_to_section (function_section (decl)); 1345 switch_to_section (function_section (decl));
1223 ASM_OUTPUT_FUNCTION_LABEL (f, name, decl); 1346 ASM_OUTPUT_FUNCTION_LABEL (f, name, decl);
1224 } 1347 }
1225 1348
1226 void 1349 void
1227 i386_pe_end_function (FILE *f, const char *, tree) 1350 i386_pe_end_function (FILE *f, const char *, tree)
1228 { 1351 {
1229 i386_pe_seh_fini (f); 1352 i386_pe_seh_fini (f, false);
1230 } 1353 }
1231 1354
1355 void
1356 i386_pe_end_cold_function (FILE *f, const char *, tree)
1357 {
1358 i386_pe_seh_fini (f, true);
1359 }
1232 1360
1233 #include "gt-winnt.h" 1361 #include "gt-winnt.h"