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