]> gcc.gnu.org Git - gcc.git/blame - gcc/config/i386/winnt.c
varasm.c (named_section_flags): Remove align parameter.
[gcc.git] / gcc / config / i386 / winnt.c
CommitLineData
30c71308
RK
1/* Subroutines for insn-output.c for Windows NT.
2 Contributed by Douglas Rupp (drupp@cs.washington.edu)
c675621f 3 Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
30c71308
RK
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
97aadbb9
RK
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
30c71308 21
30c71308 22#include "config.h"
293bcdc9 23#include "system.h"
30c71308
RK
24#include "rtl.h"
25#include "regs.h"
26#include "hard-reg-set.h"
27#include "output.h"
28#include "tree.h"
29#include "flags.h"
79f96374
DB
30#include "tm_p.h"
31#include "toplev.h"
7c262518 32#include "hashtab.h"
30c71308 33
27da1b4d
MK
34/* i386/PE specific attribute support.
35
36 i386/PE has two new attributes:
37 dllexport - for exporting a function/variable that will live in a dll
38 dllimport - for importing a function/variable from a dll
39
40 Microsoft allows multiple declspecs in one __declspec, separating
41 them with spaces. We do NOT support this. Instead, use __declspec
42 multiple times.
43*/
44
79f96374
DB
45static tree associated_type PARAMS ((tree));
46const char * gen_stdcall_suffix PARAMS ((tree));
47int i386_pe_dllexport_p PARAMS ((tree));
48int i386_pe_dllimport_p PARAMS ((tree));
49void i386_pe_mark_dllexport PARAMS ((tree));
50void i386_pe_mark_dllimport PARAMS ((tree));
51
27da1b4d
MK
52/* Return nonzero if ATTR is a valid attribute for DECL.
53 ATTRIBUTES are any existing attributes and ARGS are the arguments
54 supplied with ATTR. */
55
56int
57i386_pe_valid_decl_attribute_p (decl, attributes, attr, args)
58 tree decl;
7c262518 59 tree attributes ATTRIBUTE_UNUSED;
27da1b4d
MK
60 tree attr;
61 tree args;
62{
ac478ac0
JM
63 if (args == NULL_TREE)
64 {
65 if (is_attribute_p ("dllexport", attr))
66 return 1;
67 if (is_attribute_p ("dllimport", attr))
68 return 1;
593d3a34
MK
69 if (is_attribute_p ("shared", attr))
70 return TREE_CODE (decl) == VAR_DECL;
ac478ac0 71 }
27da1b4d 72
f5f4be42 73 return 0;
27da1b4d
MK
74}
75
ac478ac0
JM
76/* Return nonzero if ATTR is a valid attribute for TYPE.
77 ATTRIBUTES are any existing attributes and ARGS are the arguments
78 supplied with ATTR. */
79
80int
81i386_pe_valid_type_attribute_p (type, attributes, attr, args)
82 tree type;
83 tree attributes;
84 tree attr;
85 tree args;
86{
87 if (args == NULL_TREE
88 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
89 {
90 if (is_attribute_p ("dllexport", attr))
91 return 1;
92 if (is_attribute_p ("dllimport", attr))
93 return 1;
94 }
95
e075ae69 96 return ix86_valid_type_attribute_p (type, attributes, attr, args);
ac478ac0 97}
27da1b4d 98\f
ac478ac0
JM
99/* Return the type that we should use to determine if DECL is
100 imported or exported. */
27da1b4d 101
ac478ac0
JM
102static tree
103associated_type (decl)
104 tree decl;
27da1b4d 105{
ac478ac0 106 tree t = NULL_TREE;
27da1b4d 107
ac478ac0
JM
108 /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer
109 to the containing class. So we look at the 'this' arg. */
110 if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
27da1b4d 111 {
ac478ac0
JM
112 /* Artificial methods are not affected by the import/export status of
113 their class unless they are virtual. */
114 if (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl))
115 t = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))));
27da1b4d 116 }
ac478ac0
JM
117 else if (DECL_CONTEXT (decl)
118 && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
119 t = DECL_CONTEXT (decl);
27da1b4d 120
ac478ac0 121 return t;
27da1b4d
MK
122}
123
124/* Return non-zero if DECL is a dllexport'd object. */
125
27da1b4d
MK
126int
127i386_pe_dllexport_p (decl)
128 tree decl;
129{
130 tree exp;
131
132 if (TREE_CODE (decl) != VAR_DECL
133 && TREE_CODE (decl) != FUNCTION_DECL)
134 return 0;
135 exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
136 if (exp)
137 return 1;
138
ac478ac0
JM
139 /* Class members get the dllexport status of their class. */
140 if (associated_type (decl))
27da1b4d 141 {
ac478ac0
JM
142 exp = lookup_attribute ("dllexport",
143 TYPE_ATTRIBUTES (associated_type (decl)));
144 if (exp)
27da1b4d
MK
145 return 1;
146 }
27da1b4d
MK
147
148 return 0;
149}
150
151/* Return non-zero if DECL is a dllimport'd object. */
152
153int
154i386_pe_dllimport_p (decl)
155 tree decl;
156{
157 tree imp;
158
159 if (TREE_CODE (decl) == FUNCTION_DECL
160 && TARGET_NOP_FUN_DLLIMPORT)
161 return 0;
162
163 if (TREE_CODE (decl) != VAR_DECL
164 && TREE_CODE (decl) != FUNCTION_DECL)
165 return 0;
166 imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
167 if (imp)
168 return 1;
169
ac478ac0
JM
170 /* Class members get the dllimport status of their class. */
171 if (associated_type (decl))
27da1b4d 172 {
ac478ac0
JM
173 imp = lookup_attribute ("dllimport",
174 TYPE_ATTRIBUTES (associated_type (decl)));
175 if (imp)
27da1b4d
MK
176 return 1;
177 }
27da1b4d
MK
178
179 return 0;
180}
181
182/* Return non-zero if SYMBOL is marked as being dllexport'd. */
183
184int
185i386_pe_dllexport_name_p (symbol)
79f96374 186 const char *symbol;
27da1b4d
MK
187{
188 return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.';
189}
190
191/* Return non-zero if SYMBOL is marked as being dllimport'd. */
192
193int
194i386_pe_dllimport_name_p (symbol)
79f96374 195 const char *symbol;
27da1b4d
MK
196{
197 return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.';
198}
199
200/* Mark a DECL as being dllexport'd.
201 Note that we override the previous setting (eg: dllimport). */
202
203void
204i386_pe_mark_dllexport (decl)
205 tree decl;
206{
79f96374
DB
207 const char *oldname;
208 char *newname;
27da1b4d
MK
209 rtx rtlname;
210 tree idp;
211
212 rtlname = XEXP (DECL_RTL (decl), 0);
213 if (GET_CODE (rtlname) == SYMBOL_REF)
214 oldname = XSTR (rtlname, 0);
215 else if (GET_CODE (rtlname) == MEM
216 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
217 oldname = XSTR (XEXP (rtlname, 0), 0);
218 else
219 abort ();
220 if (i386_pe_dllimport_name_p (oldname))
221 oldname += 9;
222 else if (i386_pe_dllexport_name_p (oldname))
223 return; /* already done */
224
225 newname = alloca (strlen (oldname) + 4);
226 sprintf (newname, "@e.%s", oldname);
227
228 /* We pass newname through get_identifier to ensure it has a unique
229 address. RTL processing can sometimes peek inside the symbol ref
230 and compare the string's addresses to see if two symbols are
231 identical. */
232 idp = get_identifier (newname);
233
234 XEXP (DECL_RTL (decl), 0) =
235 gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
236}
237
238/* Mark a DECL as being dllimport'd. */
239
240void
241i386_pe_mark_dllimport (decl)
242 tree decl;
243{
79f96374
DB
244 const char *oldname;
245 char *newname;
27da1b4d
MK
246 tree idp;
247 rtx rtlname, newrtl;
248
249 rtlname = XEXP (DECL_RTL (decl), 0);
250 if (GET_CODE (rtlname) == SYMBOL_REF)
251 oldname = XSTR (rtlname, 0);
252 else if (GET_CODE (rtlname) == MEM
253 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
254 oldname = XSTR (XEXP (rtlname, 0), 0);
255 else
256 abort ();
257 if (i386_pe_dllexport_name_p (oldname))
258 {
259 error ("`%s' declared as both exported to and imported from a DLL.",
260 IDENTIFIER_POINTER (DECL_NAME (decl)));
261 return;
262 }
263 else if (i386_pe_dllimport_name_p (oldname))
264 {
265 /* Already done, but force correct linkage since the redeclaration
266 might have omitted explicit extern. Sigh. */
267 if (TREE_CODE (decl) == VAR_DECL
268 /* ??? Is this test for vtables needed? */
269 && !DECL_VIRTUAL_P (decl))
270 {
271 DECL_EXTERNAL (decl) = 1;
272 TREE_PUBLIC (decl) = 1;
273 }
274 return;
275 }
276
277 /* ??? One can well ask why we're making these checks here,
278 and that would be a good question. */
279
280 /* Imported variables can't be initialized. Note that C++ classes
281 are marked initial, so we need to check. */
282 if (TREE_CODE (decl) == VAR_DECL
283 && !DECL_VIRTUAL_P (decl)
284 && (DECL_INITIAL (decl)
285 && ! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
286 {
287 error_with_decl (decl, "initialized variable `%s' is marked dllimport");
288 return;
289 }
290 /* Nor can they be static. */
291 if (TREE_CODE (decl) == VAR_DECL
292 /* ??? Is this test for vtables needed? */
293 && !DECL_VIRTUAL_P (decl)
294 && 0 /*???*/)
295 {
296 error_with_decl (decl, "static variable `%s' is marked dllimport");
297 return;
298 }
299
300 /* `extern' needn't be specified with dllimport.
301 Specify `extern' now and hope for the best. Sigh. */
302 if (TREE_CODE (decl) == VAR_DECL
303 /* ??? Is this test for vtables needed? */
304 && !DECL_VIRTUAL_P (decl))
305 {
306 DECL_EXTERNAL (decl) = 1;
307 TREE_PUBLIC (decl) = 1;
308 }
309
310 newname = alloca (strlen (oldname) + 11);
311 sprintf (newname, "@i._imp__%s", oldname);
312
313 /* We pass newname through get_identifier to ensure it has a unique
314 address. RTL processing can sometimes peek inside the symbol ref
315 and compare the string's addresses to see if two symbols are
316 identical. */
317 idp = get_identifier (newname);
318
319 newrtl = gen_rtx (MEM, Pmode,
320 gen_rtx (SYMBOL_REF, Pmode,
321 IDENTIFIER_POINTER (idp)));
322 XEXP (DECL_RTL (decl), 0) = newrtl;
323
324 /* Can't treat a pointer to this as a constant address */
325 DECL_NON_ADDR_CONST_P (decl) = 1;
326}
327
0ea6b275
RK
328/* Return string which is the former assembler name modified with a
329 suffix consisting of an atsign (@) followed by the number of bytes of
330 arguments */
30c71308 331
79f96374 332const char *
0ea6b275
RK
333gen_stdcall_suffix (decl)
334 tree decl;
30c71308 335{
0ea6b275 336 int total = 0;
92d4501f
JW
337 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
338 of DECL_ASSEMBLER_NAME. */
79f96374 339 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
0ea6b275 340 char *newsym;
30c71308 341
0ea6b275
RK
342 if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
343 if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
344 == void_type_node)
30c71308 345 {
3d5c883b 346 tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
30c71308 347
3d5c883b
SC
348 while (TREE_VALUE (formal_type) != void_type_node)
349 {
350 int parm_size
351 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
352 /* Must round up to include padding. This is done the same
353 way as in store_one_arg. */
354 parm_size = ((parm_size + PARM_BOUNDARY - 1)
355 / PARM_BOUNDARY * PARM_BOUNDARY);
356 total += parm_size;
357 formal_type = TREE_CHAIN (formal_type);
358 }
0ea6b275 359 }
30c71308 360
0ea6b275
RK
361 newsym = xmalloc (strlen (asmname) + 10);
362 sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT);
363 return IDENTIFIER_POINTER (get_identifier (newsym));
30c71308 364}
0ea6b275 365
27da1b4d
MK
366/* Cover function to implement ENCODE_SECTION_INFO. */
367
368void
369i386_pe_encode_section_info (decl)
370 tree decl;
371{
372 /* This bit is copied from i386.h. */
373 if (optimize > 0 && TREE_CONSTANT (decl)
374 && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
375 {
376 rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
377 ? TREE_CST_RTL (decl) : DECL_RTL (decl));
378 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
379 }
380
381 if (TREE_CODE (decl) == FUNCTION_DECL)
382 if (lookup_attribute ("stdcall",
383 TYPE_ATTRIBUTES (TREE_TYPE (decl))))
384 XEXP (DECL_RTL (decl), 0) =
385 gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl));
386
387 /* Mark the decl so we can tell from the rtl whether the object is
388 dllexport'd or dllimport'd. */
389
390 if (i386_pe_dllexport_p (decl))
391 i386_pe_mark_dllexport (decl);
392 else if (i386_pe_dllimport_p (decl))
393 i386_pe_mark_dllimport (decl);
394 /* It might be that DECL has already been marked as dllimport, but a
395 subsequent definition nullified that. The attribute is gone but
396 DECL_RTL still has @i._imp__foo. We need to remove that. Ditto
397 for the DECL_NON_ADDR_CONST_P flag. */
398 else if ((TREE_CODE (decl) == FUNCTION_DECL
399 || TREE_CODE (decl) == VAR_DECL)
400 && DECL_RTL (decl) != NULL_RTX
401 && GET_CODE (DECL_RTL (decl)) == MEM
402 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
403 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
404 && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
405 {
79f96374 406 const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
27da1b4d
MK
407 tree idp = get_identifier (oldname + 9);
408 rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
409
410 XEXP (DECL_RTL (decl), 0) = newrtl;
411
412 DECL_NON_ADDR_CONST_P (decl) = 0;
413
414 /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
415 We leave these alone for now. */
416 }
417}
418
b64deb96
JM
419/* Cover function for UNIQUE_SECTION. */
420
516dd80f 421void
ad4ff310 422i386_pe_unique_section (decl, reloc)
b64deb96 423 tree decl;
ad4ff310 424 int reloc;
b64deb96
JM
425{
426 int len;
79f96374
DB
427 const char *name, *prefix;
428 char *string;
b64deb96
JM
429
430 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
27da1b4d
MK
431 /* Strip off any encoding in fnname. */
432 STRIP_NAME_ENCODING (name, name);
b64deb96
JM
433
434 /* The object is put in, for example, section .text$foo.
435 The linker will then ultimately place them in .text
81023100
MK
436 (everything from the $ on is stripped). Don't put
437 read-only data in .rdata section to avoid a PE linker
438 bug when .rdata$* grouped sections are used in code
439 without a .rdata section. */
b64deb96
JM
440 if (TREE_CODE (decl) == FUNCTION_DECL)
441 prefix = ".text$";
e8c3586a 442/* else if (DECL_INITIAL (decl) == 0
a56e7c08 443 || DECL_INITIAL (decl) == error_mark_node)
e8c3586a 444 prefix = ".bss"; */
ad4ff310 445 else if (DECL_READONLY_SECTION (decl, reloc))
81023100 446#ifdef READONLY_DATA_SECTION
b64deb96 447 prefix = ".rdata$";
81023100
MK
448#else
449 prefix = ".text$";
450#endif
b64deb96
JM
451 else
452 prefix = ".data$";
453 len = strlen (name) + strlen (prefix);
454 string = alloca (len + 1);
455 sprintf (string, "%s%s", prefix, name);
456
516dd80f 457 DECL_SECTION_NAME (decl) = build_string (len, string);
b64deb96 458}
7c262518
RH
459
460/* Select a set of attributes for section NAME based on the properties
461 of DECL and whether or not RELOC indicates that DECL's initializer
462 might contain runtime relocations.
463
464 We make the section read-only and executable for a function decl,
465 read-only for a const data decl, and writable for a non-const data decl.
466
467 If the section has already been defined, to not allow it to have
468 different attributes, as (1) this is ambiguous since we're not seeing
469 all the declarations up front and (2) some assemblers (e.g. SVR4)
470 do not recoginize section redefinitions. */
471/* ??? This differs from the "standard" PE implementation in that we
472 handle the SHARED variable attribute. Should this be done for all
473 PE targets? */
474
475#define SECTION_PE_SHARED SECTION_MACH_DEP
476
477unsigned int
478i386_pe_section_type_flags (decl, name, reloc)
479 tree decl;
480 const char *name;
481 int reloc;
482{
483 static htab_t htab;
484 unsigned int flags;
485 unsigned int **slot;
486
487 /* The names we put in the hashtable will always be the unique
488 versions gived to us by the stringtable, so we can just use
489 their addresses as the keys. */
490 if (!htab)
491 htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL);
492
493 if (decl && TREE_CODE (decl) == FUNCTION_DECL)
494 flags = SECTION_CODE;
495 else if (decl && DECL_READONLY_SECTION (decl, reloc))
496 flags = 0;
497 else
498 {
499 flags = SECTION_WRITE;
500
501 if (decl && TREE_CODE (decl) == VAR_DECL
502 && lookup_attribute ("shared", DECL_MACHINE_ATTRIBUTES (decl)))
503 flags |= SECTION_PE_SHARED;
504 }
505
506 if (decl && DECL_ONE_ONLY (decl))
507 flags |= SECTION_LINKONCE;
508
509 /* See if we already have an entry for this section. */
510 slot = (unsigned int **) htab_find_slot (htab, name, INSERT);
511 if (!*slot)
512 {
513 *slot = (unsigned int *) xmalloc (sizeof (unsigned int));
514 **slot = flags;
515 }
516 else
517 {
518 if (decl && **slot != flags)
519 error_with_decl (decl, "%s causes a section type conflict");
520 }
521
522 return flags;
523}
524
525void
715bdd29 526i386_pe_asm_named_section (name, flags)
7c262518
RH
527 const char *name;
528 unsigned int flags;
7c262518
RH
529{
530 char flagchars[8], *f = flagchars;
531
532 if (flags & SECTION_CODE)
533 *f++ = 'x';
534 if (flags & SECTION_WRITE)
535 *f++ = 'w';
536 if (flags & SECTION_PE_SHARED)
537 *f++ = 's';
538 *f = '\0';
539
540 fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
541
542 if (flags & SECTION_LINKONCE)
543 {
544 /* Functions may have been compiled at various levels of
545 optimization so we can't use `same_size' here.
546 Instead, have the linker pick one. */
547 fprintf (asm_out_file, "\t.linkonce %s\n",
548 (flags & SECTION_CODE ? "discard" : "same_size"));
549 }
550}
9fa1246d
JL
551\f
552/* The Microsoft linker requires that every function be marked as
cae21ae8 553 DT_FCN. When using gas on cygwin, we must emit appropriate .type
9fa1246d
JL
554 directives. */
555
556#include "gsyms.h"
557
558/* Mark a function appropriately. This should only be called for
559 functions for which we are not emitting COFF debugging information.
560 FILE is the assembler output file, NAME is the name of the
561 function, and PUBLIC is non-zero if the function is globally
562 visible. */
563
564void
565i386_pe_declare_function_type (file, name, public)
566 FILE *file;
79f96374 567 const char *name;
9fa1246d
JL
568 int public;
569{
570 fprintf (file, "\t.def\t");
571 assemble_name (file, name);
572 fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
573 public ? (int) C_EXT : (int) C_STAT,
574 (int) DT_FCN << N_BTSHFT);
575}
576
577/* Keep a list of external functions. */
578
579struct extern_list
580{
581 struct extern_list *next;
79f96374 582 const char *name;
9fa1246d
JL
583};
584
585static struct extern_list *extern_head;
586
587/* Assemble an external function reference. We need to keep a list of
588 these, so that we can output the function types at the end of the
589 assembly. We can't output the types now, because we might see a
590 definition of the function later on and emit debugging information
591 for it then. */
592
593void
594i386_pe_record_external_function (name)
79f96374 595 const char *name;
9fa1246d
JL
596{
597 struct extern_list *p;
598
599 p = (struct extern_list *) permalloc (sizeof *p);
600 p->next = extern_head;
601 p->name = name;
602 extern_head = p;
603}
604
8e260ba4
MK
605/* Keep a list of exported symbols. */
606
607struct export_list
608{
609 struct export_list *next;
79f96374 610 const char *name;
8e260ba4
MK
611 int is_data; /* used to type tag exported symbols. */
612};
613
614static struct export_list *export_head;
e43f9c10
MK
615
616/* Assemble an export symbol entry. We need to keep a list of
617 these, so that we can output the export list at the end of the
618 assembly. We used to output these export symbols in each function,
619 but that causes problems with GNU ld when the sections are
620 linkonce. */
621
622void
8e260ba4 623i386_pe_record_exported_symbol (name, is_data)
79f96374 624 const char *name;
8e260ba4 625 int is_data;
e43f9c10 626{
8e260ba4 627 struct export_list *p;
e43f9c10 628
8e260ba4
MK
629 p = (struct export_list *) permalloc (sizeof *p);
630 p->next = export_head;
e43f9c10 631 p->name = name;
8e260ba4
MK
632 p->is_data = is_data;
633 export_head = p;
e43f9c10
MK
634}
635
9fa1246d 636/* This is called at the end of assembly. For each external function
e43f9c10
MK
637 which has not been defined, we output a declaration now. We also
638 output the .drectve section. */
9fa1246d
JL
639
640void
641i386_pe_asm_file_end (file)
642 FILE *file;
643{
644 struct extern_list *p;
645
4cf12e7e
RH
646 ix86_asm_file_end (file);
647
9fa1246d
JL
648 for (p = extern_head; p != NULL; p = p->next)
649 {
650 tree decl;
651
652 decl = get_identifier (p->name);
653
654 /* Positively ensure only one declaration for any given symbol. */
6ece2487 655 if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl))
9fa1246d
JL
656 {
657 TREE_ASM_WRITTEN (decl) = 1;
658 i386_pe_declare_function_type (file, p->name, TREE_PUBLIC (decl));
659 }
660 }
e43f9c10 661
8e260ba4 662 if (export_head)
e43f9c10 663 {
8e260ba4
MK
664 struct export_list *q;
665 drectve_section ();
666 for (q = export_head; q != NULL; q = q->next)
667 {
668 fprintf (file, "\t.ascii \" -export:%s%s\"\n",
669 I386_PE_STRIP_ENCODING (q->name),
670 (q->is_data) ? ",data" : "");
671 }
e43f9c10 672 }
9fa1246d 673}
e43f9c10 674
This page took 0.832125 seconds and 5 git commands to generate.