OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / pe.c
1 /* Routines for GCC for ARM/pe.
2    Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004
3    Free Software Foundation, Inc.
4    Contributed by Doug Evans (dje@cygnus.com).
5
6    This file is part of GCC.
7
8    GCC is free software; you can redistribute it and/or modify it
9    under the terms of the GNU General Public License as published
10    by the Free Software Foundation; either version 2, or (at your
11    option) any later version.
12
13    GCC is distributed in the hope that it will be useful, but WITHOUT
14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16    License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with GCC; see the file COPYING.  If not, write to
20    the Free Software Foundation, 59 Temple Place - Suite 330,
21    Boston, MA 02111-1307, USA.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "output.h"
29 #include "flags.h"
30 #include "tree.h"
31 #include "expr.h"
32 #include "toplev.h"
33 #include "tm_p.h"
34
35 extern int current_function_anonymous_args;
36
37 \f
38 /* Return nonzero if DECL is a dllexport'd object.  */
39
40 tree current_class_type; /* FIXME */
41
42 int
43 arm_dllexport_p (decl)
44      tree decl;
45 {
46   tree exp;
47
48   if (TREE_CODE (decl) != VAR_DECL
49       && TREE_CODE (decl) != FUNCTION_DECL)
50     return 0;
51   exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
52   if (exp)
53     return 1;
54
55   return 0;
56 }
57
58 /* Return nonzero if DECL is a dllimport'd object.  */
59
60 int
61 arm_dllimport_p (decl)
62      tree decl;
63 {
64   tree imp;
65
66   if (TREE_CODE (decl) == FUNCTION_DECL
67       && TARGET_NOP_FUN_DLLIMPORT)
68     return 0;
69
70   if (TREE_CODE (decl) != VAR_DECL
71       && TREE_CODE (decl) != FUNCTION_DECL)
72     return 0;
73   imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
74   if (imp)
75     return 1;
76
77   return 0;
78 }
79
80 /* Return nonzero if SYMBOL is marked as being dllexport'd.  */
81
82 int
83 arm_dllexport_name_p (symbol)
84      const char * symbol;
85 {
86   return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.';
87 }
88
89 /* Return nonzero if SYMBOL is marked as being dllimport'd.  */
90
91 int
92 arm_dllimport_name_p (symbol)
93      const char * symbol;
94 {
95   return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'i' && symbol[2] == '.';
96 }
97
98 /* Mark a DECL as being dllexport'd.
99    Note that we override the previous setting (eg: dllimport).  */
100
101 void
102 arm_mark_dllexport (decl)
103      tree decl;
104 {
105   const char * oldname;
106   char * newname;
107   rtx rtlname;
108   tree idp;
109
110   rtlname = XEXP (DECL_RTL (decl), 0);
111   if (GET_CODE (rtlname) == SYMBOL_REF)
112     oldname = XSTR (rtlname, 0);
113   else if (GET_CODE (rtlname) == MEM
114            && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
115     oldname = XSTR (XEXP (rtlname, 0), 0);
116   else
117     abort ();
118   if (arm_dllimport_name_p (oldname))
119     oldname += 9;
120   else if (arm_dllexport_name_p (oldname))
121     return; /* already done */
122
123   newname = alloca (strlen (oldname) + 4);
124   sprintf (newname, "%ce.%s", ARM_PE_FLAG_CHAR, oldname);
125
126   /* We pass newname through get_identifier to ensure it has a unique
127      address.  RTL processing can sometimes peek inside the symbol ref
128      and compare the string's addresses to see if two symbols are
129      identical.  */
130   /* ??? At least I think that's why we do this.  */
131   idp = get_identifier (newname);
132
133   XEXP (DECL_RTL (decl), 0) =
134     gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
135 }
136
137 /* Mark a DECL as being dllimport'd.  */
138
139 void
140 arm_mark_dllimport (decl)
141      tree decl;
142 {
143   const char * oldname;
144   char * newname;
145   tree idp;
146   rtx rtlname, newrtl;
147
148   rtlname = XEXP (DECL_RTL (decl), 0);
149   
150   if (GET_CODE (rtlname) == SYMBOL_REF)
151     oldname = XSTR (rtlname, 0);
152   else if (GET_CODE (rtlname) == MEM
153            && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
154     oldname = XSTR (XEXP (rtlname, 0), 0);
155   else
156     abort ();
157   
158   if (arm_dllexport_name_p (oldname))
159     abort (); /* this shouldn't happen */
160   else if (arm_dllimport_name_p (oldname))
161     return; /* already done */
162
163   /* ??? One can well ask why we're making these checks here,
164      and that would be a good question.  */
165
166   /* Imported variables can't be initialized.  */
167   if (TREE_CODE (decl) == VAR_DECL
168       && !DECL_VIRTUAL_P (decl)
169       && DECL_INITIAL (decl))
170     {
171       error ("%Jinitialized variable '%D' is marked dllimport", decl, decl);
172       return;
173     }
174   /* Nor can they be static.  */
175   if (TREE_CODE (decl) == VAR_DECL
176       /* ??? Is this test for vtables needed?  */
177       && !DECL_VIRTUAL_P (decl)
178       && 0 /*???*/)
179     {
180       error ("%Jstatic variable '%D' is marked dllimport", decl, decl);
181       return;
182     }
183
184   /* `extern' needn't be specified with dllimport.
185      Specify `extern' now and hope for the best.  Sigh.  */
186   if (TREE_CODE (decl) == VAR_DECL
187       /* ??? Is this test for vtables needed?  */
188       && !DECL_VIRTUAL_P (decl))
189     {
190       DECL_EXTERNAL (decl) = 1;
191       TREE_PUBLIC (decl) = 1;
192     }
193
194   newname = alloca (strlen (oldname) + 11);
195   sprintf (newname, "%ci.__imp_%s", ARM_PE_FLAG_CHAR, oldname);
196
197   /* We pass newname through get_identifier to ensure it has a unique
198      address.  RTL processing can sometimes peek inside the symbol ref
199      and compare the string's addresses to see if two symbols are
200      identical.  */
201   /* ??? At least I think that's why we do this.  */
202   idp = get_identifier (newname);
203
204   newrtl = gen_rtx_MEM (Pmode,
205                         gen_rtx_SYMBOL_REF (Pmode,
206                                             IDENTIFIER_POINTER (idp)));
207   XEXP (DECL_RTL (decl), 0) = newrtl;
208 }
209
210 void
211 arm_pe_encode_section_info (decl, rtl, first)
212      tree decl;
213      rtx rtl;
214      int first ATTRIBUTE_UNUSED;
215 {
216   /* This bit is copied from arm_encode_section_info.  */
217   if (optimize > 0 && TREE_CONSTANT (decl))
218     SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
219
220   /* Mark the decl so we can tell from the rtl whether the object is
221      dllexport'd or dllimport'd.  */
222   if (arm_dllexport_p (decl))
223     arm_mark_dllexport (decl);
224   else if (arm_dllimport_p (decl))
225     arm_mark_dllimport (decl);
226   /* It might be that DECL has already been marked as dllimport, but a
227      subsequent definition nullified that.  The attribute is gone but
228      DECL_RTL still has @i.__imp_foo.  We need to remove that.  */
229   else if ((TREE_CODE (decl) == FUNCTION_DECL
230             || TREE_CODE (decl) == VAR_DECL)
231            && DECL_RTL (decl) != NULL_RTX
232            && GET_CODE (DECL_RTL (decl)) == MEM
233            && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
234            && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
235            && arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
236     {
237       const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
238       tree idp = get_identifier (oldname + 9);
239       rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
240
241       XEXP (DECL_RTL (decl), 0) = newrtl;
242
243       /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
244          ??? We leave these alone for now.  */
245     }
246 }
247
248 void
249 arm_pe_unique_section (decl, reloc)
250      tree decl;
251      int reloc;
252 {
253   int len;
254   const char * name;
255   char * string;
256   const char * prefix;
257
258   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
259   name = arm_strip_name_encoding (name);
260
261   /* The object is put in, for example, section .text$foo.
262      The linker will then ultimately place them in .text
263      (everything from the $ on is stripped).  */
264   if (TREE_CODE (decl) == FUNCTION_DECL)
265     prefix = ".text$";
266   else if (decl_readonly_section (decl, reloc))
267     prefix = ".rdata$";
268   else
269     prefix = ".data$";
270   len = strlen (name) + strlen (prefix);
271   string = alloca (len + 1);
272   sprintf (string, "%s%s", prefix, name);
273
274   DECL_SECTION_NAME (decl) = build_string (len, string);
275 }