OSDN Git Service

* target.h (encode_section_info): Add new argument carrying
[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
4    Free Software Foundation, Inc.
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, 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 PARAMS ((tree));
50 const char * gen_stdcall_suffix PARAMS ((tree));
51 const char * gen_fastcall_suffix PARAMS ((tree));
52 int i386_pe_dllexport_p PARAMS ((tree));
53 int i386_pe_dllimport_p PARAMS ((tree));
54 void i386_pe_mark_dllexport PARAMS ((tree));
55 void i386_pe_mark_dllimport PARAMS ((tree));
56
57 /* This is we how mark internal identifiers with dllimport or dllexport
58    attributes.  */
59 #ifndef DLL_IMPORT_PREFIX
60 #define DLL_IMPORT_PREFIX "#i."
61 #endif
62 #ifndef DLL_EXPORT_PREFIX
63 #define DLL_EXPORT_PREFIX "#e."
64 #endif
65
66 /* Handle a "dllimport" or "dllexport" attribute;
67    arguments as in struct attribute_spec.handler.  */
68 tree
69 ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs)
70      tree *node;
71      tree name;
72      tree args;
73      int flags;
74      bool *no_add_attrs;
75 {
76   /* These attributes may apply to structure and union types being created,
77      but otherwise should pass to the declaration involved.  */
78   if (!DECL_P (*node))
79     {
80       if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
81                    | (int) ATTR_FLAG_ARRAY_NEXT))
82         {
83           *no_add_attrs = true;
84           return tree_cons (name, args, NULL_TREE);
85         }
86       if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
87         {
88           warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
89           *no_add_attrs = true;
90         }
91     }
92
93   /* `extern' needn't be specified with dllimport.
94      Specify `extern' now and hope for the best.  Sigh.  */
95   else if (TREE_CODE (*node) == VAR_DECL
96            && is_attribute_p ("dllimport", name))
97     {
98       DECL_EXTERNAL (*node) = 1;
99       TREE_PUBLIC (*node) = 1;
100     }
101
102   return NULL_TREE;
103 }
104
105 /* Handle a "shared" attribute;
106    arguments as in struct attribute_spec.handler.  */
107 tree
108 ix86_handle_shared_attribute (node, name, args, flags, no_add_attrs)
109      tree *node;
110      tree name;
111      tree args ATTRIBUTE_UNUSED;
112      int flags ATTRIBUTE_UNUSED;
113      bool *no_add_attrs;
114 {
115   if (TREE_CODE (*node) != VAR_DECL)
116     {
117       warning ("`%s' attribute only applies to variables",
118                IDENTIFIER_POINTER (name));
119       *no_add_attrs = true;
120     }
121
122   return NULL_TREE;
123 }
124 \f
125 /* Return the type that we should use to determine if DECL is
126    imported or exported.  */
127
128 static tree
129 associated_type (decl)
130      tree decl;
131 {
132   tree t = NULL_TREE;
133
134   /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer
135      to the containing class.  So we look at the 'this' arg.  */
136   if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
137     {
138       /* Artificial methods are not affected by the import/export status of
139          their class unless they are virtual.  */
140       if (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl))
141         t = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))));
142     }
143   else if (DECL_CONTEXT (decl)
144            && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
145     t = DECL_CONTEXT (decl);
146
147   return t;
148 }
149
150 /* Return nonzero if DECL is a dllexport'd object.  */
151
152 int
153 i386_pe_dllexport_p (decl)
154      tree decl;
155 {
156   tree exp;
157
158   if (TREE_CODE (decl) != VAR_DECL
159       && TREE_CODE (decl) != FUNCTION_DECL)
160     return 0;
161   exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
162   if (exp)
163     return 1;
164
165   /* Class members get the dllexport status of their class.  */
166   if (associated_type (decl))
167     {
168       exp = lookup_attribute ("dllexport",
169                               TYPE_ATTRIBUTES (associated_type (decl)));
170       if (exp)
171         return 1;
172     }
173
174   return 0;
175 }
176
177 /* Return nonzero if DECL is a dllimport'd object.  */
178
179 int
180 i386_pe_dllimport_p (decl)
181      tree decl;
182 {
183   tree imp;
184
185   if (TREE_CODE (decl) == FUNCTION_DECL
186       && TARGET_NOP_FUN_DLLIMPORT)
187     return 0;
188
189   if (TREE_CODE (decl) != VAR_DECL
190       && TREE_CODE (decl) != FUNCTION_DECL)
191     return 0;
192   imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
193   if (imp)
194     return 1;
195
196   /* Class members get the dllimport status of their class.  */
197   if (associated_type (decl))
198     {
199       imp = lookup_attribute ("dllimport",
200                               TYPE_ATTRIBUTES (associated_type (decl)));
201       if (imp)
202         return 1;
203     }
204
205   return 0;
206 }
207
208 /* Return nonzero if SYMBOL is marked as being dllexport'd.  */
209
210 int
211 i386_pe_dllexport_name_p (symbol)
212      const char *symbol;
213 {
214   return (strncmp (DLL_EXPORT_PREFIX, symbol,
215                    strlen (DLL_EXPORT_PREFIX)) == 0);
216 }
217
218 /* Return nonzero if SYMBOL is marked as being dllimport'd.  */
219
220 int
221 i386_pe_dllimport_name_p (symbol)
222      const char *symbol;
223 {
224   return (strncmp (DLL_IMPORT_PREFIX, symbol,
225                    strlen (DLL_IMPORT_PREFIX)) == 0);
226 }
227
228 /* Mark a DECL as being dllexport'd.
229    Note that we override the previous setting (eg: dllimport).  */
230
231 void
232 i386_pe_mark_dllexport (decl)
233      tree decl;
234 {
235   const char *oldname;
236   char  *newname;
237   rtx rtlname;
238   tree idp;
239
240   rtlname = XEXP (DECL_RTL (decl), 0);
241   if (GET_CODE (rtlname) == SYMBOL_REF)
242     oldname = XSTR (rtlname, 0);
243   else if (GET_CODE (rtlname) == MEM
244            && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
245     oldname = XSTR (XEXP (rtlname, 0), 0);
246   else
247     abort ();
248   if (i386_pe_dllimport_name_p (oldname))
249     /* Remove DLL_IMPORT_PREFIX.  */
250     oldname += strlen (DLL_IMPORT_PREFIX);
251   else if (i386_pe_dllexport_name_p (oldname))
252     return; /* already done */
253
254   newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
255   sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
256
257   /* We pass newname through get_identifier to ensure it has a unique
258      address.  RTL processing can sometimes peek inside the symbol ref
259      and compare the string's addresses to see if two symbols are
260      identical.  */
261   idp = get_identifier (newname);
262
263   XEXP (DECL_RTL (decl), 0) =
264     gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
265 }
266
267 /* Mark a DECL as being dllimport'd.  */
268
269 void
270 i386_pe_mark_dllimport (decl)
271      tree decl;
272 {
273   const char *oldname;
274   char  *newname;
275   tree idp;
276   rtx rtlname;
277
278   rtlname = XEXP (DECL_RTL (decl), 0);
279   if (GET_CODE (rtlname) == SYMBOL_REF)
280     oldname = XSTR (rtlname, 0);
281   else if (GET_CODE (rtlname) == MEM
282            && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
283     oldname = XSTR (XEXP (rtlname, 0), 0);
284   else
285     abort ();
286   if (i386_pe_dllexport_name_p (oldname))
287     {
288       error ("`%s' declared as both exported to and imported from a DLL",
289              IDENTIFIER_POINTER (DECL_NAME (decl)));
290       return;
291     }
292   else if (i386_pe_dllimport_name_p (oldname))
293     {
294       /* Already done, but force correct linkage since the redeclaration 
295          might have omitted explicit extern.  Sigh.  */
296       if (TREE_CODE (decl) == VAR_DECL
297           /* ??? Is this test for vtables needed?  */
298           && !DECL_VIRTUAL_P (decl))
299         {
300           DECL_EXTERNAL (decl) = 1;
301           TREE_PUBLIC (decl) = 1;
302         }
303       return;
304     }
305
306   /* ??? One can well ask why we're making these checks here,
307      and that would be a good question.  */
308
309   /* Imported variables can't be initialized. Note that C++ classes
310      are marked initial, so we need to check.  */
311   if (TREE_CODE (decl) == VAR_DECL
312       && !DECL_VIRTUAL_P (decl)
313       && (DECL_INITIAL (decl)
314           && ! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
315     {
316       error_with_decl (decl, "initialized variable `%s' is marked dllimport");
317       return;
318     }
319   /* Nor can they be static.  */
320   if (TREE_CODE (decl) == VAR_DECL
321       /* ??? Is this test for vtables needed?  */
322       && !DECL_VIRTUAL_P (decl)
323       && 0 /*???*/)
324     {
325       error_with_decl (decl, "static variable `%s' is marked dllimport");
326       return;
327     }
328
329   newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
330   sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
331
332   /* We pass newname through get_identifier to ensure it has a unique
333      address.  RTL processing can sometimes peek inside the symbol ref
334      and compare the string's addresses to see if two symbols are
335      identical.  */
336   idp = get_identifier (newname);
337
338   XEXP (DECL_RTL (decl), 0) 
339     = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
340
341   /* Can't treat a pointer to this as a constant address */
342   DECL_NON_ADDR_CONST_P (decl) = 1;
343 }
344
345 /* Return string which is the former assembler name modified with a 
346    prefix consisting of FASTCALL_PREFIX and a suffix consisting of an
347    atsign (@) followed by the number of bytes of arguments.  */
348
349 const char *
350 gen_fastcall_suffix (decl)
351   tree decl;
352 {
353   int total = 0;
354
355   const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
356   char *newsym;
357
358   if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
359     if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
360         == void_type_node)
361       {
362         tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
363
364         while (TREE_VALUE (formal_type) != void_type_node)
365           {
366             int parm_size
367               = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
368             /* Must round up to include padding.  This is done the same
369                way as in store_one_arg.  */
370             parm_size = ((parm_size + PARM_BOUNDARY - 1)
371                          / PARM_BOUNDARY * PARM_BOUNDARY);
372             total += parm_size;
373             formal_type = TREE_CHAIN (formal_type);
374           }
375       }
376
377   /* Assume max of 8 base 10 digits in the suffix.  */ 
378   newsym = xmalloc (1 + strlen (asmname) + 1 + 8 + 1);
379   sprintf (newsym, "%c%s@%d", FASTCALL_PREFIX, asmname, total/BITS_PER_UNIT);
380   return IDENTIFIER_POINTER (get_identifier (newsym));
381 }
382
383 /* Return string which is the former assembler name modified with a 
384    suffix consisting of an atsign (@) followed by the number of bytes of 
385    arguments */
386
387 const char *
388 gen_stdcall_suffix (decl)
389   tree decl;
390 {
391   int total = 0;
392   /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
393      of DECL_ASSEMBLER_NAME.  */
394   const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
395   char *newsym;
396
397   if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
398     if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl)))) 
399         == void_type_node)
400       {
401         tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
402
403         while (TREE_VALUE (formal_type) != void_type_node)
404           {
405             int parm_size
406               = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
407             /* Must round up to include padding.  This is done the same
408                way as in store_one_arg.  */
409             parm_size = ((parm_size + PARM_BOUNDARY - 1)
410                          / PARM_BOUNDARY * PARM_BOUNDARY);
411             total += parm_size;
412             formal_type = TREE_CHAIN (formal_type);
413           }
414       }
415
416   /* Assume max of 8 base 10 digits in the suffix.  */ 
417   newsym = xmalloc (strlen (asmname) + 1 + 8 + 1);
418   sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT);
419   return IDENTIFIER_POINTER (get_identifier (newsym));
420 }
421
422 void
423 i386_pe_encode_section_info (decl, rtl, first)
424      tree decl;
425      rtx rtl;
426      int first;
427 {
428   if (!first)
429     return;
430
431   default_encode_section_info (decl, rtl, first);
432
433   if (TREE_CODE (decl) == FUNCTION_DECL)
434     {
435       if (lookup_attribute ("stdcall",
436                             TYPE_ATTRIBUTES (TREE_TYPE (decl))))
437         XEXP (DECL_RTL (decl), 0) = 
438           gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl));
439       else if (lookup_attribute ("fastcall",
440                                  TYPE_ATTRIBUTES (TREE_TYPE (decl))))
441         XEXP (DECL_RTL (decl), 0) =
442           gen_rtx (SYMBOL_REF, Pmode, gen_fastcall_suffix (decl));
443     }
444
445   /* Mark the decl so we can tell from the rtl whether the object is
446      dllexport'd or dllimport'd.  */
447
448   if (i386_pe_dllexport_p (decl))
449     i386_pe_mark_dllexport (decl);
450   else if (i386_pe_dllimport_p (decl))
451     i386_pe_mark_dllimport (decl);
452   /* It might be that DECL has already been marked as dllimport, but a
453      subsequent definition nullified that.  The attribute is gone but
454      DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
455      that. Ditto for the DECL_NON_ADDR_CONST_P flag.  */
456   else if ((TREE_CODE (decl) == FUNCTION_DECL
457             || TREE_CODE (decl) == VAR_DECL)
458            && DECL_RTL (decl) != NULL_RTX
459            && GET_CODE (DECL_RTL (decl)) == MEM
460            && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
461            && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
462            && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
463     {
464       const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
465       /* Remove DLL_IMPORT_PREFIX.  */
466       tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
467       rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
468
469       XEXP (DECL_RTL (decl), 0) = newrtl;
470
471       DECL_NON_ADDR_CONST_P (decl) = 0;
472
473       /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
474          We leave these alone for now.  */
475     }
476 }
477
478 /* Strip only the leading encoding, leaving the stdcall suffix and fastcall
479    prefix if it exists.  */
480
481 const char *
482 i386_pe_strip_name_encoding (str)
483      const char *str;
484 {
485   if (strncmp (str, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
486       == 0)
487     str += strlen (DLL_IMPORT_PREFIX);
488   else if (strncmp (str, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
489            == 0)
490     str += strlen (DLL_EXPORT_PREFIX);
491   if (*str == '*')
492     str += 1;
493   return str;
494 }
495
496 /* Also strip the stdcall suffix.  */
497
498 const char *
499 i386_pe_strip_name_encoding_full (str)
500      const char *str;
501 {
502   const char *p;
503   const char *name = i386_pe_strip_name_encoding (str);
504  
505   p = strchr (name, '@');
506   if (p)
507     return ggc_alloc_string (name, p - name);
508
509   return name;
510 }
511
512 /* Output a reference to a label. Fastcall symbols are prefixed with @,
513    whereas symbols for functions using other calling conventions don't
514    have a prefix (unless they are marked dllimport or dllexport).  */
515
516 void i386_pe_output_labelref (stream, name)
517      FILE *stream;
518      const char *name;
519 {
520   if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
521       == 0)
522    /* A dll import */ 
523    {
524       if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX)
525       /* A dllimport fastcall symbol.  */   
526         {
527           fprintf (stream, "__imp_%s",
528                    i386_pe_strip_name_encoding (name));
529         }
530       else
531       /* A dllimport non-fastcall symbol.  */ 
532         {
533           fprintf (stream, "__imp__%s",
534                    i386_pe_strip_name_encoding (name));
535         }
536     }
537   else if ((name[0] == FASTCALL_PREFIX)
538            || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX)
539                == 0 
540                && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX)))
541     /* A fastcall symbol.  */
542     {
543       fprintf (stream, "%s",
544                i386_pe_strip_name_encoding (name));
545     }
546   else
547     /* Everything else.  */
548     {
549       fprintf (stream, "%s%s", USER_LABEL_PREFIX,
550                i386_pe_strip_name_encoding (name));
551     }
552 }
553
554 void
555 i386_pe_unique_section (decl, reloc)
556      tree decl;
557      int reloc;
558 {
559   int len;
560   const char *name, *prefix;
561   char *string;
562
563   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
564   name = i386_pe_strip_name_encoding_full (name);
565
566   /* The object is put in, for example, section .text$foo.
567      The linker will then ultimately place them in .text
568      (everything from the $ on is stripped). Don't put
569      read-only data in .rdata section to avoid a PE linker 
570      bug when .rdata$* grouped sections are used in code
571      without a .rdata section.  */
572   if (TREE_CODE (decl) == FUNCTION_DECL)
573     prefix = ".text$";
574   else if (decl_readonly_section (decl, reloc))
575     prefix = ".rdata$";
576   else
577     prefix = ".data$";
578   len = strlen (name) + strlen (prefix);
579   string = alloca (len + 1);
580   sprintf (string, "%s%s", prefix, name);
581
582   DECL_SECTION_NAME (decl) = build_string (len, string);
583 }
584
585 /* Select a set of attributes for section NAME based on the properties
586    of DECL and whether or not RELOC indicates that DECL's initializer
587    might contain runtime relocations.
588
589    We make the section read-only and executable for a function decl,
590    read-only for a const data decl, and writable for a non-const data decl.
591
592    If the section has already been defined, to not allow it to have
593    different attributes, as (1) this is ambiguous since we're not seeing
594    all the declarations up front and (2) some assemblers (e.g. SVR4)
595    do not recognize section redefinitions.  */
596 /* ??? This differs from the "standard" PE implementation in that we
597    handle the SHARED variable attribute.  Should this be done for all
598    PE targets?  */
599
600 #define SECTION_PE_SHARED       SECTION_MACH_DEP
601
602 unsigned int
603 i386_pe_section_type_flags (decl, name, reloc)
604      tree decl;
605      const char *name;
606      int reloc;
607 {
608   static htab_t htab;
609   unsigned int flags;
610   unsigned int **slot;
611
612   /* The names we put in the hashtable will always be the unique
613      versions gived to us by the stringtable, so we can just use
614      their addresses as the keys.  */
615   if (!htab)
616     htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL);
617
618   if (decl && TREE_CODE (decl) == FUNCTION_DECL)
619     flags = SECTION_CODE;
620   else if (decl && decl_readonly_section (decl, reloc))
621     flags = 0;
622   else
623     {
624       flags = SECTION_WRITE;
625
626       if (decl && TREE_CODE (decl) == VAR_DECL
627           && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
628         flags |= SECTION_PE_SHARED;
629     }
630
631   if (decl && DECL_ONE_ONLY (decl))
632     flags |= SECTION_LINKONCE;
633
634   /* See if we already have an entry for this section.  */
635   slot = (unsigned int **) htab_find_slot (htab, name, INSERT);
636   if (!*slot)
637     {
638       *slot = (unsigned int *) xmalloc (sizeof (unsigned int));
639       **slot = flags;
640     }
641   else
642     {
643       if (decl && **slot != flags)
644         error_with_decl (decl, "%s causes a section type conflict");
645     }
646
647   return flags;
648 }
649
650 void
651 i386_pe_asm_named_section (name, flags)
652      const char *name;
653      unsigned int flags;
654 {
655   char flagchars[8], *f = flagchars;
656
657   if (flags & SECTION_CODE)
658     *f++ = 'x';
659   if (flags & SECTION_WRITE)
660     *f++ = 'w';
661   if (flags & SECTION_PE_SHARED)
662     *f++ = 's';
663   *f = '\0';
664
665   fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
666
667   if (flags & SECTION_LINKONCE)
668     {
669       /* Functions may have been compiled at various levels of
670          optimization so we can't use `same_size' here.
671          Instead, have the linker pick one.  */
672       fprintf (asm_out_file, "\t.linkonce %s\n",
673                (flags & SECTION_CODE ? "discard" : "same_size"));
674     }
675 }
676 \f
677 /* The Microsoft linker requires that every function be marked as
678    DT_FCN.  When using gas on cygwin, we must emit appropriate .type
679    directives.  */
680
681 #include "gsyms.h"
682
683 /* Mark a function appropriately.  This should only be called for
684    functions for which we are not emitting COFF debugging information.
685    FILE is the assembler output file, NAME is the name of the
686    function, and PUBLIC is nonzero if the function is globally
687    visible.  */
688
689 void
690 i386_pe_declare_function_type (file, name, public)
691      FILE *file;
692      const char *name;
693      int public;
694 {
695   fprintf (file, "\t.def\t");
696   assemble_name (file, name);
697   fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
698            public ? (int) C_EXT : (int) C_STAT,
699            (int) DT_FCN << N_BTSHFT);
700 }
701
702 /* Keep a list of external functions.  */
703
704 struct extern_list
705 {
706   struct extern_list *next;
707   const char *name;
708 };
709
710 static struct extern_list *extern_head;
711
712 /* Assemble an external function reference.  We need to keep a list of
713    these, so that we can output the function types at the end of the
714    assembly.  We can't output the types now, because we might see a
715    definition of the function later on and emit debugging information
716    for it then.  */
717
718 void
719 i386_pe_record_external_function (name)
720      const char *name;
721 {
722   struct extern_list *p;
723
724   p = (struct extern_list *) xmalloc (sizeof *p);
725   p->next = extern_head;
726   p->name = name;
727   extern_head = p;
728 }
729
730 /* Keep a list of exported symbols.  */
731
732 struct export_list
733 {
734   struct export_list *next;
735   const char *name;
736   int is_data;          /* used to type tag exported symbols.  */
737 };
738
739 static struct export_list *export_head;
740
741 /* Assemble an export symbol entry.  We need to keep a list of
742    these, so that we can output the export list at the end of the
743    assembly.  We used to output these export symbols in each function,
744    but that causes problems with GNU ld when the sections are 
745    linkonce.  */
746
747 void
748 i386_pe_record_exported_symbol (name, is_data)
749      const char *name;
750      int is_data;
751 {
752   struct export_list *p;
753
754   p = (struct export_list *) xmalloc (sizeof *p);
755   p->next = export_head;
756   p->name = name;
757   p->is_data = is_data;
758   export_head = p;
759 }
760
761 /* This is called at the end of assembly.  For each external function
762    which has not been defined, we output a declaration now.  We also
763    output the .drectve section.  */
764
765 void
766 i386_pe_asm_file_end (file)
767      FILE *file;
768 {
769   struct extern_list *p;
770
771   ix86_asm_file_end (file);
772
773   for (p = extern_head; p != NULL; p = p->next)
774     {
775       tree decl;
776
777       decl = get_identifier (p->name);
778
779       /* Positively ensure only one declaration for any given symbol.  */
780       if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl))
781         {
782           TREE_ASM_WRITTEN (decl) = 1;
783           i386_pe_declare_function_type (file, p->name, TREE_PUBLIC (decl));
784         }
785     }
786
787   if (export_head)
788     {
789       struct export_list *q;
790       drectve_section ();
791       for (q = export_head; q != NULL; q = q->next)
792         {
793           fprintf (file, "\t.ascii \" -export:%s%s\"\n",
794                    i386_pe_strip_name_encoding (q->name),
795                    (q->is_data) ? ",data" : "");
796         }
797     }
798 }
799