OSDN Git Service

PR debug/9963
[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) == SYMBOL_REF)
277     oldname = XSTR (rtlname, 0);
278   else if (GET_CODE (rtlname) == MEM
279            && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
280     oldname = XSTR (XEXP (rtlname, 0), 0);
281   else
282     abort ();
283   if (i386_pe_dllimport_name_p (oldname))
284     {
285       warning ("%Jinconsistent dll linkage for '%D', dllexport assumed.",
286                decl, decl);
287      /* Remove DLL_IMPORT_PREFIX.  */
288       oldname += strlen (DLL_IMPORT_PREFIX);
289       DECL_NON_ADDR_CONST_P (decl) = 0;
290     }
291   else if (i386_pe_dllexport_name_p (oldname))
292     return;  /*  already done  */
293
294   newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
295   sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
296
297   /* We pass newname through get_identifier to ensure it has a unique
298      address.  RTL processing can sometimes peek inside the symbol ref
299      and compare the string's addresses to see if two symbols are
300      identical.  */
301   idp = get_identifier (newname);
302
303   symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
304   SYMBOL_REF_DECL (symref) = decl;
305   XEXP (DECL_RTL (decl), 0) = symref;
306 }
307
308 /* Mark a DECL as being dllimport'd.  */
309
310 static void
311 i386_pe_mark_dllimport (tree decl)
312 {
313   const char *oldname;
314   char  *newname;
315   tree idp;
316   rtx rtlname, newrtl;
317   rtx symref;
318
319   rtlname = XEXP (DECL_RTL (decl), 0);
320   if (GET_CODE (rtlname) == SYMBOL_REF)
321     oldname = XSTR (rtlname, 0);
322   else if (GET_CODE (rtlname) == MEM
323            && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
324     oldname = XSTR (XEXP (rtlname, 0), 0);
325   else
326     abort ();
327   if (i386_pe_dllexport_name_p (oldname))
328     {
329       error ("%qs declared as both exported to and imported from a DLL",
330              IDENTIFIER_POINTER (DECL_NAME (decl)));
331       return;
332     }
333   else if (i386_pe_dllimport_name_p (oldname))
334     {
335       /* Already done, but do a sanity check to prevent assembler errors.  */
336       if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
337         {
338           error ("%Jfailure in redeclaration of '%D': dllimport'd "
339                  "symbol lacks external linkage.", decl, decl);
340           abort();
341         }
342       return;
343     }
344
345   newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
346   sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
347
348   /* We pass newname through get_identifier to ensure it has a unique
349      address.  RTL processing can sometimes peek inside the symbol ref
350      and compare the string's addresses to see if two symbols are
351      identical.  */
352   idp = get_identifier (newname);
353
354   symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
355   SYMBOL_REF_DECL (symref) = decl;
356   newrtl = gen_rtx_MEM (Pmode,symref);
357   XEXP (DECL_RTL (decl), 0) = newrtl;
358
359   /* Can't treat a pointer to this as a constant address */
360   DECL_NON_ADDR_CONST_P (decl) = 1;
361 }
362
363 /* Return string which is the former assembler name modified with a
364    suffix consisting of an atsign (@) followed by the number of bytes of
365    arguments.  If FASTCALL is true, also add the FASTCALL_PREFIX.  */
366
367 static tree
368 gen_stdcall_or_fastcall_suffix (tree decl, bool fastcall)
369 {
370   int total = 0;
371   /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
372      of DECL_ASSEMBLER_NAME.  */
373    const char *asmname =  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
374   char *newsym;
375   char *p;
376   tree formal_type;
377
378   /* Do not change the identifier if a verbatim asmspec or already done. */
379   if (*asmname == '*' || strchr (asmname, '@'))
380     return DECL_ASSEMBLER_NAME (decl);
381
382   formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
383   if (formal_type != NULL_TREE)
384     {
385       /* These attributes are ignored for variadic functions in
386          i386.c:ix86_return_pops_args. For compatibility with MS
387          compiler do not add @0 suffix here.  */ 
388       if (TREE_VALUE (tree_last (formal_type)) != void_type_node)
389         return DECL_ASSEMBLER_NAME (decl);
390
391       /* Quit if we hit an incomplete type.  Error is reported
392          by convert_arguments in c-typeck.c or cp/typeck.c.  */
393       while (TREE_VALUE (formal_type) != void_type_node
394              && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))     
395         {
396           int parm_size
397             = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
398             /* Must round up to include padding.  This is done the same
399                way as in store_one_arg.  */
400           parm_size = ((parm_size + PARM_BOUNDARY - 1)
401                        / PARM_BOUNDARY * PARM_BOUNDARY);
402           total += parm_size;
403           formal_type = TREE_CHAIN (formal_type);\
404         }
405      }
406
407   /* Assume max of 8 base 10 digits in the suffix.  */
408   newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1);
409   p = newsym;
410   if (fastcall)
411     *p++ = FASTCALL_PREFIX;
412   sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT);
413   return get_identifier (newsym);
414 }
415
416 void
417 i386_pe_encode_section_info (tree decl, rtx rtl, int first)
418 {
419   default_encode_section_info (decl, rtl, first);
420
421   if (first && TREE_CODE (decl) == FUNCTION_DECL)
422     {
423       tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
424       tree newid = NULL_TREE;
425
426       if (lookup_attribute ("stdcall", type_attributes))
427         newid = gen_stdcall_or_fastcall_suffix (decl, false);
428       else if (lookup_attribute ("fastcall", type_attributes))
429         newid = gen_stdcall_or_fastcall_suffix (decl, true);
430       if (newid != NULL_TREE)   
431         {
432           rtx rtlname = XEXP (rtl, 0);
433           if (GET_CODE (rtlname) == MEM)
434             rtlname = XEXP (rtlname, 0);
435           XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid);
436           /* These attributes must be present on first declaration,
437              change_decl_assembler_name will warn if they are added
438              later and the decl has been referenced, but duplicate_decls
439              should catch the mismatch before this is called.  */ 
440           change_decl_assembler_name (decl, newid);
441         }
442     }
443
444   /* Mark the decl so we can tell from the rtl whether the object is
445      dllexport'd or dllimport'd.  This also handles dllexport/dllimport
446      override semantics.  */
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
466       /* Remove DLL_IMPORT_PREFIX.  */
467       tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
468       rtx symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
469       SYMBOL_REF_DECL (symref) = decl;
470       XEXP (DECL_RTL (decl), 0) = symref;
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       if (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
477         warning ("%J'%D' defined locally after being "
478                  "referenced with dllimport linkage", decl, decl);
479       else
480         warning ("%J'%D' redeclared without dllimport attribute "
481                  "after being referenced with dllimport linkage", decl, decl);
482     }
483 }
484
485 /* Strip only the leading encoding, leaving the stdcall suffix and fastcall
486    prefix if it exists.  */
487
488 const char *
489 i386_pe_strip_name_encoding (const char *str)
490 {
491   if (strncmp (str, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
492       == 0)
493     str += strlen (DLL_IMPORT_PREFIX);
494   else if (strncmp (str, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
495            == 0)
496     str += strlen (DLL_EXPORT_PREFIX);
497   if (*str == '*')
498     str += 1;
499   return str;
500 }
501
502 /* Also strip the fastcall prefix and stdcall suffix.  */
503
504 const char *
505 i386_pe_strip_name_encoding_full (const char *str)
506 {
507   const char *p;
508   const char *name = i386_pe_strip_name_encoding (str);
509
510   /* Strip leading '@' on fastcall symbols.  */
511   if (*name == '@')
512     name++;
513
514   /* Strip trailing "@n".  */
515   p = strchr (name, '@');
516   if (p)
517     return ggc_alloc_string (name, p - name);
518
519   return name;
520 }
521
522 /* Output a reference to a label. Fastcall symbols are prefixed with @,
523    whereas symbols for functions using other calling conventions don't
524    have a prefix (unless they are marked dllimport or dllexport).  */
525
526 void i386_pe_output_labelref (FILE *stream, const char *name)
527 {
528   if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
529       == 0)
530     /* A dll import */
531     {
532       if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX)
533       /* A dllimport fastcall symbol.  */
534         {
535           fprintf (stream, "__imp_%s",
536                    i386_pe_strip_name_encoding (name));
537         }
538       else
539       /* A dllimport non-fastcall symbol.  */
540         {
541           fprintf (stream, "__imp__%s",
542                    i386_pe_strip_name_encoding (name));
543         }
544     }
545   else if ((name[0] == FASTCALL_PREFIX)
546            || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
547                == 0
548                && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX))
549     /* A fastcall symbol.  */
550     {
551       fprintf (stream, "%s",
552                i386_pe_strip_name_encoding (name));
553     }
554   else
555     /* Everything else.  */
556     {
557       fprintf (stream, "%s%s", USER_LABEL_PREFIX,
558                i386_pe_strip_name_encoding (name));
559     }
560 }
561
562 void
563 i386_pe_unique_section (tree decl, int reloc)
564 {
565   int len;
566   const char *name, *prefix;
567   char *string;
568
569   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
570   name = i386_pe_strip_name_encoding_full (name);
571
572   /* The object is put in, for example, section .text$foo.
573      The linker will then ultimately place them in .text
574      (everything from the $ on is stripped). Don't put
575      read-only data in .rdata section to avoid a PE linker
576      bug when .rdata$* grouped sections are used in code
577      without a .rdata section.  */
578   if (TREE_CODE (decl) == FUNCTION_DECL)
579     prefix = ".text$";
580   else if (decl_readonly_section (decl, reloc))
581     prefix = ".rdata$";
582   else
583     prefix = ".data$";
584   len = strlen (name) + strlen (prefix);
585   string = alloca (len + 1);
586   sprintf (string, "%s%s", prefix, name);
587
588   DECL_SECTION_NAME (decl) = build_string (len, string);
589 }
590
591 /* Select a set of attributes for section NAME based on the properties
592    of DECL and whether or not RELOC indicates that DECL's initializer
593    might contain runtime relocations.
594
595    We make the section read-only and executable for a function decl,
596    read-only for a const data decl, and writable for a non-const data decl.
597
598    If the section has already been defined, to not allow it to have
599    different attributes, as (1) this is ambiguous since we're not seeing
600    all the declarations up front and (2) some assemblers (e.g. SVR4)
601    do not recognize section redefinitions.  */
602 /* ??? This differs from the "standard" PE implementation in that we
603    handle the SHARED variable attribute.  Should this be done for all
604    PE targets?  */
605
606 #define SECTION_PE_SHARED       SECTION_MACH_DEP
607
608 unsigned int
609 i386_pe_section_type_flags (tree decl, const char *name, int reloc)
610 {
611   static htab_t htab;
612   unsigned int flags;
613   unsigned int **slot;
614
615   /* The names we put in the hashtable will always be the unique
616      versions given to us by the stringtable, so we can just use
617      their addresses as the keys.  */
618   if (!htab)
619     htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL);
620
621   if (decl && TREE_CODE (decl) == FUNCTION_DECL)
622     flags = SECTION_CODE;
623   else if (decl && decl_readonly_section (decl, reloc))
624     flags = 0;
625   else
626     {
627       flags = SECTION_WRITE;
628
629       if (decl && TREE_CODE (decl) == VAR_DECL
630           && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
631         flags |= SECTION_PE_SHARED;
632     }
633
634   if (decl && DECL_ONE_ONLY (decl))
635     flags |= SECTION_LINKONCE;
636
637   /* See if we already have an entry for this section.  */
638   slot = (unsigned int **) htab_find_slot (htab, name, INSERT);
639   if (!*slot)
640     {
641       *slot = (unsigned int *) xmalloc (sizeof (unsigned int));
642       **slot = flags;
643     }
644   else
645     {
646       if (decl && **slot != flags)
647         error ("%J'%D' causes a section type conflict", decl, decl);
648     }
649
650   return flags;
651 }
652
653 void
654 i386_pe_asm_named_section (const char *name, unsigned int flags, 
655                            tree decl)
656 {
657   char flagchars[8], *f = flagchars;
658
659   if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0)
660     /* readonly data */
661     {
662       *f++ ='d';  /* This is necessary for older versions of gas.  */
663       *f++ ='r';
664     }
665   else  
666     {
667       if (flags & SECTION_CODE)
668         *f++ = 'x';
669       if (flags & SECTION_WRITE)
670         *f++ = 'w';
671       if (flags & SECTION_PE_SHARED)
672         *f++ = 's';
673     }
674
675   *f = '\0';
676
677   fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
678
679   if (flags & SECTION_LINKONCE)
680     {
681       /* Functions may have been compiled at various levels of
682          optimization so we can't use `same_size' here.
683          Instead, have the linker pick one, without warning.
684          If 'selectany' attribute has been specified,  MS compiler
685          sets 'discard' characteristic, rather than telling linker
686          to warn of size or content mismatch, so do the same.  */ 
687       bool discard = (flags & SECTION_CODE)
688                       || lookup_attribute ("selectany",
689                                            DECL_ATTRIBUTES (decl));      
690       fprintf (asm_out_file, "\t.linkonce %s\n",
691                (discard  ? "discard" : "same_size"));
692     }
693 }
694 \f
695 /* The Microsoft linker requires that every function be marked as
696    DT_FCN.  When using gas on cygwin, we must emit appropriate .type
697    directives.  */
698
699 #include "gsyms.h"
700
701 /* Mark a function appropriately.  This should only be called for
702    functions for which we are not emitting COFF debugging information.
703    FILE is the assembler output file, NAME is the name of the
704    function, and PUBLIC is nonzero if the function is globally
705    visible.  */
706
707 void
708 i386_pe_declare_function_type (FILE *file, const char *name, int public)
709 {
710   fprintf (file, "\t.def\t");
711   assemble_name (file, name);
712   fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
713            public ? (int) C_EXT : (int) C_STAT,
714            (int) DT_FCN << N_BTSHFT);
715 }
716
717 /* Keep a list of external functions.  */
718
719 struct extern_list GTY(())
720 {
721   struct extern_list *next;
722   tree decl;
723   const char *name;
724 };
725
726 static GTY(()) struct extern_list *extern_head;
727
728 /* Assemble an external function reference.  We need to keep a list of
729    these, so that we can output the function types at the end of the
730    assembly.  We can't output the types now, because we might see a
731    definition of the function later on and emit debugging information
732    for it then.  */
733
734 void
735 i386_pe_record_external_function (tree decl, const char *name)
736 {
737   struct extern_list *p;
738
739   p = (struct extern_list *) ggc_alloc (sizeof *p);
740   p->next = extern_head;
741   p->decl = decl;
742   p->name = name;
743   extern_head = p;
744 }
745
746 /* Keep a list of exported symbols.  */
747
748 struct export_list GTY(())
749 {
750   struct export_list *next;
751   const char *name;
752   int is_data;          /* used to type tag exported symbols.  */
753 };
754
755 static GTY(()) struct export_list *export_head;
756
757 /* Assemble an export symbol entry.  We need to keep a list of
758    these, so that we can output the export list at the end of the
759    assembly.  We used to output these export symbols in each function,
760    but that causes problems with GNU ld when the sections are
761    linkonce.  */
762
763 void
764 i386_pe_record_exported_symbol (const char *name, int is_data)
765 {
766   struct export_list *p;
767
768   p = (struct export_list *) ggc_alloc (sizeof *p);
769   p->next = export_head;
770   p->name = name;
771   p->is_data = is_data;
772   export_head = p;
773 }
774
775 /* This is called at the end of assembly.  For each external function
776    which has not been defined, we output a declaration now.  We also
777    output the .drectve section.  */
778
779 void
780 i386_pe_file_end (void)
781 {
782   struct extern_list *p;
783
784   ix86_file_end ();
785
786   for (p = extern_head; p != NULL; p = p->next)
787     {
788       tree decl;
789
790       decl = p->decl;
791
792       /* Positively ensure only one declaration for any given symbol.  */
793       if (! TREE_ASM_WRITTEN (decl)
794           && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
795         {
796           TREE_ASM_WRITTEN (decl) = 1;
797           i386_pe_declare_function_type (asm_out_file, p->name,
798                                          TREE_PUBLIC (decl));
799         }
800     }
801
802   if (export_head)
803     {
804       struct export_list *q;
805       drectve_section ();
806       for (q = export_head; q != NULL; q = q->next)
807         {
808           fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n",
809                    i386_pe_strip_name_encoding (q->name),
810                    (q->is_data) ? ",data" : "");
811         }
812     }
813 }
814
815 #include "gt-winnt.h"