OSDN Git Service

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