OSDN Git Service

c4326f01a287522db058d401521fb666248023de
[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 fastcall prefix and 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   /* Strip leading '@' on fastcall symbols.  */
570   if (*name == '@')
571     name++;
572
573   /* Strip trailing "@n".  */
574   p = strchr (name, '@');
575   if (p)
576     return ggc_alloc_string (name, p - name);
577
578   return name;
579 }
580
581 /* Output a reference to a label. Fastcall symbols are prefixed with @,
582    whereas symbols for functions using other calling conventions don't
583    have a prefix (unless they are marked dllimport or dllexport).  */
584
585 void i386_pe_output_labelref (FILE *stream, const char *name)
586 {
587   if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
588       == 0)
589     /* A dll import */
590     {
591       if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX)
592       /* A dllimport fastcall symbol.  */
593         {
594           fprintf (stream, "__imp_%s",
595                    i386_pe_strip_name_encoding (name));
596         }
597       else
598       /* A dllimport non-fastcall symbol.  */
599         {
600           fprintf (stream, "__imp__%s",
601                    i386_pe_strip_name_encoding (name));
602         }
603     }
604   else if ((name[0] == FASTCALL_PREFIX)
605            || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX)
606                == 0
607                && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX)))
608     /* A fastcall symbol.  */
609     {
610       fprintf (stream, "%s",
611                i386_pe_strip_name_encoding (name));
612     }
613   else
614     /* Everything else.  */
615     {
616       fprintf (stream, "%s%s", USER_LABEL_PREFIX,
617                i386_pe_strip_name_encoding (name));
618     }
619 }
620
621 void
622 i386_pe_unique_section (tree decl, int reloc)
623 {
624   int len;
625   const char *name, *prefix;
626   char *string;
627
628   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
629   name = i386_pe_strip_name_encoding_full (name);
630
631   /* The object is put in, for example, section .text$foo.
632      The linker will then ultimately place them in .text
633      (everything from the $ on is stripped). Don't put
634      read-only data in .rdata section to avoid a PE linker
635      bug when .rdata$* grouped sections are used in code
636      without a .rdata section.  */
637   if (TREE_CODE (decl) == FUNCTION_DECL)
638     prefix = ".text$";
639   else if (decl_readonly_section (decl, reloc))
640     prefix = ".rdata$";
641   else
642     prefix = ".data$";
643   len = strlen (name) + strlen (prefix);
644   string = alloca (len + 1);
645   sprintf (string, "%s%s", prefix, name);
646
647   DECL_SECTION_NAME (decl) = build_string (len, string);
648 }
649
650 /* Select a set of attributes for section NAME based on the properties
651    of DECL and whether or not RELOC indicates that DECL's initializer
652    might contain runtime relocations.
653
654    We make the section read-only and executable for a function decl,
655    read-only for a const data decl, and writable for a non-const data decl.
656
657    If the section has already been defined, to not allow it to have
658    different attributes, as (1) this is ambiguous since we're not seeing
659    all the declarations up front and (2) some assemblers (e.g. SVR4)
660    do not recognize section redefinitions.  */
661 /* ??? This differs from the "standard" PE implementation in that we
662    handle the SHARED variable attribute.  Should this be done for all
663    PE targets?  */
664
665 #define SECTION_PE_SHARED       SECTION_MACH_DEP
666
667 unsigned int
668 i386_pe_section_type_flags (tree decl, const char *name, int reloc)
669 {
670   static htab_t htab;
671   unsigned int flags;
672   unsigned int **slot;
673
674   /* The names we put in the hashtable will always be the unique
675      versions gived to us by the stringtable, so we can just use
676      their addresses as the keys.  */
677   if (!htab)
678     htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL);
679
680   if (decl && TREE_CODE (decl) == FUNCTION_DECL)
681     flags = SECTION_CODE;
682   else if (decl && decl_readonly_section (decl, reloc))
683     flags = 0;
684   else
685     {
686       flags = SECTION_WRITE;
687
688       if (decl && TREE_CODE (decl) == VAR_DECL
689           && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
690         flags |= SECTION_PE_SHARED;
691     }
692
693   if (decl && DECL_ONE_ONLY (decl))
694     flags |= SECTION_LINKONCE;
695
696   /* See if we already have an entry for this section.  */
697   slot = (unsigned int **) htab_find_slot (htab, name, INSERT);
698   if (!*slot)
699     {
700       *slot = (unsigned int *) xmalloc (sizeof (unsigned int));
701       **slot = flags;
702     }
703   else
704     {
705       if (decl && **slot != flags)
706         error ("%J'%D' causes a section type conflict", decl, decl);
707     }
708
709   return flags;
710 }
711
712 void
713 i386_pe_asm_named_section (const char *name, unsigned int flags)
714 {
715   char flagchars[8], *f = flagchars;
716
717   if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0)
718     /* readonly data */
719     {
720       *f++ ='d';  /* This is necessary for older versions of gas.  */
721       *f++ ='r';
722     }
723   else  
724     {
725       if (flags & SECTION_CODE)
726         *f++ = 'x';
727       if (flags & SECTION_WRITE)
728         *f++ = 'w';
729       if (flags & SECTION_PE_SHARED)
730         *f++ = 's';
731     }
732
733   *f = '\0';
734
735   fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
736
737   if (flags & SECTION_LINKONCE)
738     {
739       /* Functions may have been compiled at various levels of
740          optimization so we can't use `same_size' here.
741          Instead, have the linker pick one.  */
742       fprintf (asm_out_file, "\t.linkonce %s\n",
743                (flags & SECTION_CODE ? "discard" : "same_size"));
744     }
745 }
746 \f
747 /* The Microsoft linker requires that every function be marked as
748    DT_FCN.  When using gas on cygwin, we must emit appropriate .type
749    directives.  */
750
751 #include "gsyms.h"
752
753 /* Mark a function appropriately.  This should only be called for
754    functions for which we are not emitting COFF debugging information.
755    FILE is the assembler output file, NAME is the name of the
756    function, and PUBLIC is nonzero if the function is globally
757    visible.  */
758
759 void
760 i386_pe_declare_function_type (FILE *file, const char *name, int public)
761 {
762   fprintf (file, "\t.def\t");
763   assemble_name (file, name);
764   fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
765            public ? (int) C_EXT : (int) C_STAT,
766            (int) DT_FCN << N_BTSHFT);
767 }
768
769 /* Keep a list of external functions.  */
770
771 struct extern_list
772 {
773   struct extern_list *next;
774   const char *name;
775 };
776
777 static struct extern_list *extern_head;
778
779 /* Assemble an external function reference.  We need to keep a list of
780    these, so that we can output the function types at the end of the
781    assembly.  We can't output the types now, because we might see a
782    definition of the function later on and emit debugging information
783    for it then.  */
784
785 void
786 i386_pe_record_external_function (const char *name)
787 {
788   struct extern_list *p;
789
790   p = (struct extern_list *) xmalloc (sizeof *p);
791   p->next = extern_head;
792   p->name = name;
793   extern_head = p;
794 }
795
796 /* Keep a list of exported symbols.  */
797
798 struct export_list
799 {
800   struct export_list *next;
801   const char *name;
802   int is_data;          /* used to type tag exported symbols.  */
803 };
804
805 static struct export_list *export_head;
806
807 /* Assemble an export symbol entry.  We need to keep a list of
808    these, so that we can output the export list at the end of the
809    assembly.  We used to output these export symbols in each function,
810    but that causes problems with GNU ld when the sections are
811    linkonce.  */
812
813 void
814 i386_pe_record_exported_symbol (const char *name, int is_data)
815 {
816   struct export_list *p;
817
818   p = (struct export_list *) xmalloc (sizeof *p);
819   p->next = export_head;
820   p->name = name;
821   p->is_data = is_data;
822   export_head = p;
823 }
824
825 /* This is called at the end of assembly.  For each external function
826    which has not been defined, we output a declaration now.  We also
827    output the .drectve section.  */
828
829 void
830 i386_pe_file_end (void)
831 {
832   struct extern_list *p;
833
834   ix86_file_end ();
835
836   for (p = extern_head; p != NULL; p = p->next)
837     {
838       tree decl;
839
840       decl = get_identifier (p->name);
841
842       /* Positively ensure only one declaration for any given symbol.  */
843       if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl))
844         {
845           TREE_ASM_WRITTEN (decl) = 1;
846           i386_pe_declare_function_type (asm_out_file, p->name,
847                                          TREE_PUBLIC (decl));
848         }
849     }
850
851   if (export_head)
852     {
853       struct export_list *q;
854       drectve_section ();
855       for (q = export_head; q != NULL; q = q->next)
856         {
857           fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n",
858                    i386_pe_strip_name_encoding (q->name),
859                    (q->is_data) ? ",data" : "");
860         }
861     }
862 }