OSDN Git Service

gcc/ChangeLog:
[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    2005, 2006, 2007, 2008, 2009 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 3, 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 COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "output.h"
30 #include "tree.h"
31 #include "flags.h"
32 #include "tm_p.h"
33 #include "toplev.h"
34 #include "hashtab.h"
35 #include "langhooks.h"
36 #include "ggc.h"
37 #include "target.h"
38
39 /* i386/PE specific attribute support.
40
41    i386/PE has two new attributes:
42    dllexport - for exporting a function/variable that will live in a dll
43    dllimport - for importing a function/variable from a dll
44
45    Microsoft allows multiple declspecs in one __declspec, separating
46    them with spaces.  We do NOT support this.  Instead, use __declspec
47    multiple times.
48 */
49
50 /* Handle a "shared" attribute;
51    arguments as in struct attribute_spec.handler.  */
52 tree
53 ix86_handle_shared_attribute (tree *node, tree name,
54                               tree args ATTRIBUTE_UNUSED,
55                               int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
56 {
57   if (TREE_CODE (*node) != VAR_DECL)
58     {
59       warning (OPT_Wattributes, "%qE attribute only applies to variables",
60                name);
61       *no_add_attrs = true;
62     }
63
64   return NULL_TREE;
65 }
66
67 /* Handle a "selectany" attribute;
68    arguments as in struct attribute_spec.handler.  */
69 tree
70 ix86_handle_selectany_attribute (tree *node, tree name,
71                                  tree args ATTRIBUTE_UNUSED,
72                                  int flags ATTRIBUTE_UNUSED,
73                                  bool *no_add_attrs)
74 {
75   /* The attribute applies only to objects that are initialized and have
76      external linkage.  However, we may not know about initialization
77      until the language frontend has processed the decl. We'll check for
78      initialization later in encode_section_info.  */
79   if (TREE_CODE (*node) != VAR_DECL || !TREE_PUBLIC (*node))
80     {   
81       error ("%qE attribute applies only to initialized variables"
82              " with external linkage", name);
83       *no_add_attrs = true;
84     }
85
86   return NULL_TREE;
87 }
88
89 \f
90 /* Return the type that we should use to determine if DECL is
91    imported or exported.  */
92
93 static tree
94 associated_type (tree decl)
95 {
96   return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))
97           ?  DECL_CONTEXT (decl) : NULL_TREE);
98 }
99
100 /* Return true if DECL should be a dllexport'd object.  */
101
102 static bool
103 i386_pe_determine_dllexport_p (tree decl)
104 {
105   if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
106     return false;
107
108   /* Don't export local clones of dllexports.  */
109   if (!TREE_PUBLIC (decl))
110     return false;
111
112   if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
113     return true;
114
115   return false;
116 }
117
118 /* Return true if DECL should be a dllimport'd object.  */
119
120 static bool
121 i386_pe_determine_dllimport_p (tree decl)
122 {
123   tree assoc;
124
125   if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
126     return false;
127
128   if (DECL_DLLIMPORT_P (decl))
129     return true;
130
131   /* The DECL_DLLIMPORT_P flag was set for decls in the class definition
132      by  targetm.cxx.adjust_class_at_definition.  Check again to emit
133      error message if the class attribute has been overridden by an
134      out-of-class definition of static data.  */
135   assoc = associated_type (decl);
136   if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc))
137       && TREE_CODE (decl) == VAR_DECL
138       && TREE_STATIC (decl) && TREE_PUBLIC (decl)
139       && !DECL_EXTERNAL (decl)
140       /* vtable's are linkonce constants, so defining a vtable is not
141          an error as long as we don't try to import it too.  */
142       && !DECL_VIRTUAL_P (decl))
143         error ("definition of static data member %q+D of "
144                "dllimport'd class", decl);
145
146   return false;
147 }
148
149 /* Handle the -mno-fun-dllimport target switch.  */
150
151 bool
152 i386_pe_valid_dllimport_attribute_p (const_tree decl)
153 {
154    if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
155      return false;
156    return true;
157 }
158
159 /* Return string which is the function name, identified by ID, modified
160    with a suffix consisting of an atsign (@) followed by the number of
161    bytes of arguments.  If ID is NULL use the DECL_NAME as base. If
162    FASTCALL is true, also add the FASTCALL_PREFIX.
163    Return NULL if no change required.  */
164
165 static tree
166 gen_stdcall_or_fastcall_suffix (tree decl, tree id, bool fastcall)
167 {
168   HOST_WIDE_INT total = 0;
169   const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl));
170   char *new_str, *p;
171   tree type = TREE_TYPE (decl);
172   tree arg;
173   function_args_iterator args_iter;
174
175   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);  
176
177   if (prototype_p (type))
178     {
179       /* This attribute is ignored for variadic functions.  */ 
180       if (stdarg_p (type))
181         return NULL_TREE;
182
183       /* Quit if we hit an incomplete type.  Error is reported
184          by convert_arguments in c-typeck.c or cp/typeck.c.  */
185       FOREACH_FUNCTION_ARGS(type, arg, args_iter)
186         {
187           HOST_WIDE_INT parm_size;
188           HOST_WIDE_INT parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT;
189
190           if (! COMPLETE_TYPE_P (arg))
191             break;
192
193           parm_size = int_size_in_bytes (arg);
194           if (parm_size < 0)
195             break;
196
197           /* Must round up to include padding.  This is done the same
198              way as in store_one_arg.  */
199           parm_size = ((parm_size + parm_boundary_bytes - 1)
200                        / parm_boundary_bytes * parm_boundary_bytes);
201           total += parm_size;
202         }
203       }
204   /* Assume max of 8 base 10 digits in the suffix.  */
205   p = new_str = XALLOCAVEC (char, 1 + strlen (old_str) + 1 + 8 + 1);
206   if (fastcall)
207     *p++ = FASTCALL_PREFIX;
208   sprintf (p, "%s@" HOST_WIDE_INT_PRINT_DEC, old_str, total);
209
210   return get_identifier (new_str);
211 }
212
213 /* Maybe decorate and get a new identifier for the DECL of a stdcall or
214    fastcall function. The original identifier is supplied in ID. */
215
216 static tree
217 i386_pe_maybe_mangle_decl_assembler_name (tree decl, tree id)
218 {
219   tree new_id = NULL_TREE;
220
221   if (TREE_CODE (decl) == FUNCTION_DECL)
222     { 
223       tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
224       if (lookup_attribute ("stdcall", type_attributes))
225         new_id = gen_stdcall_or_fastcall_suffix (decl, id, false);
226       else if (lookup_attribute ("fastcall", type_attributes))
227         new_id = gen_stdcall_or_fastcall_suffix (decl, id, true);
228     }
229
230   return new_id;
231 }
232
233 /* This is used as a target hook to modify the DECL_ASSEMBLER_NAME
234    in the language-independent default hook
235    langhooks,c:lhd_set_decl_assembler_name ()
236    and in cp/mangle,c:mangle_decl ().  */
237 tree
238 i386_pe_mangle_decl_assembler_name (tree decl, tree id)
239 {
240   tree new_id = i386_pe_maybe_mangle_decl_assembler_name (decl, id);   
241
242   return (new_id ? new_id : id);
243 }
244
245 void
246 i386_pe_encode_section_info (tree decl, rtx rtl, int first)
247 {
248   rtx symbol;
249   int flags;
250
251   /* Do this last, due to our frobbing of DECL_DLLIMPORT_P above.  */
252   default_encode_section_info (decl, rtl, first);
253
254   /* Careful not to prod global register variables.  */
255   if (!MEM_P (rtl))
256     return;
257
258   symbol = XEXP (rtl, 0);
259   gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
260
261   switch (TREE_CODE (decl))
262     {
263     case FUNCTION_DECL:
264       /* FIXME:  Imported stdcall names are not modified by the Ada frontend.
265          Check and decorate the RTL name now.  */
266       if  (strcmp (lang_hooks.name, "GNU Ada") == 0)
267         {
268           tree new_id;
269           tree old_id = DECL_ASSEMBLER_NAME (decl);
270           const char* asm_str = IDENTIFIER_POINTER (old_id);
271           /* Do not change the identifier if a verbatim asmspec
272              or if stdcall suffix already added. */
273           if (!(*asm_str == '*' || strchr (asm_str, '@'))
274               && (new_id = i386_pe_maybe_mangle_decl_assembler_name (decl,
275                                                                      old_id)))
276             XSTR (symbol, 0) = IDENTIFIER_POINTER (new_id);
277         }
278       break;
279
280     case VAR_DECL:
281       if (lookup_attribute ("selectany", DECL_ATTRIBUTES (decl)))
282         {
283           if (DECL_INITIAL (decl)
284               /* If an object is initialized with a ctor, the static
285                  initialization and destruction code for it is present in
286                  each unit defining the object.  The code that calls the
287                  ctor is protected by a link-once guard variable, so that
288                  the object still has link-once semantics,  */
289               || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
290             make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
291           else
292             error ("%q+D:'selectany' attribute applies only to "
293                    "initialized objects", decl);
294         }
295       break;
296
297     default:
298       return;
299     }
300
301   /* Mark the decl so we can tell from the rtl whether the object is
302      dllexport'd or dllimport'd.  tree.c: merge_dllimport_decl_attributes
303      handles dllexport/dllimport override semantics.  */
304   flags = (SYMBOL_REF_FLAGS (symbol) &
305            ~(SYMBOL_FLAG_DLLIMPORT | SYMBOL_FLAG_DLLEXPORT));
306   if (i386_pe_determine_dllexport_p (decl))
307     flags |= SYMBOL_FLAG_DLLEXPORT;
308   else if (i386_pe_determine_dllimport_p (decl))
309     flags |= SYMBOL_FLAG_DLLIMPORT;
310  
311   SYMBOL_REF_FLAGS (symbol) = flags;
312 }
313
314 bool
315 i386_pe_binds_local_p (const_tree exp)
316 {
317   /* PE does not do dynamic binding.  Indeed, the only kind of
318      non-local reference comes from a dllimport'd symbol.  */
319   if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
320       && DECL_DLLIMPORT_P (exp))
321     return false;
322
323   return true;
324 }
325
326 /* Also strip the fastcall prefix and stdcall suffix.  */
327
328 const char *
329 i386_pe_strip_name_encoding_full (const char *str)
330 {
331   const char *p;
332   const char *name = default_strip_name_encoding (str);
333
334   /* Strip leading '@' on fastcall symbols.  */
335   if (*name == '@')
336     name++;
337
338   /* Strip trailing "@n".  */
339   p = strchr (name, '@');
340   if (p)
341     return ggc_alloc_string (name, p - name);
342
343   return name;
344 }
345
346 void
347 i386_pe_unique_section (tree decl, int reloc)
348 {
349   int len;
350   const char *name, *prefix;
351   char *string;
352
353   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
354   name = i386_pe_strip_name_encoding_full (name);
355
356   /* The object is put in, for example, section .text$foo.
357      The linker will then ultimately place them in .text
358      (everything from the $ on is stripped). Don't put
359      read-only data in .rdata section to avoid a PE linker
360      bug when .rdata$* grouped sections are used in code
361      without a .rdata section.  */
362   if (TREE_CODE (decl) == FUNCTION_DECL)
363     prefix = ".text$";
364   else if (decl_readonly_section (decl, reloc))
365     prefix = ".rdata$";
366   else
367     prefix = ".data$";
368   len = strlen (name) + strlen (prefix);
369   string = XALLOCAVEC (char, len + 1);
370   sprintf (string, "%s%s", prefix, name);
371
372   DECL_SECTION_NAME (decl) = build_string (len, string);
373 }
374
375 /* Select a set of attributes for section NAME based on the properties
376    of DECL and whether or not RELOC indicates that DECL's initializer
377    might contain runtime relocations.
378
379    We make the section read-only and executable for a function decl,
380    read-only for a const data decl, and writable for a non-const data decl.
381
382    If the section has already been defined, to not allow it to have
383    different attributes, as (1) this is ambiguous since we're not seeing
384    all the declarations up front and (2) some assemblers (e.g. SVR4)
385    do not recognize section redefinitions.  */
386 /* ??? This differs from the "standard" PE implementation in that we
387    handle the SHARED variable attribute.  Should this be done for all
388    PE targets?  */
389
390 #define SECTION_PE_SHARED       SECTION_MACH_DEP
391
392 unsigned int
393 i386_pe_section_type_flags (tree decl, const char *name, int reloc)
394 {
395   static htab_t htab;
396   unsigned int flags;
397   unsigned int **slot;
398
399   /* The names we put in the hashtable will always be the unique
400      versions given to us by the stringtable, so we can just use
401      their addresses as the keys.  */
402   if (!htab)
403     htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL);
404
405   if (decl && TREE_CODE (decl) == FUNCTION_DECL)
406     flags = SECTION_CODE;
407   else if (decl && decl_readonly_section (decl, reloc))
408     flags = 0;
409   else if (current_function_decl
410            && cfun
411            && crtl->subsections.unlikely_text_section_name
412            && strcmp (name, crtl->subsections.unlikely_text_section_name) == 0)
413     flags = SECTION_CODE;
414   else if (!decl
415            && (!current_function_decl || !cfun)
416            && strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
417     flags = SECTION_CODE;
418   else
419     {
420       flags = SECTION_WRITE;
421
422       if (decl && TREE_CODE (decl) == VAR_DECL
423           && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
424         flags |= SECTION_PE_SHARED;
425     }
426
427   if (decl && DECL_ONE_ONLY (decl))
428     flags |= SECTION_LINKONCE;
429
430   /* See if we already have an entry for this section.  */
431   slot = (unsigned int **) htab_find_slot (htab, name, INSERT);
432   if (!*slot)
433     {
434       *slot = (unsigned int *) xmalloc (sizeof (unsigned int));
435       **slot = flags;
436     }
437   else
438     {
439       if (decl && **slot != flags)
440         error ("%q+D causes a section type conflict", decl);
441     }
442
443   return flags;
444 }
445
446 void
447 i386_pe_asm_named_section (const char *name, unsigned int flags, 
448                            tree decl)
449 {
450   char flagchars[8], *f = flagchars;
451
452   if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0)
453     /* readonly data */
454     {
455       *f++ ='d';  /* This is necessary for older versions of gas.  */
456       *f++ ='r';
457     }
458   else  
459     {
460       if (flags & SECTION_CODE)
461         *f++ = 'x';
462       if (flags & SECTION_WRITE)
463         *f++ = 'w';
464       if (flags & SECTION_PE_SHARED)
465         *f++ = 's';
466     }
467
468   *f = '\0';
469
470   fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
471
472   if (flags & SECTION_LINKONCE)
473     {
474       /* Functions may have been compiled at various levels of
475          optimization so we can't use `same_size' here.
476          Instead, have the linker pick one, without warning.
477          If 'selectany' attribute has been specified,  MS compiler
478          sets 'discard' characteristic, rather than telling linker
479          to warn of size or content mismatch, so do the same.  */ 
480       bool discard = (flags & SECTION_CODE)
481                       || lookup_attribute ("selectany",
482                                            DECL_ATTRIBUTES (decl));      
483       fprintf (asm_out_file, "\t.linkonce %s\n",
484                (discard  ? "discard" : "same_size"));
485     }
486 }
487
488 void
489 i386_pe_asm_output_aligned_decl_common (FILE *stream, tree decl,
490                                         const char *name, HOST_WIDE_INT size,
491                                         HOST_WIDE_INT align ATTRIBUTE_UNUSED)
492 {
493   HOST_WIDE_INT rounded;
494
495   /* Compute as in assemble_noswitch_variable, since we don't have
496      support for aligned common on older binutils.  We must also
497      avoid emitting a common symbol of size zero, as this is the
498      overloaded representation that indicates an undefined external
499      symbol in the PE object file format.  */
500   rounded = size ? size : 1;
501   rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
502   rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
503              * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
504   
505   i386_pe_maybe_record_exported_symbol (decl, name, 1);
506
507   fprintf (stream, "\t.comm\t");
508   assemble_name (stream, name);
509   if (use_pe_aligned_common)
510     fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC ", %d\n",
511            size ? size : (HOST_WIDE_INT) 1,
512            exact_log2 (align) - exact_log2 (CHAR_BIT));
513   else
514     fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START
515            " " HOST_WIDE_INT_PRINT_DEC "\n", rounded, size);
516 }
517 \f
518 /* The Microsoft linker requires that every function be marked as
519    DT_FCN.  When using gas on cygwin, we must emit appropriate .type
520    directives.  */
521
522 #include "gsyms.h"
523
524 /* Mark a function appropriately.  This should only be called for
525    functions for which we are not emitting COFF debugging information.
526    FILE is the assembler output file, NAME is the name of the
527    function, and PUB is nonzero if the function is globally
528    visible.  */
529
530 void
531 i386_pe_declare_function_type (FILE *file, const char *name, int pub)
532 {
533   fprintf (file, "\t.def\t");
534   assemble_name (file, name);
535   fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
536            pub ? (int) C_EXT : (int) C_STAT,
537            (int) DT_FCN << N_BTSHFT);
538 }
539
540 /* Keep a list of external functions.  */
541
542 struct GTY(()) extern_list
543 {
544   struct extern_list *next;
545   tree decl;
546   const char *name;
547 };
548
549 static GTY(()) struct extern_list *extern_head;
550
551 /* Assemble an external function reference.  We need to keep a list of
552    these, so that we can output the function types at the end of the
553    assembly.  We can't output the types now, because we might see a
554    definition of the function later on and emit debugging information
555    for it then.  */
556
557 void
558 i386_pe_record_external_function (tree decl, const char *name)
559 {
560   struct extern_list *p;
561
562   p = (struct extern_list *) ggc_alloc (sizeof *p);
563   p->next = extern_head;
564   p->decl = decl;
565   p->name = name;
566   extern_head = p;
567 }
568
569 /* Keep a list of exported symbols.  */
570
571 struct GTY(()) export_list
572 {
573   struct export_list *next;
574   const char *name;
575   int is_data;          /* used to type tag exported symbols.  */
576 };
577
578 static GTY(()) struct export_list *export_head;
579
580 /* Assemble an export symbol entry.  We need to keep a list of
581    these, so that we can output the export list at the end of the
582    assembly.  We used to output these export symbols in each function,
583    but that causes problems with GNU ld when the sections are
584    linkonce.  */
585
586 void
587 i386_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_data)
588 {
589   rtx symbol;
590   struct export_list *p;
591
592   symbol = XEXP (DECL_RTL (decl), 0);
593   gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
594   if (!SYMBOL_REF_DLLEXPORT_P (symbol))
595     return;
596
597   gcc_assert (TREE_PUBLIC (decl));
598
599   p = (struct export_list *) ggc_alloc (sizeof *p);
600   p->next = export_head;
601   p->name = name;
602   p->is_data = is_data;
603   export_head = p;
604 }
605
606 #ifdef CXX_WRAP_SPEC_LIST
607
608 /*  Hash table equality helper function.  */
609
610 static int
611 wrapper_strcmp (const void *x, const void *y)
612 {
613   return !strcmp ((const char *) x, (const char *) y);
614 }
615
616 /* Search for a function named TARGET in the list of library wrappers
617    we are using, returning a pointer to it if found or NULL if not.
618    This function might be called on quite a few symbols, and we only
619    have the list of names of wrapped functions available to us as a
620    spec string, so first time round we lazily initialise a hash table
621    to make things quicker.  */
622
623 static const char *
624 i386_find_on_wrapper_list (const char *target)
625 {
626   static char first_time = 1;
627   static htab_t wrappers;
628
629   if (first_time)
630     {
631       /* Beware that this is not a complicated parser, it assumes
632          that any sequence of non-whitespace beginning with an
633          underscore is one of the wrapped symbols.  For now that's
634          adequate to distinguish symbols from spec substitutions
635          and command-line options.  */
636       static char wrapper_list_buffer[] = CXX_WRAP_SPEC_LIST;
637       char *bufptr;
638       /* Breaks up the char array into separated strings
639          strings and enter them into the hash table.  */
640       wrappers = htab_create_alloc (8, htab_hash_string, wrapper_strcmp,
641         0, xcalloc, free);
642       for (bufptr = wrapper_list_buffer; *bufptr; ++bufptr)
643         {
644           char *found = NULL;
645           if (ISSPACE (*bufptr))
646             continue;
647           if (*bufptr == '_')
648             found = bufptr;
649           while (*bufptr && !ISSPACE (*bufptr))
650             ++bufptr;
651           if (*bufptr)
652             *bufptr = 0;
653           if (found)
654             *htab_find_slot (wrappers, found, INSERT) = found;
655         }
656       first_time = 0;
657     }
658
659   return (const char *) htab_find (wrappers, target);
660 }
661
662 #endif /* CXX_WRAP_SPEC_LIST */
663
664 /* This is called at the end of assembly.  For each external function
665    which has not been defined, we output a declaration now.  We also
666    output the .drectve section.  */
667
668 void
669 i386_pe_file_end (void)
670 {
671   struct extern_list *p;
672
673   ix86_file_end ();
674
675   for (p = extern_head; p != NULL; p = p->next)
676     {
677       tree decl;
678
679       decl = p->decl;
680
681       /* Positively ensure only one declaration for any given symbol.  */
682       if (! TREE_ASM_WRITTEN (decl)
683           && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
684         {
685 #ifdef CXX_WRAP_SPEC_LIST
686           /* To ensure the DLL that provides the corresponding real
687              functions is still loaded at runtime, we must reference
688              the real function so that an (unused) import is created.  */
689           const char *realsym = i386_find_on_wrapper_list (p->name);
690           if (realsym)
691             i386_pe_declare_function_type (asm_out_file,
692                 concat ("__real_", realsym, NULL), TREE_PUBLIC (decl));
693 #endif /* CXX_WRAP_SPEC_LIST */
694           TREE_ASM_WRITTEN (decl) = 1;
695           i386_pe_declare_function_type (asm_out_file, p->name,
696                                          TREE_PUBLIC (decl));
697         }
698     }
699
700   if (export_head)
701     {
702       struct export_list *q;
703       drectve_section ();
704       for (q = export_head; q != NULL; q = q->next)
705         {
706           fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n",
707                    default_strip_name_encoding (q->name),
708                    (q->is_data ? ",data" : ""));
709         }
710     }
711 }
712
713 #include "gt-winnt.h"