Apply Dimitri Makarov's patch to import attribute short_call and #pragma
[official-gcc.git] / gcc / config / arm / pe.c
blob90158ff6f275b494acc74e13b4483702c7d3755c
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 "arm-protos.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;
62 if (is_attribute_p ("dllimport", attr))
63 return 1;
65 return arm_valid_machine_decl_attribute (decl, attr, args);
68 /* Merge attributes in decls OLD and NEW.
70 This handles the following situation:
72 __declspec (dllimport) int foo;
73 int foo;
75 The second instance of `foo' nullifies the dllimport. */
77 tree
78 arm_pe_merge_machine_decl_attributes (old, new)
79 tree old, new;
81 tree a;
82 int delete_dllimport_p;
84 old = DECL_MACHINE_ATTRIBUTES (old);
85 new = DECL_MACHINE_ATTRIBUTES (new);
87 /* What we need to do here is remove from `old' dllimport if it doesn't
88 appear in `new'. dllimport behaves like extern: if a declaration is
89 marked dllimport and a definition appears later, then the object
90 is not dllimport'd. */
92 if (lookup_attribute ("dllimport", old) != NULL_TREE
93 && lookup_attribute ("dllimport", new) == NULL_TREE)
94 delete_dllimport_p = 1;
95 else
96 delete_dllimport_p = 0;
98 a = merge_attributes (old, new);
100 if (delete_dllimport_p)
102 tree prev,t;
104 /* Scan the list for dllimport and delete it. */
105 for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
107 if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
109 if (prev == NULL_TREE)
110 a = TREE_CHAIN (a);
111 else
112 TREE_CHAIN (prev) = TREE_CHAIN (t);
113 break;
118 return a;
121 #if 0
122 /* Check a type that has a virtual table, and see if any virtual methods are
123 marked for import or export, and if so, arrange for the vtable to
124 be imported or exported. */
126 static int
127 arm_check_vtable_importexport (type)
128 tree type;
130 tree methods = TYPE_METHODS (type);
131 tree fndecl;
133 if (TREE_CODE (methods) == FUNCTION_DECL)
134 fndecl = methods;
135 else if (TREE_VEC_ELT (methods, 0) != NULL_TREE)
136 fndecl = TREE_VEC_ELT (methods, 0);
137 else
138 fndecl = TREE_VEC_ELT (methods, 1);
140 while (fndecl)
142 if (DECL_VIRTUAL_P (fndecl) || DECL_VINDEX (fndecl) != NULL_TREE)
144 tree exp = lookup_attribute ("dllimport",
145 DECL_MACHINE_ATTRIBUTES (fndecl));
146 if (exp == 0)
147 exp = lookup_attribute ("dllexport",
148 DECL_MACHINE_ATTRIBUTES (fndecl));
149 if (exp)
150 return 1;
153 fndecl = TREE_CHAIN (fndecl);
156 return 0;
158 #endif
160 /* Return non-zero if DECL is a dllexport'd object. */
162 tree current_class_type; /* FIXME */
165 arm_dllexport_p (decl)
166 tree decl;
168 tree exp;
170 if (TREE_CODE (decl) != VAR_DECL
171 && TREE_CODE (decl) != FUNCTION_DECL)
172 return 0;
173 exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
174 if (exp)
175 return 1;
177 #if 0 /* This was a hack to get vtable's exported or imported since only one
178 copy of them is ever output. Disabled pending better solution. */
179 /* For C++, the vtables might have to be marked. */
180 if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
182 if (TREE_PUBLIC (decl)
183 && DECL_EXTERNAL (decl) == 0
184 && (DECL_CONTEXT (decl)
185 ? arm_check_vtable_importexport (DECL_CONTEXT (decl))
186 : current_class_type
187 ? arm_check_vtable_importexport (current_class_type)
188 : 0)
190 return 1;
192 #endif
194 return 0;
197 /* Return non-zero if DECL is a dllimport'd object. */
200 arm_dllimport_p (decl)
201 tree decl;
203 tree imp;
205 if (TREE_CODE (decl) == FUNCTION_DECL
206 && TARGET_NOP_FUN_DLLIMPORT)
207 return 0;
209 if (TREE_CODE (decl) != VAR_DECL
210 && TREE_CODE (decl) != FUNCTION_DECL)
211 return 0;
212 imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
213 if (imp)
214 return 1;
216 #if 0 /* This was a hack to get vtable's exported or imported since only one
217 copy of them is ever output. Disabled pending better solution. */
218 /* For C++, the vtables might have to be marked. */
219 if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
221 if (TREE_PUBLIC (decl)
222 && DECL_EXTERNAL (decl)
223 && (DECL_CONTEXT (decl)
224 ? arm_check_vtable_importexport (DECL_CONTEXT (decl))
225 : current_class_type
226 ? arm_check_vtable_importexport (current_class_type)
227 : 0)
229 return 1;
231 #endif
233 return 0;
236 /* Return non-zero if SYMBOL is marked as being dllexport'd. */
239 arm_dllexport_name_p (symbol)
240 char * symbol;
242 return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.';
245 /* Return non-zero if SYMBOL is marked as being dllimport'd. */
248 arm_dllimport_name_p (symbol)
249 char * symbol;
251 return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'i' && symbol[2] == '.';
254 /* Mark a DECL as being dllexport'd.
255 Note that we override the previous setting (eg: dllimport). */
257 void
258 arm_mark_dllexport (decl)
259 tree decl;
261 char * oldname;
262 char * newname;
263 rtx rtlname;
264 tree idp;
266 rtlname = XEXP (DECL_RTL (decl), 0);
267 if (GET_CODE (rtlname) == SYMBOL_REF)
268 oldname = XSTR (rtlname, 0);
269 else if (GET_CODE (rtlname) == MEM
270 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
271 oldname = XSTR (XEXP (rtlname, 0), 0);
272 else
273 abort ();
274 if (arm_dllimport_name_p (oldname))
275 oldname += 9;
276 else if (arm_dllexport_name_p (oldname))
277 return; /* already done */
279 newname = alloca (strlen (oldname) + 4);
280 sprintf (newname, "%ce.%s", ARM_PE_FLAG_CHAR, oldname);
282 /* We pass newname through get_identifier to ensure it has a unique
283 address. RTL processing can sometimes peek inside the symbol ref
284 and compare the string's addresses to see if two symbols are
285 identical. */
286 /* ??? At least I think that's why we do this. */
287 idp = get_identifier (newname);
289 XEXP (DECL_RTL (decl), 0) =
290 gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
293 /* Mark a DECL as being dllimport'd. */
295 void
296 arm_mark_dllimport (decl)
297 tree decl;
299 char * oldname;
300 char * newname;
301 tree idp;
302 rtx rtlname, newrtl;
304 rtlname = XEXP (DECL_RTL (decl), 0);
306 if (GET_CODE (rtlname) == SYMBOL_REF)
307 oldname = XSTR (rtlname, 0);
308 else if (GET_CODE (rtlname) == MEM
309 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
310 oldname = XSTR (XEXP (rtlname, 0), 0);
311 else
312 abort ();
314 if (arm_dllexport_name_p (oldname))
315 abort (); /* this shouldn't happen */
316 else if (arm_dllimport_name_p (oldname))
317 return; /* already done */
319 /* ??? One can well ask why we're making these checks here,
320 and that would be a good question. */
322 /* Imported variables can't be initialized. */
323 if (TREE_CODE (decl) == VAR_DECL
324 && !DECL_VIRTUAL_P (decl)
325 && DECL_INITIAL (decl))
327 error_with_decl (decl, "initialized variable `%s' is marked dllimport");
328 return;
330 /* Nor can they be static. */
331 if (TREE_CODE (decl) == VAR_DECL
332 /* ??? Is this test for vtables needed? */
333 && !DECL_VIRTUAL_P (decl)
334 && 0 /*???*/)
336 error_with_decl (decl, "static variable `%s' is marked dllimport");
337 return;
340 /* `extern' needn't be specified with dllimport.
341 Specify `extern' now and hope for the best. Sigh. */
342 if (TREE_CODE (decl) == VAR_DECL
343 /* ??? Is this test for vtables needed? */
344 && !DECL_VIRTUAL_P (decl))
346 DECL_EXTERNAL (decl) = 1;
347 TREE_PUBLIC (decl) = 1;
350 newname = alloca (strlen (oldname) + 11);
351 sprintf (newname, "%ci.__imp_%s", ARM_PE_FLAG_CHAR, oldname);
353 /* We pass newname through get_identifier to ensure it has a unique
354 address. RTL processing can sometimes peek inside the symbol ref
355 and compare the string's addresses to see if two symbols are
356 identical. */
357 /* ??? At least I think that's why we do this. */
358 idp = get_identifier (newname);
360 newrtl = gen_rtx (MEM, Pmode,
361 gen_rtx (SYMBOL_REF, Pmode,
362 IDENTIFIER_POINTER (idp)));
363 XEXP (DECL_RTL (decl), 0) = newrtl;
366 /* Cover function to implement ENCODE_SECTION_INFO. */
368 void
369 arm_pe_encode_section_info (decl)
370 tree decl;
372 /* This bit is copied from arm.h. */
373 if (optimize > 0 && TREE_CONSTANT (decl)
374 && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
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;
381 /* Mark the decl so we can tell from the rtl whether the object is
382 dllexport'd or dllimport'd. */
383 if (arm_dllexport_p (decl))
384 arm_mark_dllexport (decl);
385 else if (arm_dllimport_p (decl))
386 arm_mark_dllimport (decl);
387 /* It might be that DECL has already been marked as dllimport, but a
388 subsequent definition nullified that. The attribute is gone but
389 DECL_RTL still has @i.__imp_foo. We need to remove that. */
390 else if ((TREE_CODE (decl) == FUNCTION_DECL
391 || TREE_CODE (decl) == VAR_DECL)
392 && DECL_RTL (decl) != NULL_RTX
393 && GET_CODE (DECL_RTL (decl)) == MEM
394 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
395 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
396 && arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
398 char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
399 tree idp = get_identifier (oldname + 9);
400 rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
402 XEXP (DECL_RTL (decl), 0) = newrtl;
404 /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
405 ??? We leave these alone for now. */
409 /* Cover function for UNIQUE_SECTION. */
411 void
412 arm_pe_unique_section (decl, reloc)
413 tree decl;
414 int reloc;
416 int len;
417 const char * name;
418 char * string;
419 char * prefix;
421 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
422 /* Strip off any encoding in fnname. */
423 STRIP_NAME_ENCODING (name, name);
425 /* The object is put in, for example, section .text$foo.
426 The linker will then ultimately place them in .text
427 (everything from the $ on is stripped). */
428 if (TREE_CODE (decl) == FUNCTION_DECL)
429 prefix = ".text$";
430 else if (DECL_READONLY_SECTION (decl, reloc))
431 prefix = ".rdata$";
432 else
433 prefix = ".data$";
434 len = strlen (name) + strlen (prefix);
435 string = alloca (len + 1);
436 sprintf (string, "%s%s", prefix, name);
438 DECL_SECTION_NAME (decl) = build_string (len, string);
441 /* This is to better conform to the ARM PCS.
442 Richard Earnshaw hasn't put this into FSF sources yet so it's here. */
445 arm_pe_return_in_memory (type)
446 tree type;
448 if (TREE_CODE (type) == RECORD_TYPE)
450 tree field;
451 int num_fields = 0;
453 /* For a record containing just a single element, we can be a little
454 less restrictive. */
455 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
457 if (TREE_CODE (field) == FIELD_DECL && ! TREE_STATIC (field))
459 if ((AGGREGATE_TYPE_P (TREE_TYPE (field))
460 && RETURN_IN_MEMORY (TREE_TYPE (field)))
461 || FLOAT_TYPE_P (TREE_TYPE (field)))
462 return 1;
463 num_fields++;
467 if (num_fields == 1)
468 return 0;
470 /* For a struct, we can return in a register if every element was a
471 bit-field and it all fits in one word. */
472 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
474 if (TREE_CODE (field) == FIELD_DECL
475 && ! TREE_STATIC (field)
476 && (! DECL_BIT_FIELD_TYPE (field)
477 || (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field))
478 + TREE_INT_CST_LOW (DECL_SIZE (field))) > 32))
479 return 1;
481 return 0;
483 else if (TREE_CODE (type) == UNION_TYPE
484 || TREE_CODE (type) == QUAL_UNION_TYPE)
486 tree field;
488 /* Unions can be returned in registers if every element is
489 integral, or can be returned in an integer register. */
490 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
492 if (TREE_CODE (field) == FIELD_DECL
493 && ! TREE_STATIC (field)
494 && ((AGGREGATE_TYPE_P (TREE_TYPE (field))
495 && RETURN_IN_MEMORY (TREE_TYPE (field)))
496 || FLOAT_TYPE_P (TREE_TYPE (field))))
497 return 1;
499 return 0;
501 /* XXX Not sure what should be done for other aggregates, so put them in
502 memory. */
503 return 1;