Mercurial > hg > CbC > CbC_gcc
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" |