OSDN Git Service

Jumbo patch from Geoff Noer to rename CYGWIN32 to CYGWIN.
[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 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
31 /* i386/PE specific attribute support.
32
33    i386/PE has two new attributes:
34    dllexport - for exporting a function/variable that will live in a dll
35    dllimport - for importing a function/variable from a dll
36
37    Microsoft allows multiple declspecs in one __declspec, separating
38    them with spaces.  We do NOT support this.  Instead, use __declspec
39    multiple times.
40 */
41
42 /* Return nonzero if ATTR is a valid attribute for DECL.
43    ATTRIBUTES are any existing attributes and ARGS are the arguments
44    supplied with ATTR.  */
45
46 int
47 i386_pe_valid_decl_attribute_p (decl, attributes, attr, args)
48      tree decl;
49      tree attributes;
50      tree attr;
51      tree args;
52 {
53   if (args == NULL_TREE)
54     {
55       if (is_attribute_p ("dllexport", attr))
56         return 1;
57       if (is_attribute_p ("dllimport", attr))
58         return 1;
59     }
60
61   return i386_valid_decl_attribute_p (decl, attributes, attr, args);
62 }
63
64 /* Return nonzero if ATTR is a valid attribute for TYPE.
65    ATTRIBUTES are any existing attributes and ARGS are the arguments
66    supplied with ATTR.  */
67
68 int
69 i386_pe_valid_type_attribute_p (type, attributes, attr, args)
70      tree type;
71      tree attributes;
72      tree attr;
73      tree args;
74 {
75   if (args == NULL_TREE
76       && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
77     {
78       if (is_attribute_p ("dllexport", attr))
79         return 1;
80       if (is_attribute_p ("dllimport", attr))
81         return 1;
82     }
83
84   return i386_valid_type_attribute_p (type, attributes, attr, args);
85 }
86
87 /* Merge attributes in decls OLD and NEW.
88
89    This handles the following situation:
90
91    __declspec (dllimport) int foo;
92    int foo;
93
94    The second instance of `foo' nullifies the dllimport.  */
95
96 tree
97 i386_pe_merge_decl_attributes (old, new)
98      tree old, new;
99 {
100   tree a;
101   int delete_dllimport_p;
102
103   old = DECL_MACHINE_ATTRIBUTES (old);
104   new = DECL_MACHINE_ATTRIBUTES (new);
105
106   /* What we need to do here is remove from `old' dllimport if it doesn't
107      appear in `new'.  dllimport behaves like extern: if a declaration is
108      marked dllimport and a definition appears later, then the object
109      is not dllimport'd.  */
110
111   if (lookup_attribute ("dllimport", old) != NULL_TREE
112       && lookup_attribute ("dllimport", new) == NULL_TREE)
113     delete_dllimport_p = 1;
114   else
115     delete_dllimport_p = 0;
116
117   a = merge_attributes (old, new);
118
119   if (delete_dllimport_p)
120     {
121       tree prev,t;
122
123       /* Scan the list for dllimport and delete it.  */
124       for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
125         {
126           if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
127             {
128               if (prev == NULL_TREE)
129                 a = TREE_CHAIN (a);
130               else
131                 TREE_CHAIN (prev) = TREE_CHAIN (t);
132               break;
133             }
134         }
135     }
136
137   return a;
138 }
139 \f
140 /* Return the type that we should use to determine if DECL is
141    imported or exported.  */
142
143 static tree
144 associated_type (decl)
145      tree decl;
146 {
147   tree t = NULL_TREE;
148
149   /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer
150      to the containing class.  So we look at the 'this' arg.  */
151   if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
152     {
153       /* Artificial methods are not affected by the import/export status of
154          their class unless they are virtual.  */
155       if (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl))
156         t = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))));
157     }
158   else if (DECL_CONTEXT (decl)
159            && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
160     t = DECL_CONTEXT (decl);
161
162   return t;
163 }
164
165 /* Return non-zero if DECL is a dllexport'd object.  */
166
167 int
168 i386_pe_dllexport_p (decl)
169      tree decl;
170 {
171   tree exp;
172
173   if (TREE_CODE (decl) != VAR_DECL
174       && TREE_CODE (decl) != FUNCTION_DECL)
175     return 0;
176   exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
177   if (exp)
178     return 1;
179
180   /* Class members get the dllexport status of their class.  */
181   if (associated_type (decl))
182     {
183       exp = lookup_attribute ("dllexport",
184                               TYPE_ATTRIBUTES (associated_type (decl)));
185       if (exp)
186         return 1;
187     }
188
189   return 0;
190 }
191
192 /* Return non-zero if DECL is a dllimport'd object.  */
193
194 int
195 i386_pe_dllimport_p (decl)
196      tree decl;
197 {
198   tree imp;
199
200   if (TREE_CODE (decl) == FUNCTION_DECL
201       && TARGET_NOP_FUN_DLLIMPORT)
202     return 0;
203
204   if (TREE_CODE (decl) != VAR_DECL
205       && TREE_CODE (decl) != FUNCTION_DECL)
206     return 0;
207   imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
208   if (imp)
209     return 1;
210
211   /* Class members get the dllimport status of their class.  */
212   if (associated_type (decl))
213     {
214       imp = lookup_attribute ("dllimport",
215                               TYPE_ATTRIBUTES (associated_type (decl)));
216       if (imp)
217         return 1;
218     }
219
220   return 0;
221 }
222
223 /* Return non-zero if SYMBOL is marked as being dllexport'd.  */
224
225 int
226 i386_pe_dllexport_name_p (symbol)
227      char *symbol;
228 {
229   return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.';
230 }
231
232 /* Return non-zero if SYMBOL is marked as being dllimport'd.  */
233
234 int
235 i386_pe_dllimport_name_p (symbol)
236      char *symbol;
237 {
238   return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.';
239 }
240
241 /* Mark a DECL as being dllexport'd.
242    Note that we override the previous setting (eg: dllimport).  */
243
244 void
245 i386_pe_mark_dllexport (decl)
246      tree decl;
247 {
248   char *oldname, *newname;
249   rtx rtlname;
250   tree idp;
251
252   rtlname = XEXP (DECL_RTL (decl), 0);
253   if (GET_CODE (rtlname) == SYMBOL_REF)
254     oldname = XSTR (rtlname, 0);
255   else if (GET_CODE (rtlname) == MEM
256            && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
257     oldname = XSTR (XEXP (rtlname, 0), 0);
258   else
259     abort ();
260   if (i386_pe_dllimport_name_p (oldname))
261     oldname += 9;
262   else if (i386_pe_dllexport_name_p (oldname))
263     return; /* already done */
264
265   newname = alloca (strlen (oldname) + 4);
266   sprintf (newname, "@e.%s", oldname);
267
268   /* We pass newname through get_identifier to ensure it has a unique
269      address.  RTL processing can sometimes peek inside the symbol ref
270      and compare the string's addresses to see if two symbols are
271      identical.  */
272   idp = get_identifier (newname);
273
274   XEXP (DECL_RTL (decl), 0) =
275     gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
276 }
277
278 /* Mark a DECL as being dllimport'd.  */
279
280 void
281 i386_pe_mark_dllimport (decl)
282      tree decl;
283 {
284   char *oldname, *newname;
285   tree idp;
286   rtx rtlname, newrtl;
287
288   rtlname = XEXP (DECL_RTL (decl), 0);
289   if (GET_CODE (rtlname) == SYMBOL_REF)
290     oldname = XSTR (rtlname, 0);
291   else if (GET_CODE (rtlname) == MEM
292            && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
293     oldname = XSTR (XEXP (rtlname, 0), 0);
294   else
295     abort ();
296   if (i386_pe_dllexport_name_p (oldname))
297     {
298       error ("`%s' declared as both exported to and imported from a DLL.",
299              IDENTIFIER_POINTER (DECL_NAME (decl)));
300       return;
301     }
302   else if (i386_pe_dllimport_name_p (oldname))
303     {
304       /* Already done, but force correct linkage since the redeclaration 
305          might have omitted explicit extern.  Sigh.  */
306       if (TREE_CODE (decl) == VAR_DECL
307           /* ??? Is this test for vtables needed?  */
308           && !DECL_VIRTUAL_P (decl))
309         {
310           DECL_EXTERNAL (decl) = 1;
311           TREE_PUBLIC (decl) = 1;
312         }
313       return;
314     }
315
316   /* ??? One can well ask why we're making these checks here,
317      and that would be a good question.  */
318
319   /* Imported variables can't be initialized. Note that C++ classes
320      are marked initial, so we need to check.  */
321   if (TREE_CODE (decl) == VAR_DECL
322       && !DECL_VIRTUAL_P (decl)
323       && (DECL_INITIAL (decl)
324           && ! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
325     {
326       error_with_decl (decl, "initialized variable `%s' is marked dllimport");
327       return;
328     }
329   /* Nor can they be static.  */
330   if (TREE_CODE (decl) == VAR_DECL
331       /* ??? Is this test for vtables needed?  */
332       && !DECL_VIRTUAL_P (decl)
333       && 0 /*???*/)
334     {
335       error_with_decl (decl, "static variable `%s' is marked dllimport");
336       return;
337     }
338
339   /* `extern' needn't be specified with dllimport.
340      Specify `extern' now and hope for the best.  Sigh.  */
341   if (TREE_CODE (decl) == VAR_DECL
342       /* ??? Is this test for vtables needed?  */
343       && !DECL_VIRTUAL_P (decl))
344     {
345       DECL_EXTERNAL (decl) = 1;
346       TREE_PUBLIC (decl) = 1;
347     }
348
349   newname = alloca (strlen (oldname) + 11);
350   sprintf (newname, "@i._imp__%s", oldname);
351
352   /* We pass newname through get_identifier to ensure it has a unique
353      address.  RTL processing can sometimes peek inside the symbol ref
354      and compare the string's addresses to see if two symbols are
355      identical.  */
356   idp = get_identifier (newname);
357
358   newrtl = gen_rtx (MEM, Pmode,
359                     gen_rtx (SYMBOL_REF, Pmode,
360                              IDENTIFIER_POINTER (idp)));
361   XEXP (DECL_RTL (decl), 0) = newrtl;
362
363   /* Can't treat a pointer to this as a constant address */
364   DECL_NON_ADDR_CONST_P (decl) = 1;
365 }
366
367 /* Return string which is the former assembler name modified with a 
368    suffix consisting of an atsign (@) followed by the number of bytes of 
369    arguments */
370
371 char *
372 gen_stdcall_suffix (decl)
373   tree decl;
374 {
375   int total = 0;
376   /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
377      of DECL_ASSEMBLER_NAME.  */
378   char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
379   char *newsym;
380
381   if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
382     if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl)))) 
383         == void_type_node)
384       {
385         tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
386
387         while (TREE_VALUE (formal_type) != void_type_node)
388           {
389             int parm_size
390               = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
391             /* Must round up to include padding.  This is done the same
392                way as in store_one_arg.  */
393             parm_size = ((parm_size + PARM_BOUNDARY - 1)
394                          / PARM_BOUNDARY * PARM_BOUNDARY);
395             total += parm_size;
396             formal_type = TREE_CHAIN (formal_type);
397           }
398       }
399
400   newsym = xmalloc (strlen (asmname) + 10);
401   sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT);
402   return IDENTIFIER_POINTER (get_identifier (newsym));
403 }
404
405 /* Cover function to implement ENCODE_SECTION_INFO.  */
406
407 void
408 i386_pe_encode_section_info (decl)
409      tree decl;
410 {
411   /* This bit is copied from i386.h.  */
412   if (optimize > 0 && TREE_CONSTANT (decl)
413       && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
414     {
415       rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
416                  ? TREE_CST_RTL (decl) : DECL_RTL (decl));
417       SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
418     }
419
420   if (TREE_CODE (decl) == FUNCTION_DECL)
421     if (lookup_attribute ("stdcall",
422                           TYPE_ATTRIBUTES (TREE_TYPE (decl))))
423       XEXP (DECL_RTL (decl), 0) = 
424         gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl));
425
426   /* Mark the decl so we can tell from the rtl whether the object is
427      dllexport'd or dllimport'd.  */
428
429   if (i386_pe_dllexport_p (decl))
430     i386_pe_mark_dllexport (decl);
431   else if (i386_pe_dllimport_p (decl))
432     i386_pe_mark_dllimport (decl);
433   /* It might be that DECL has already been marked as dllimport, but a
434      subsequent definition nullified that.  The attribute is gone but
435      DECL_RTL still has @i._imp__foo.  We need to remove that. Ditto
436      for the DECL_NON_ADDR_CONST_P flag.  */
437   else if ((TREE_CODE (decl) == FUNCTION_DECL
438             || TREE_CODE (decl) == VAR_DECL)
439            && DECL_RTL (decl) != NULL_RTX
440            && GET_CODE (DECL_RTL (decl)) == MEM
441            && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
442            && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
443            && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
444     {
445       char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
446       tree idp = get_identifier (oldname + 9);
447       rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
448
449       XEXP (DECL_RTL (decl), 0) = newrtl;
450
451       DECL_NON_ADDR_CONST_P (decl) = 0;
452
453       /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
454          We leave these alone for now.  */
455     }
456 }
457
458 /* Cover function for UNIQUE_SECTION.  */
459
460 void
461 i386_pe_unique_section (decl, reloc)
462      tree decl;
463      int reloc;
464 {
465   int len;
466   char *name,*string,*prefix;
467
468   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
469   /* Strip off any encoding in fnname.  */
470   STRIP_NAME_ENCODING (name, name);
471
472   /* The object is put in, for example, section .text$foo.
473      The linker will then ultimately place them in .text
474      (everything from the $ on is stripped). Don't put
475      read-only data in .rdata section to avoid a PE linker 
476      bug when .rdata$* grouped sections are used in code
477      without a .rdata section.  */
478   if (TREE_CODE (decl) == FUNCTION_DECL)
479     prefix = ".text$";
480   else if (DECL_READONLY_SECTION (decl, reloc))
481 #ifdef READONLY_DATA_SECTION
482     prefix = ".rdata$";
483 #else
484     prefix = ".text$";
485 #endif
486   else
487     prefix = ".data$";
488   len = strlen (name) + strlen (prefix);
489   string = alloca (len + 1);
490   sprintf (string, "%s%s", prefix, name);
491
492   DECL_SECTION_NAME (decl) = build_string (len, string);
493 }
494 \f
495 /* The Microsoft linker requires that every function be marked as
496    DT_FCN.  When using gas on cygwin, we must emit appropriate .type
497    directives.  */
498
499 #include "gsyms.h"
500
501 /* Mark a function appropriately.  This should only be called for
502    functions for which we are not emitting COFF debugging information.
503    FILE is the assembler output file, NAME is the name of the
504    function, and PUBLIC is non-zero if the function is globally
505    visible.  */
506
507 void
508 i386_pe_declare_function_type (file, name, public)
509      FILE *file;
510      char *name;
511      int public;
512 {
513   fprintf (file, "\t.def\t");
514   assemble_name (file, name);
515   fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
516            public ? (int) C_EXT : (int) C_STAT,
517            (int) DT_FCN << N_BTSHFT);
518 }
519
520 /* Keep a list of external functions.  */
521
522 struct extern_list
523 {
524   struct extern_list *next;
525   char *name;
526 };
527
528 static struct extern_list *extern_head;
529
530 /* Assemble an external function reference.  We need to keep a list of
531    these, so that we can output the function types at the end of the
532    assembly.  We can't output the types now, because we might see a
533    definition of the function later on and emit debugging information
534    for it then.  */
535
536 void
537 i386_pe_record_external_function (name)
538      char *name;
539 {
540   struct extern_list *p;
541
542   p = (struct extern_list *) permalloc (sizeof *p);
543   p->next = extern_head;
544   p->name = name;
545   extern_head = p;
546 }
547
548 /* This is called at the end of assembly.  For each external function
549    which has not been defined, we output a declaration now.  */
550
551 void
552 i386_pe_asm_file_end (file)
553      FILE *file;
554 {
555   struct extern_list *p;
556
557   for (p = extern_head; p != NULL; p = p->next)
558     {
559       tree decl;
560
561       decl = get_identifier (p->name);
562
563       /* Positively ensure only one declaration for any given symbol.  */
564       if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl))
565         {
566           TREE_ASM_WRITTEN (decl) = 1;
567           i386_pe_declare_function_type (file, p->name, TREE_PUBLIC (decl));
568         }
569     }
570 }