1/* Subroutines for insn-output.c for Windows NT. 2 Contributed by Douglas Rupp (drupp@cs.washington.edu) 3 Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 4 2005, 2006 Free Software Foundation, Inc. 5 6This file is part of GCC. 7 8GCC is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 2, or (at your option) any later 11version. 12 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14WARRANTY; without even the implied warranty of MERCHANTABILITY or 15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16for more details. 17 18You should have received a copy of the GNU General Public License 19along with GCC; see the file COPYING. If not, write to the Free 20Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2102110-1301, USA. */ 22 23#include "config.h" 24#include "system.h" 25#include "coretypes.h" 26#include "tm.h" 27#include "rtl.h" 28#include "regs.h" 29#include "hard-reg-set.h" 30#include "output.h" 31#include "tree.h" 32#include "flags.h" 33#include "tm_p.h" 34#include "toplev.h" 35#include "hashtab.h" 36#include "ggc.h" 37 38/* i386/PE specific attribute support. 39 40 i386/PE has two new attributes: 41 dllexport - for exporting a function/variable that will live in a dll 42 dllimport - for importing a function/variable from a dll 43 44 Microsoft allows multiple declspecs in one __declspec, separating 45 them with spaces. We do NOT support this. Instead, use __declspec 46 multiple times. 47*/ 48 49static tree associated_type (tree); 50static tree gen_stdcall_or_fastcall_suffix (tree, bool); 51static bool i386_pe_dllexport_p (tree); 52static bool i386_pe_dllimport_p (tree); 53static void i386_pe_mark_dllexport (tree); 54static void i386_pe_mark_dllimport (tree); 55 56/* This is we how mark internal identifiers with dllimport or dllexport 57 attributes. */ 58#ifndef DLL_IMPORT_PREFIX 59#define DLL_IMPORT_PREFIX "#i." 60#endif 61#ifndef DLL_EXPORT_PREFIX 62#define DLL_EXPORT_PREFIX "#e." 63#endif 64 65/* Handle a "shared" attribute; 66 arguments as in struct attribute_spec.handler. */ 67tree 68ix86_handle_shared_attribute (tree *node, tree name, 69 tree args ATTRIBUTE_UNUSED, 70 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) 71{ 72 if (TREE_CODE (*node) != VAR_DECL) 73 { 74 warning (OPT_Wattributes, "%qs attribute only applies to variables", 75 IDENTIFIER_POINTER (name)); 76 *no_add_attrs = true; 77 } 78 79 return NULL_TREE; 80} 81 82/* Handle a "selectany" attribute; 83 arguments as in struct attribute_spec.handler. */ 84tree 85ix86_handle_selectany_attribute (tree *node, tree name, 86 tree args ATTRIBUTE_UNUSED, 87 int flags ATTRIBUTE_UNUSED, 88 bool *no_add_attrs) 89{ 90 /* The attribute applies only to objects that are initialized and have 91 external linkage. However, we may not know about initialization 92 until the language frontend has processed the decl. We'll check for 93 initialization later in encode_section_info. */ 94 if (TREE_CODE (*node) != VAR_DECL || !TREE_PUBLIC (*node)) 95 { 96 error ("%qs attribute applies only to initialized variables" 97 " with external linkage", IDENTIFIER_POINTER (name)); 98 *no_add_attrs = true; 99 } 100 101 return NULL_TREE; 102} 103 104 105/* Return the type that we should use to determine if DECL is 106 imported or exported. */ 107 108static tree 109associated_type (tree decl) 110{ 111 return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) 112 ? DECL_CONTEXT (decl) : NULL_TREE; 113} 114 115 116/* Return true if DECL is a dllexport'd object. */ 117 118static bool 119i386_pe_dllexport_p (tree decl) 120{ 121 if (TREE_CODE (decl) != VAR_DECL 122 && TREE_CODE (decl) != FUNCTION_DECL) 123 return false; 124 125 if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) 126 return true; 127 128 /* Also mark class members of exported classes with dllexport. */ 129 if (associated_type (decl) 130 && lookup_attribute ("dllexport", 131 TYPE_ATTRIBUTES (associated_type (decl)))) 132 return i386_pe_type_dllexport_p (decl); 133 134 return false; 135} 136 137static bool 138i386_pe_dllimport_p (tree decl) 139{ 140 if (TREE_CODE (decl) != VAR_DECL 141 && TREE_CODE (decl) != FUNCTION_DECL) 142 return false; 143 144 /* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag. 145 We may need to override an earlier decision. */ 146 if (DECL_DLLIMPORT_P (decl) 147 && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))) 148 { 149 /* Make a final check to see if this is a definition before we generate 150 RTL for an indirect reference. */ 151 if (!DECL_EXTERNAL (decl)) 152 { 153 error ("%q+D: definition is marked as dllimport", decl); 154 DECL_DLLIMPORT_P (decl) = 0; 155 return false; 156 } 157 return true; 158 } 159 /* The DECL_DLLIMPORT_P flag was set for decls in the class definition 160 by targetm.cxx.adjust_class_at_definition. Check again to emit 161 warnings if the class attribute has been overridden by an 162 out-of-class definition. */ 163 else if (associated_type (decl) 164 && lookup_attribute ("dllimport", 165 TYPE_ATTRIBUTES (associated_type (decl)))) 166 return i386_pe_type_dllimport_p (decl); 167 168 return false; 169} 170 171/* Handle the -mno-fun-dllimport target switch. */ 172bool 173i386_pe_valid_dllimport_attribute_p (tree decl) 174{ 175 if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL) 176 return false; 177 return true; 178} 179 180/* Return nonzero if SYMBOL is marked as being dllexport'd. */ 181 182int 183i386_pe_dllexport_name_p (const char *symbol) 184{ 185 return (strncmp (DLL_EXPORT_PREFIX, symbol, 186 strlen (DLL_EXPORT_PREFIX)) == 0); 187} 188 189/* Return nonzero if SYMBOL is marked as being dllimport'd. */ 190 191int 192i386_pe_dllimport_name_p (const char *symbol) 193{ 194 return (strncmp (DLL_IMPORT_PREFIX, symbol, 195 strlen (DLL_IMPORT_PREFIX)) == 0); 196} 197 198/* Mark a DECL as being dllexport'd. 199 Note that we override the previous setting (e.g.: dllimport). */ 200 201static void 202i386_pe_mark_dllexport (tree decl) 203{ 204 const char *oldname; 205 char *newname; 206 rtx rtlname; 207 rtx symref; 208 tree idp; 209 210 rtlname = XEXP (DECL_RTL (decl), 0); 211 if (GET_CODE (rtlname) == MEM) 212 rtlname = XEXP (rtlname, 0); 213 gcc_assert (GET_CODE (rtlname) == SYMBOL_REF); 214 oldname = XSTR (rtlname, 0); 215 if (i386_pe_dllimport_name_p (oldname)) 216 { 217 warning (0, "inconsistent dll linkage for %q+D, dllexport assumed", 218 decl); 219 /* Remove DLL_IMPORT_PREFIX. */ 220 oldname += strlen (DLL_IMPORT_PREFIX); 221 } 222 else if (i386_pe_dllexport_name_p (oldname)) 223 return; /* already done */ 224 225 newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1); 226 sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname); 227 228 /* We pass newname through get_identifier to ensure it has a unique 229 address. RTL processing can sometimes peek inside the symbol ref 230 and compare the string's addresses to see if two symbols are 231 identical. */ 232 idp = get_identifier (newname); 233 234 symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); 235 SET_SYMBOL_REF_DECL (symref, decl); 236 XEXP (DECL_RTL (decl), 0) = symref; 237} 238 239/* Mark a DECL as being dllimport'd. */ 240 241static void 242i386_pe_mark_dllimport (tree decl) 243{ 244 const char *oldname; 245 char *newname; 246 tree idp; 247 rtx rtlname, newrtl; 248 rtx symref; 249 250 rtlname = XEXP (DECL_RTL (decl), 0); 251 if (GET_CODE (rtlname) == MEM) 252 rtlname = XEXP (rtlname, 0); 253 gcc_assert (GET_CODE (rtlname) == SYMBOL_REF); 254 oldname = XSTR (rtlname, 0); 255 if (i386_pe_dllexport_name_p (oldname)) 256 { 257 error ("%qs declared as both exported to and imported from a DLL", 258 IDENTIFIER_POINTER (DECL_NAME (decl))); 259 return; 260 } 261 else if (i386_pe_dllimport_name_p (oldname)) 262 { 263 /* Already done, but do a sanity check to prevent assembler 264 errors. */ 265 gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl) 266 && DECL_DLLIMPORT_P (decl)); 267 return; 268 } 269 270 newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1); 271 sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname); 272 273 /* We pass newname through get_identifier to ensure it has a unique 274 address. RTL processing can sometimes peek inside the symbol ref 275 and compare the string's addresses to see if two symbols are 276 identical. */ 277 idp = get_identifier (newname); 278 279 symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); 280 SET_SYMBOL_REF_DECL (symref, decl); 281 newrtl = gen_rtx_MEM (Pmode,symref); 282 XEXP (DECL_RTL (decl), 0) = newrtl; 283 284 DECL_DLLIMPORT_P (decl) = 1; 285} 286 287/* Return string which is the former assembler name modified with a 288 suffix consisting of an atsign (@) followed by the number of bytes of 289 arguments. If FASTCALL is true, also add the FASTCALL_PREFIX. */ 290 291static tree 292gen_stdcall_or_fastcall_suffix (tree decl, bool fastcall) 293{ 294 int total = 0; 295 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead 296 of DECL_ASSEMBLER_NAME. */ 297 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 298 char *newsym; 299 char *p; 300 tree formal_type; 301 302 /* Do not change the identifier if a verbatim asmspec or already done. */ 303 if (*asmname == '*' || strchr (asmname, '@')) 304 return DECL_ASSEMBLER_NAME (decl); 305 306 formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); 307 if (formal_type != NULL_TREE) 308 { 309 /* These attributes are ignored for variadic functions in 310 i386.c:ix86_return_pops_args. For compatibility with MS 311 compiler do not add @0 suffix here. */ 312 if (TREE_VALUE (tree_last (formal_type)) != void_type_node) 313 return DECL_ASSEMBLER_NAME (decl); 314 315 /* Quit if we hit an incomplete type. Error is reported 316 by convert_arguments in c-typeck.c or cp/typeck.c. */ 317 while (TREE_VALUE (formal_type) != void_type_node 318 && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) 319 { 320 int parm_size 321 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); 322 /* Must round up to include padding. This is done the same 323 way as in store_one_arg. */ 324 parm_size = ((parm_size + PARM_BOUNDARY - 1) 325 / PARM_BOUNDARY * PARM_BOUNDARY); 326 total += parm_size; 327 formal_type = TREE_CHAIN (formal_type);\ 328 } 329 } 330 331 /* Assume max of 8 base 10 digits in the suffix. */ 332 newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1); 333 p = newsym; 334 if (fastcall) 335 *p++ = FASTCALL_PREFIX; 336 sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT); 337 return get_identifier (newsym); 338} 339 340void 341i386_pe_encode_section_info (tree decl, rtx rtl, int first) 342{ 343 default_encode_section_info (decl, rtl, first); 344 345 if (first && TREE_CODE (decl) == FUNCTION_DECL) 346 { 347 tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl)); 348 tree newid = NULL_TREE; 349 350 if (lookup_attribute ("stdcall", type_attributes)) 351 newid = gen_stdcall_or_fastcall_suffix (decl, false); 352 else if (lookup_attribute ("fastcall", type_attributes)) 353 newid = gen_stdcall_or_fastcall_suffix (decl, true); 354 if (newid != NULL_TREE) 355 { 356 rtx rtlname = XEXP (rtl, 0); 357 if (GET_CODE (rtlname) == MEM) 358 rtlname = XEXP (rtlname, 0); 359 XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid); 360 /* These attributes must be present on first declaration, 361 change_decl_assembler_name will warn if they are added 362 later and the decl has been referenced, but duplicate_decls 363 should catch the mismatch before this is called. */ 364 change_decl_assembler_name (decl, newid); 365 } 366 } 367 368 else if (TREE_CODE (decl) == VAR_DECL 369 && lookup_attribute ("selectany", DECL_ATTRIBUTES (decl))) 370 { 371 if (DECL_INITIAL (decl) 372 /* If an object is initialized with a ctor, the static 373 initialization and destruction code for it is present in 374 each unit defining the object. The code that calls the 375 ctor is protected by a link-once guard variable, so that 376 the object still has link-once semantics, */ 377 || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) 378 make_decl_one_only (decl); 379 else 380 error ("%q+D:'selectany' attribute applies only to initialized objects", 381 decl); 382 } 383 384 /* Mark the decl so we can tell from the rtl whether the object is 385 dllexport'd or dllimport'd. tree.c: merge_dllimport_decl_attributes 386 handles dllexport/dllimport override semantics. */ 387 388 if (i386_pe_dllexport_p (decl)) 389 i386_pe_mark_dllexport (decl); 390 else if (i386_pe_dllimport_p (decl)) 391 i386_pe_mark_dllimport (decl); 392 /* It might be that DECL has been declared as dllimport, but a 393 subsequent definition nullified that. Assert that 394 tree.c: merge_dllimport_decl_attributes has removed the attribute 395 before the RTL name was marked with the DLL_IMPORT_PREFIX. */ 396 else 397 gcc_assert (!((TREE_CODE (decl) == FUNCTION_DECL 398 || TREE_CODE (decl) == VAR_DECL) 399 && rtl != NULL_RTX 400 && GET_CODE (rtl) == MEM 401 && GET_CODE (XEXP (rtl, 0)) == MEM 402 && GET_CODE (XEXP (XEXP (rtl, 0), 0)) == SYMBOL_REF 403 && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (rtl, 0), 0), 0)))); 404} 405 406/* Strip only the leading encoding, leaving the stdcall suffix and fastcall 407 prefix if it exists. */ 408 409const char * 410i386_pe_strip_name_encoding (const char *str) 411{ 412 if (strncmp (str, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX)) 413 == 0) 414 str += strlen (DLL_IMPORT_PREFIX); 415 else if (strncmp (str, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX)) 416 == 0) 417 str += strlen (DLL_EXPORT_PREFIX); 418 if (*str == '*') 419 str += 1; 420 return str; 421} 422 423/* Also strip the fastcall prefix and stdcall suffix. */ 424 425const char * 426i386_pe_strip_name_encoding_full (const char *str) 427{ 428 const char *p; 429 const char *name = i386_pe_strip_name_encoding (str); 430 431 /* Strip leading '@' on fastcall symbols. */ 432 if (*name == '@') 433 name++; 434 435 /* Strip trailing "@n". */ 436 p = strchr (name, '@'); 437 if (p) 438 return ggc_alloc_string (name, p - name); 439 440 return name; 441} 442 443/* Output a reference to a label. Fastcall symbols are prefixed with @, 444 whereas symbols for functions using other calling conventions don't 445 have a prefix (unless they are marked dllimport or dllexport). */ 446 447void i386_pe_output_labelref (FILE *stream, const char *name) 448{ 449 if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX)) 450 == 0) 451 /* A dll import */ 452 { 453 if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX) 454 /* A dllimport fastcall symbol. */ 455 { 456 fprintf (stream, "__imp_%s", 457 i386_pe_strip_name_encoding (name)); 458 } 459 else 460 /* A dllimport non-fastcall symbol. */ 461 { 462 fprintf (stream, "__imp__%s", 463 i386_pe_strip_name_encoding (name)); 464 } 465 } 466 else if ((name[0] == FASTCALL_PREFIX) 467 || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX)) 468 == 0 469 && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX)) 470 /* A fastcall symbol. */ 471 { 472 fprintf (stream, "%s", 473 i386_pe_strip_name_encoding (name)); 474 } 475 else 476 /* Everything else. */ 477 { 478 fprintf (stream, "%s%s", USER_LABEL_PREFIX, 479 i386_pe_strip_name_encoding (name)); 480 } 481} 482 483void 484i386_pe_unique_section (tree decl, int reloc) 485{ 486 int len; 487 const char *name, *prefix; 488 char *string; 489 490 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 491 name = i386_pe_strip_name_encoding_full (name); 492 493 /* The object is put in, for example, section .text$foo. 494 The linker will then ultimately place them in .text 495 (everything from the $ on is stripped). Don't put 496 read-only data in .rdata section to avoid a PE linker 497 bug when .rdata$* grouped sections are used in code 498 without a .rdata section. */ 499 if (TREE_CODE (decl) == FUNCTION_DECL) 500 prefix = ".text$"; 501 else if (decl_readonly_section (decl, reloc)) 502 prefix = ".rdata$"; 503 else 504 prefix = ".data$"; 505 len = strlen (name) + strlen (prefix); 506 string = alloca (len + 1); 507 sprintf (string, "%s%s", prefix, name); 508 509 DECL_SECTION_NAME (decl) = build_string (len, string); 510} 511 512/* Select a set of attributes for section NAME based on the properties 513 of DECL and whether or not RELOC indicates that DECL's initializer 514 might contain runtime relocations. 515 516 We make the section read-only and executable for a function decl, 517 read-only for a const data decl, and writable for a non-const data decl. 518 519 If the section has already been defined, to not allow it to have 520 different attributes, as (1) this is ambiguous since we're not seeing 521 all the declarations up front and (2) some assemblers (e.g. SVR4) 522 do not recognize section redefinitions. */ 523/* ??? This differs from the "standard" PE implementation in that we 524 handle the SHARED variable attribute. Should this be done for all 525 PE targets? */ 526 527#define SECTION_PE_SHARED SECTION_MACH_DEP 528 529unsigned int 530i386_pe_section_type_flags (tree decl, const char *name, int reloc) 531{ 532 static htab_t htab; 533 unsigned int flags; 534 unsigned int **slot; 535 536 /* The names we put in the hashtable will always be the unique 537 versions given to us by the stringtable, so we can just use 538 their addresses as the keys. */ 539 if (!htab) 540 htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL); 541 542 if (decl && TREE_CODE (decl) == FUNCTION_DECL) 543 flags = SECTION_CODE; 544 else if (decl && decl_readonly_section (decl, reloc)) 545 flags = 0; 546 else 547 { 548 flags = SECTION_WRITE; 549 550 if (decl && TREE_CODE (decl) == VAR_DECL 551 && lookup_attribute ("shared", DECL_ATTRIBUTES (decl))) 552 flags |= SECTION_PE_SHARED; 553 } 554 555 if (decl && DECL_ONE_ONLY (decl)) 556 flags |= SECTION_LINKONCE; 557 558 /* See if we already have an entry for this section. */ 559 slot = (unsigned int **) htab_find_slot (htab, name, INSERT); 560 if (!*slot) 561 { 562 *slot = (unsigned int *) xmalloc (sizeof (unsigned int)); 563 **slot = flags; 564 } 565 else 566 { 567 if (decl && **slot != flags) 568 error ("%q+D causes a section type conflict", decl); 569 } 570 571 return flags; 572} 573 574void 575i386_pe_asm_named_section (const char *name, unsigned int flags, 576 tree decl) 577{ 578 char flagchars[8], *f = flagchars; 579 580 if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0) 581 /* readonly data */ 582 { 583 *f++ ='d'; /* This is necessary for older versions of gas. */ 584 *f++ ='r'; 585 } 586 else 587 { 588 if (flags & SECTION_CODE) 589 *f++ = 'x'; 590 if (flags & SECTION_WRITE) 591 *f++ = 'w'; 592 if (flags & SECTION_PE_SHARED) 593 *f++ = 's'; 594 } 595 596 *f = '\0'; 597 598 fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars); 599 600 if (flags & SECTION_LINKONCE) 601 { 602 /* Functions may have been compiled at various levels of 603 optimization so we can't use `same_size' here. 604 Instead, have the linker pick one, without warning. 605 If 'selectany' attribute has been specified, MS compiler 606 sets 'discard' characteristic, rather than telling linker 607 to warn of size or content mismatch, so do the same. */ 608 bool discard = (flags & SECTION_CODE) 609 || lookup_attribute ("selectany", 610 DECL_ATTRIBUTES (decl)); 611 fprintf (asm_out_file, "\t.linkonce %s\n", 612 (discard ? "discard" : "same_size")); 613 } 614} 615 616/* The Microsoft linker requires that every function be marked as 617 DT_FCN. When using gas on cygwin, we must emit appropriate .type 618 directives. */ 619 620#include "gsyms.h" 621 622/* Mark a function appropriately. This should only be called for 623 functions for which we are not emitting COFF debugging information. 624 FILE is the assembler output file, NAME is the name of the 625 function, and PUBLIC is nonzero if the function is globally 626 visible. */ 627 628void 629i386_pe_declare_function_type (FILE *file, const char *name, int public) 630{ 631 fprintf (file, "\t.def\t"); 632 assemble_name (file, name); 633 fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n", 634 public ? (int) C_EXT : (int) C_STAT, 635 (int) DT_FCN << N_BTSHFT); 636} 637 638/* Keep a list of external functions. */ 639 640struct extern_list GTY(()) 641{ 642 struct extern_list *next; 643 tree decl; 644 const char *name; 645}; 646 647static GTY(()) struct extern_list *extern_head; 648 649/* Assemble an external function reference. We need to keep a list of 650 these, so that we can output the function types at the end of the 651 assembly. We can't output the types now, because we might see a 652 definition of the function later on and emit debugging information 653 for it then. */ 654 655void 656i386_pe_record_external_function (tree decl, const char *name) 657{ 658 struct extern_list *p; 659 660 p = (struct extern_list *) ggc_alloc (sizeof *p); 661 p->next = extern_head; 662 p->decl = decl; 663 p->name = name; 664 extern_head = p; 665} 666 667/* Keep a list of exported symbols. */ 668 669struct export_list GTY(()) 670{ 671 struct export_list *next; 672 const char *name; 673 int is_data; /* used to type tag exported symbols. */ 674}; 675 676static GTY(()) struct export_list *export_head; 677 678/* Assemble an export symbol entry. We need to keep a list of 679 these, so that we can output the export list at the end of the 680 assembly. We used to output these export symbols in each function, 681 but that causes problems with GNU ld when the sections are 682 linkonce. */ 683 684void 685i386_pe_record_exported_symbol (const char *name, int is_data) 686{ 687 struct export_list *p; 688 689 p = (struct export_list *) ggc_alloc (sizeof *p); 690 p->next = export_head; 691 p->name = name; 692 p->is_data = is_data; 693 export_head = p; 694} 695 696/* This is called at the end of assembly. For each external function 697 which has not been defined, we output a declaration now. We also 698 output the .drectve section. */ 699 700void 701i386_pe_file_end (void) 702{ 703 struct extern_list *p; 704 705 ix86_file_end (); 706 707 for (p = extern_head; p != NULL; p = p->next) 708 { 709 tree decl; 710 711 decl = p->decl; 712 713 /* Positively ensure only one declaration for any given symbol. */ 714 if (! TREE_ASM_WRITTEN (decl) 715 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) 716 { 717 TREE_ASM_WRITTEN (decl) = 1; 718 i386_pe_declare_function_type (asm_out_file, p->name, 719 TREE_PUBLIC (decl)); 720 } 721 } 722 723 if (export_head) 724 { 725 struct export_list *q; 726 drectve_section (); 727 for (q = export_head; q != NULL; q = q->next) 728 { 729 fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n", 730 i386_pe_strip_name_encoding (q->name), 731 (q->is_data) ? ",data" : ""); 732 } 733 } 734} 735 736#include "gt-winnt.h" 737