OSDN Git Service

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