]> gcc.gnu.org Git - gcc.git/blob - gcc/config/i386/winnt.c
cygwin.h: Declare ctor_section, dtor_section drectve_section, switch_to_section.
[gcc.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 Free Software Foundation, Inc.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include "config.h"
23 #include "system.h"
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"
30 #include "tm_p.h"
31 #include "toplev.h"
32
33 /* i386/PE specific attribute support.
34
35 i386/PE has two new attributes:
36 dllexport - for exporting a function/variable that will live in a dll
37 dllimport - for importing a function/variable from a dll
38
39 Microsoft allows multiple declspecs in one __declspec, separating
40 them with spaces. We do NOT support this. Instead, use __declspec
41 multiple times.
42 */
43
44 static tree associated_type PARAMS ((tree));
45 const char * gen_stdcall_suffix PARAMS ((tree));
46 int i386_pe_dllexport_p PARAMS ((tree));
47 int i386_pe_dllimport_p PARAMS ((tree));
48 void i386_pe_mark_dllexport PARAMS ((tree));
49 void i386_pe_mark_dllimport PARAMS ((tree));
50
51 /* Return nonzero if ATTR is a valid attribute for DECL.
52 ATTRIBUTES are any existing attributes and ARGS are the arguments
53 supplied with ATTR. */
54
55 int
56 i386_pe_valid_decl_attribute_p (decl, attributes, attr, args)
57 tree decl;
58 tree attributes;
59 tree attr;
60 tree args;
61 {
62 if (args == NULL_TREE)
63 {
64 if (is_attribute_p ("dllexport", attr))
65 return 1;
66 if (is_attribute_p ("dllimport", attr))
67 return 1;
68 if (is_attribute_p ("shared", attr))
69 return TREE_CODE (decl) == VAR_DECL;
70 }
71
72 return ix86_valid_decl_attribute_p (decl, attributes, attr, args);
73 }
74
75 /* Return nonzero if ATTR is a valid attribute for TYPE.
76 ATTRIBUTES are any existing attributes and ARGS are the arguments
77 supplied with ATTR. */
78
79 int
80 i386_pe_valid_type_attribute_p (type, attributes, attr, args)
81 tree type;
82 tree attributes;
83 tree attr;
84 tree args;
85 {
86 if (args == NULL_TREE
87 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
88 {
89 if (is_attribute_p ("dllexport", attr))
90 return 1;
91 if (is_attribute_p ("dllimport", attr))
92 return 1;
93 }
94
95 return ix86_valid_type_attribute_p (type, attributes, attr, args);
96 }
97
98 /* Merge attributes in decls OLD and NEW.
99
100 This handles the following situation:
101
102 __declspec (dllimport) int foo;
103 int foo;
104
105 The second instance of `foo' nullifies the dllimport. */
106
107 tree
108 i386_pe_merge_decl_attributes (old, new)
109 tree old, new;
110 {
111 tree a;
112 int delete_dllimport_p;
113
114 old = DECL_MACHINE_ATTRIBUTES (old);
115 new = DECL_MACHINE_ATTRIBUTES (new);
116
117 /* What we need to do here is remove from `old' dllimport if it doesn't
118 appear in `new'. dllimport behaves like extern: if a declaration is
119 marked dllimport and a definition appears later, then the object
120 is not dllimport'd. */
121
122 if (lookup_attribute ("dllimport", old) != NULL_TREE
123 && lookup_attribute ("dllimport", new) == NULL_TREE)
124 delete_dllimport_p = 1;
125 else
126 delete_dllimport_p = 0;
127
128 a = merge_attributes (old, new);
129
130 if (delete_dllimport_p)
131 {
132 tree prev,t;
133
134 /* Scan the list for dllimport and delete it. */
135 for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
136 {
137 if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
138 {
139 if (prev == NULL_TREE)
140 a = TREE_CHAIN (a);
141 else
142 TREE_CHAIN (prev) = TREE_CHAIN (t);
143 break;
144 }
145 }
146 }
147
148 return a;
149 }
150 \f
151 /* Return the type that we should use to determine if DECL is
152 imported or exported. */
153
154 static tree
155 associated_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 non-zero if DECL is a dllexport'd object. */
177
178 int
179 i386_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_MACHINE_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 non-zero if DECL is a dllimport'd object. */
204
205 int
206 i386_pe_dllimport_p (decl)
207 tree decl;
208 {
209 tree imp;
210
211 if (TREE_CODE (decl) == FUNCTION_DECL
212 && TARGET_NOP_FUN_DLLIMPORT)
213 return 0;
214
215 if (TREE_CODE (decl) != VAR_DECL
216 && TREE_CODE (decl) != FUNCTION_DECL)
217 return 0;
218 imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
219 if (imp)
220 return 1;
221
222 /* Class members get the dllimport status of their class. */
223 if (associated_type (decl))
224 {
225 imp = lookup_attribute ("dllimport",
226 TYPE_ATTRIBUTES (associated_type (decl)));
227 if (imp)
228 return 1;
229 }
230
231 return 0;
232 }
233
234 /* Return non-zero if SYMBOL is marked as being dllexport'd. */
235
236 int
237 i386_pe_dllexport_name_p (symbol)
238 const char *symbol;
239 {
240 return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.';
241 }
242
243 /* Return non-zero if SYMBOL is marked as being dllimport'd. */
244
245 int
246 i386_pe_dllimport_name_p (symbol)
247 const char *symbol;
248 {
249 return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.';
250 }
251
252 /* Mark a DECL as being dllexport'd.
253 Note that we override the previous setting (eg: dllimport). */
254
255 void
256 i386_pe_mark_dllexport (decl)
257 tree decl;
258 {
259 const char *oldname;
260 char *newname;
261 rtx rtlname;
262 tree idp;
263
264 rtlname = XEXP (DECL_RTL (decl), 0);
265 if (GET_CODE (rtlname) == SYMBOL_REF)
266 oldname = XSTR (rtlname, 0);
267 else if (GET_CODE (rtlname) == MEM
268 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
269 oldname = XSTR (XEXP (rtlname, 0), 0);
270 else
271 abort ();
272 if (i386_pe_dllimport_name_p (oldname))
273 oldname += 9;
274 else if (i386_pe_dllexport_name_p (oldname))
275 return; /* already done */
276
277 newname = alloca (strlen (oldname) + 4);
278 sprintf (newname, "@e.%s", oldname);
279
280 /* We pass newname through get_identifier to ensure it has a unique
281 address. RTL processing can sometimes peek inside the symbol ref
282 and compare the string's addresses to see if two symbols are
283 identical. */
284 idp = get_identifier (newname);
285
286 XEXP (DECL_RTL (decl), 0) =
287 gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
288 }
289
290 /* Mark a DECL as being dllimport'd. */
291
292 void
293 i386_pe_mark_dllimport (decl)
294 tree decl;
295 {
296 const char *oldname;
297 char *newname;
298 tree idp;
299 rtx rtlname, newrtl;
300
301 rtlname = XEXP (DECL_RTL (decl), 0);
302 if (GET_CODE (rtlname) == SYMBOL_REF)
303 oldname = XSTR (rtlname, 0);
304 else if (GET_CODE (rtlname) == MEM
305 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
306 oldname = XSTR (XEXP (rtlname, 0), 0);
307 else
308 abort ();
309 if (i386_pe_dllexport_name_p (oldname))
310 {
311 error ("`%s' declared as both exported to and imported from a DLL.",
312 IDENTIFIER_POINTER (DECL_NAME (decl)));
313 return;
314 }
315 else if (i386_pe_dllimport_name_p (oldname))
316 {
317 /* Already done, but force correct linkage since the redeclaration
318 might have omitted explicit extern. Sigh. */
319 if (TREE_CODE (decl) == VAR_DECL
320 /* ??? Is this test for vtables needed? */
321 && !DECL_VIRTUAL_P (decl))
322 {
323 DECL_EXTERNAL (decl) = 1;
324 TREE_PUBLIC (decl) = 1;
325 }
326 return;
327 }
328
329 /* ??? One can well ask why we're making these checks here,
330 and that would be a good question. */
331
332 /* Imported variables can't be initialized. Note that C++ classes
333 are marked initial, so we need to check. */
334 if (TREE_CODE (decl) == VAR_DECL
335 && !DECL_VIRTUAL_P (decl)
336 && (DECL_INITIAL (decl)
337 && ! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
338 {
339 error_with_decl (decl, "initialized variable `%s' is marked dllimport");
340 return;
341 }
342 /* Nor can they be static. */
343 if (TREE_CODE (decl) == VAR_DECL
344 /* ??? Is this test for vtables needed? */
345 && !DECL_VIRTUAL_P (decl)
346 && 0 /*???*/)
347 {
348 error_with_decl (decl, "static variable `%s' is marked dllimport");
349 return;
350 }
351
352 /* `extern' needn't be specified with dllimport.
353 Specify `extern' now and hope for the best. Sigh. */
354 if (TREE_CODE (decl) == VAR_DECL
355 /* ??? Is this test for vtables needed? */
356 && !DECL_VIRTUAL_P (decl))
357 {
358 DECL_EXTERNAL (decl) = 1;
359 TREE_PUBLIC (decl) = 1;
360 }
361
362 newname = alloca (strlen (oldname) + 11);
363 sprintf (newname, "@i._imp__%s", oldname);
364
365 /* We pass newname through get_identifier to ensure it has a unique
366 address. RTL processing can sometimes peek inside the symbol ref
367 and compare the string's addresses to see if two symbols are
368 identical. */
369 idp = get_identifier (newname);
370
371 newrtl = gen_rtx (MEM, Pmode,
372 gen_rtx (SYMBOL_REF, Pmode,
373 IDENTIFIER_POINTER (idp)));
374 XEXP (DECL_RTL (decl), 0) = newrtl;
375
376 /* Can't treat a pointer to this as a constant address */
377 DECL_NON_ADDR_CONST_P (decl) = 1;
378 }
379
380 /* Return string which is the former assembler name modified with a
381 suffix consisting of an atsign (@) followed by the number of bytes of
382 arguments */
383
384 const char *
385 gen_stdcall_suffix (decl)
386 tree decl;
387 {
388 int total = 0;
389 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
390 of DECL_ASSEMBLER_NAME. */
391 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
392 char *newsym;
393
394 if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
395 if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
396 == void_type_node)
397 {
398 tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
399
400 while (TREE_VALUE (formal_type) != void_type_node)
401 {
402 int parm_size
403 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
404 /* Must round up to include padding. This is done the same
405 way as in store_one_arg. */
406 parm_size = ((parm_size + PARM_BOUNDARY - 1)
407 / PARM_BOUNDARY * PARM_BOUNDARY);
408 total += parm_size;
409 formal_type = TREE_CHAIN (formal_type);
410 }
411 }
412
413 newsym = xmalloc (strlen (asmname) + 10);
414 sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT);
415 return IDENTIFIER_POINTER (get_identifier (newsym));
416 }
417
418 /* Cover function to implement ENCODE_SECTION_INFO. */
419
420 void
421 i386_pe_encode_section_info (decl)
422 tree decl;
423 {
424 /* This bit is copied from i386.h. */
425 if (optimize > 0 && TREE_CONSTANT (decl)
426 && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
427 {
428 rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
429 ? TREE_CST_RTL (decl) : DECL_RTL (decl));
430 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
431 }
432
433 if (TREE_CODE (decl) == FUNCTION_DECL)
434 if (lookup_attribute ("stdcall",
435 TYPE_ATTRIBUTES (TREE_TYPE (decl))))
436 XEXP (DECL_RTL (decl), 0) =
437 gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl));
438
439 /* Mark the decl so we can tell from the rtl whether the object is
440 dllexport'd or dllimport'd. */
441
442 if (i386_pe_dllexport_p (decl))
443 i386_pe_mark_dllexport (decl);
444 else if (i386_pe_dllimport_p (decl))
445 i386_pe_mark_dllimport (decl);
446 /* It might be that DECL has already been marked as dllimport, but a
447 subsequent definition nullified that. The attribute is gone but
448 DECL_RTL still has @i._imp__foo. We need to remove that. Ditto
449 for the DECL_NON_ADDR_CONST_P flag. */
450 else if ((TREE_CODE (decl) == FUNCTION_DECL
451 || TREE_CODE (decl) == VAR_DECL)
452 && DECL_RTL (decl) != NULL_RTX
453 && GET_CODE (DECL_RTL (decl)) == MEM
454 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
455 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
456 && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
457 {
458 const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
459 tree idp = get_identifier (oldname + 9);
460 rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
461
462 XEXP (DECL_RTL (decl), 0) = newrtl;
463
464 DECL_NON_ADDR_CONST_P (decl) = 0;
465
466 /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
467 We leave these alone for now. */
468 }
469 }
470
471 /* Cover function for UNIQUE_SECTION. */
472
473 void
474 i386_pe_unique_section (decl, reloc)
475 tree decl;
476 int reloc;
477 {
478 int len;
479 const char *name, *prefix;
480 char *string;
481
482 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
483 /* Strip off any encoding in fnname. */
484 STRIP_NAME_ENCODING (name, name);
485
486 /* The object is put in, for example, section .text$foo.
487 The linker will then ultimately place them in .text
488 (everything from the $ on is stripped). Don't put
489 read-only data in .rdata section to avoid a PE linker
490 bug when .rdata$* grouped sections are used in code
491 without a .rdata section. */
492 if (TREE_CODE (decl) == FUNCTION_DECL)
493 prefix = ".text$";
494 /* else if (DECL_INITIAL (decl) == 0
495 || DECL_INITIAL (decl) == error_mark_node)
496 prefix = ".bss"; */
497 else if (DECL_READONLY_SECTION (decl, reloc))
498 #ifdef READONLY_DATA_SECTION
499 prefix = ".rdata$";
500 #else
501 prefix = ".text$";
502 #endif
503 else
504 prefix = ".data$";
505 len = strlen (name) + strlen (prefix);
506 string = alloca (len + 1);
507 sprintf (string, "%s%s", prefix, name);
508
509 DECL_SECTION_NAME (decl) = build_string (len, string);
510 }
511 \f
512 /* The Microsoft linker requires that every function be marked as
513 DT_FCN. When using gas on cygwin, we must emit appropriate .type
514 directives. */
515
516 #include "gsyms.h"
517
518 /* Mark a function appropriately. This should only be called for
519 functions for which we are not emitting COFF debugging information.
520 FILE is the assembler output file, NAME is the name of the
521 function, and PUBLIC is non-zero if the function is globally
522 visible. */
523
524 void
525 i386_pe_declare_function_type (file, name, public)
526 FILE *file;
527 const char *name;
528 int public;
529 {
530 fprintf (file, "\t.def\t");
531 assemble_name (file, name);
532 fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
533 public ? (int) C_EXT : (int) C_STAT,
534 (int) DT_FCN << N_BTSHFT);
535 }
536
537 /* Keep a list of external functions. */
538
539 struct extern_list
540 {
541 struct extern_list *next;
542 const char *name;
543 };
544
545 static struct extern_list *extern_head;
546
547 /* Assemble an external function reference. We need to keep a list of
548 these, so that we can output the function types at the end of the
549 assembly. We can't output the types now, because we might see a
550 definition of the function later on and emit debugging information
551 for it then. */
552
553 void
554 i386_pe_record_external_function (name)
555 const char *name;
556 {
557 struct extern_list *p;
558
559 p = (struct extern_list *) permalloc (sizeof *p);
560 p->next = extern_head;
561 p->name = name;
562 extern_head = p;
563 }
564
565 /* Keep a list of exported symbols. */
566
567 struct export_list
568 {
569 struct export_list *next;
570 const char *name;
571 int is_data; /* used to type tag exported symbols. */
572 };
573
574 static struct export_list *export_head;
575
576 /* Assemble an export symbol entry. We need to keep a list of
577 these, so that we can output the export list at the end of the
578 assembly. We used to output these export symbols in each function,
579 but that causes problems with GNU ld when the sections are
580 linkonce. */
581
582 void
583 i386_pe_record_exported_symbol (name, is_data)
584 const char *name;
585 int is_data;
586 {
587 struct export_list *p;
588
589 p = (struct export_list *) permalloc (sizeof *p);
590 p->next = export_head;
591 p->name = name;
592 p->is_data = is_data;
593 export_head = p;
594 }
595
596 /* This is called at the end of assembly. For each external function
597 which has not been defined, we output a declaration now. We also
598 output the .drectve section. */
599
600 void
601 i386_pe_asm_file_end (file)
602 FILE *file;
603 {
604 struct extern_list *p;
605
606 ix86_asm_file_end (file);
607
608 for (p = extern_head; p != NULL; p = p->next)
609 {
610 tree decl;
611
612 decl = get_identifier (p->name);
613
614 /* Positively ensure only one declaration for any given symbol. */
615 if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl))
616 {
617 TREE_ASM_WRITTEN (decl) = 1;
618 i386_pe_declare_function_type (file, p->name, TREE_PUBLIC (decl));
619 }
620 }
621
622 if (export_head)
623 {
624 struct export_list *q;
625 drectve_section ();
626 for (q = export_head; q != NULL; q = q->next)
627 {
628 fprintf (file, "\t.ascii \" -export:%s%s\"\n",
629 I386_PE_STRIP_ENCODING (q->name),
630 (q->is_data) ? ",data" : "");
631 }
632 }
633 }
634
This page took 0.065282 seconds and 5 git commands to generate.