1 /* Routines for GCC for ARM/pe.
2 Copyright (C) 1995, 1996 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)
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. */
31 extern int current_function_anonymous_args
;
33 /* ARM/PE specific attribute support.
35 ARM/PE has three new attributes:
36 naked - for interrupt functions
37 dllexport - for exporting a function/variable that will live in a dll
38 dllimport - for importing a function/variable from a dll
40 Microsoft allows multiple declspecs in one __declspec, separating
41 them with spaces. We do NOT support this. Instead, use __declspec
45 /* Return nonzero if ATTR is a valid attribute for DECL.
46 ATTRIBUTES are any existing attributes and ARGS are the arguments
47 supplied with ATTR. */
50 arm_pe_valid_machine_decl_attribute (decl
, attributes
, attr
, args
)
56 if (args
!= NULL_TREE
)
59 if (is_attribute_p ("dllexport", attr
))
61 if (is_attribute_p ("dllimport", attr
))
64 return arm_valid_machine_decl_attribute (decl
, attr
, args
);
67 /* Merge attributes in decls OLD and NEW.
69 This handles the following situation:
71 __declspec (dllimport) int foo;
74 The second instance of `foo' nullifies the dllimport. */
77 arm_pe_merge_machine_decl_attributes (old
, new)
81 int delete_dllimport_p
;
83 old
= DECL_MACHINE_ATTRIBUTES (old
);
84 new = DECL_MACHINE_ATTRIBUTES (new);
86 /* What we need to do here is remove from `old' dllimport if it doesn't
87 appear in `new'. dllimport behaves like extern: if a declaration is
88 marked dllimport and a definition appears later, then the object
89 is not dllimport'd. */
91 if (lookup_attribute ("dllimport", old
) != NULL_TREE
92 && lookup_attribute ("dllimport", new) == NULL_TREE
)
93 delete_dllimport_p
= 1;
95 delete_dllimport_p
= 0;
97 a
= merge_attributes (old
, new);
99 if (delete_dllimport_p
)
103 /* Scan the list for dllimport and delete it. */
104 for (prev
= NULL_TREE
, t
= a
; t
; prev
= t
, t
= TREE_CHAIN (t
))
106 if (is_attribute_p ("dllimport", TREE_PURPOSE (t
)))
108 if (prev
== NULL_TREE
)
111 TREE_CHAIN (prev
) = TREE_CHAIN (t
);
120 /* Check a type that has a virtual table, and see if any virtual methods are
121 marked for import or export, and if so, arrange for the vtable to
122 be imported or exported. */
125 arm_check_vtable_importexport (type
)
128 tree methods
= TYPE_METHODS (type
);
131 if (TREE_CODE (methods
) == FUNCTION_DECL
)
133 else if (TREE_VEC_ELT (methods
, 0) != NULL_TREE
)
134 fndecl
= TREE_VEC_ELT (methods
, 0);
136 fndecl
= TREE_VEC_ELT (methods
, 1);
140 if (DECL_VIRTUAL_P (fndecl
) || DECL_VINDEX (fndecl
) != NULL_TREE
)
142 tree exp
= lookup_attribute ("dllimport",
143 DECL_MACHINE_ATTRIBUTES (fndecl
));
145 exp
= lookup_attribute ("dllexport",
146 DECL_MACHINE_ATTRIBUTES (fndecl
));
151 fndecl
= TREE_CHAIN (fndecl
);
157 /* Return non-zero if DECL is a dllexport'd object. */
159 tree current_class_type
; /* FIXME */
162 arm_dllexport_p (decl
)
167 if (TREE_CODE (decl
) != VAR_DECL
168 && TREE_CODE (decl
) != FUNCTION_DECL
)
170 exp
= lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl
));
174 #if 0 /* This was a hack to get vtable's exported or imported since only one
175 copy of them is ever output. Disabled pending better solution. */
176 /* For C++, the vtables might have to be marked. */
177 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_VIRTUAL_P (decl
))
179 if (TREE_PUBLIC (decl
)
180 && DECL_EXTERNAL (decl
) == 0
181 && (DECL_CONTEXT (decl
)
182 ? arm_check_vtable_importexport (DECL_CONTEXT (decl
))
184 ? arm_check_vtable_importexport (current_class_type
)
194 /* Return non-zero if DECL is a dllimport'd object. */
197 arm_dllimport_p (decl
)
202 if (TREE_CODE (decl
) == FUNCTION_DECL
203 && TARGET_NOP_FUN_DLLIMPORT
)
206 if (TREE_CODE (decl
) != VAR_DECL
207 && TREE_CODE (decl
) != FUNCTION_DECL
)
209 imp
= lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl
));
213 #if 0 /* This was a hack to get vtable's exported or imported since only one
214 copy of them is ever output. Disabled pending better solution. */
215 /* For C++, the vtables might have to be marked. */
216 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_VIRTUAL_P (decl
))
218 if (TREE_PUBLIC (decl
)
219 && DECL_EXTERNAL (decl
)
220 && (DECL_CONTEXT (decl
)
221 ? arm_check_vtable_importexport (DECL_CONTEXT (decl
))
223 ? arm_check_vtable_importexport (current_class_type
)
233 /* Return non-zero if SYMBOL is marked as being dllexport'd. */
236 arm_dllexport_name_p (symbol
)
239 return symbol
[0] == '@' && symbol
[1] == 'e' && symbol
[2] == '.';
242 /* Return non-zero if SYMBOL is marked as being dllimport'd. */
245 arm_dllimport_name_p (symbol
)
248 return symbol
[0] == '@' && symbol
[1] == 'i' && symbol
[2] == '.';
251 /* Mark a DECL as being dllexport'd.
252 Note that we override the previous setting (eg: dllimport). */
255 arm_mark_dllexport (decl
)
263 rtlname
= XEXP (DECL_RTL (decl
), 0);
264 if (GET_CODE (rtlname
) == SYMBOL_REF
)
265 oldname
= XSTR (rtlname
, 0);
266 else if (GET_CODE (rtlname
) == MEM
267 && GET_CODE (XEXP (rtlname
, 0)) == SYMBOL_REF
)
268 oldname
= XSTR (XEXP (rtlname
, 0), 0);
271 if (arm_dllimport_name_p (oldname
))
273 else if (arm_dllexport_name_p (oldname
))
274 return; /* already done */
276 newname
= alloca (strlen (oldname
) + 4);
277 sprintf (newname
, "@e.%s", oldname
);
279 /* We pass newname through get_identifier to ensure it has a unique
280 address. RTL processing can sometimes peek inside the symbol ref
281 and compare the string's addresses to see if two symbols are
283 /* ??? At least I think that's why we do this. */
284 idp
= get_identifier (newname
);
286 XEXP (DECL_RTL (decl
), 0) =
287 gen_rtx (SYMBOL_REF
, Pmode
, IDENTIFIER_POINTER (idp
));
290 /* Mark a DECL as being dllimport'd. */
293 arm_mark_dllimport (decl
)
301 rtlname
= XEXP (DECL_RTL (decl
), 0);
303 if (GET_CODE (rtlname
) == SYMBOL_REF
)
304 oldname
= XSTR (rtlname
, 0);
305 else if (GET_CODE (rtlname
) == MEM
306 && GET_CODE (XEXP (rtlname
, 0)) == SYMBOL_REF
)
307 oldname
= XSTR (XEXP (rtlname
, 0), 0);
311 if (arm_dllexport_name_p (oldname
))
312 abort (); /* this shouldn't happen */
313 else if (arm_dllimport_name_p (oldname
))
314 return; /* already done */
316 /* ??? One can well ask why we're making these checks here,
317 and that would be a good question. */
319 /* Imported variables can't be initialized. */
320 if (TREE_CODE (decl
) == VAR_DECL
321 && !DECL_VIRTUAL_P (decl
)
322 && DECL_INITIAL (decl
))
324 error_with_decl (decl
, "initialized variable `%s' is marked dllimport");
327 /* Nor can they be static. */
328 if (TREE_CODE (decl
) == VAR_DECL
329 /* ??? Is this test for vtables needed? */
330 && !DECL_VIRTUAL_P (decl
)
333 error_with_decl (decl
, "static variable `%s' is marked dllimport");
337 /* `extern' needn't be specified with dllimport.
338 Specify `extern' now and hope for the best. Sigh. */
339 if (TREE_CODE (decl
) == VAR_DECL
340 /* ??? Is this test for vtables needed? */
341 && !DECL_VIRTUAL_P (decl
))
343 DECL_EXTERNAL (decl
) = 1;
344 TREE_PUBLIC (decl
) = 1;
347 newname
= alloca (strlen (oldname
) + 11);
348 sprintf (newname
, "@i.__imp_%s", oldname
);
350 /* We pass newname through get_identifier to ensure it has a unique
351 address. RTL processing can sometimes peek inside the symbol ref
352 and compare the string's addresses to see if two symbols are
354 /* ??? At least I think that's why we do this. */
355 idp
= get_identifier (newname
);
357 newrtl
= gen_rtx (MEM
, Pmode
,
358 gen_rtx (SYMBOL_REF
, Pmode
,
359 IDENTIFIER_POINTER (idp
)));
360 XEXP (DECL_RTL (decl
), 0) = newrtl
;
363 /* Cover function to implement ENCODE_SECTION_INFO. */
366 arm_pe_encode_section_info (decl
)
369 /* This bit is copied from arm.h. */
370 if (optimize
> 0 && TREE_CONSTANT (decl
)
371 && (!flag_writable_strings
|| TREE_CODE (decl
) != STRING_CST
))
373 rtx rtl
= (TREE_CODE_CLASS (TREE_CODE (decl
)) != 'd'
374 ? TREE_CST_RTL (decl
) : DECL_RTL (decl
));
375 SYMBOL_REF_FLAG (XEXP (rtl
, 0)) = 1;
378 /* Mark the decl so we can tell from the rtl whether the object is
379 dllexport'd or dllimport'd. */
380 if (arm_dllexport_p (decl
))
381 arm_mark_dllexport (decl
);
382 else if (arm_dllimport_p (decl
))
383 arm_mark_dllimport (decl
);
384 /* It might be that DECL has already been marked as dllimport, but a
385 subsequent definition nullified that. The attribute is gone but
386 DECL_RTL still has @i.__imp_foo. We need to remove that. */
387 else if ((TREE_CODE (decl
) == FUNCTION_DECL
388 || TREE_CODE (decl
) == VAR_DECL
)
389 && DECL_RTL (decl
) != NULL_RTX
390 && GET_CODE (DECL_RTL (decl
)) == MEM
391 && GET_CODE (XEXP (DECL_RTL (decl
), 0)) == MEM
392 && GET_CODE (XEXP (XEXP (DECL_RTL (decl
), 0), 0)) == SYMBOL_REF
393 && arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl
), 0), 0), 0)))
395 char *oldname
= XSTR (XEXP (XEXP (DECL_RTL (decl
), 0), 0), 0);
396 tree idp
= get_identifier (oldname
+ 9);
397 rtx newrtl
= gen_rtx (SYMBOL_REF
, Pmode
, IDENTIFIER_POINTER (idp
));
399 XEXP (DECL_RTL (decl
), 0) = newrtl
;
401 /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
402 ??? We leave these alone for now. */
406 /* Cover function for UNIQUE_SECTION. */
409 arm_pe_unique_section (decl
, reloc
)
418 name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
));
419 /* Strip off any encoding in fnname. */
420 STRIP_NAME_ENCODING (name
, name
);
422 /* The object is put in, for example, section .text$foo.
423 The linker will then ultimately place them in .text
424 (everything from the $ on is stripped). */
425 if (TREE_CODE (decl
) == FUNCTION_DECL
)
427 else if (DECL_READONLY_SECTION (decl
, reloc
))
431 len
= strlen (name
) + strlen (prefix
);
432 string
= alloca (len
+ 1);
433 sprintf (string
, "%s%s", prefix
, name
);
435 DECL_SECTION_NAME (decl
) = build_string (len
, string
);
438 /* This is to better conform to the ARM PCS.
439 Richard Earnshaw hasn't put this into FSF sources yet so it's here. */
442 arm_pe_return_in_memory (type
)
445 if (TREE_CODE (type
) == RECORD_TYPE
)
450 /* For a record containing just a single element, we can be a little
452 for (field
= TYPE_FIELDS (type
); field
; field
= TREE_CHAIN (field
))
454 if (TREE_CODE (field
) == FIELD_DECL
&& ! TREE_STATIC (field
))
456 if ((AGGREGATE_TYPE_P (TREE_TYPE (field
))
457 && RETURN_IN_MEMORY (TREE_TYPE (field
)))
458 || FLOAT_TYPE_P (TREE_TYPE (field
)))
467 /* For a struct, we can return in a register if every element was a
468 bit-field and it all fits in one word. */
469 for (field
= TYPE_FIELDS (type
); field
; field
= TREE_CHAIN (field
))
471 if (TREE_CODE (field
) == FIELD_DECL
472 && ! TREE_STATIC (field
)
473 && (! DECL_BIT_FIELD_TYPE (field
)
474 || (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field
))
475 + TREE_INT_CST_LOW (DECL_SIZE (field
))) > 32))
480 else if (TREE_CODE (type
) == UNION_TYPE
481 || TREE_CODE (type
) == QUAL_UNION_TYPE
)
485 /* Unions can be returned in registers if every element is
486 integral, or can be returned in an integer register. */
487 for (field
= TYPE_FIELDS (type
); field
; field
= TREE_CHAIN (field
))
489 if (TREE_CODE (field
) == FIELD_DECL
490 && ! TREE_STATIC (field
)
491 && ((AGGREGATE_TYPE_P (TREE_TYPE (field
))
492 && RETURN_IN_MEMORY (TREE_TYPE (field
)))
493 || FLOAT_TYPE_P (TREE_TYPE (field
))))
498 /* XXX Not sure what should be done for other aggregates, so put them in