winnt.c revision 119256
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 4 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, 59 Temple Place - Suite 330, Boston, MA 2102111-1307, USA. */ 22 23#include "config.h" 24#include "system.h" 25#include "rtl.h" 26#include "regs.h" 27#include "hard-reg-set.h" 28#include "output.h" 29#include "tree.h" 30#include "flags.h" 31#include "tm_p.h" 32#include "toplev.h" 33#include "hashtab.h" 34#include "ggc.h" 35 36/* i386/PE specific attribute support. 37 38 i386/PE has two new attributes: 39 dllexport - for exporting a function/variable that will live in a dll 40 dllimport - for importing a function/variable from a dll 41 42 Microsoft allows multiple declspecs in one __declspec, separating 43 them with spaces. We do NOT support this. Instead, use __declspec 44 multiple times. 45*/ 46 47static tree associated_type PARAMS ((tree)); 48const char * gen_stdcall_suffix PARAMS ((tree)); 49int i386_pe_dllexport_p PARAMS ((tree)); 50int i386_pe_dllimport_p PARAMS ((tree)); 51void i386_pe_mark_dllexport PARAMS ((tree)); 52void i386_pe_mark_dllimport PARAMS ((tree)); 53 54/* Handle a "dllimport" or "dllexport" attribute; 55 arguments as in struct attribute_spec.handler. */ 56tree 57ix86_handle_dll_attribute (pnode, name, args, flags, no_add_attrs) 58 tree * pnode; 59 tree name; 60 tree args; 61 int flags; 62 bool *no_add_attrs; 63{ 64 tree node = *pnode; 65 66 /* These attributes may apply to structure and union types being created, 67 but otherwise should pass to the declaration involved. */ 68 if (!DECL_P (node)) 69 { 70 if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT 71 | (int) ATTR_FLAG_ARRAY_NEXT)) 72 { 73 *no_add_attrs = true; 74 return tree_cons (name, args, NULL_TREE); 75 } 76 if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) 77 { 78 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 79 *no_add_attrs = true; 80 } 81 82 return NULL_TREE; 83 } 84 85 /* Report error on dllimport ambiguities seen now before they cause 86 any damage. */ 87 else if (is_attribute_p ("dllimport", name)) 88 { 89 /* Like MS, treat definition of dllimported variables and 90 non-inlined functions on declaration as syntax errors. 91 We allow the attribute for function definitions if declared 92 inline, but just ignore it in i386_pe_dllimport_p. */ 93 if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node) 94 && !DECL_INLINE (node)) 95 { 96 error_with_decl (node, "function `%s' definition is marked dllimport."); 97 *no_add_attrs = true; 98 } 99 100 else if (TREE_CODE (node) == VAR_DECL) 101 { 102 if (DECL_INITIAL (node)) 103 { 104 error_with_decl (node,"variable `%s' definition is marked dllimport."); 105 *no_add_attrs = true; 106 } 107 108 /* `extern' needn't be specified with dllimport. 109 Specify `extern' now and hope for the best. Sigh. */ 110 DECL_EXTERNAL (node) = 1; 111 /* Also, implicitly give dllimport'd variables declared within 112 a function global scope, unless declared static. */ 113 if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) 114 TREE_PUBLIC (node) = 1; 115 } 116 } 117 118 /* Report error if symbol is not accessible at global scope. */ 119 if (!TREE_PUBLIC (node) 120 && (TREE_CODE (node) == VAR_DECL 121 || TREE_CODE (node) == FUNCTION_DECL)) 122 { 123 error_with_decl (node, "external linkage required for symbol '%s' because of '%s' attribute.", 124 IDENTIFIER_POINTER (name)); 125 *no_add_attrs = true; 126 } 127 128 return NULL_TREE; 129} 130 131/* Handle a "shared" attribute; 132 arguments as in struct attribute_spec.handler. */ 133tree 134ix86_handle_shared_attribute (node, name, args, flags, no_add_attrs) 135 tree *node; 136 tree name; 137 tree args ATTRIBUTE_UNUSED; 138 int flags ATTRIBUTE_UNUSED; 139 bool *no_add_attrs; 140{ 141 if (TREE_CODE (*node) != VAR_DECL) 142 { 143 warning ("`%s' attribute only applies to variables", 144 IDENTIFIER_POINTER (name)); 145 *no_add_attrs = true; 146 } 147 148 return NULL_TREE; 149} 150 151/* Return the type that we should use to determine if DECL is 152 imported or exported. */ 153 154static tree 155associated_type (decl) 156 tree decl; 157{ 158 tree t = NULL_TREE; 159 160 /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer 161 to the containing class. So we look at the 'this' arg. */ 162 if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) 163 { 164 /* Artificial methods are not affected by the import/export status of 165 their class unless they are virtual. */ 166 if (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl)) 167 t = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))); 168 } 169 else if (DECL_CONTEXT (decl) 170 && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') 171 t = DECL_CONTEXT (decl); 172 173 return t; 174} 175 176/* Return nonzero if DECL is a dllexport'd object. */ 177 178int 179i386_pe_dllexport_p (decl) 180 tree decl; 181{ 182 tree exp; 183 184 if (TREE_CODE (decl) != VAR_DECL 185 && TREE_CODE (decl) != FUNCTION_DECL) 186 return 0; 187 exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)); 188 if (exp) 189 return 1; 190 191 /* Class members get the dllexport status of their class. */ 192 if (associated_type (decl)) 193 { 194 exp = lookup_attribute ("dllexport", 195 TYPE_ATTRIBUTES (associated_type (decl))); 196 if (exp) 197 return 1; 198 } 199 200 return 0; 201} 202 203/* Return nonzero if DECL is a dllimport'd object. */ 204 205int 206i386_pe_dllimport_p (decl) 207 tree decl; 208{ 209 tree imp; 210 int context_imp = 0; 211 212 if (TREE_CODE (decl) == FUNCTION_DECL 213 && TARGET_NOP_FUN_DLLIMPORT) 214 return 0; 215 216 if (TREE_CODE (decl) != VAR_DECL 217 && TREE_CODE (decl) != FUNCTION_DECL) 218 return 0; 219 220 imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); 221 222 /* Class members get the dllimport status of their class. */ 223 if (!imp && associated_type (decl)) 224 { 225 imp = lookup_attribute ("dllimport", 226 TYPE_ATTRIBUTES (associated_type (decl))); 227 if (imp) 228 context_imp = 1; 229 } 230 231 if (imp) 232 { 233 /* Don't mark defined functions as dllimport. If the definition 234 itself was marked with dllimport, than ix86_handle_dll_attribute 235 reports an error. This handles the case when the definition 236 overrides an earlier declaration. */ 237 if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) 238 && !DECL_INLINE (decl)) 239 { 240 /* Don't warn about artificial methods. */ 241 if (!DECL_ARTIFICIAL (decl)) 242 warning_with_decl (decl,"function '%s' is defined after prior declaration as dllimport: attribute ignored."); 243 return 0; 244 } 245 246 /* We ignore the dllimport attribute for inline member functions. 247 This differs from MSVC behaviour which treats it like GNUC 248 'extern inline' extension. */ 249 else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl)) 250 { 251 if (extra_warnings) 252 warning_with_decl (decl, "inline function '%s' is declared as dllimport: attribute ignored."); 253 return 0; 254 } 255 256 /* Don't allow definitions of static data members in dllimport class, 257 Just ignore attribute for vtable data. */ 258 else if (TREE_CODE (decl) == VAR_DECL 259 && TREE_STATIC (decl) && TREE_PUBLIC (decl) 260 && !DECL_EXTERNAL (decl) && context_imp) 261 { 262 if (!DECL_VIRTUAL_P (decl)) 263 error_with_decl (decl, "definition of static data member '%s' of dllimport'd class."); 264 return 0; 265 } 266 267 /* Since we can't treat a pointer to a dllimport'd symbol as a 268 constant address, we turn off the attribute on C++ virtual 269 methods to allow creation of vtables using thunks. */ 270 else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE 271 && (DECL_VIRTUAL_P (decl))) 272 return 0; 273 274 return 1; 275 } 276 277 return 0; 278} 279 280/* Return nonzero if SYMBOL is marked as being dllexport'd. */ 281 282int 283i386_pe_dllexport_name_p (symbol) 284 const char *symbol; 285{ 286 return symbol[0] == DLL_IMPORT_EXPORT_PREFIX 287 && symbol[1] == 'e' && symbol[2] == '.'; 288} 289 290/* Return nonzero if SYMBOL is marked as being dllimport'd. */ 291 292int 293i386_pe_dllimport_name_p (symbol) 294 const char *symbol; 295{ 296 return symbol[0] == DLL_IMPORT_EXPORT_PREFIX 297 && symbol[1] == 'i' && symbol[2] == '.'; 298} 299 300/* Mark a DECL as being dllexport'd. 301 Note that we override the previous setting (eg: dllimport). */ 302 303void 304i386_pe_mark_dllexport (decl) 305 tree decl; 306{ 307 const char *oldname; 308 char *newname; 309 rtx rtlname; 310 tree idp; 311 312 rtlname = XEXP (DECL_RTL (decl), 0); 313 if (GET_CODE (rtlname) == SYMBOL_REF) 314 oldname = XSTR (rtlname, 0); 315 else if (GET_CODE (rtlname) == MEM 316 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) 317 oldname = XSTR (XEXP (rtlname, 0), 0); 318 else 319 abort (); 320 if (i386_pe_dllimport_name_p (oldname)) 321 { 322 warning_with_decl (decl,"inconsistent dll linkage for '%s': dllexport assumed."); 323 /* Remove DLL_IMPORT_PREFIX. */ 324 oldname += 9; 325 DECL_NON_ADDR_CONST_P (decl) = 0; 326 } 327 else if (i386_pe_dllexport_name_p (oldname)) 328 return; /* already done */ 329 330 newname = alloca (strlen (oldname) + 4); 331 sprintf (newname, "%ce.%s", DLL_IMPORT_EXPORT_PREFIX, oldname); 332 333 /* We pass newname through get_identifier to ensure it has a unique 334 address. RTL processing can sometimes peek inside the symbol ref 335 and compare the string's addresses to see if two symbols are 336 identical. */ 337 idp = get_identifier (newname); 338 339 XEXP (DECL_RTL (decl), 0) = 340 gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); 341} 342 343/* Mark a DECL as being dllimport'd. */ 344 345void 346i386_pe_mark_dllimport (decl) 347 tree decl; 348{ 349 const char *oldname; 350 char *newname; 351 tree idp; 352 rtx rtlname, newrtl; 353 354 rtlname = XEXP (DECL_RTL (decl), 0); 355 if (GET_CODE (rtlname) == SYMBOL_REF) 356 oldname = XSTR (rtlname, 0); 357 else if (GET_CODE (rtlname) == MEM 358 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) 359 oldname = XSTR (XEXP (rtlname, 0), 0); 360 else 361 abort (); 362 if (i386_pe_dllexport_name_p (oldname)) 363 { 364 error ("`%s' declared as both exported to and imported from a DLL", 365 IDENTIFIER_POINTER (DECL_NAME (decl))); 366 return; 367 } 368 else if (i386_pe_dllimport_name_p (oldname)) 369 { 370 /* Already done, but do a sanity check to prevent assembler errors. */ 371 if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)) 372 { 373 error_with_decl (decl, "failure in redeclaration of '%s': dllimport'd symbol lacks external linkage."); 374 abort(); 375 } 376 return; 377 } 378 379 newname = alloca (strlen (oldname) + 11); 380 sprintf (newname, "%ci._imp__%s", DLL_IMPORT_EXPORT_PREFIX, oldname); 381 382 /* We pass newname through get_identifier to ensure it has a unique 383 address. RTL processing can sometimes peek inside the symbol ref 384 and compare the string's addresses to see if two symbols are 385 identical. */ 386 idp = get_identifier (newname); 387 388 newrtl = gen_rtx (MEM, Pmode, 389 gen_rtx (SYMBOL_REF, Pmode, 390 IDENTIFIER_POINTER (idp))); 391 XEXP (DECL_RTL (decl), 0) = newrtl; 392 393 /* Can't treat a pointer to this as a constant address */ 394 DECL_NON_ADDR_CONST_P (decl) = 1; 395} 396 397/* Return string which is the former assembler name modified with a 398 suffix consisting of an atsign (@) followed by the number of bytes of 399 arguments */ 400 401const char * 402gen_stdcall_suffix (decl) 403 tree decl; 404{ 405 int total = 0; 406 /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead 407 of DECL_ASSEMBLER_NAME. */ 408 const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 409 char *newsym; 410 411 if (TYPE_ARG_TYPES (TREE_TYPE (decl))) 412 if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl)))) 413 == void_type_node) 414 { 415 tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); 416 417 while (TREE_VALUE (formal_type) != void_type_node) 418 { 419 int parm_size 420 = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); 421 /* Must round up to include padding. This is done the same 422 way as in store_one_arg. */ 423 parm_size = ((parm_size + PARM_BOUNDARY - 1) 424 / PARM_BOUNDARY * PARM_BOUNDARY); 425 total += parm_size; 426 formal_type = TREE_CHAIN (formal_type); 427 } 428 } 429 430 newsym = xmalloc (strlen (asmname) + 10); 431 sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT); 432 return IDENTIFIER_POINTER (get_identifier (newsym)); 433} 434 435void 436i386_pe_encode_section_info (decl, first) 437 tree decl; 438 int first ATTRIBUTE_UNUSED; 439{ 440 /* This bit is copied from i386.h. */ 441 if (optimize > 0 && TREE_CONSTANT (decl) 442 && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST)) 443 { 444 rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd' 445 ? TREE_CST_RTL (decl) : DECL_RTL (decl)); 446 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; 447 } 448 449 if (TREE_CODE (decl) == FUNCTION_DECL) 450 if (lookup_attribute ("stdcall", 451 TYPE_ATTRIBUTES (TREE_TYPE (decl)))) 452 XEXP (DECL_RTL (decl), 0) = 453 gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl)); 454 455 /* Mark the decl so we can tell from the rtl whether the object is 456 dllexport'd or dllimport'd. This also handles dllexport/dllimport 457 override semantics. */ 458 459 if (i386_pe_dllexport_p (decl)) 460 i386_pe_mark_dllexport (decl); 461 else if (i386_pe_dllimport_p (decl)) 462 i386_pe_mark_dllimport (decl); 463 /* It might be that DECL has already been marked as dllimport, but a 464 subsequent definition nullified that. The attribute is gone but 465 DECL_RTL still has (DLL_IMPORT_EXPORT_PREFIX)i._imp__foo. We need 466 to remove that. Ditto for the DECL_NON_ADDR_CONST_P flag. */ 467 else if ((TREE_CODE (decl) == FUNCTION_DECL 468 || TREE_CODE (decl) == VAR_DECL) 469 && DECL_RTL (decl) != NULL_RTX 470 && GET_CODE (DECL_RTL (decl)) == MEM 471 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM 472 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF 473 && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0))) 474 { 475 const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0); 476 tree idp = get_identifier (oldname + 9); 477 rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); 478 479 warning_with_decl (decl, "'%s' %s after being referenced with dllimport linkage.", 480 (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl)) 481 ? "defined locally" : "redeclared without dllimport attribute"); 482 483 XEXP (DECL_RTL (decl), 0) = newrtl; 484 485 DECL_NON_ADDR_CONST_P (decl) = 0; 486 487 /* We previously set TREE_PUBLIC and DECL_EXTERNAL. 488 We leave these alone for now. */ 489 } 490} 491 492/* Strip only the leading encoding, leaving the stdcall suffix. */ 493 494const char * 495i386_pe_strip_name_encoding (str) 496 const char *str; 497{ 498 if (*str == DLL_IMPORT_EXPORT_PREFIX) 499 str += 3; 500 if (*str == '*') 501 str += 1; 502 return str; 503} 504 505/* Also strip the stdcall suffix. */ 506 507const char * 508i386_pe_strip_name_encoding_full (str) 509 const char *str; 510{ 511 const char *p; 512 const char *name = i386_pe_strip_name_encoding (str); 513 514 p = strchr (name, '@'); 515 if (p) 516 return ggc_alloc_string (name, p - name); 517 518 return name; 519} 520 521void 522i386_pe_unique_section (decl, reloc) 523 tree decl; 524 int reloc; 525{ 526 int len; 527 const char *name, *prefix; 528 char *string; 529 530 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 531 name = i386_pe_strip_name_encoding_full (name); 532 533 /* The object is put in, for example, section .text$foo. 534 The linker will then ultimately place them in .text 535 (everything from the $ on is stripped). Don't put 536 read-only data in .rdata section to avoid a PE linker 537 bug when .rdata$* grouped sections are used in code 538 without a .rdata section. */ 539 if (TREE_CODE (decl) == FUNCTION_DECL) 540 prefix = ".text$"; 541 else if (decl_readonly_section (decl, reloc)) 542 prefix = ".rdata$"; 543 else 544 prefix = ".data$"; 545 len = strlen (name) + strlen (prefix); 546 string = alloca (len + 1); 547 sprintf (string, "%s%s", prefix, name); 548 549 DECL_SECTION_NAME (decl) = build_string (len, string); 550} 551 552/* Select a set of attributes for section NAME based on the properties 553 of DECL and whether or not RELOC indicates that DECL's initializer 554 might contain runtime relocations. 555 556 We make the section read-only and executable for a function decl, 557 read-only for a const data decl, and writable for a non-const data decl. 558 559 If the section has already been defined, to not allow it to have 560 different attributes, as (1) this is ambiguous since we're not seeing 561 all the declarations up front and (2) some assemblers (e.g. SVR4) 562 do not recoginize section redefinitions. */ 563/* ??? This differs from the "standard" PE implementation in that we 564 handle the SHARED variable attribute. Should this be done for all 565 PE targets? */ 566 567#define SECTION_PE_SHARED SECTION_MACH_DEP 568 569unsigned int 570i386_pe_section_type_flags (decl, name, reloc) 571 tree decl; 572 const char *name; 573 int reloc; 574{ 575 static htab_t htab; 576 unsigned int flags; 577 unsigned int **slot; 578 579 /* The names we put in the hashtable will always be the unique 580 versions gived to us by the stringtable, so we can just use 581 their addresses as the keys. */ 582 if (!htab) 583 htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL); 584 585 if (decl && TREE_CODE (decl) == FUNCTION_DECL) 586 flags = SECTION_CODE; 587 else if (decl && decl_readonly_section (decl, reloc)) 588 flags = 0; 589 else 590 { 591 flags = SECTION_WRITE; 592 593 if (decl && TREE_CODE (decl) == VAR_DECL 594 && lookup_attribute ("shared", DECL_ATTRIBUTES (decl))) 595 flags |= SECTION_PE_SHARED; 596 } 597 598 if (decl && DECL_ONE_ONLY (decl)) 599 flags |= SECTION_LINKONCE; 600 601 /* See if we already have an entry for this section. */ 602 slot = (unsigned int **) htab_find_slot (htab, name, INSERT); 603 if (!*slot) 604 { 605 *slot = (unsigned int *) xmalloc (sizeof (unsigned int)); 606 **slot = flags; 607 } 608 else 609 { 610 if (decl && **slot != flags) 611 error_with_decl (decl, "%s causes a section type conflict"); 612 } 613 614 return flags; 615} 616 617void 618i386_pe_asm_named_section (name, flags) 619 const char *name; 620 unsigned int flags; 621{ 622 char flagchars[8], *f = flagchars; 623 624 if (flags & SECTION_CODE) 625 *f++ = 'x'; 626 if (flags & SECTION_WRITE) 627 *f++ = 'w'; 628 if (flags & SECTION_PE_SHARED) 629 *f++ = 's'; 630 *f = '\0'; 631 632 fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars); 633 634 if (flags & SECTION_LINKONCE) 635 { 636 /* Functions may have been compiled at various levels of 637 optimization so we can't use `same_size' here. 638 Instead, have the linker pick one. */ 639 fprintf (asm_out_file, "\t.linkonce %s\n", 640 (flags & SECTION_CODE ? "discard" : "same_size")); 641 } 642} 643 644/* The Microsoft linker requires that every function be marked as 645 DT_FCN. When using gas on cygwin, we must emit appropriate .type 646 directives. */ 647 648#include "gsyms.h" 649 650/* Mark a function appropriately. This should only be called for 651 functions for which we are not emitting COFF debugging information. 652 FILE is the assembler output file, NAME is the name of the 653 function, and PUBLIC is nonzero if the function is globally 654 visible. */ 655 656void 657i386_pe_declare_function_type (file, name, public) 658 FILE *file; 659 const char *name; 660 int public; 661{ 662 fprintf (file, "\t.def\t"); 663 assemble_name (file, name); 664 fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n", 665 public ? (int) C_EXT : (int) C_STAT, 666 (int) DT_FCN << N_BTSHFT); 667} 668 669/* Keep a list of external functions. */ 670 671struct extern_list 672{ 673 struct extern_list *next; 674 const char *name; 675}; 676 677static struct extern_list *extern_head; 678 679/* Assemble an external function reference. We need to keep a list of 680 these, so that we can output the function types at the end of the 681 assembly. We can't output the types now, because we might see a 682 definition of the function later on and emit debugging information 683 for it then. */ 684 685void 686i386_pe_record_external_function (name) 687 const char *name; 688{ 689 struct extern_list *p; 690 691 p = (struct extern_list *) xmalloc (sizeof *p); 692 p->next = extern_head; 693 p->name = name; 694 extern_head = p; 695} 696 697/* Keep a list of exported symbols. */ 698 699struct export_list 700{ 701 struct export_list *next; 702 const char *name; 703 int is_data; /* used to type tag exported symbols. */ 704}; 705 706static struct export_list *export_head; 707 708/* Assemble an export symbol entry. We need to keep a list of 709 these, so that we can output the export list at the end of the 710 assembly. We used to output these export symbols in each function, 711 but that causes problems with GNU ld when the sections are 712 linkonce. */ 713 714void 715i386_pe_record_exported_symbol (name, is_data) 716 const char *name; 717 int is_data; 718{ 719 struct export_list *p; 720 721 p = (struct export_list *) xmalloc (sizeof *p); 722 p->next = export_head; 723 p->name = name; 724 p->is_data = is_data; 725 export_head = p; 726} 727 728/* This is called at the end of assembly. For each external function 729 which has not been defined, we output a declaration now. We also 730 output the .drectve section. */ 731 732void 733i386_pe_asm_file_end (file) 734 FILE *file; 735{ 736 struct extern_list *p; 737 738 ix86_asm_file_end (file); 739 740 for (p = extern_head; p != NULL; p = p->next) 741 { 742 tree decl; 743 744 decl = get_identifier (p->name); 745 746 /* Positively ensure only one declaration for any given symbol. */ 747 if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl)) 748 { 749 TREE_ASM_WRITTEN (decl) = 1; 750 i386_pe_declare_function_type (file, p->name, TREE_PUBLIC (decl)); 751 } 752 } 753 754 if (export_head) 755 { 756 struct export_list *q; 757 drectve_section (); 758 for (q = export_head; q != NULL; q = q->next) 759 { 760 fprintf (file, "\t.ascii \" -export:%s%s\"\n", 761 i386_pe_strip_name_encoding (q->name), 762 (q->is_data) ? ",data" : ""); 763 } 764 } 765} 766