]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/i386/winnt.c
Update copyright years.
[thirdparty/gcc.git] / gcc / config / i386 / winnt.c
CommitLineData
30c71308
RK
1/* Subroutines for insn-output.c for Windows NT.
2 Contributed by Douglas Rupp (drupp@cs.washington.edu)
99dee823 3 Copyright (C) 1995-2021 Free Software Foundation, Inc.
30c71308 4
6b6cb52e 5This file is part of GCC.
30c71308 6
6b6cb52e
DS
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
2f83c7d6 9Software Foundation; either version 3, or (at your option) any later
6b6cb52e 10version.
30c71308 11
6b6cb52e
DS
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
30c71308
RK
16
17You should have received a copy of the GNU General Public License
2f83c7d6
NC
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
40dcd88b 20
8fcc61f8
RS
21#define IN_TARGET_CODE 1
22
30c71308 23#include "config.h"
293bcdc9 24#include "system.h"
4977bab6 25#include "coretypes.h"
e11c4407 26#include "target.h"
c7131fb2 27#include "function.h"
c7131fb2 28#include "basic-block.h"
e11c4407 29#include "rtl.h"
c7131fb2
AM
30#include "tree.h"
31#include "gimple.h"
4d0cdd0c 32#include "memmodel.h"
79f96374 33#include "tm_p.h"
e11c4407 34#include "stringpool.h"
314e6352 35#include "attribs.h"
2bb8cb58 36#include "emit-rtl.h"
c582198b 37#include "cgraph.h"
3bec79c5 38#include "lto-streamer.h"
b78b513e 39#include "except.h"
e11c4407
AM
40#include "output.h"
41#include "varasm.h"
4000360e 42#include "lto-section-names.h"
30c71308 43
27da1b4d
MK
44/* i386/PE specific attribute support.
45
46 i386/PE has two new attributes:
47 dllexport - for exporting a function/variable that will live in a dll
48 dllimport - for importing a function/variable from a dll
49
50 Microsoft allows multiple declspecs in one __declspec, separating
51 them with spaces. We do NOT support this. Instead, use __declspec
52 multiple times.
53*/
54
91d231cb
JM
55/* Handle a "shared" attribute;
56 arguments as in struct attribute_spec.handler. */
57tree
997ef9e7
TS
58ix86_handle_shared_attribute (tree *node, tree name, tree, int,
59 bool *no_add_attrs)
ac478ac0 60{
91d231cb 61 if (TREE_CODE (*node) != VAR_DECL)
ac478ac0 62 {
29d08eba
JM
63 warning (OPT_Wattributes, "%qE attribute only applies to variables",
64 name);
91d231cb 65 *no_add_attrs = true;
ac478ac0
JM
66 }
67
91d231cb 68 return NULL_TREE;
ac478ac0 69}
a20f6f00
DS
70
71/* Handle a "selectany" attribute;
72 arguments as in struct attribute_spec.handler. */
73tree
997ef9e7 74ix86_handle_selectany_attribute (tree *node, tree name, tree, int,
a20f6f00
DS
75 bool *no_add_attrs)
76{
63578ef9 77 tree decl = *node;
a20f6f00 78 /* The attribute applies only to objects that are initialized and have
4e2bb0a4 79 external linkage. However, we may not know about initialization
63578ef9
KT
80 until the language frontend has processed the decl. Therefore
81 we make sure that variable isn't initialized as common. */
82 if (TREE_CODE (decl) != VAR_DECL || !TREE_PUBLIC (decl))
83 error ("%qE attribute applies only to initialized variables"
84 " with external linkage", name);
85 else
86 {
87 make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
88 /* A variable with attribute selectany never can be common. */
89 DECL_COMMON (decl) = 0;
a20f6f00
DS
90 }
91
63578ef9
KT
92 /* We don't need to keep attribute itself. */
93 *no_add_attrs = true;
a20f6f00
DS
94 return NULL_TREE;
95}
96
27da1b4d 97\f
ac478ac0
JM
98/* Return the type that we should use to determine if DECL is
99 imported or exported. */
27da1b4d 100
ac478ac0 101static tree
9c808aad 102associated_type (tree decl)
27da1b4d 103{
da489f73
RH
104 return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))
105 ? DECL_CONTEXT (decl) : NULL_TREE);
27da1b4d
MK
106}
107
da489f73 108/* Return true if DECL should be a dllexport'd object. */
43d9ad1d
DS
109
110static bool
da489f73 111i386_pe_determine_dllexport_p (tree decl)
27da1b4d 112{
da489f73 113 if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
43d9ad1d 114 return false;
27da1b4d 115
b20231fe
DS
116 /* Don't export local clones of dllexports. */
117 if (!TREE_PUBLIC (decl))
118 return false;
119
34f56efc
KT
120 if (TREE_CODE (decl) == FUNCTION_DECL
121 && DECL_DECLARED_INLINE_P (decl)
122 && !flag_keep_inline_dllexport)
123 return false;
124
43d9ad1d
DS
125 if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
126 return true;
27da1b4d 127
43d9ad1d
DS
128 return false;
129}
130
da489f73
RH
131/* Return true if DECL should be a dllimport'd object. */
132
43d9ad1d 133static bool
da489f73 134i386_pe_determine_dllimport_p (tree decl)
27da1b4d 135{
da489f73
RH
136 tree assoc;
137
138 if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
43d9ad1d
DS
139 return false;
140
da489f73
RH
141 if (DECL_DLLIMPORT_P (decl))
142 return true;
143
43d9ad1d
DS
144 /* The DECL_DLLIMPORT_P flag was set for decls in the class definition
145 by targetm.cxx.adjust_class_at_definition. Check again to emit
09a6b8a4
DS
146 error message if the class attribute has been overridden by an
147 out-of-class definition of static data. */
da489f73 148 assoc = associated_type (decl);
09a6b8a4
DS
149 if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc))
150 && TREE_CODE (decl) == VAR_DECL
151 && TREE_STATIC (decl) && TREE_PUBLIC (decl)
152 && !DECL_EXTERNAL (decl)
153 /* vtable's are linkonce constants, so defining a vtable is not
154 an error as long as we don't try to import it too. */
155 && !DECL_VIRTUAL_P (decl))
156 error ("definition of static data member %q+D of "
d8a07487 157 "dllimport%'d class", decl);
43d9ad1d
DS
158
159 return false;
160}
27da1b4d 161
43d9ad1d 162/* Handle the -mno-fun-dllimport target switch. */
da489f73 163
43d9ad1d 164bool
3101faab 165i386_pe_valid_dllimport_attribute_p (const_tree decl)
43d9ad1d
DS
166{
167 if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
168 return false;
169 return true;
27da1b4d
MK
170}
171
5234b8f5
DS
172/* Return string which is the function name, identified by ID, modified
173 with a suffix consisting of an atsign (@) followed by the number of
174 bytes of arguments. If ID is NULL use the DECL_NAME as base. If
175 FASTCALL is true, also add the FASTCALL_PREFIX.
da489f73 176 Return NULL if no change required. */
30c71308 177
23d34220 178static tree
5234b8f5 179gen_stdcall_or_fastcall_suffix (tree decl, tree id, bool fastcall)
30c71308 180{
da489f73 181 HOST_WIDE_INT total = 0;
5234b8f5 182 const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl));
da489f73 183 char *new_str, *p;
b8ce4e94 184 tree type = TREE_TYPE (DECL_ORIGIN (decl));
04e1d06b
MM
185 tree arg;
186 function_args_iterator args_iter;
30c71308 187
5234b8f5 188 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
23d34220 189
04e1d06b
MM
190 if (prototype_p (type))
191 {
192 /* This attribute is ignored for variadic functions. */
193 if (stdarg_p (type))
194 return NULL_TREE;
195
196 /* Quit if we hit an incomplete type. Error is reported
197 by convert_arguments in c-typeck.c or cp/typeck.c. */
198 FOREACH_FUNCTION_ARGS(type, arg, args_iter)
199 {
200 HOST_WIDE_INT parm_size;
201 HOST_WIDE_INT parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT;
202
203 if (! COMPLETE_TYPE_P (arg))
204 break;
205
206 parm_size = int_size_in_bytes (arg);
207 if (parm_size < 0)
208 break;
209
210 /* Must round up to include padding. This is done the same
211 way as in store_one_arg. */
212 parm_size = ((parm_size + parm_boundary_bytes - 1)
213 / parm_boundary_bytes * parm_boundary_bytes);
214 total += parm_size;
215 }
b8ce4e94
KT
216 }
217
9c808aad 218 /* Assume max of 8 base 10 digits in the suffix. */
5ead67f6 219 p = new_str = XALLOCAVEC (char, 1 + strlen (old_str) + 1 + 8 + 1);
23d34220
DS
220 if (fastcall)
221 *p++ = FASTCALL_PREFIX;
5234b8f5 222 sprintf (p, "%s@" HOST_WIDE_INT_PRINT_DEC, old_str, total);
da489f73
RH
223
224 return get_identifier (new_str);
30c71308 225}
0ea6b275 226
5234b8f5
DS
227/* Maybe decorate and get a new identifier for the DECL of a stdcall or
228 fastcall function. The original identifier is supplied in ID. */
229
230static tree
231i386_pe_maybe_mangle_decl_assembler_name (tree decl, tree id)
232{
233 tree new_id = NULL_TREE;
234
235 if (TREE_CODE (decl) == FUNCTION_DECL)
236 {
b8ce4e94
KT
237 unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (decl));
238 if ((ccvt & IX86_CALLCVT_STDCALL) != 0)
239 {
240 if (TARGET_RTD)
241 /* If we are using -mrtd emit undecorated symbol and let linker
242 do the proper resolving. */
243 return NULL_TREE;
244 new_id = gen_stdcall_or_fastcall_suffix (decl, id, false);
245 }
246 else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
5234b8f5
DS
247 new_id = gen_stdcall_or_fastcall_suffix (decl, id, true);
248 }
249
250 return new_id;
251}
252
a2b63a20
KT
253/* Emit an assembler directive to set symbol for DECL visibility to
254 the visibility type VIS, which must not be VISIBILITY_DEFAULT.
255 As for PE there is no hidden support in gas, we just warn for
256 user-specified visibility attributes. */
257
258void
997ef9e7 259i386_pe_assemble_visibility (tree decl, int)
a2b63a20
KT
260{
261 if (!decl
262 || !lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)))
263 return;
7ac3af38
JJ
264 if (!DECL_ARTIFICIAL (decl))
265 warning (OPT_Wattributes, "visibility attribute not supported "
266 "in this configuration; ignored");
a2b63a20
KT
267}
268
5234b8f5
DS
269/* This is used as a target hook to modify the DECL_ASSEMBLER_NAME
270 in the language-independent default hook
271 langhooks,c:lhd_set_decl_assembler_name ()
272 and in cp/mangle,c:mangle_decl (). */
273tree
274i386_pe_mangle_decl_assembler_name (tree decl, tree id)
275{
276 tree new_id = i386_pe_maybe_mangle_decl_assembler_name (decl, id);
277
278 return (new_id ? new_id : id);
279}
280
77754180
DK
281/* This hook behaves the same as varasm.c/assemble_name(), but
282 generates the name into memory rather than outputting it to
283 a file stream. */
284
285tree
997ef9e7 286i386_pe_mangle_assembler_name (const char *name)
77754180
DK
287{
288 const char *skipped = name + (*name == '*' ? 1 : 0);
289 const char *stripped = targetm.strip_name_encoding (skipped);
290 if (*name != '*' && *user_label_prefix && *stripped != FASTCALL_PREFIX)
291 stripped = ACONCAT ((user_label_prefix, stripped, NULL));
292 return get_identifier (stripped);
293}
294
27da1b4d 295void
9c808aad 296i386_pe_encode_section_info (tree decl, rtx rtl, int first)
27da1b4d 297{
da489f73
RH
298 rtx symbol;
299 int flags;
300
301 /* Do this last, due to our frobbing of DECL_DLLIMPORT_P above. */
c6a2438a 302 default_encode_section_info (decl, rtl, first);
27da1b4d 303
da489f73
RH
304 /* Careful not to prod global register variables. */
305 if (!MEM_P (rtl))
306 return;
307
308 symbol = XEXP (rtl, 0);
309 gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
310
311 switch (TREE_CODE (decl))
e91f04de 312 {
da489f73 313 case FUNCTION_DECL:
da489f73 314 case VAR_DECL:
da489f73
RH
315 break;
316
317 default:
318 return;
4e2bb0a4
DS
319 }
320
27da1b4d 321 /* Mark the decl so we can tell from the rtl whether the object is
43d9ad1d
DS
322 dllexport'd or dllimport'd. tree.c: merge_dllimport_decl_attributes
323 handles dllexport/dllimport override semantics. */
da489f73
RH
324 flags = (SYMBOL_REF_FLAGS (symbol) &
325 ~(SYMBOL_FLAG_DLLIMPORT | SYMBOL_FLAG_DLLEXPORT));
326 if (i386_pe_determine_dllexport_p (decl))
327 flags |= SYMBOL_FLAG_DLLEXPORT;
328 else if (i386_pe_determine_dllimport_p (decl))
09a6b8a4
DS
329 flags |= SYMBOL_FLAG_DLLIMPORT;
330
da489f73 331 SYMBOL_REF_FLAGS (symbol) = flags;
27da1b4d
MK
332}
333
986ce92f 334
da489f73 335bool
3101faab 336i386_pe_binds_local_p (const_tree exp)
772c5265 337{
da489f73
RH
338 if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
339 && DECL_DLLIMPORT_P (exp))
340 return false;
341
986ce92f
KT
342 /* External public symbols, which aren't weakref-s,
343 have local-binding for PE targets. */
344 if (DECL_P (exp)
345 && !lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
346 && TREE_PUBLIC (exp)
347 && DECL_EXTERNAL (exp))
348 return true;
b8b025dc
NC
349
350#ifndef MAKE_DECL_ONE_ONLY
351 /* PR target/66655: If a function has been marked as DECL_ONE_ONLY
352 but we do not the means to make it so, then do not allow it to
353 bind locally. */
354 if (DECL_P (exp)
355 && TREE_CODE (exp) == FUNCTION_DECL
356 && TREE_PUBLIC (exp)
357 && DECL_ONE_ONLY (exp)
358 && ! DECL_EXTERNAL (exp)
359 && DECL_DECLARED_INLINE_P (exp))
360 return false;
361#endif
362
986ce92f 363 return default_binds_local_p_1 (exp, 0);
772c5265
RH
364}
365
b1f123c7 366/* Also strip the fastcall prefix and stdcall suffix. */
772c5265
RH
367
368const char *
9c808aad 369i386_pe_strip_name_encoding_full (const char *str)
772c5265
RH
370{
371 const char *p;
da489f73 372 const char *name = default_strip_name_encoding (str);
9c808aad 373
b1f123c7
DS
374 /* Strip leading '@' on fastcall symbols. */
375 if (*name == '@')
376 name++;
377
378 /* Strip trailing "@n". */
772c5265
RH
379 p = strchr (name, '@');
380 if (p)
12df9508
DS
381 return ggc_alloc_string (name, p - name);
382
772c5265
RH
383 return name;
384}
385
516dd80f 386void
9c808aad 387i386_pe_unique_section (tree decl, int reloc)
b64deb96
JM
388{
389 int len;
79f96374
DB
390 const char *name, *prefix;
391 char *string;
b64deb96 392
98b1d9b2
KT
393 /* Ignore RELOC, if we are allowed to put relocated
394 const data into read-only section. */
395 if (!flag_writable_rel_rdata)
396 reloc = 0;
b64deb96 397 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
772c5265 398 name = i386_pe_strip_name_encoding_full (name);
b64deb96
JM
399
400 /* The object is put in, for example, section .text$foo.
401 The linker will then ultimately place them in .text
81023100 402 (everything from the $ on is stripped). Don't put
9c808aad 403 read-only data in .rdata section to avoid a PE linker
81023100
MK
404 bug when .rdata$* grouped sections are used in code
405 without a .rdata section. */
b64deb96
JM
406 if (TREE_CODE (decl) == FUNCTION_DECL)
407 prefix = ".text$";
4e4d733e 408 else if (decl_readonly_section (decl, reloc))
b64deb96
JM
409 prefix = ".rdata$";
410 else
411 prefix = ".data$";
412 len = strlen (name) + strlen (prefix);
5ead67f6 413 string = XALLOCAVEC (char, len + 1);
b64deb96
JM
414 sprintf (string, "%s%s", prefix, name);
415
f961457f 416 set_decl_section_name (decl, string);
b64deb96 417}
7c262518 418
463d5aa0
KT
419/* Local and global relocs can be placed always into readonly memory for
420 memory for PE-COFF targets. */
421int
422i386_pe_reloc_rw_mask (void)
423{
424 return 0;
425}
426
7c262518
RH
427/* Select a set of attributes for section NAME based on the properties
428 of DECL and whether or not RELOC indicates that DECL's initializer
429 might contain runtime relocations.
430
431 We make the section read-only and executable for a function decl,
432 read-only for a const data decl, and writable for a non-const data decl.
433
434 If the section has already been defined, to not allow it to have
435 different attributes, as (1) this is ambiguous since we're not seeing
436 all the declarations up front and (2) some assemblers (e.g. SVR4)
d1f87653 437 do not recognize section redefinitions. */
7c262518
RH
438/* ??? This differs from the "standard" PE implementation in that we
439 handle the SHARED variable attribute. Should this be done for all
440 PE targets? */
441
442#define SECTION_PE_SHARED SECTION_MACH_DEP
443
444unsigned int
997ef9e7 445i386_pe_section_type_flags (tree decl, const char *, int reloc)
7c262518 446{
7c262518 447 unsigned int flags;
7c262518 448
98b1d9b2
KT
449 /* Ignore RELOC, if we are allowed to put relocated
450 const data into read-only section. */
451 if (!flag_writable_rel_rdata)
452 reloc = 0;
7c262518
RH
453
454 if (decl && TREE_CODE (decl) == FUNCTION_DECL)
455 flags = SECTION_CODE;
4e4d733e 456 else if (decl && decl_readonly_section (decl, reloc))
7c262518
RH
457 flags = 0;
458 else
459 {
460 flags = SECTION_WRITE;
461
462 if (decl && TREE_CODE (decl) == VAR_DECL
91d231cb 463 && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
7c262518
RH
464 flags |= SECTION_PE_SHARED;
465 }
466
ebc9a431 467 if (decl && DECL_P (decl) && DECL_ONE_ONLY (decl))
7c262518
RH
468 flags |= SECTION_LINKONCE;
469
7c262518
RH
470 return flags;
471}
472
473void
c18a5b6c 474i386_pe_asm_named_section (const char *name, unsigned int flags,
a20f6f00 475 tree decl)
7c262518
RH
476{
477 char flagchars[8], *f = flagchars;
478
08c71c82
KT
479#if defined (HAVE_GAS_SECTION_EXCLUDE) && HAVE_GAS_SECTION_EXCLUDE == 1
480 if ((flags & SECTION_EXCLUDE) != 0)
481 *f++ = 'e';
482#endif
483
7f27395d
DS
484 if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0)
485 /* readonly data */
486 {
487 *f++ ='d'; /* This is necessary for older versions of gas. */
488 *f++ ='r';
489 }
490 else
1e8a5248
DS
491 {
492 if (flags & SECTION_CODE)
493 *f++ = 'x';
494 if (flags & SECTION_WRITE)
495 *f++ = 'w';
496 if (flags & SECTION_PE_SHARED)
497 *f++ = 's';
08c71c82
KT
498#if !defined (HAVE_GAS_SECTION_EXCLUDE) || HAVE_GAS_SECTION_EXCLUDE == 0
499 /* If attribute "e" isn't supported we mark this section as
500 never-load. */
501 if ((flags & SECTION_EXCLUDE) != 0)
502 *f++ = 'n';
503#endif
1e8a5248 504 }
7f27395d 505
3bec79c5
DK
506 /* LTO sections need 1-byte alignment to avoid confusing the
507 zlib decompression algorithm with trailing zero pad bytes. */
508 if (strncmp (name, LTO_SECTION_NAME_PREFIX,
509 strlen (LTO_SECTION_NAME_PREFIX)) == 0)
510 *f++ = '0';
511
7c262518
RH
512 *f = '\0';
513
514 fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
515
516 if (flags & SECTION_LINKONCE)
517 {
518 /* Functions may have been compiled at various levels of
a20f6f00
DS
519 optimization so we can't use `same_size' here.
520 Instead, have the linker pick one, without warning.
315682fb 521 If 'selectany' attribute has been specified, MS compiler
a20f6f00
DS
522 sets 'discard' characteristic, rather than telling linker
523 to warn of size or content mismatch, so do the same. */
524 bool discard = (flags & SECTION_CODE)
06623961
EB
525 || (TREE_CODE (decl) != IDENTIFIER_NODE
526 && lookup_attribute ("selectany",
527 DECL_ATTRIBUTES (decl)));
7c262518 528 fprintf (asm_out_file, "\t.linkonce %s\n",
a20f6f00 529 (discard ? "discard" : "same_size"));
7c262518
RH
530 }
531}
da489f73 532
3bec79c5
DK
533/* Beware, DECL may be NULL if compile_file() is emitting the LTO marker. */
534
da489f73
RH
535void
536i386_pe_asm_output_aligned_decl_common (FILE *stream, tree decl,
537 const char *name, HOST_WIDE_INT size,
997ef9e7 538 HOST_WIDE_INT align)
da489f73
RH
539{
540 HOST_WIDE_INT rounded;
541
233215fe
DK
542 /* Compute as in assemble_noswitch_variable, since we don't have
543 support for aligned common on older binutils. We must also
544 avoid emitting a common symbol of size zero, as this is the
545 overloaded representation that indicates an undefined external
546 symbol in the PE object file format. */
da489f73
RH
547 rounded = size ? size : 1;
548 rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
549 rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
550 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
551
552 i386_pe_maybe_record_exported_symbol (decl, name, 1);
553
ecb8c3cc 554 fprintf (stream, "\t.comm\t");
da489f73 555 assemble_name (stream, name);
233215fe
DK
556 if (use_pe_aligned_common)
557 fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC ", %d\n",
6987c384 558 size ? size : HOST_WIDE_INT_1,
233215fe
DK
559 exact_log2 (align) - exact_log2 (CHAR_BIT));
560 else
561 fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START
562 " " HOST_WIDE_INT_PRINT_DEC "\n", rounded, size);
da489f73 563}
9fa1246d
JL
564\f
565/* The Microsoft linker requires that every function be marked as
cae21ae8 566 DT_FCN. When using gas on cygwin, we must emit appropriate .type
9fa1246d
JL
567 directives. */
568
569#include "gsyms.h"
570
571/* Mark a function appropriately. This should only be called for
572 functions for which we are not emitting COFF debugging information.
573 FILE is the assembler output file, NAME is the name of the
0a2aaacc 574 function, and PUB is nonzero if the function is globally
9fa1246d
JL
575 visible. */
576
577void
0a2aaacc 578i386_pe_declare_function_type (FILE *file, const char *name, int pub)
9fa1246d
JL
579{
580 fprintf (file, "\t.def\t");
581 assemble_name (file, name);
582 fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
0a2aaacc 583 pub ? (int) C_EXT : (int) C_STAT,
9fa1246d
JL
584 (int) DT_FCN << N_BTSHFT);
585}
586
587/* Keep a list of external functions. */
588
d1b38208 589struct GTY(()) extern_list
9fa1246d
JL
590{
591 struct extern_list *next;
3ce9c824 592 tree decl;
79f96374 593 const char *name;
9fa1246d
JL
594};
595
90aa6719 596static GTY(()) struct extern_list *extern_head;
9fa1246d
JL
597
598/* Assemble an external function reference. We need to keep a list of
599 these, so that we can output the function types at the end of the
600 assembly. We can't output the types now, because we might see a
601 definition of the function later on and emit debugging information
602 for it then. */
603
604void
3ce9c824 605i386_pe_record_external_function (tree decl, const char *name)
9fa1246d
JL
606{
607 struct extern_list *p;
608
766090c2 609 p = ggc_alloc<extern_list> ();
9fa1246d 610 p->next = extern_head;
3ce9c824 611 p->decl = decl;
9fa1246d
JL
612 p->name = name;
613 extern_head = p;
614}
615
8e260ba4
MK
616/* Keep a list of exported symbols. */
617
d1b38208 618struct GTY(()) export_list
8e260ba4
MK
619{
620 struct export_list *next;
79f96374 621 const char *name;
892a2d68 622 int is_data; /* used to type tag exported symbols. */
8e260ba4
MK
623};
624
82c0e1a0
KT
625/* Keep a list of stub symbols. */
626
627struct GTY(()) stub_list
628{
629 struct stub_list *next;
630 const char *name;
631};
632
90aa6719 633static GTY(()) struct export_list *export_head;
e43f9c10 634
82c0e1a0
KT
635static GTY(()) struct stub_list *stub_head;
636
e43f9c10
MK
637/* Assemble an export symbol entry. We need to keep a list of
638 these, so that we can output the export list at the end of the
639 assembly. We used to output these export symbols in each function,
9c808aad 640 but that causes problems with GNU ld when the sections are
3bec79c5
DK
641 linkonce. Beware, DECL may be NULL if compile_file() is emitting
642 the LTO marker. */
e43f9c10
MK
643
644void
da489f73 645i386_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_data)
e43f9c10 646{
da489f73 647 rtx symbol;
8e260ba4 648 struct export_list *p;
e43f9c10 649
3bec79c5
DK
650 if (!decl)
651 return;
652
da489f73
RH
653 symbol = XEXP (DECL_RTL (decl), 0);
654 gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
655 if (!SYMBOL_REF_DLLEXPORT_P (symbol))
656 return;
657
b20231fe
DS
658 gcc_assert (TREE_PUBLIC (decl));
659
766090c2 660 p = ggc_alloc<export_list> ();
8e260ba4 661 p->next = export_head;
e43f9c10 662 p->name = name;
8e260ba4
MK
663 p->is_data = is_data;
664 export_head = p;
e43f9c10
MK
665}
666
82c0e1a0
KT
667void
668i386_pe_record_stub (const char *name)
669{
670 struct stub_list *p;
671
672 if (!name || *name == 0)
673 return;
674
675 p = stub_head;
676 while (p != NULL)
677 {
678 if (p->name[0] == *name
679 && !strcmp (p->name, name))
680 return;
681 p = p->next;
682 }
683
766090c2 684 p = ggc_alloc<stub_list> ();
82c0e1a0
KT
685 p->next = stub_head;
686 p->name = name;
687 stub_head = p;
688}
689
690
f7e413e2
DK
691#ifdef CXX_WRAP_SPEC_LIST
692
f7e413e2
DK
693/* Search for a function named TARGET in the list of library wrappers
694 we are using, returning a pointer to it if found or NULL if not.
695 This function might be called on quite a few symbols, and we only
696 have the list of names of wrapped functions available to us as a
697 spec string, so first time round we lazily initialise a hash table
698 to make things quicker. */
699
700static const char *
701i386_find_on_wrapper_list (const char *target)
702{
703 static char first_time = 1;
20d2c372 704 static hash_table<nofree_string_hash> *wrappers;
f7e413e2
DK
705
706 if (first_time)
707 {
708 /* Beware that this is not a complicated parser, it assumes
709 that any sequence of non-whitespace beginning with an
710 underscore is one of the wrapped symbols. For now that's
711 adequate to distinguish symbols from spec substitutions
712 and command-line options. */
713 static char wrapper_list_buffer[] = CXX_WRAP_SPEC_LIST;
714 char *bufptr;
715 /* Breaks up the char array into separated strings
716 strings and enter them into the hash table. */
20d2c372 717 wrappers = new hash_table<nofree_string_hash> (8);
f7e413e2
DK
718 for (bufptr = wrapper_list_buffer; *bufptr; ++bufptr)
719 {
720 char *found = NULL;
721 if (ISSPACE (*bufptr))
722 continue;
723 if (*bufptr == '_')
724 found = bufptr;
725 while (*bufptr && !ISSPACE (*bufptr))
726 ++bufptr;
727 if (*bufptr)
728 *bufptr = 0;
729 if (found)
c203e8a7 730 *wrappers->find_slot (found, INSERT) = found;
f7e413e2
DK
731 }
732 first_time = 0;
733 }
734
c203e8a7 735 return wrappers->find (target);
f7e413e2
DK
736}
737
738#endif /* CXX_WRAP_SPEC_LIST */
739
9fa1246d 740/* This is called at the end of assembly. For each external function
e43f9c10
MK
741 which has not been defined, we output a declaration now. We also
742 output the .drectve section. */
9fa1246d
JL
743
744void
9c808aad 745i386_pe_file_end (void)
9fa1246d
JL
746{
747 struct extern_list *p;
748
749 for (p = extern_head; p != NULL; p = p->next)
750 {
751 tree decl;
752
3ce9c824 753 decl = p->decl;
9fa1246d
JL
754
755 /* Positively ensure only one declaration for any given symbol. */
3ce9c824
ILT
756 if (! TREE_ASM_WRITTEN (decl)
757 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
9fa1246d 758 {
f7e413e2
DK
759#ifdef CXX_WRAP_SPEC_LIST
760 /* To ensure the DLL that provides the corresponding real
761 functions is still loaded at runtime, we must reference
762 the real function so that an (unused) import is created. */
763 const char *realsym = i386_find_on_wrapper_list (p->name);
764 if (realsym)
765 i386_pe_declare_function_type (asm_out_file,
766 concat ("__real_", realsym, NULL), TREE_PUBLIC (decl));
767#endif /* CXX_WRAP_SPEC_LIST */
9fa1246d 768 TREE_ASM_WRITTEN (decl) = 1;
a5fe455b 769 i386_pe_declare_function_type (asm_out_file, p->name,
9c808aad 770 TREE_PUBLIC (decl));
9fa1246d
JL
771 }
772 }
e43f9c10 773
8e260ba4 774 if (export_head)
e43f9c10 775 {
8e260ba4
MK
776 struct export_list *q;
777 drectve_section ();
778 for (q = export_head; q != NULL; q = q->next)
779 {
23b488ad 780 fprintf (asm_out_file, "\t.ascii \" -export:\\\"%s\\\"%s\"\n",
4b07e9f7 781 default_strip_name_encoding (q->name),
da489f73 782 (q->is_data ? ",data" : ""));
8e260ba4 783 }
e43f9c10 784 }
82c0e1a0
KT
785
786 if (stub_head)
787 {
788 struct stub_list *q;
789
790 for (q = stub_head; q != NULL; q = q->next)
791 {
792 const char *name = q->name;
793 const char *oname;
794
795 if (name[0] == '*')
796 ++name;
797 oname = name;
798 if (name[0] == '.')
799 ++name;
800 if (strncmp (name, "refptr.", 7) != 0)
801 continue;
802 name += 7;
803 fprintf (asm_out_file, "\t.section\t.rdata$%s, \"dr\"\n"
804 "\t.globl\t%s\n"
805 "\t.linkonce\tdiscard\n", oname, oname);
806 fprintf (asm_out_file, "%s:\n\t.quad\t%s\n", oname, name);
807 }
808 }
9fa1246d 809}
90aa6719 810
dc0e0c6b
EB
811/* Kludge because of missing PE-COFF support for early LTO debug. */
812
813static enum debug_info_levels saved_debug_info_level;
814
815void
816i386_pe_asm_lto_start (void)
817{
818 saved_debug_info_level = debug_info_level;
819 debug_info_level = DINFO_LEVEL_NONE;
820}
821
822void
823i386_pe_asm_lto_end (void)
824{
825 debug_info_level = saved_debug_info_level;
826}
827
f81c9774
RH
828\f
829/* x64 Structured Exception Handling unwind info. */
830
831struct seh_frame_state
832{
833 /* SEH records saves relative to the "current" stack pointer, whether
834 or not there's a frame pointer in place. This tracks the current
835 stack pointer offset from the CFA. */
836 HOST_WIDE_INT sp_offset;
837
838 /* The CFA is located at CFA_REG + CFA_OFFSET. */
839 HOST_WIDE_INT cfa_offset;
840 rtx cfa_reg;
b78b513e
EB
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;
f81c9774
RH
850};
851
852/* Set up data structures beginning output for SEH. */
853
854void
855i386_pe_seh_init (FILE *f)
856{
857 struct seh_frame_state *seh;
858
859 if (!TARGET_SEH)
860 return;
861 if (cfun->is_thunk)
862 return;
863
864 /* We cannot support DRAP with SEH. We turned off support for it by
865 re-defining MAX_STACK_ALIGNMENT when SEH is enabled. */
866 gcc_assert (!stack_realign_drap);
867
868 seh = XCNEW (struct seh_frame_state);
869 cfun->machine->seh = seh;
870
871 seh->sp_offset = INCOMING_FRAME_SP_OFFSET;
872 seh->cfa_offset = INCOMING_FRAME_SP_OFFSET;
873 seh->cfa_reg = stack_pointer_rtx;
874
875 fputs ("\t.seh_proc\t", f);
876 assemble_name (f, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (cfun->decl)));
877 fputc ('\n', f);
878}
879
b78b513e
EB
880/* Emit an assembler directive for the end of the prologue. */
881
f81c9774
RH
882void
883i386_pe_seh_end_prologue (FILE *f)
b78b513e
EB
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
895void
896i386_pe_seh_cold_init (FILE *f, const char *name)
f81c9774
RH
897{
898 struct seh_frame_state *seh;
00db1bf1 899 HOST_WIDE_INT alloc_offset, offset;
f81c9774
RH
900
901 if (!TARGET_SEH)
902 return;
903 if (cfun->is_thunk)
904 return;
905 seh = cfun->machine->seh;
906
b78b513e
EB
907 fputs ("\t.seh_proc\t", f);
908 assemble_name (f, name);
909 fputc ('\n', f);
910
00db1bf1
EB
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;
b78b513e
EB
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++)
70e18df7 925 if (seh->reg_offset[regno] > 0 && seh->reg_offset[regno] <= alloc_offset)
b78b513e 926 {
70e18df7
EB
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 ();
b78b513e
EB
933 print_reg (gen_rtx_REG (DImode, regno), 0, f);
934 fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n",
00db1bf1 935 alloc_offset - seh->reg_offset[regno]);
b78b513e
EB
936 }
937
938 if (seh->cfa_reg != stack_pointer_rtx)
939 {
00db1bf1 940 offset = alloc_offset - seh->cfa_offset;
b78b513e
EB
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 }
f81c9774 949
00db1bf1
EB
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);
70e18df7
EB
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 }
00db1bf1
EB
969 }
970
f81c9774
RH
971 fputs ("\t.seh_endprologue\n", f);
972}
973
b78b513e
EB
974/* Emit an assembler directive for the end of the function. */
975
f81c9774 976static void
b78b513e 977i386_pe_seh_fini (FILE *f, bool cold)
f81c9774 978{
b78b513e
EB
979 struct seh_frame_state *seh;
980
f81c9774
RH
981 if (!TARGET_SEH)
982 return;
983 if (cfun->is_thunk)
984 return;
b78b513e
EB
985 seh = cfun->machine->seh;
986 if (cold != seh->in_cold_section)
987 return;
988 XDELETE (seh);
989 cfun->machine->seh = NULL;
f81c9774
RH
990 fputs ("\t.seh_endproc\n", f);
991}
992
993/* Emit an assembler directive to save REG via a PUSH. */
994
995static void
996seh_emit_push (FILE *f, struct seh_frame_state *seh, rtx reg)
997{
b78b513e 998 const unsigned int regno = REGNO (reg);
f81c9774
RH
999
1000 gcc_checking_assert (GENERAL_REGNO_P (regno));
1001
1002 seh->sp_offset += UNITS_PER_WORD;
b78b513e 1003 seh->reg_offset[regno] = seh->sp_offset;
f81c9774
RH
1004 if (seh->cfa_reg == stack_pointer_rtx)
1005 seh->cfa_offset += UNITS_PER_WORD;
1006
1007 fputs ("\t.seh_pushreg\t", f);
1008 print_reg (reg, 0, f);
1009 fputc ('\n', f);
1010}
1011
1012/* Emit an assembler directive to save REG at CFA - CFA_OFFSET. */
1013
1014static void
1015seh_emit_save (FILE *f, struct seh_frame_state *seh,
1016 rtx reg, HOST_WIDE_INT cfa_offset)
1017{
b78b513e 1018 const unsigned int regno = REGNO (reg);
f81c9774
RH
1019 HOST_WIDE_INT offset;
1020
b78b513e
EB
1021 seh->reg_offset[regno] = cfa_offset;
1022
f81c9774
RH
1023 /* Negative save offsets are of course not supported, since that
1024 would be a store below the stack pointer and thus clobberable. */
1025 gcc_assert (seh->sp_offset >= cfa_offset);
1026 offset = seh->sp_offset - cfa_offset;
1027
1028 fputs ((SSE_REGNO_P (regno) ? "\t.seh_savexmm\t"
1029 : GENERAL_REGNO_P (regno) ? "\t.seh_savereg\t"
1030 : (gcc_unreachable (), "")), f);
1031 print_reg (reg, 0, f);
1032 fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", offset);
1033}
1034
1035/* Emit an assembler directive to adjust RSP by OFFSET. */
1036
1037static void
1038seh_emit_stackalloc (FILE *f, struct seh_frame_state *seh,
1039 HOST_WIDE_INT offset)
1040{
1041 /* We're only concerned with prologue stack allocations, which all
1042 are subtractions from the stack pointer. */
1043 gcc_assert (offset < 0);
1044 offset = -offset;
1045
1046 if (seh->cfa_reg == stack_pointer_rtx)
1047 seh->cfa_offset += offset;
1048 seh->sp_offset += offset;
1049
a2851b75
TG
1050 /* Do not output the stackalloc in that case (it won't work as there is no
1051 encoding for very large frame size). */
1052 if (offset < SEH_MAX_FRAME_SIZE)
1053 fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset);
f81c9774
RH
1054}
1055
1056/* Process REG_CFA_ADJUST_CFA for SEH. */
1057
1058static void
1059seh_cfa_adjust_cfa (FILE *f, struct seh_frame_state *seh, rtx pat)
1060{
1061 rtx dest, src;
1062 HOST_WIDE_INT reg_offset = 0;
1063 unsigned int dest_regno;
1064
1065 dest = SET_DEST (pat);
1066 src = SET_SRC (pat);
1067
1068 if (GET_CODE (src) == PLUS)
1069 {
1070 reg_offset = INTVAL (XEXP (src, 1));
1071 src = XEXP (src, 0);
1072 }
1073 else if (GET_CODE (src) == MINUS)
1074 {
1075 reg_offset = -INTVAL (XEXP (src, 1));
1076 src = XEXP (src, 0);
1077 }
1078 gcc_assert (src == stack_pointer_rtx);
1079 gcc_assert (seh->cfa_reg == stack_pointer_rtx);
1080 dest_regno = REGNO (dest);
1081
1082 if (dest_regno == STACK_POINTER_REGNUM)
1083 seh_emit_stackalloc (f, seh, reg_offset);
1084 else if (dest_regno == HARD_FRAME_POINTER_REGNUM)
1085 {
a2851b75
TG
1086 HOST_WIDE_INT offset;
1087
f81c9774
RH
1088 seh->cfa_reg = dest;
1089 seh->cfa_offset -= reg_offset;
a2851b75
TG
1090
1091 offset = seh->sp_offset - seh->cfa_offset;
1092
1093 gcc_assert ((offset & 15) == 0);
1094 gcc_assert (IN_RANGE (offset, 0, 240));
1095
1096 fputs ("\t.seh_setframe\t", f);
1097 print_reg (seh->cfa_reg, 0, f);
1098 fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", offset);
f81c9774
RH
1099 }
1100 else
1101 gcc_unreachable ();
1102}
1103
1104/* Process REG_CFA_OFFSET for SEH. */
1105
1106static void
1107seh_cfa_offset (FILE *f, struct seh_frame_state *seh, rtx pat)
1108{
1109 rtx dest, src;
1110 HOST_WIDE_INT reg_offset;
1111
1112 dest = SET_DEST (pat);
1113 src = SET_SRC (pat);
1114
1115 gcc_assert (MEM_P (dest));
1116 dest = XEXP (dest, 0);
1117 if (REG_P (dest))
1118 reg_offset = 0;
1119 else
1120 {
1121 gcc_assert (GET_CODE (dest) == PLUS);
1122 reg_offset = INTVAL (XEXP (dest, 1));
1123 dest = XEXP (dest, 0);
1124 }
1125 gcc_assert (dest == seh->cfa_reg);
1126
1127 seh_emit_save (f, seh, src, seh->cfa_offset - reg_offset);
1128}
1129
1130/* Process a FRAME_RELATED_EXPR for SEH. */
1131
1132static void
1133seh_frame_related_expr (FILE *f, struct seh_frame_state *seh, rtx pat)
1134{
1135 rtx dest, src;
1136 HOST_WIDE_INT addend;
1137
1138 /* See the full loop in dwarf2out_frame_debug_expr. */
1139 if (GET_CODE (pat) == PARALLEL || GET_CODE (pat) == SEQUENCE)
1140 {
1141 int i, n = XVECLEN (pat, 0), pass, npass;
1142
1143 npass = (GET_CODE (pat) == PARALLEL ? 2 : 1);
1144 for (pass = 0; pass < npass; ++pass)
1145 for (i = 0; i < n; ++i)
1146 {
1147 rtx ele = XVECEXP (pat, 0, i);
1148
1149 if (GET_CODE (ele) != SET)
1150 continue;
1151 dest = SET_DEST (ele);
1152
1153 /* Process each member of the PARALLEL independently. The first
1154 member is always processed; others only if they are marked. */
1155 if (i == 0 || RTX_FRAME_RELATED_P (ele))
1156 {
1157 /* Evaluate all register saves in the first pass and all
1158 register updates in the second pass. */
1159 if ((MEM_P (dest) ^ pass) || npass == 1)
1160 seh_frame_related_expr (f, seh, ele);
1161 }
1162 }
1163 return;
1164 }
1165
1166 dest = SET_DEST (pat);
1167 src = SET_SRC (pat);
1168
1169 switch (GET_CODE (dest))
1170 {
1171 case REG:
1172 switch (GET_CODE (src))
1173 {
1174 case REG:
1175 /* REG = REG: This should be establishing a frame pointer. */
1176 gcc_assert (src == stack_pointer_rtx);
1177 gcc_assert (dest == hard_frame_pointer_rtx);
1178 seh_cfa_adjust_cfa (f, seh, pat);
1179 break;
1180
1181 case PLUS:
1182 addend = INTVAL (XEXP (src, 1));
1183 src = XEXP (src, 0);
1184 if (dest == hard_frame_pointer_rtx)
1185 seh_cfa_adjust_cfa (f, seh, pat);
1186 else if (dest == stack_pointer_rtx)
1187 {
1188 gcc_assert (src == stack_pointer_rtx);
1189 seh_emit_stackalloc (f, seh, addend);
1190 }
1191 else
1192 gcc_unreachable ();
1193 break;
1194
1195 default:
1196 gcc_unreachable ();
1197 }
1198 break;
1199
1200 case MEM:
1201 /* A save of some kind. */
1202 dest = XEXP (dest, 0);
1203 if (GET_CODE (dest) == PRE_DEC)
1204 {
1205 gcc_checking_assert (GET_MODE (src) == Pmode);
1206 gcc_checking_assert (REG_P (src));
1207 seh_emit_push (f, seh, src);
1208 }
1209 else
1210 seh_cfa_offset (f, seh, pat);
1211 break;
1212
1213 default:
1214 gcc_unreachable ();
1215 }
1216}
1217
1218/* This function looks at a single insn and emits any SEH directives
1219 required for unwind of this insn. */
1220
1221void
ac44248e 1222i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn)
f81c9774
RH
1223{
1224 rtx note, pat;
1225 bool handled_one = false;
1226 struct seh_frame_state *seh;
1227
1228 if (!TARGET_SEH)
1229 return;
1230
f81c9774 1231 seh = cfun->machine->seh;
b78b513e
EB
1232 if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
1233 {
1234 fputs ("\t.seh_endproc\n", asm_out_file);
1235 seh->in_cold_section = true;
1236 return;
1237 }
f81c9774
RH
1238
1239 if (NOTE_P (insn) || !RTX_FRAME_RELATED_P (insn))
1240 return;
1241
b78b513e
EB
1242 /* Skip RTX_FRAME_RELATED_P insns that are associated with the epilogue. */
1243 if (seh->after_prologue)
1244 return;
1245
f81c9774
RH
1246 for (note = REG_NOTES (insn); note ; note = XEXP (note, 1))
1247 {
f81c9774
RH
1248 switch (REG_NOTE_KIND (note))
1249 {
1250 case REG_FRAME_RELATED_EXPR:
e5af9ddd 1251 pat = XEXP (note, 0);
f81c9774
RH
1252 goto found;
1253
1254 case REG_CFA_DEF_CFA:
1255 case REG_CFA_EXPRESSION:
d6d4d770
DS
1256 /* Only emitted with DRAP and aligned memory access using a
1257 realigned SP, both of which we disable. */
f81c9774
RH
1258 gcc_unreachable ();
1259 break;
1260
1261 case REG_CFA_REGISTER:
1262 /* Only emitted in epilogues, which we skip. */
1263 gcc_unreachable ();
1264
1265 case REG_CFA_ADJUST_CFA:
e5af9ddd 1266 pat = XEXP (note, 0);
f81c9774
RH
1267 if (pat == NULL)
1268 {
1269 pat = PATTERN (insn);
1270 if (GET_CODE (pat) == PARALLEL)
1271 pat = XVECEXP (pat, 0, 0);
1272 }
1273 seh_cfa_adjust_cfa (asm_out_file, seh, pat);
1274 handled_one = true;
1275 break;
1276
1277 case REG_CFA_OFFSET:
e5af9ddd 1278 pat = XEXP (note, 0);
f81c9774
RH
1279 if (pat == NULL)
1280 pat = single_set (insn);
1281 seh_cfa_offset (asm_out_file, seh, pat);
1282 handled_one = true;
1283 break;
1284
1285 default:
1286 break;
1287 }
1288 }
1289 if (handled_one)
1290 return;
1291 pat = PATTERN (insn);
1292 found:
1293 seh_frame_related_expr (asm_out_file, seh, pat);
1294}
bf1431e3
TG
1295
1296void
1297i386_pe_seh_emit_except_personality (rtx personality)
1298{
1299 int flags = 0;
1300
1301 if (!TARGET_SEH)
1302 return;
1303
1304 fputs ("\t.seh_handler\t", asm_out_file);
1305 output_addr_const (asm_out_file, personality);
1306
1307#if 0
1308 /* ??? The current implementation of _GCC_specific_handler requires
1309 both except and unwind handling, regardless of which sorts the
1310 user-level function requires. */
1311 eh_region r;
1312 FOR_ALL_EH_REGION(r)
1313 {
1314 if (r->type == ERT_CLEANUP)
1315 flags |= 1;
1316 else
1317 flags |= 2;
1318 }
1319#else
1320 flags = 3;
1321#endif
1322
1323 if (flags & 1)
1324 fputs (", @unwind", asm_out_file);
1325 if (flags & 2)
1326 fputs (", @except", asm_out_file);
1327 fputc ('\n', asm_out_file);
1328}
1329
1330void
1331i386_pe_seh_init_sections (void)
1332{
1333 if (TARGET_SEH)
1334 exception_section = get_unnamed_section (0, output_section_asm_op,
1335 "\t.seh_handlerdata");
1336}
f81c9774
RH
1337\f
1338void
1339i386_pe_start_function (FILE *f, const char *name, tree decl)
1340{
1341 i386_pe_maybe_record_exported_symbol (decl, name, 0);
180295ed 1342 i386_pe_declare_function_type (f, name, TREE_PUBLIC (decl));
1ba6516f
KT
1343 /* In case section was altered by debugging output. */
1344 if (decl != NULL_TREE)
1345 switch_to_section (function_section (decl));
f81c9774
RH
1346 ASM_OUTPUT_FUNCTION_LABEL (f, name, decl);
1347}
1348
1349void
997ef9e7 1350i386_pe_end_function (FILE *f, const char *, tree)
f81c9774 1351{
b78b513e 1352 i386_pe_seh_fini (f, false);
f81c9774
RH
1353}
1354\f
b78b513e
EB
1355void
1356i386_pe_end_cold_function (FILE *f, const char *, tree)
1357{
1358 i386_pe_seh_fini (f, true);
1359}
f81c9774 1360
90aa6719 1361#include "gt-winnt.h"