]>
Commit | Line | Data |
---|---|---|
30c71308 RK |
1 | /* Subroutines for insn-output.c for Windows NT. |
2 | Contributed by Douglas Rupp (drupp@cs.washington.edu) | |
4e2bb0a4 | 3 | Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, |
6d217c32 | 4 | 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. |
30c71308 | 5 | |
6b6cb52e | 6 | This file is part of GCC. |
30c71308 | 7 | |
6b6cb52e DS |
8 | GCC is free software; you can redistribute it and/or modify it under |
9 | the terms of the GNU General Public License as published by the Free | |
2f83c7d6 | 10 | Software Foundation; either version 3, or (at your option) any later |
6b6cb52e | 11 | version. |
30c71308 | 12 | |
6b6cb52e DS |
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
30c71308 RK |
17 | |
18 | You should have received a copy of the GNU General Public License | |
2f83c7d6 NC |
19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. */ | |
40dcd88b | 21 | |
30c71308 | 22 | #include "config.h" |
293bcdc9 | 23 | #include "system.h" |
4977bab6 ZW |
24 | #include "coretypes.h" |
25 | #include "tm.h" | |
30c71308 RK |
26 | #include "rtl.h" |
27 | #include "regs.h" | |
28 | #include "hard-reg-set.h" | |
29 | #include "output.h" | |
30 | #include "tree.h" | |
31 | #include "flags.h" | |
79f96374 DB |
32 | #include "tm_p.h" |
33 | #include "toplev.h" | |
7c262518 | 34 | #include "hashtab.h" |
bfb139b4 | 35 | #include "langhooks.h" |
772c5265 | 36 | #include "ggc.h" |
da489f73 | 37 | #include "target.h" |
3bec79c5 | 38 | #include "lto-streamer.h" |
30c71308 | 39 | |
27da1b4d MK |
40 | /* i386/PE specific attribute support. |
41 | ||
42 | i386/PE has two new attributes: | |
43 | dllexport - for exporting a function/variable that will live in a dll | |
44 | dllimport - for importing a function/variable from a dll | |
45 | ||
46 | Microsoft allows multiple declspecs in one __declspec, separating | |
47 | them with spaces. We do NOT support this. Instead, use __declspec | |
48 | multiple times. | |
49 | */ | |
50 | ||
91d231cb JM |
51 | /* Handle a "shared" attribute; |
52 | arguments as in struct attribute_spec.handler. */ | |
53 | tree | |
9c808aad AJ |
54 | ix86_handle_shared_attribute (tree *node, tree name, |
55 | tree args ATTRIBUTE_UNUSED, | |
56 | int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) | |
ac478ac0 | 57 | { |
91d231cb | 58 | if (TREE_CODE (*node) != VAR_DECL) |
ac478ac0 | 59 | { |
29d08eba JM |
60 | warning (OPT_Wattributes, "%qE attribute only applies to variables", |
61 | name); | |
91d231cb | 62 | *no_add_attrs = true; |
ac478ac0 JM |
63 | } |
64 | ||
91d231cb | 65 | return NULL_TREE; |
ac478ac0 | 66 | } |
a20f6f00 DS |
67 | |
68 | /* Handle a "selectany" attribute; | |
69 | arguments as in struct attribute_spec.handler. */ | |
70 | tree | |
71 | ix86_handle_selectany_attribute (tree *node, tree name, | |
72 | tree args ATTRIBUTE_UNUSED, | |
73 | int flags ATTRIBUTE_UNUSED, | |
74 | bool *no_add_attrs) | |
75 | { | |
76 | /* The attribute applies only to objects that are initialized and have | |
4e2bb0a4 DS |
77 | external linkage. However, we may not know about initialization |
78 | until the language frontend has processed the decl. We'll check for | |
5234b8f5 | 79 | initialization later in encode_section_info. */ |
4e2bb0a4 | 80 | if (TREE_CODE (*node) != VAR_DECL || !TREE_PUBLIC (*node)) |
a20f6f00 | 81 | { |
29d08eba JM |
82 | error ("%qE attribute applies only to initialized variables" |
83 | " with external linkage", name); | |
a20f6f00 DS |
84 | *no_add_attrs = true; |
85 | } | |
86 | ||
87 | return NULL_TREE; | |
88 | } | |
89 | ||
27da1b4d | 90 | \f |
ac478ac0 JM |
91 | /* Return the type that we should use to determine if DECL is |
92 | imported or exported. */ | |
27da1b4d | 93 | |
ac478ac0 | 94 | static tree |
9c808aad | 95 | associated_type (tree decl) |
27da1b4d | 96 | { |
da489f73 RH |
97 | return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)) |
98 | ? DECL_CONTEXT (decl) : NULL_TREE); | |
27da1b4d MK |
99 | } |
100 | ||
da489f73 | 101 | /* Return true if DECL should be a dllexport'd object. */ |
43d9ad1d DS |
102 | |
103 | static bool | |
da489f73 | 104 | i386_pe_determine_dllexport_p (tree decl) |
27da1b4d | 105 | { |
da489f73 | 106 | if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) |
43d9ad1d | 107 | return false; |
27da1b4d | 108 | |
b20231fe DS |
109 | /* Don't export local clones of dllexports. */ |
110 | if (!TREE_PUBLIC (decl)) | |
111 | return false; | |
112 | ||
43d9ad1d DS |
113 | if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) |
114 | return true; | |
27da1b4d | 115 | |
43d9ad1d DS |
116 | return false; |
117 | } | |
118 | ||
da489f73 RH |
119 | /* Return true if DECL should be a dllimport'd object. */ |
120 | ||
43d9ad1d | 121 | static bool |
da489f73 | 122 | i386_pe_determine_dllimport_p (tree decl) |
27da1b4d | 123 | { |
da489f73 RH |
124 | tree assoc; |
125 | ||
126 | if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) | |
43d9ad1d DS |
127 | return false; |
128 | ||
da489f73 RH |
129 | if (DECL_DLLIMPORT_P (decl)) |
130 | return true; | |
131 | ||
43d9ad1d DS |
132 | /* The DECL_DLLIMPORT_P flag was set for decls in the class definition |
133 | by targetm.cxx.adjust_class_at_definition. Check again to emit | |
09a6b8a4 DS |
134 | error message if the class attribute has been overridden by an |
135 | out-of-class definition of static data. */ | |
da489f73 | 136 | assoc = associated_type (decl); |
09a6b8a4 DS |
137 | if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc)) |
138 | && TREE_CODE (decl) == VAR_DECL | |
139 | && TREE_STATIC (decl) && TREE_PUBLIC (decl) | |
140 | && !DECL_EXTERNAL (decl) | |
141 | /* vtable's are linkonce constants, so defining a vtable is not | |
142 | an error as long as we don't try to import it too. */ | |
143 | && !DECL_VIRTUAL_P (decl)) | |
144 | error ("definition of static data member %q+D of " | |
145 | "dllimport'd class", decl); | |
43d9ad1d DS |
146 | |
147 | return false; | |
148 | } | |
27da1b4d | 149 | |
43d9ad1d | 150 | /* Handle the -mno-fun-dllimport target switch. */ |
da489f73 | 151 | |
43d9ad1d | 152 | bool |
3101faab | 153 | i386_pe_valid_dllimport_attribute_p (const_tree decl) |
43d9ad1d DS |
154 | { |
155 | if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL) | |
156 | return false; | |
157 | return true; | |
27da1b4d MK |
158 | } |
159 | ||
5234b8f5 DS |
160 | /* Return string which is the function name, identified by ID, modified |
161 | with a suffix consisting of an atsign (@) followed by the number of | |
162 | bytes of arguments. If ID is NULL use the DECL_NAME as base. If | |
163 | FASTCALL is true, also add the FASTCALL_PREFIX. | |
da489f73 | 164 | Return NULL if no change required. */ |
30c71308 | 165 | |
23d34220 | 166 | static tree |
5234b8f5 | 167 | gen_stdcall_or_fastcall_suffix (tree decl, tree id, bool fastcall) |
30c71308 | 168 | { |
da489f73 | 169 | HOST_WIDE_INT total = 0; |
5234b8f5 | 170 | const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl)); |
da489f73 | 171 | char *new_str, *p; |
04e1d06b MM |
172 | tree type = TREE_TYPE (decl); |
173 | tree arg; | |
174 | function_args_iterator args_iter; | |
30c71308 | 175 | |
5234b8f5 | 176 | gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); |
23d34220 | 177 | |
04e1d06b MM |
178 | if (prototype_p (type)) |
179 | { | |
180 | /* This attribute is ignored for variadic functions. */ | |
181 | if (stdarg_p (type)) | |
182 | return NULL_TREE; | |
183 | ||
184 | /* Quit if we hit an incomplete type. Error is reported | |
185 | by convert_arguments in c-typeck.c or cp/typeck.c. */ | |
186 | FOREACH_FUNCTION_ARGS(type, arg, args_iter) | |
187 | { | |
188 | HOST_WIDE_INT parm_size; | |
189 | HOST_WIDE_INT parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT; | |
190 | ||
191 | if (! COMPLETE_TYPE_P (arg)) | |
192 | break; | |
193 | ||
194 | parm_size = int_size_in_bytes (arg); | |
195 | if (parm_size < 0) | |
196 | break; | |
197 | ||
198 | /* Must round up to include padding. This is done the same | |
199 | way as in store_one_arg. */ | |
200 | parm_size = ((parm_size + parm_boundary_bytes - 1) | |
201 | / parm_boundary_bytes * parm_boundary_bytes); | |
202 | total += parm_size; | |
203 | } | |
da489f73 | 204 | } |
9c808aad | 205 | /* Assume max of 8 base 10 digits in the suffix. */ |
5ead67f6 | 206 | p = new_str = XALLOCAVEC (char, 1 + strlen (old_str) + 1 + 8 + 1); |
23d34220 DS |
207 | if (fastcall) |
208 | *p++ = FASTCALL_PREFIX; | |
5234b8f5 | 209 | sprintf (p, "%s@" HOST_WIDE_INT_PRINT_DEC, old_str, total); |
da489f73 RH |
210 | |
211 | return get_identifier (new_str); | |
30c71308 | 212 | } |
0ea6b275 | 213 | |
5234b8f5 DS |
214 | /* Maybe decorate and get a new identifier for the DECL of a stdcall or |
215 | fastcall function. The original identifier is supplied in ID. */ | |
216 | ||
217 | static tree | |
218 | i386_pe_maybe_mangle_decl_assembler_name (tree decl, tree id) | |
219 | { | |
220 | tree new_id = NULL_TREE; | |
221 | ||
222 | if (TREE_CODE (decl) == FUNCTION_DECL) | |
223 | { | |
224 | tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl)); | |
225 | if (lookup_attribute ("stdcall", type_attributes)) | |
226 | new_id = gen_stdcall_or_fastcall_suffix (decl, id, false); | |
227 | else if (lookup_attribute ("fastcall", type_attributes)) | |
228 | new_id = gen_stdcall_or_fastcall_suffix (decl, id, true); | |
229 | } | |
230 | ||
231 | return new_id; | |
232 | } | |
233 | ||
234 | /* This is used as a target hook to modify the DECL_ASSEMBLER_NAME | |
235 | in the language-independent default hook | |
236 | langhooks,c:lhd_set_decl_assembler_name () | |
237 | and in cp/mangle,c:mangle_decl (). */ | |
238 | tree | |
239 | i386_pe_mangle_decl_assembler_name (tree decl, tree id) | |
240 | { | |
241 | tree new_id = i386_pe_maybe_mangle_decl_assembler_name (decl, id); | |
242 | ||
243 | return (new_id ? new_id : id); | |
244 | } | |
245 | ||
27da1b4d | 246 | void |
9c808aad | 247 | i386_pe_encode_section_info (tree decl, rtx rtl, int first) |
27da1b4d | 248 | { |
da489f73 RH |
249 | rtx symbol; |
250 | int flags; | |
251 | ||
252 | /* Do this last, due to our frobbing of DECL_DLLIMPORT_P above. */ | |
c6a2438a | 253 | default_encode_section_info (decl, rtl, first); |
27da1b4d | 254 | |
da489f73 RH |
255 | /* Careful not to prod global register variables. */ |
256 | if (!MEM_P (rtl)) | |
257 | return; | |
258 | ||
259 | symbol = XEXP (rtl, 0); | |
260 | gcc_assert (GET_CODE (symbol) == SYMBOL_REF); | |
261 | ||
262 | switch (TREE_CODE (decl)) | |
e91f04de | 263 | { |
da489f73 | 264 | case FUNCTION_DECL: |
bfb139b4 DS |
265 | /* FIXME: Imported stdcall names are not modified by the Ada frontend. |
266 | Check and decorate the RTL name now. */ | |
267 | if (strcmp (lang_hooks.name, "GNU Ada") == 0) | |
23d34220 | 268 | { |
bfb139b4 DS |
269 | tree new_id; |
270 | tree old_id = DECL_ASSEMBLER_NAME (decl); | |
271 | const char* asm_str = IDENTIFIER_POINTER (old_id); | |
272 | /* Do not change the identifier if a verbatim asmspec | |
5234b8f5 | 273 | or if stdcall suffix already added. */ |
bfb139b4 DS |
274 | if (!(*asm_str == '*' || strchr (asm_str, '@')) |
275 | && (new_id = i386_pe_maybe_mangle_decl_assembler_name (decl, | |
276 | old_id))) | |
277 | XSTR (symbol, 0) = IDENTIFIER_POINTER (new_id); | |
23d34220 | 278 | } |
da489f73 | 279 | break; |
27da1b4d | 280 | |
da489f73 RH |
281 | case VAR_DECL: |
282 | if (lookup_attribute ("selectany", DECL_ATTRIBUTES (decl))) | |
283 | { | |
284 | if (DECL_INITIAL (decl) | |
285 | /* If an object is initialized with a ctor, the static | |
286 | initialization and destruction code for it is present in | |
287 | each unit defining the object. The code that calls the | |
288 | ctor is protected by a link-once guard variable, so that | |
289 | the object still has link-once semantics, */ | |
290 | || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) | |
daa0eeb8 | 291 | make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl)); |
da489f73 RH |
292 | else |
293 | error ("%q+D:'selectany' attribute applies only to " | |
294 | "initialized objects", decl); | |
295 | } | |
296 | break; | |
297 | ||
298 | default: | |
299 | return; | |
4e2bb0a4 DS |
300 | } |
301 | ||
27da1b4d | 302 | /* Mark the decl so we can tell from the rtl whether the object is |
43d9ad1d DS |
303 | dllexport'd or dllimport'd. tree.c: merge_dllimport_decl_attributes |
304 | handles dllexport/dllimport override semantics. */ | |
da489f73 RH |
305 | flags = (SYMBOL_REF_FLAGS (symbol) & |
306 | ~(SYMBOL_FLAG_DLLIMPORT | SYMBOL_FLAG_DLLEXPORT)); | |
307 | if (i386_pe_determine_dllexport_p (decl)) | |
308 | flags |= SYMBOL_FLAG_DLLEXPORT; | |
309 | else if (i386_pe_determine_dllimport_p (decl)) | |
09a6b8a4 DS |
310 | flags |= SYMBOL_FLAG_DLLIMPORT; |
311 | ||
da489f73 | 312 | SYMBOL_REF_FLAGS (symbol) = flags; |
27da1b4d MK |
313 | } |
314 | ||
da489f73 | 315 | bool |
3101faab | 316 | i386_pe_binds_local_p (const_tree exp) |
772c5265 | 317 | { |
da489f73 RH |
318 | /* PE does not do dynamic binding. Indeed, the only kind of |
319 | non-local reference comes from a dllimport'd symbol. */ | |
320 | if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL) | |
321 | && DECL_DLLIMPORT_P (exp)) | |
322 | return false; | |
323 | ||
2dfccd83 DK |
324 | /* Or a weak one, now that they are supported. */ |
325 | if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL) | |
326 | && DECL_WEAK (exp)) | |
e97580ce DK |
327 | /* But x64 gets confused and attempts to use unsupported GOTPCREL |
328 | relocations if we tell it the truth, so we still return true in | |
329 | that case until the deeper problem can be fixed. */ | |
330 | return (TARGET_64BIT && DEFAULT_ABI == MS_ABI); | |
2dfccd83 | 331 | |
da489f73 | 332 | return true; |
772c5265 RH |
333 | } |
334 | ||
b1f123c7 | 335 | /* Also strip the fastcall prefix and stdcall suffix. */ |
772c5265 RH |
336 | |
337 | const char * | |
9c808aad | 338 | i386_pe_strip_name_encoding_full (const char *str) |
772c5265 RH |
339 | { |
340 | const char *p; | |
da489f73 | 341 | const char *name = default_strip_name_encoding (str); |
9c808aad | 342 | |
b1f123c7 DS |
343 | /* Strip leading '@' on fastcall symbols. */ |
344 | if (*name == '@') | |
345 | name++; | |
346 | ||
347 | /* Strip trailing "@n". */ | |
772c5265 RH |
348 | p = strchr (name, '@'); |
349 | if (p) | |
12df9508 DS |
350 | return ggc_alloc_string (name, p - name); |
351 | ||
772c5265 RH |
352 | return name; |
353 | } | |
354 | ||
516dd80f | 355 | void |
9c808aad | 356 | i386_pe_unique_section (tree decl, int reloc) |
b64deb96 JM |
357 | { |
358 | int len; | |
79f96374 DB |
359 | const char *name, *prefix; |
360 | char *string; | |
b64deb96 JM |
361 | |
362 | name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); | |
772c5265 | 363 | name = i386_pe_strip_name_encoding_full (name); |
b64deb96 JM |
364 | |
365 | /* The object is put in, for example, section .text$foo. | |
366 | The linker will then ultimately place them in .text | |
81023100 | 367 | (everything from the $ on is stripped). Don't put |
9c808aad | 368 | read-only data in .rdata section to avoid a PE linker |
81023100 MK |
369 | bug when .rdata$* grouped sections are used in code |
370 | without a .rdata section. */ | |
b64deb96 JM |
371 | if (TREE_CODE (decl) == FUNCTION_DECL) |
372 | prefix = ".text$"; | |
4e4d733e | 373 | else if (decl_readonly_section (decl, reloc)) |
b64deb96 JM |
374 | prefix = ".rdata$"; |
375 | else | |
376 | prefix = ".data$"; | |
377 | len = strlen (name) + strlen (prefix); | |
5ead67f6 | 378 | string = XALLOCAVEC (char, len + 1); |
b64deb96 JM |
379 | sprintf (string, "%s%s", prefix, name); |
380 | ||
516dd80f | 381 | DECL_SECTION_NAME (decl) = build_string (len, string); |
b64deb96 | 382 | } |
7c262518 RH |
383 | |
384 | /* Select a set of attributes for section NAME based on the properties | |
385 | of DECL and whether or not RELOC indicates that DECL's initializer | |
386 | might contain runtime relocations. | |
387 | ||
388 | We make the section read-only and executable for a function decl, | |
389 | read-only for a const data decl, and writable for a non-const data decl. | |
390 | ||
391 | If the section has already been defined, to not allow it to have | |
392 | different attributes, as (1) this is ambiguous since we're not seeing | |
393 | all the declarations up front and (2) some assemblers (e.g. SVR4) | |
d1f87653 | 394 | do not recognize section redefinitions. */ |
7c262518 RH |
395 | /* ??? This differs from the "standard" PE implementation in that we |
396 | handle the SHARED variable attribute. Should this be done for all | |
397 | PE targets? */ | |
398 | ||
399 | #define SECTION_PE_SHARED SECTION_MACH_DEP | |
400 | ||
401 | unsigned int | |
9c808aad | 402 | i386_pe_section_type_flags (tree decl, const char *name, int reloc) |
7c262518 RH |
403 | { |
404 | static htab_t htab; | |
405 | unsigned int flags; | |
406 | unsigned int **slot; | |
407 | ||
408 | /* The names we put in the hashtable will always be the unique | |
1ae58c30 | 409 | versions given to us by the stringtable, so we can just use |
7c262518 RH |
410 | their addresses as the keys. */ |
411 | if (!htab) | |
412 | htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL); | |
413 | ||
414 | if (decl && TREE_CODE (decl) == FUNCTION_DECL) | |
415 | flags = SECTION_CODE; | |
4e4d733e | 416 | else if (decl && decl_readonly_section (decl, reloc)) |
7c262518 | 417 | flags = 0; |
40f39798 ZM |
418 | else if (current_function_decl |
419 | && cfun | |
420 | && crtl->subsections.unlikely_text_section_name | |
421 | && strcmp (name, crtl->subsections.unlikely_text_section_name) == 0) | |
422 | flags = SECTION_CODE; | |
423 | else if (!decl | |
424 | && (!current_function_decl || !cfun) | |
425 | && strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0) | |
426 | flags = SECTION_CODE; | |
7c262518 RH |
427 | else |
428 | { | |
429 | flags = SECTION_WRITE; | |
430 | ||
431 | if (decl && TREE_CODE (decl) == VAR_DECL | |
91d231cb | 432 | && lookup_attribute ("shared", DECL_ATTRIBUTES (decl))) |
7c262518 RH |
433 | flags |= SECTION_PE_SHARED; |
434 | } | |
435 | ||
436 | if (decl && DECL_ONE_ONLY (decl)) | |
437 | flags |= SECTION_LINKONCE; | |
438 | ||
439 | /* See if we already have an entry for this section. */ | |
440 | slot = (unsigned int **) htab_find_slot (htab, name, INSERT); | |
441 | if (!*slot) | |
442 | { | |
443 | *slot = (unsigned int *) xmalloc (sizeof (unsigned int)); | |
444 | **slot = flags; | |
445 | } | |
446 | else | |
447 | { | |
448 | if (decl && **slot != flags) | |
dee15844 | 449 | error ("%q+D causes a section type conflict", decl); |
7c262518 RH |
450 | } |
451 | ||
452 | return flags; | |
453 | } | |
454 | ||
455 | void | |
c18a5b6c | 456 | i386_pe_asm_named_section (const char *name, unsigned int flags, |
a20f6f00 | 457 | tree decl) |
7c262518 RH |
458 | { |
459 | char flagchars[8], *f = flagchars; | |
460 | ||
7f27395d DS |
461 | if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0) |
462 | /* readonly data */ | |
463 | { | |
464 | *f++ ='d'; /* This is necessary for older versions of gas. */ | |
465 | *f++ ='r'; | |
466 | } | |
467 | else | |
1e8a5248 DS |
468 | { |
469 | if (flags & SECTION_CODE) | |
470 | *f++ = 'x'; | |
471 | if (flags & SECTION_WRITE) | |
472 | *f++ = 'w'; | |
473 | if (flags & SECTION_PE_SHARED) | |
474 | *f++ = 's'; | |
475 | } | |
7f27395d | 476 | |
3bec79c5 DK |
477 | /* LTO sections need 1-byte alignment to avoid confusing the |
478 | zlib decompression algorithm with trailing zero pad bytes. */ | |
479 | if (strncmp (name, LTO_SECTION_NAME_PREFIX, | |
480 | strlen (LTO_SECTION_NAME_PREFIX)) == 0) | |
481 | *f++ = '0'; | |
482 | ||
7c262518 RH |
483 | *f = '\0'; |
484 | ||
485 | fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars); | |
486 | ||
487 | if (flags & SECTION_LINKONCE) | |
488 | { | |
489 | /* Functions may have been compiled at various levels of | |
a20f6f00 DS |
490 | optimization so we can't use `same_size' here. |
491 | Instead, have the linker pick one, without warning. | |
315682fb | 492 | If 'selectany' attribute has been specified, MS compiler |
a20f6f00 DS |
493 | sets 'discard' characteristic, rather than telling linker |
494 | to warn of size or content mismatch, so do the same. */ | |
495 | bool discard = (flags & SECTION_CODE) | |
496 | || lookup_attribute ("selectany", | |
497 | DECL_ATTRIBUTES (decl)); | |
7c262518 | 498 | fprintf (asm_out_file, "\t.linkonce %s\n", |
a20f6f00 | 499 | (discard ? "discard" : "same_size")); |
7c262518 RH |
500 | } |
501 | } | |
da489f73 | 502 | |
3bec79c5 DK |
503 | /* Beware, DECL may be NULL if compile_file() is emitting the LTO marker. */ |
504 | ||
da489f73 RH |
505 | void |
506 | i386_pe_asm_output_aligned_decl_common (FILE *stream, tree decl, | |
507 | const char *name, HOST_WIDE_INT size, | |
508 | HOST_WIDE_INT align ATTRIBUTE_UNUSED) | |
509 | { | |
510 | HOST_WIDE_INT rounded; | |
511 | ||
233215fe DK |
512 | /* Compute as in assemble_noswitch_variable, since we don't have |
513 | support for aligned common on older binutils. We must also | |
514 | avoid emitting a common symbol of size zero, as this is the | |
515 | overloaded representation that indicates an undefined external | |
516 | symbol in the PE object file format. */ | |
da489f73 RH |
517 | rounded = size ? size : 1; |
518 | rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; | |
519 | rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) | |
520 | * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); | |
521 | ||
522 | i386_pe_maybe_record_exported_symbol (decl, name, 1); | |
523 | ||
ecb8c3cc | 524 | fprintf (stream, "\t.comm\t"); |
da489f73 | 525 | assemble_name (stream, name); |
233215fe DK |
526 | if (use_pe_aligned_common) |
527 | fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC ", %d\n", | |
528 | size ? size : (HOST_WIDE_INT) 1, | |
529 | exact_log2 (align) - exact_log2 (CHAR_BIT)); | |
530 | else | |
531 | fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START | |
532 | " " HOST_WIDE_INT_PRINT_DEC "\n", rounded, size); | |
da489f73 | 533 | } |
9fa1246d JL |
534 | \f |
535 | /* The Microsoft linker requires that every function be marked as | |
cae21ae8 | 536 | DT_FCN. When using gas on cygwin, we must emit appropriate .type |
9fa1246d JL |
537 | directives. */ |
538 | ||
539 | #include "gsyms.h" | |
540 | ||
541 | /* Mark a function appropriately. This should only be called for | |
542 | functions for which we are not emitting COFF debugging information. | |
543 | FILE is the assembler output file, NAME is the name of the | |
0a2aaacc | 544 | function, and PUB is nonzero if the function is globally |
9fa1246d JL |
545 | visible. */ |
546 | ||
547 | void | |
0a2aaacc | 548 | i386_pe_declare_function_type (FILE *file, const char *name, int pub) |
9fa1246d JL |
549 | { |
550 | fprintf (file, "\t.def\t"); | |
551 | assemble_name (file, name); | |
552 | fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n", | |
0a2aaacc | 553 | pub ? (int) C_EXT : (int) C_STAT, |
9fa1246d JL |
554 | (int) DT_FCN << N_BTSHFT); |
555 | } | |
556 | ||
557 | /* Keep a list of external functions. */ | |
558 | ||
d1b38208 | 559 | struct GTY(()) extern_list |
9fa1246d JL |
560 | { |
561 | struct extern_list *next; | |
3ce9c824 | 562 | tree decl; |
79f96374 | 563 | const char *name; |
9fa1246d JL |
564 | }; |
565 | ||
90aa6719 | 566 | static GTY(()) struct extern_list *extern_head; |
9fa1246d JL |
567 | |
568 | /* Assemble an external function reference. We need to keep a list of | |
569 | these, so that we can output the function types at the end of the | |
570 | assembly. We can't output the types now, because we might see a | |
571 | definition of the function later on and emit debugging information | |
572 | for it then. */ | |
573 | ||
574 | void | |
3ce9c824 | 575 | i386_pe_record_external_function (tree decl, const char *name) |
9fa1246d JL |
576 | { |
577 | struct extern_list *p; | |
578 | ||
a9429e29 | 579 | p = ggc_alloc_extern_list (); |
9fa1246d | 580 | p->next = extern_head; |
3ce9c824 | 581 | p->decl = decl; |
9fa1246d JL |
582 | p->name = name; |
583 | extern_head = p; | |
584 | } | |
585 | ||
8e260ba4 MK |
586 | /* Keep a list of exported symbols. */ |
587 | ||
d1b38208 | 588 | struct GTY(()) export_list |
8e260ba4 MK |
589 | { |
590 | struct export_list *next; | |
79f96374 | 591 | const char *name; |
892a2d68 | 592 | int is_data; /* used to type tag exported symbols. */ |
8e260ba4 MK |
593 | }; |
594 | ||
90aa6719 | 595 | static GTY(()) struct export_list *export_head; |
e43f9c10 MK |
596 | |
597 | /* Assemble an export symbol entry. We need to keep a list of | |
598 | these, so that we can output the export list at the end of the | |
599 | assembly. We used to output these export symbols in each function, | |
9c808aad | 600 | but that causes problems with GNU ld when the sections are |
3bec79c5 DK |
601 | linkonce. Beware, DECL may be NULL if compile_file() is emitting |
602 | the LTO marker. */ | |
e43f9c10 MK |
603 | |
604 | void | |
da489f73 | 605 | i386_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_data) |
e43f9c10 | 606 | { |
da489f73 | 607 | rtx symbol; |
8e260ba4 | 608 | struct export_list *p; |
e43f9c10 | 609 | |
3bec79c5 DK |
610 | if (!decl) |
611 | return; | |
612 | ||
da489f73 RH |
613 | symbol = XEXP (DECL_RTL (decl), 0); |
614 | gcc_assert (GET_CODE (symbol) == SYMBOL_REF); | |
615 | if (!SYMBOL_REF_DLLEXPORT_P (symbol)) | |
616 | return; | |
617 | ||
b20231fe DS |
618 | gcc_assert (TREE_PUBLIC (decl)); |
619 | ||
a9429e29 | 620 | p = ggc_alloc_export_list (); |
8e260ba4 | 621 | p->next = export_head; |
e43f9c10 | 622 | p->name = name; |
8e260ba4 MK |
623 | p->is_data = is_data; |
624 | export_head = p; | |
e43f9c10 MK |
625 | } |
626 | ||
f7e413e2 DK |
627 | #ifdef CXX_WRAP_SPEC_LIST |
628 | ||
629 | /* Hash table equality helper function. */ | |
630 | ||
631 | static int | |
632 | wrapper_strcmp (const void *x, const void *y) | |
633 | { | |
634 | return !strcmp ((const char *) x, (const char *) y); | |
635 | } | |
636 | ||
637 | /* Search for a function named TARGET in the list of library wrappers | |
638 | we are using, returning a pointer to it if found or NULL if not. | |
639 | This function might be called on quite a few symbols, and we only | |
640 | have the list of names of wrapped functions available to us as a | |
641 | spec string, so first time round we lazily initialise a hash table | |
642 | to make things quicker. */ | |
643 | ||
644 | static const char * | |
645 | i386_find_on_wrapper_list (const char *target) | |
646 | { | |
647 | static char first_time = 1; | |
648 | static htab_t wrappers; | |
649 | ||
650 | if (first_time) | |
651 | { | |
652 | /* Beware that this is not a complicated parser, it assumes | |
653 | that any sequence of non-whitespace beginning with an | |
654 | underscore is one of the wrapped symbols. For now that's | |
655 | adequate to distinguish symbols from spec substitutions | |
656 | and command-line options. */ | |
657 | static char wrapper_list_buffer[] = CXX_WRAP_SPEC_LIST; | |
658 | char *bufptr; | |
659 | /* Breaks up the char array into separated strings | |
660 | strings and enter them into the hash table. */ | |
661 | wrappers = htab_create_alloc (8, htab_hash_string, wrapper_strcmp, | |
662 | 0, xcalloc, free); | |
663 | for (bufptr = wrapper_list_buffer; *bufptr; ++bufptr) | |
664 | { | |
665 | char *found = NULL; | |
666 | if (ISSPACE (*bufptr)) | |
667 | continue; | |
668 | if (*bufptr == '_') | |
669 | found = bufptr; | |
670 | while (*bufptr && !ISSPACE (*bufptr)) | |
671 | ++bufptr; | |
672 | if (*bufptr) | |
673 | *bufptr = 0; | |
674 | if (found) | |
675 | *htab_find_slot (wrappers, found, INSERT) = found; | |
676 | } | |
677 | first_time = 0; | |
678 | } | |
679 | ||
680 | return (const char *) htab_find (wrappers, target); | |
681 | } | |
682 | ||
683 | #endif /* CXX_WRAP_SPEC_LIST */ | |
684 | ||
9fa1246d | 685 | /* This is called at the end of assembly. For each external function |
e43f9c10 MK |
686 | which has not been defined, we output a declaration now. We also |
687 | output the .drectve section. */ | |
9fa1246d JL |
688 | |
689 | void | |
9c808aad | 690 | i386_pe_file_end (void) |
9fa1246d JL |
691 | { |
692 | struct extern_list *p; | |
693 | ||
694 | for (p = extern_head; p != NULL; p = p->next) | |
695 | { | |
696 | tree decl; | |
697 | ||
3ce9c824 | 698 | decl = p->decl; |
9fa1246d JL |
699 | |
700 | /* Positively ensure only one declaration for any given symbol. */ | |
3ce9c824 ILT |
701 | if (! TREE_ASM_WRITTEN (decl) |
702 | && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) | |
9fa1246d | 703 | { |
f7e413e2 DK |
704 | #ifdef CXX_WRAP_SPEC_LIST |
705 | /* To ensure the DLL that provides the corresponding real | |
706 | functions is still loaded at runtime, we must reference | |
707 | the real function so that an (unused) import is created. */ | |
708 | const char *realsym = i386_find_on_wrapper_list (p->name); | |
709 | if (realsym) | |
710 | i386_pe_declare_function_type (asm_out_file, | |
711 | concat ("__real_", realsym, NULL), TREE_PUBLIC (decl)); | |
712 | #endif /* CXX_WRAP_SPEC_LIST */ | |
9fa1246d | 713 | TREE_ASM_WRITTEN (decl) = 1; |
a5fe455b | 714 | i386_pe_declare_function_type (asm_out_file, p->name, |
9c808aad | 715 | TREE_PUBLIC (decl)); |
9fa1246d JL |
716 | } |
717 | } | |
e43f9c10 | 718 | |
8e260ba4 | 719 | if (export_head) |
e43f9c10 | 720 | { |
8e260ba4 MK |
721 | struct export_list *q; |
722 | drectve_section (); | |
723 | for (q = export_head; q != NULL; q = q->next) | |
724 | { | |
a5fe455b | 725 | fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n", |
4b07e9f7 | 726 | default_strip_name_encoding (q->name), |
da489f73 | 727 | (q->is_data ? ",data" : "")); |
8e260ba4 | 728 | } |
e43f9c10 | 729 | } |
9fa1246d | 730 | } |
90aa6719 DS |
731 | |
732 | #include "gt-winnt.h" |