Merge changes from merged-arm-thumb-backend-branch onto trunk.
[official-gcc.git] / gcc / config / arm / pe.c
blob55b4668fc6a1fc78ef1ee50b05becbf22c5895d7
1 /* Routines for GCC for ARM/pe.
2 Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc.
3 Contributed by Doug Evans (dje@cygnus.com).
5 This file is part of GNU CC.
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.
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.
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. */
22 #include "config.h"
23 #include "system.h"
24 #include "rtl.h"
25 #include "output.h"
26 #include "flags.h"
27 #include "tree.h"
28 #include "expr.h"
29 #include "toplev.h"
30 #include "tm_p.h"
32 extern int current_function_anonymous_args;
34 /* ARM/PE specific attribute support.
36 ARM/PE has three new attributes:
37 naked - for interrupt functions
38 dllexport - for exporting a function/variable that will live in a dll
39 dllimport - for importing a function/variable from a dll
41 Microsoft allows multiple declspecs in one __declspec, separating
42 them with spaces. We do NOT support this. Instead, use __declspec
43 multiple times.
46 /* Return nonzero if ATTR is a valid attribute for DECL.
47 ATTRIBUTES are any existing attributes and ARGS are the arguments
48 supplied with ATTR. */
50 int
51 arm_pe_valid_machine_decl_attribute (decl, attributes, attr, args)
52 tree decl;
53 tree attributes ATTRIBUTE_UNUSED;
54 tree attr;
55 tree args;
57 if (args != NULL_TREE)
58 return 0;
60 if (is_attribute_p ("dllexport", attr))
61 return 1;
63 if (is_attribute_p ("dllimport", attr))
64 return 1;
66 return arm_valid_machine_decl_attribute (decl, attr, args);
69 /* Merge attributes in decls OLD and NEW.
71 This handles the following situation:
73 __declspec (dllimport) int foo;
74 int foo;
76 The second instance of `foo' nullifies the dllimport. */
78 tree
79 arm_pe_merge_machine_decl_attributes (old, new)
80 tree old, new;
82 tree a;
83 int delete_dllimport_p;
85 old = DECL_MACHINE_ATTRIBUTES (old);
86 new = DECL_MACHINE_ATTRIBUTES (new);
88 /* What we need to do here is remove from `old' dllimport if it doesn't
89 appear in `new'. dllimport behaves like extern: if a declaration is
90 marked dllimport and a definition appears later, then the object
91 is not dllimport'd. */
93 if (lookup_attribute ("dllimport", old) != NULL_TREE
94 && lookup_attribute ("dllimport", new) == NULL_TREE)
95 delete_dllimport_p = 1;
96 else
97 delete_dllimport_p = 0;
99 a = merge_attributes (old, new);
101 if (delete_dllimport_p)
103 tree prev,t;
105 /* Scan the list for dllimport and delete it. */
106 for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
108 if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
110 if (prev == NULL_TREE)
111 a = TREE_CHAIN (a);
112 else
113 TREE_CHAIN (prev) = TREE_CHAIN (t);
114 break;
119 return a;
122 /* Return non-zero if DECL is a dllexport'd object. */
124 tree current_class_type; /* FIXME */
127 arm_dllexport_p (decl)
128 tree decl;
130 tree exp;
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;
139 return 0;
142 /* Return non-zero if DECL is a dllimport'd object. */
145 arm_dllimport_p (decl)
146 tree decl;
148 tree imp;
150 if (TREE_CODE (decl) == FUNCTION_DECL
151 && TARGET_NOP_FUN_DLLIMPORT)
152 return 0;
154 if (TREE_CODE (decl) != VAR_DECL
155 && TREE_CODE (decl) != FUNCTION_DECL)
156 return 0;
157 imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
158 if (imp)
159 return 1;
161 return 0;
164 /* Return non-zero if SYMBOL is marked as being dllexport'd. */
167 arm_dllexport_name_p (symbol)
168 const char * symbol;
170 return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.';
173 /* Return non-zero if SYMBOL is marked as being dllimport'd. */
176 arm_dllimport_name_p (symbol)
177 const char * symbol;
179 return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'i' && symbol[2] == '.';
182 /* Mark a DECL as being dllexport'd.
183 Note that we override the previous setting (eg: dllimport). */
185 void
186 arm_mark_dllexport (decl)
187 tree decl;
189 const char * oldname;
190 char * newname;
191 rtx rtlname;
192 tree idp;
194 rtlname = XEXP (DECL_RTL (decl), 0);
195 if (GET_CODE (rtlname) == SYMBOL_REF)
196 oldname = XSTR (rtlname, 0);
197 else if (GET_CODE (rtlname) == MEM
198 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
199 oldname = XSTR (XEXP (rtlname, 0), 0);
200 else
201 abort ();
202 if (arm_dllimport_name_p (oldname))
203 oldname += 9;
204 else if (arm_dllexport_name_p (oldname))
205 return; /* already done */
207 newname = alloca (strlen (oldname) + 4);
208 sprintf (newname, "%ce.%s", ARM_PE_FLAG_CHAR, oldname);
210 /* We pass newname through get_identifier to ensure it has a unique
211 address. RTL processing can sometimes peek inside the symbol ref
212 and compare the string's addresses to see if two symbols are
213 identical. */
214 /* ??? At least I think that's why we do this. */
215 idp = get_identifier (newname);
217 XEXP (DECL_RTL (decl), 0) =
218 gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
221 /* Mark a DECL as being dllimport'd. */
223 void
224 arm_mark_dllimport (decl)
225 tree decl;
227 const char * oldname;
228 char * newname;
229 tree idp;
230 rtx rtlname, newrtl;
232 rtlname = XEXP (DECL_RTL (decl), 0);
234 if (GET_CODE (rtlname) == SYMBOL_REF)
235 oldname = XSTR (rtlname, 0);
236 else if (GET_CODE (rtlname) == MEM
237 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
238 oldname = XSTR (XEXP (rtlname, 0), 0);
239 else
240 abort ();
242 if (arm_dllexport_name_p (oldname))
243 abort (); /* this shouldn't happen */
244 else if (arm_dllimport_name_p (oldname))
245 return; /* already done */
247 /* ??? One can well ask why we're making these checks here,
248 and that would be a good question. */
250 /* Imported variables can't be initialized. */
251 if (TREE_CODE (decl) == VAR_DECL
252 && !DECL_VIRTUAL_P (decl)
253 && DECL_INITIAL (decl))
255 error_with_decl (decl, "initialized variable `%s' is marked dllimport");
256 return;
258 /* Nor can they be static. */
259 if (TREE_CODE (decl) == VAR_DECL
260 /* ??? Is this test for vtables needed? */
261 && !DECL_VIRTUAL_P (decl)
262 && 0 /*???*/)
264 error_with_decl (decl, "static variable `%s' is marked dllimport");
265 return;
268 /* `extern' needn't be specified with dllimport.
269 Specify `extern' now and hope for the best. Sigh. */
270 if (TREE_CODE (decl) == VAR_DECL
271 /* ??? Is this test for vtables needed? */
272 && !DECL_VIRTUAL_P (decl))
274 DECL_EXTERNAL (decl) = 1;
275 TREE_PUBLIC (decl) = 1;
278 newname = alloca (strlen (oldname) + 11);
279 sprintf (newname, "%ci.__imp_%s", ARM_PE_FLAG_CHAR, oldname);
281 /* We pass newname through get_identifier to ensure it has a unique
282 address. RTL processing can sometimes peek inside the symbol ref
283 and compare the string's addresses to see if two symbols are
284 identical. */
285 /* ??? At least I think that's why we do this. */
286 idp = get_identifier (newname);
288 newrtl = gen_rtx (MEM, Pmode,
289 gen_rtx (SYMBOL_REF, Pmode,
290 IDENTIFIER_POINTER (idp)));
291 XEXP (DECL_RTL (decl), 0) = newrtl;
294 /* Cover function to implement ENCODE_SECTION_INFO. */
296 void
297 arm_pe_encode_section_info (decl)
298 tree decl;
300 /* This bit is copied from arm.h. */
301 if (optimize > 0 && TREE_CONSTANT (decl)
302 && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
304 rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
305 ? TREE_CST_RTL (decl) : DECL_RTL (decl));
306 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
309 /* Mark the decl so we can tell from the rtl whether the object is
310 dllexport'd or dllimport'd. */
311 if (arm_dllexport_p (decl))
312 arm_mark_dllexport (decl);
313 else if (arm_dllimport_p (decl))
314 arm_mark_dllimport (decl);
315 /* It might be that DECL has already been marked as dllimport, but a
316 subsequent definition nullified that. The attribute is gone but
317 DECL_RTL still has @i.__imp_foo. We need to remove that. */
318 else if ((TREE_CODE (decl) == FUNCTION_DECL
319 || TREE_CODE (decl) == VAR_DECL)
320 && DECL_RTL (decl) != NULL_RTX
321 && GET_CODE (DECL_RTL (decl)) == MEM
322 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
323 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
324 && arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
326 const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
327 tree idp = get_identifier (oldname + 9);
328 rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
330 XEXP (DECL_RTL (decl), 0) = newrtl;
332 /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
333 ??? We leave these alone for now. */
337 /* Cover function for UNIQUE_SECTION. */
339 void
340 arm_pe_unique_section (decl, reloc)
341 tree decl;
342 int reloc;
344 int len;
345 const char * name;
346 char * string;
347 char * prefix;
349 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
350 /* Strip off any encoding in fnname. */
351 STRIP_NAME_ENCODING (name, name);
353 /* The object is put in, for example, section .text$foo.
354 The linker will then ultimately place them in .text
355 (everything from the $ on is stripped). */
356 if (TREE_CODE (decl) == FUNCTION_DECL)
357 prefix = ".text$";
358 else if (DECL_READONLY_SECTION (decl, reloc))
359 prefix = ".rdata$";
360 else
361 prefix = ".data$";
362 len = strlen (name) + strlen (prefix);
363 string = alloca (len + 1);
364 sprintf (string, "%s%s", prefix, name);
366 DECL_SECTION_NAME (decl) = build_string (len, string);