]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/gcc/config/i386/winnt.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / gcc / config / i386 / winnt.c
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
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
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 \f
105 /* Return the type that we should use to determine if DECL is
106    imported or exported.  */
107
108 static tree
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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
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
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
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 \f
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
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
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
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
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"