OSDN Git Service

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