1 /* Subroutines for insn-output.c for Windows NT.
2 Contributed by Douglas Rupp (drupp@cs.washington.edu)
3 Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 2005, 2006 Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA. */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "regs.h"
29 #include "hard-reg-set.h"
30 #include "output.h"
31 #include "tree.h"
32 #include "flags.h"
33 #include "tm_p.h"
34 #include "toplev.h"
35 #include "hashtab.h"
36 #include "ggc.h"
37
38 /* i386/PE specific attribute support.
39
40 i386/PE has two new attributes:
41 dllexport - for exporting a function/variable that will live in a dll
42 dllimport - for importing a function/variable from a dll
43
44 Microsoft allows multiple declspecs in one __declspec, separating
45 them with spaces. We do NOT support this. Instead, use __declspec
46 multiple times.
47 */
48
49 static tree associated_type (tree);
50 static tree gen_stdcall_or_fastcall_suffix (tree, bool);
51 static bool i386_pe_dllexport_p (tree);
52 static bool i386_pe_dllimport_p (tree);
53 static void i386_pe_mark_dllexport (tree);
54 static void i386_pe_mark_dllimport (tree);
55
56 /* This is we how mark internal identifiers with dllimport or dllexport
57 attributes. */
58 #ifndef DLL_IMPORT_PREFIX
59 #define DLL_IMPORT_PREFIX "#i."
60 #endif
61 #ifndef DLL_EXPORT_PREFIX
62 #define DLL_EXPORT_PREFIX "#e."
63 #endif
64
65 /* Handle a "shared" attribute;
66 arguments as in struct attribute_spec.handler. */
67 tree
ix86_handle_shared_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)68 ix86_handle_shared_attribute (tree *node, tree name,
69 tree args ATTRIBUTE_UNUSED,
70 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
71 {
72 if (TREE_CODE (*node) != VAR_DECL)
73 {
74 warning (OPT_Wattributes, "%qs attribute only applies to variables",
75 IDENTIFIER_POINTER (name));
76 *no_add_attrs = true;
77 }
78
79 return NULL_TREE;
80 }
81
82 /* Handle a "selectany" attribute;
83 arguments as in struct attribute_spec.handler. */
84 tree
ix86_handle_selectany_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)85 ix86_handle_selectany_attribute (tree *node, tree name,
86 tree args ATTRIBUTE_UNUSED,
87 int flags ATTRIBUTE_UNUSED,
88 bool *no_add_attrs)
89 {
90 /* The attribute applies only to objects that are initialized and have
91 external linkage. However, we may not know about initialization
92 until the language frontend has processed the decl. We'll check for
93 initialization later in encode_section_info. */
94 if (TREE_CODE (*node) != VAR_DECL || !TREE_PUBLIC (*node))
95 {
96 error ("%qs attribute applies only to initialized variables"
97 " with external linkage", IDENTIFIER_POINTER (name));
98 *no_add_attrs = true;
99 }
100
101 return NULL_TREE;
102 }
103
104
105 /* Return the type that we should use to determine if DECL is
106 imported or exported. */
107
108 static tree
associated_type(tree decl)109 associated_type (tree decl)
110 {
111 return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
112 ? DECL_CONTEXT (decl) : NULL_TREE;
113 }
114
115
116 /* Return true if DECL is a dllexport'd object. */
117
118 static bool
i386_pe_dllexport_p(tree decl)119 i386_pe_dllexport_p (tree decl)
120 {
121 if (TREE_CODE (decl) != VAR_DECL
122 && TREE_CODE (decl) != FUNCTION_DECL)
123 return false;
124
125 if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
126 return true;
127
128 /* Also mark class members of exported classes with dllexport. */
129 if (associated_type (decl)
130 && lookup_attribute ("dllexport",
131 TYPE_ATTRIBUTES (associated_type (decl))))
132 return i386_pe_type_dllexport_p (decl);
133
134 return false;
135 }
136
137 static bool
i386_pe_dllimport_p(tree decl)138 i386_pe_dllimport_p (tree decl)
139 {
140 if (TREE_CODE (decl) != VAR_DECL
141 && TREE_CODE (decl) != FUNCTION_DECL)
142 return false;
143
144 /* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag.
145 We may need to override an earlier decision. */
146 if (DECL_DLLIMPORT_P (decl)
147 && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))
148 {
149 /* Make a final check to see if this is a definition before we generate
150 RTL for an indirect reference. */
151 if (!DECL_EXTERNAL (decl))
152 {
153 error ("%q+D: definition is marked as dllimport", decl);
154 DECL_DLLIMPORT_P (decl) = 0;
155 return false;
156 }
157 return true;
158 }
159 /* The DECL_DLLIMPORT_P flag was set for decls in the class definition
160 by targetm.cxx.adjust_class_at_definition. Check again to emit
161 warnings if the class attribute has been overridden by an
162 out-of-class definition. */
163 else if (associated_type (decl)
164 && lookup_attribute ("dllimport",
165 TYPE_ATTRIBUTES (associated_type (decl))))
166 return i386_pe_type_dllimport_p (decl);
167
168 return false;
169 }
170
171 /* Handle the -mno-fun-dllimport target switch. */
172 bool
i386_pe_valid_dllimport_attribute_p(tree decl)173 i386_pe_valid_dllimport_attribute_p (tree decl)
174 {
175 if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
176 return false;
177 return true;
178 }
179
180 /* Return nonzero if SYMBOL is marked as being dllexport'd. */
181
182 int
i386_pe_dllexport_name_p(const char * symbol)183 i386_pe_dllexport_name_p (const char *symbol)
184 {
185 return (strncmp (DLL_EXPORT_PREFIX, symbol,
186 strlen (DLL_EXPORT_PREFIX)) == 0);
187 }
188
189 /* Return nonzero if SYMBOL is marked as being dllimport'd. */
190
191 int
i386_pe_dllimport_name_p(const char * symbol)192 i386_pe_dllimport_name_p (const char *symbol)
193 {
194 return (strncmp (DLL_IMPORT_PREFIX, symbol,
195 strlen (DLL_IMPORT_PREFIX)) == 0);
196 }
197
198 /* Mark a DECL as being dllexport'd.
199 Note that we override the previous setting (e.g.: dllimport). */
200
201 static void
i386_pe_mark_dllexport(tree decl)202 i386_pe_mark_dllexport (tree decl)
203 {
204 const char *oldname;
205 char *newname;
206 rtx rtlname;
207 rtx symref;
208 tree idp;
209
210 rtlname = XEXP (DECL_RTL (decl), 0);
211 if (GET_CODE (rtlname) == MEM)
212 rtlname = XEXP (rtlname, 0);
213 gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
214 oldname = XSTR (rtlname, 0);
215 if (i386_pe_dllimport_name_p (oldname))
216 {
217 warning (0, "inconsistent dll linkage for %q+D, dllexport assumed",
218 decl);
219 /* Remove DLL_IMPORT_PREFIX. */
220 oldname += strlen (DLL_IMPORT_PREFIX);
221 }
222 else if (i386_pe_dllexport_name_p (oldname))
223 return; /* already done */
224
225 newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
226 sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
227
228 /* We pass newname through get_identifier to ensure it has a unique
229 address. RTL processing can sometimes peek inside the symbol ref
230 and compare the string's addresses to see if two symbols are
231 identical. */
232 idp = get_identifier (newname);
233
234 symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
235 SET_SYMBOL_REF_DECL (symref, decl);
236 XEXP (DECL_RTL (decl), 0) = symref;
237 }
238
239 /* Mark a DECL as being dllimport'd. */
240
241 static void
i386_pe_mark_dllimport(tree decl)242 i386_pe_mark_dllimport (tree decl)
243 {
244 const char *oldname;
245 char *newname;
246 tree idp;
247 rtx rtlname, newrtl;
248 rtx symref;
249
250 rtlname = XEXP (DECL_RTL (decl), 0);
251 if (GET_CODE (rtlname) == MEM)
252 rtlname = XEXP (rtlname, 0);
253 gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
254 oldname = XSTR (rtlname, 0);
255 if (i386_pe_dllexport_name_p (oldname))
256 {
257 error ("%qs declared as both exported to and imported from a DLL",
258 IDENTIFIER_POINTER (DECL_NAME (decl)));
259 return;
260 }
261 else if (i386_pe_dllimport_name_p (oldname))
262 {
263 /* Already done, but do a sanity check to prevent assembler
264 errors. */
265 gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)
266 && DECL_DLLIMPORT_P (decl));
267 return;
268 }
269
270 newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
271 sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
272
273 /* We pass newname through get_identifier to ensure it has a unique
274 address. RTL processing can sometimes peek inside the symbol ref
275 and compare the string's addresses to see if two symbols are
276 identical. */
277 idp = get_identifier (newname);
278
279 symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
280 SET_SYMBOL_REF_DECL (symref, decl);
281 newrtl = gen_rtx_MEM (Pmode,symref);
282 XEXP (DECL_RTL (decl), 0) = newrtl;
283
284 DECL_DLLIMPORT_P (decl) = 1;
285 }
286
287 /* Return string which is the former assembler name modified with a
288 suffix consisting of an atsign (@) followed by the number of bytes of
289 arguments. If FASTCALL is true, also add the FASTCALL_PREFIX. */
290
291 static tree
gen_stdcall_or_fastcall_suffix(tree decl,bool fastcall)292 gen_stdcall_or_fastcall_suffix (tree decl, bool fastcall)
293 {
294 int total = 0;
295 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
296 of DECL_ASSEMBLER_NAME. */
297 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
298 char *newsym;
299 char *p;
300 tree formal_type;
301
302 /* Do not change the identifier if a verbatim asmspec or already done. */
303 if (*asmname == '*' || strchr (asmname, '@'))
304 return DECL_ASSEMBLER_NAME (decl);
305
306 formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
307 if (formal_type != NULL_TREE)
308 {
309 /* These attributes are ignored for variadic functions in
310 i386.c:ix86_return_pops_args. For compatibility with MS
311 compiler do not add @0 suffix here. */
312 if (TREE_VALUE (tree_last (formal_type)) != void_type_node)
313 return DECL_ASSEMBLER_NAME (decl);
314
315 /* Quit if we hit an incomplete type. Error is reported
316 by convert_arguments in c-typeck.c or cp/typeck.c. */
317 while (TREE_VALUE (formal_type) != void_type_node
318 && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))
319 {
320 int parm_size
321 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
322 /* Must round up to include padding. This is done the same
323 way as in store_one_arg. */
324 parm_size = ((parm_size + PARM_BOUNDARY - 1)
325 / PARM_BOUNDARY * PARM_BOUNDARY);
326 total += parm_size;
327 formal_type = TREE_CHAIN (formal_type);\
328 }
329 }
330
331 /* Assume max of 8 base 10 digits in the suffix. */
332 newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1);
333 p = newsym;
334 if (fastcall)
335 *p++ = FASTCALL_PREFIX;
336 sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT);
337 return get_identifier (newsym);
338 }
339
340 void
i386_pe_encode_section_info(tree decl,rtx rtl,int first)341 i386_pe_encode_section_info (tree decl, rtx rtl, int first)
342 {
343 default_encode_section_info (decl, rtl, first);
344
345 if (first && TREE_CODE (decl) == FUNCTION_DECL)
346 {
347 tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
348 tree newid = NULL_TREE;
349
350 if (lookup_attribute ("stdcall", type_attributes))
351 newid = gen_stdcall_or_fastcall_suffix (decl, false);
352 else if (lookup_attribute ("fastcall", type_attributes))
353 newid = gen_stdcall_or_fastcall_suffix (decl, true);
354 if (newid != NULL_TREE)
355 {
356 rtx rtlname = XEXP (rtl, 0);
357 if (GET_CODE (rtlname) == MEM)
358 rtlname = XEXP (rtlname, 0);
359 XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid);
360 /* These attributes must be present on first declaration,
361 change_decl_assembler_name will warn if they are added
362 later and the decl has been referenced, but duplicate_decls
363 should catch the mismatch before this is called. */
364 change_decl_assembler_name (decl, newid);
365 }
366 }
367
368 else if (TREE_CODE (decl) == VAR_DECL
369 && lookup_attribute ("selectany", DECL_ATTRIBUTES (decl)))
370 {
371 if (DECL_INITIAL (decl)
372 /* If an object is initialized with a ctor, the static
373 initialization and destruction code for it is present in
374 each unit defining the object. The code that calls the
375 ctor is protected by a link-once guard variable, so that
376 the object still has link-once semantics, */
377 || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
378 make_decl_one_only (decl);
379 else
380 error ("%q+D:'selectany' attribute applies only to initialized objects",
381 decl);
382 }
383
384 /* Mark the decl so we can tell from the rtl whether the object is
385 dllexport'd or dllimport'd. tree.c: merge_dllimport_decl_attributes
386 handles dllexport/dllimport override semantics. */
387
388 if (i386_pe_dllexport_p (decl))
389 i386_pe_mark_dllexport (decl);
390 else if (i386_pe_dllimport_p (decl))
391 i386_pe_mark_dllimport (decl);
392 /* It might be that DECL has been declared as dllimport, but a
393 subsequent definition nullified that. Assert that
394 tree.c: merge_dllimport_decl_attributes has removed the attribute
395 before the RTL name was marked with the DLL_IMPORT_PREFIX. */
396 else
397 gcc_assert (!((TREE_CODE (decl) == FUNCTION_DECL
398 || TREE_CODE (decl) == VAR_DECL)
399 && rtl != NULL_RTX
400 && GET_CODE (rtl) == MEM
401 && GET_CODE (XEXP (rtl, 0)) == MEM
402 && GET_CODE (XEXP (XEXP (rtl, 0), 0)) == SYMBOL_REF
403 && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (rtl, 0), 0), 0))));
404 }
405
406 /* Strip only the leading encoding, leaving the stdcall suffix and fastcall
407 prefix if it exists. */
408
409 const char *
i386_pe_strip_name_encoding(const char * str)410 i386_pe_strip_name_encoding (const char *str)
411 {
412 if (strncmp (str, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
413 == 0)
414 str += strlen (DLL_IMPORT_PREFIX);
415 else if (strncmp (str, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
416 == 0)
417 str += strlen (DLL_EXPORT_PREFIX);
418 if (*str == '*')
419 str += 1;
420 return str;
421 }
422
423 /* Also strip the fastcall prefix and stdcall suffix. */
424
425 const char *
i386_pe_strip_name_encoding_full(const char * str)426 i386_pe_strip_name_encoding_full (const char *str)
427 {
428 const char *p;
429 const char *name = i386_pe_strip_name_encoding (str);
430
431 /* Strip leading '@' on fastcall symbols. */
432 if (*name == '@')
433 name++;
434
435 /* Strip trailing "@n". */
436 p = strchr (name, '@');
437 if (p)
438 return ggc_alloc_string (name, p - name);
439
440 return name;
441 }
442
443 /* Output a reference to a label. Fastcall symbols are prefixed with @,
444 whereas symbols for functions using other calling conventions don't
445 have a prefix (unless they are marked dllimport or dllexport). */
446
i386_pe_output_labelref(FILE * stream,const char * name)447 void i386_pe_output_labelref (FILE *stream, const char *name)
448 {
449 if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
450 == 0)
451 /* A dll import */
452 {
453 if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX)
454 /* A dllimport fastcall symbol. */
455 {
456 fprintf (stream, "__imp_%s",
457 i386_pe_strip_name_encoding (name));
458 }
459 else
460 /* A dllimport non-fastcall symbol. */
461 {
462 fprintf (stream, "__imp__%s",
463 i386_pe_strip_name_encoding (name));
464 }
465 }
466 else if ((name[0] == FASTCALL_PREFIX)
467 || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
468 == 0
469 && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX))
470 /* A fastcall symbol. */
471 {
472 fprintf (stream, "%s",
473 i386_pe_strip_name_encoding (name));
474 }
475 else
476 /* Everything else. */
477 {
478 fprintf (stream, "%s%s", USER_LABEL_PREFIX,
479 i386_pe_strip_name_encoding (name));
480 }
481 }
482
483 void
i386_pe_unique_section(tree decl,int reloc)484 i386_pe_unique_section (tree decl, int reloc)
485 {
486 int len;
487 const char *name, *prefix;
488 char *string;
489
490 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
491 name = i386_pe_strip_name_encoding_full (name);
492
493 /* The object is put in, for example, section .text$foo.
494 The linker will then ultimately place them in .text
495 (everything from the $ on is stripped). Don't put
496 read-only data in .rdata section to avoid a PE linker
497 bug when .rdata$* grouped sections are used in code
498 without a .rdata section. */
499 if (TREE_CODE (decl) == FUNCTION_DECL)
500 prefix = ".text$";
501 else if (decl_readonly_section (decl, reloc))
502 prefix = ".rdata$";
503 else
504 prefix = ".data$";
505 len = strlen (name) + strlen (prefix);
506 string = alloca (len + 1);
507 sprintf (string, "%s%s", prefix, name);
508
509 DECL_SECTION_NAME (decl) = build_string (len, string);
510 }
511
512 /* Select a set of attributes for section NAME based on the properties
513 of DECL and whether or not RELOC indicates that DECL's initializer
514 might contain runtime relocations.
515
516 We make the section read-only and executable for a function decl,
517 read-only for a const data decl, and writable for a non-const data decl.
518
519 If the section has already been defined, to not allow it to have
520 different attributes, as (1) this is ambiguous since we're not seeing
521 all the declarations up front and (2) some assemblers (e.g. SVR4)
522 do not recognize section redefinitions. */
523 /* ??? This differs from the "standard" PE implementation in that we
524 handle the SHARED variable attribute. Should this be done for all
525 PE targets? */
526
527 #define SECTION_PE_SHARED SECTION_MACH_DEP
528
529 unsigned int
i386_pe_section_type_flags(tree decl,const char * name,int reloc)530 i386_pe_section_type_flags (tree decl, const char *name, int reloc)
531 {
532 static htab_t htab;
533 unsigned int flags;
534 unsigned int **slot;
535
536 /* The names we put in the hashtable will always be the unique
537 versions given to us by the stringtable, so we can just use
538 their addresses as the keys. */
539 if (!htab)
540 htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL);
541
542 if (decl && TREE_CODE (decl) == FUNCTION_DECL)
543 flags = SECTION_CODE;
544 else if (decl && decl_readonly_section (decl, reloc))
545 flags = 0;
546 else
547 {
548 flags = SECTION_WRITE;
549
550 if (decl && TREE_CODE (decl) == VAR_DECL
551 && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
552 flags |= SECTION_PE_SHARED;
553 }
554
555 if (decl && DECL_ONE_ONLY (decl))
556 flags |= SECTION_LINKONCE;
557
558 /* See if we already have an entry for this section. */
559 slot = (unsigned int **) htab_find_slot (htab, name, INSERT);
560 if (!*slot)
561 {
562 *slot = (unsigned int *) xmalloc (sizeof (unsigned int));
563 **slot = flags;
564 }
565 else
566 {
567 if (decl && **slot != flags)
568 error ("%q+D causes a section type conflict", decl);
569 }
570
571 return flags;
572 }
573
574 void
i386_pe_asm_named_section(const char * name,unsigned int flags,tree decl)575 i386_pe_asm_named_section (const char *name, unsigned int flags,
576 tree decl)
577 {
578 char flagchars[8], *f = flagchars;
579
580 if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0)
581 /* readonly data */
582 {
583 *f++ ='d'; /* This is necessary for older versions of gas. */
584 *f++ ='r';
585 }
586 else
587 {
588 if (flags & SECTION_CODE)
589 *f++ = 'x';
590 if (flags & SECTION_WRITE)
591 *f++ = 'w';
592 if (flags & SECTION_PE_SHARED)
593 *f++ = 's';
594 }
595
596 *f = '\0';
597
598 fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
599
600 if (flags & SECTION_LINKONCE)
601 {
602 /* Functions may have been compiled at various levels of
603 optimization so we can't use `same_size' here.
604 Instead, have the linker pick one, without warning.
605 If 'selectany' attribute has been specified, MS compiler
606 sets 'discard' characteristic, rather than telling linker
607 to warn of size or content mismatch, so do the same. */
608 bool discard = (flags & SECTION_CODE)
609 || lookup_attribute ("selectany",
610 DECL_ATTRIBUTES (decl));
611 fprintf (asm_out_file, "\t.linkonce %s\n",
612 (discard ? "discard" : "same_size"));
613 }
614 }
615
616 /* The Microsoft linker requires that every function be marked as
617 DT_FCN. When using gas on cygwin, we must emit appropriate .type
618 directives. */
619
620 #include "gsyms.h"
621
622 /* Mark a function appropriately. This should only be called for
623 functions for which we are not emitting COFF debugging information.
624 FILE is the assembler output file, NAME is the name of the
625 function, and PUBLIC is nonzero if the function is globally
626 visible. */
627
628 void
i386_pe_declare_function_type(FILE * file,const char * name,int public)629 i386_pe_declare_function_type (FILE *file, const char *name, int public)
630 {
631 fprintf (file, "\t.def\t");
632 assemble_name (file, name);
633 fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
634 public ? (int) C_EXT : (int) C_STAT,
635 (int) DT_FCN << N_BTSHFT);
636 }
637
638 /* Keep a list of external functions. */
639
640 struct extern_list GTY(())
641 {
642 struct extern_list *next;
643 tree decl;
644 const char *name;
645 };
646
647 static GTY(()) struct extern_list *extern_head;
648
649 /* Assemble an external function reference. We need to keep a list of
650 these, so that we can output the function types at the end of the
651 assembly. We can't output the types now, because we might see a
652 definition of the function later on and emit debugging information
653 for it then. */
654
655 void
i386_pe_record_external_function(tree decl,const char * name)656 i386_pe_record_external_function (tree decl, const char *name)
657 {
658 struct extern_list *p;
659
660 p = (struct extern_list *) ggc_alloc (sizeof *p);
661 p->next = extern_head;
662 p->decl = decl;
663 p->name = name;
664 extern_head = p;
665 }
666
667 /* Keep a list of exported symbols. */
668
669 struct export_list GTY(())
670 {
671 struct export_list *next;
672 const char *name;
673 int is_data; /* used to type tag exported symbols. */
674 };
675
676 static GTY(()) struct export_list *export_head;
677
678 /* Assemble an export symbol entry. We need to keep a list of
679 these, so that we can output the export list at the end of the
680 assembly. We used to output these export symbols in each function,
681 but that causes problems with GNU ld when the sections are
682 linkonce. */
683
684 void
i386_pe_record_exported_symbol(const char * name,int is_data)685 i386_pe_record_exported_symbol (const char *name, int is_data)
686 {
687 struct export_list *p;
688
689 p = (struct export_list *) ggc_alloc (sizeof *p);
690 p->next = export_head;
691 p->name = name;
692 p->is_data = is_data;
693 export_head = p;
694 }
695
696 /* This is called at the end of assembly. For each external function
697 which has not been defined, we output a declaration now. We also
698 output the .drectve section. */
699
700 void
i386_pe_file_end(void)701 i386_pe_file_end (void)
702 {
703 struct extern_list *p;
704
705 ix86_file_end ();
706
707 for (p = extern_head; p != NULL; p = p->next)
708 {
709 tree decl;
710
711 decl = p->decl;
712
713 /* Positively ensure only one declaration for any given symbol. */
714 if (! TREE_ASM_WRITTEN (decl)
715 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
716 {
717 TREE_ASM_WRITTEN (decl) = 1;
718 i386_pe_declare_function_type (asm_out_file, p->name,
719 TREE_PUBLIC (decl));
720 }
721 }
722
723 if (export_head)
724 {
725 struct export_list *q;
726 drectve_section ();
727 for (q = export_head; q != NULL; q = q->next)
728 {
729 fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n",
730 i386_pe_strip_name_encoding (q->name),
731 (q->is_data) ? ",data" : "");
732 }
733 }
734 }
735
736 #include "gt-winnt.h"
737