1135446Strhodes/* Subroutines for insn-output.c for Windows NT. 2254402Serwin Contributed by Douglas Rupp (drupp@cs.washington.edu) 3135446Strhodes Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 4135446Strhodes Free Software Foundation, Inc. 5174187Sdougb 6135446StrhodesThis file is part of GCC. 7135446Strhodes 8135446StrhodesGCC is free software; you can redistribute it and/or modify it under 9135446Strhodesthe terms of the GNU General Public License as published by the Free 10135446StrhodesSoftware Foundation; either version 2, or (at your option) any later 11135446Strhodesversion. 12135446Strhodes 13135446StrhodesGCC is distributed in the hope that it will be useful, but WITHOUT ANY 14135446StrhodesWARRANTY; without even the implied warranty of MERCHANTABILITY or 15135446StrhodesFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16135446Strhodesfor more details. 17135446Strhodes 18254897SerwinYou should have received a copy of the GNU General Public License 19135446Strhodesalong with GCC; see the file COPYING. If not, write to the Free 20170222SdougbSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21170222Sdougb02110-1301, USA. */ 22135446Strhodes 23135446Strhodes#include "config.h" 24135446Strhodes#include "system.h" 25135446Strhodes#include "coretypes.h" 26135446Strhodes#include "tm.h" 27135446Strhodes#include "rtl.h" 28135446Strhodes#include "regs.h" 29135446Strhodes#include "hard-reg-set.h" 30135446Strhodes#include "output.h" 31135446Strhodes#include "tree.h" 32135446Strhodes#include "flags.h" 33135446Strhodes#include "tm_p.h" 34135446Strhodes#include "toplev.h" 35135446Strhodes#include "hashtab.h" 36135446Strhodes#include "ggc.h" 37135446Strhodes 38135446Strhodes/* i386/PE specific attribute support. 39135446Strhodes 40135446Strhodes i386/PE has two new attributes: 41135446Strhodes dllexport - for exporting a function/variable that will live in a dll 42135446Strhodes dllimport - for importing a function/variable from a dll 43135446Strhodes 44135446Strhodes Microsoft allows multiple declspecs in one __declspec, separating 45170222Sdougb them with spaces. We do NOT support this. Instead, use __declspec 46135446Strhodes multiple times. 47135446Strhodes*/ 48135446Strhodes 49135446Strhodesstatic tree associated_type (tree); 50135446Strhodesstatic tree gen_stdcall_or_fastcall_suffix (tree, bool); 51186462Sdougbstatic bool i386_pe_dllexport_p (tree); 52135446Strhodesstatic bool i386_pe_dllimport_p (tree); 53135446Strhodesstatic void i386_pe_mark_dllexport (tree); 54135446Strhodesstatic void i386_pe_mark_dllimport (tree); 55135446Strhodes 56143731Sdougb/* This is we how mark internal identifiers with dllimport or dllexport 57135446Strhodes attributes. */ 58135446Strhodes#ifndef DLL_IMPORT_PREFIX 59135446Strhodes#define DLL_IMPORT_PREFIX "#i." 60135446Strhodes#endif 61135446Strhodes#ifndef DLL_EXPORT_PREFIX 62135446Strhodes#define DLL_EXPORT_PREFIX "#e." 63143731Sdougb#endif 64135446Strhodes 65135446Strhodes/* Handle a "shared" attribute; 66135446Strhodes arguments as in struct attribute_spec.handler. */ 67135446Strhodestree 68135446Strhodesix86_handle_shared_attribute (tree *node, tree name, 69224092Sdougb tree args ATTRIBUTE_UNUSED, 70254897Serwin int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) 71254897Serwin{ 72135446Strhodes if (TREE_CODE (*node) != VAR_DECL) 73170222Sdougb { 74186462Sdougb warning (OPT_Wattributes, "%qs attribute only applies to variables", 75135446Strhodes IDENTIFIER_POINTER (name)); 76135446Strhodes *no_add_attrs = true; 77135446Strhodes } 78135446Strhodes 79135446Strhodes return NULL_TREE; 80135446Strhodes} 81135446Strhodes 82135446Strhodes/* Handle a "selectany" attribute; 83135446Strhodes arguments as in struct attribute_spec.handler. */ 84135446Strhodestree 85135446Strhodesix86_handle_selectany_attribute (tree *node, tree name, 86135446Strhodes tree args ATTRIBUTE_UNUSED, 87135446Strhodes int flags ATTRIBUTE_UNUSED, 88135446Strhodes bool *no_add_attrs) 89135446Strhodes{ 90135446Strhodes /* The attribute applies only to objects that are initialized and have 91135446Strhodes external linkage, */ 92135446Strhodes if (TREE_CODE (*node) == VAR_DECL && TREE_PUBLIC (*node) 93170222Sdougb && (DECL_INITIAL (*node) 94186462Sdougb /* If an object is initialized with a ctor, the static 95135446Strhodes initialization and destruction code for it is present in 96135446Strhodes each unit defining the object. The code that calls the 97135446Strhodes ctor is protected by a link-once guard variable, so that 98135446Strhodes the object still has link-once semantics, */ 99135446Strhodes || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (*node)))) 100135446Strhodes make_decl_one_only (*node); 101135446Strhodes else 102135446Strhodes { 103135446Strhodes error ("%qs attribute applies only to initialized variables" 104135446Strhodes " with external linkage", IDENTIFIER_POINTER (name)); 105135446Strhodes *no_add_attrs = true; 106135446Strhodes } 107135446Strhodes 108135446Strhodes return NULL_TREE; 109135446Strhodes} 110135446Strhodes 111135446Strhodes 112135446Strhodes/* Return the type that we should use to determine if DECL is 113135446Strhodes imported or exported. */ 114193149Sdougb 115193149Sdougbstatic tree 116193149Sdougbassociated_type (tree decl) 117193149Sdougb{ 118193149Sdougb return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) 119193149Sdougb ? DECL_CONTEXT (decl) : NULL_TREE; 120193149Sdougb} 121193149Sdougb 122193149Sdougb 123193149Sdougb/* Return true if DECL is a dllexport'd object. */ 124193149Sdougb 125193149Sdougbstatic bool 126193149Sdougbi386_pe_dllexport_p (tree decl) 127193149Sdougb{ 128193149Sdougb if (TREE_CODE (decl) != VAR_DECL 129193149Sdougb && TREE_CODE (decl) != FUNCTION_DECL) 130193149Sdougb return false; 131193149Sdougb 132170222Sdougb if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) 133135446Strhodes return true; 134135446Strhodes 135135446Strhodes /* Also mark class members of exported classes with dllexport. */ 136135446Strhodes if (associated_type (decl) 137135446Strhodes && lookup_attribute ("dllexport", 138135446Strhodes TYPE_ATTRIBUTES (associated_type (decl)))) 139135446Strhodes return i386_pe_type_dllexport_p (decl); 140135446Strhodes 141224092Sdougb return false; 142224092Sdougb} 143224092Sdougb 144135446Strhodesstatic bool 145135446Strhodesi386_pe_dllimport_p (tree decl) 146135446Strhodes{ 147135446Strhodes if (TREE_CODE (decl) != VAR_DECL 148135446Strhodes && TREE_CODE (decl) != FUNCTION_DECL) 149135446Strhodes return false; 150135446Strhodes 151135446Strhodes /* Lookup the attribute rather than rely on the DECL_DLLIMPORT_P flag. 152170222Sdougb We may need to override an earlier decision. */ 153135446Strhodes if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))) 154135446Strhodes return true; 155135446Strhodes 156135446Strhodes /* The DECL_DLLIMPORT_P flag was set for decls in the class definition 157135446Strhodes by targetm.cxx.adjust_class_at_definition. Check again to emit 158170222Sdougb warnings if the class attribute has been overriden by an 159135446Strhodes out-of-class definition. */ 160135446Strhodes if (associated_type (decl) 161135446Strhodes && lookup_attribute ("dllimport", 162135446Strhodes TYPE_ATTRIBUTES (associated_type (decl)))) 163135446Strhodes return i386_pe_type_dllimport_p (decl); 164135446Strhodes 165135446Strhodes return false; 166135446Strhodes} 167135446Strhodes 168186462Sdougb/* Handle the -mno-fun-dllimport target switch. */ 169186462Sdougbbool 170135446Strhodesi386_pe_valid_dllimport_attribute_p (tree decl) 171135446Strhodes{ 172135446Strhodes if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL) 173170222Sdougb return false; 174135446Strhodes return true; 175135446Strhodes} 176135446Strhodes 177170222Sdougb/* Return nonzero if SYMBOL is marked as being dllexport'd. */ 178135446Strhodes 179135446Strhodesint 180186462Sdougbi386_pe_dllexport_name_p (const char *symbol) 181135446Strhodes{ 182135446Strhodes return (strncmp (DLL_EXPORT_PREFIX, symbol, 183135446Strhodes strlen (DLL_EXPORT_PREFIX)) == 0); 184135446Strhodes} 185135446Strhodes 186135446Strhodes/* Return nonzero if SYMBOL is marked as being dllimport'd. */ 187135446Strhodes 188135446Strhodesint 189135446Strhodesi386_pe_dllimport_name_p (const char *symbol) 190254402Serwin{ 191135446Strhodes return (strncmp (DLL_IMPORT_PREFIX, symbol, 192170222Sdougb strlen (DLL_IMPORT_PREFIX)) == 0); 193135446Strhodes} 194135446Strhodes 195135446Strhodes/* Mark a DECL as being dllexport'd. 196135446Strhodes Note that we override the previous setting (e.g.: dllimport). */ 197135446Strhodes 198135446Strhodesstatic void 199135446Strhodesi386_pe_mark_dllexport (tree decl) 200135446Strhodes{ 201135446Strhodes const char *oldname; 202135446Strhodes char *newname; 203135446Strhodes rtx rtlname; 204135446Strhodes rtx symref; 205254897Serwin tree idp; 206254897Serwin 207135446Strhodes rtlname = XEXP (DECL_RTL (decl), 0); 208135446Strhodes if (GET_CODE (rtlname) == MEM) 209135446Strhodes rtlname = XEXP (rtlname, 0); 210135446Strhodes gcc_assert (GET_CODE (rtlname) == SYMBOL_REF); 211135446Strhodes oldname = XSTR (rtlname, 0); 212135446Strhodes if (i386_pe_dllimport_name_p (oldname)) 213135446Strhodes { 214135446Strhodes warning (0, "inconsistent dll linkage for %q+D, dllexport assumed", 215135446Strhodes decl); 216135446Strhodes /* Remove DLL_IMPORT_PREFIX. */ 217135446Strhodes oldname += strlen (DLL_IMPORT_PREFIX); 218135446Strhodes } 219254897Serwin else if (i386_pe_dllexport_name_p (oldname)) 220135446Strhodes return; /* already done */ 221193149Sdougb 222135446Strhodes newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1); 223135446Strhodes sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname); 224135446Strhodes 225135446Strhodes /* We pass newname through get_identifier to ensure it has a unique 226135446Strhodes address. RTL processing can sometimes peek inside the symbol ref 227135446Strhodes and compare the string's addresses to see if two symbols are 228135446Strhodes identical. */ 229254897Serwin idp = get_identifier (newname); 230135446Strhodes 231224092Sdougb symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); 232262706Serwin SYMBOL_REF_DECL (symref) = decl; 233135446Strhodes XEXP (DECL_RTL (decl), 0) = symref; 234135446Strhodes} 235135446Strhodes 236135446Strhodes/* Mark a DECL as being dllimport'd. */ 237135446Strhodes 238135446Strhodesstatic void 239135446Strhodesi386_pe_mark_dllimport (tree decl) 240170222Sdougb{ 241135446Strhodes const char *oldname; 242135446Strhodes char *newname; 243135446Strhodes tree idp; 244135446Strhodes rtx rtlname, newrtl; 245135446Strhodes rtx symref; 246135446Strhodes 247135446Strhodes rtlname = XEXP (DECL_RTL (decl), 0); 248254402Serwin if (GET_CODE (rtlname) == MEM) 249254402Serwin rtlname = XEXP (rtlname, 0); 250135446Strhodes gcc_assert (GET_CODE (rtlname) == SYMBOL_REF); 251135446Strhodes oldname = XSTR (rtlname, 0); 252135446Strhodes if (i386_pe_dllexport_name_p (oldname)) 253135446Strhodes { 254135446Strhodes error ("%qs declared as both exported to and imported from a DLL", 255135446Strhodes IDENTIFIER_POINTER (DECL_NAME (decl))); 256135446Strhodes return; 257135446Strhodes } 258135446Strhodes else if (i386_pe_dllimport_name_p (oldname)) 259135446Strhodes { 260135446Strhodes /* Already done, but do a sanity check to prevent assembler 261254402Serwin errors. */ 262254402Serwin gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl) 263254402Serwin && DECL_DLLIMPORT_P (decl)); 264254402Serwin return; 265135446Strhodes } 266170222Sdougb 267170222Sdougb newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1); 268170222Sdougb sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname); 269170222Sdougb 270135446Strhodes /* We pass newname through get_identifier to ensure it has a unique 271170222Sdougb address. RTL processing can sometimes peek inside the symbol ref 272135446Strhodes and compare the string's addresses to see if two symbols are 273135446Strhodes identical. */ 274135446Strhodes idp = get_identifier (newname); 275135446Strhodes 276135446Strhodes symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); 277135446Strhodes SYMBOL_REF_DECL (symref) = decl; 278135446Strhodes newrtl = gen_rtx_MEM (Pmode,symref); 279135446Strhodes XEXP (DECL_RTL (decl), 0) = newrtl; 280135446Strhodes 281135446Strhodes DECL_DLLIMPORT_P (decl) = 1; 282135446Strhodes} 283135446Strhodes 284170222Sdougb/* Return string which is the former assembler name modified with a 285170222Sdougb suffix consisting of an atsign (@) followed by the number of bytes of 286170222Sdougb arguments. If FASTCALL is true, also add the FASTCALL_PREFIX. */ 287170222Sdougb 288254402Serwinstatic tree 289135446Strhodesgen_stdcall_or_fastcall_suffix (tree decl, bool fastcall) 290135446Strhodes{ 291135446Strhodes int total = 0; 292135446Strhodes /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead 293135446Strhodes of DECL_ASSEMBLER_NAME. */ 294135446Strhodes const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 295135446Strhodes char *newsym; 296135446Strhodes char *p; 297135446Strhodes tree formal_type; 298135446Strhodes 299135446Strhodes /* Do not change the identifier if a verbatim asmspec or already done. */ 300135446Strhodes if (*asmname == '*' || strchr (asmname, '@')) 301135446Strhodes return DECL_ASSEMBLER_NAME (decl); 302135446Strhodes 303135446Strhodes formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); 304170222Sdougb if (formal_type != NULL_TREE) 305135446Strhodes { 306135446Strhodes /* These attributes are ignored for variadic functions in 307135446Strhodes i386.c:ix86_return_pops_args. For compatibility with MS 308135446Strhodes compiler do not add @0 suffix here. */ 309135446Strhodes if (TREE_VALUE (tree_last (formal_type)) != void_type_node) 310135446Strhodes return DECL_ASSEMBLER_NAME (decl); 311135446Strhodes 312135446Strhodes /* Quit if we hit an incomplete type. Error is reported 313135446Strhodes by convert_arguments in c-typeck.c or cp/typeck.c. */ 314135446Strhodes while (TREE_VALUE (formal_type) != void_type_node 315135446Strhodes && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) 316135446Strhodes { 317135446Strhodes int parm_size 318135446Strhodes = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); 319135446Strhodes /* Must round up to include padding. This is done the same 320135446Strhodes way as in store_one_arg. */ 321218384Sdougb parm_size = ((parm_size + PARM_BOUNDARY - 1) 322218384Sdougb / PARM_BOUNDARY * PARM_BOUNDARY); 323135446Strhodes total += parm_size; 324135446Strhodes formal_type = TREE_CHAIN (formal_type);\ 325135446Strhodes } 326135446Strhodes } 327135446Strhodes 328135446Strhodes /* Assume max of 8 base 10 digits in the suffix. */ 329135446Strhodes newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1); 330135446Strhodes p = newsym; 331135446Strhodes if (fastcall) 332135446Strhodes *p++ = FASTCALL_PREFIX; 333135446Strhodes sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT); 334135446Strhodes return get_identifier (newsym); 335135446Strhodes} 336170222Sdougb 337135446Strhodesvoid 338135446Strhodesi386_pe_encode_section_info (tree decl, rtx rtl, int first) 339135446Strhodes{ 340135446Strhodes default_encode_section_info (decl, rtl, first); 341135446Strhodes 342135446Strhodes if (first && TREE_CODE (decl) == FUNCTION_DECL) 343135446Strhodes { 344135446Strhodes tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl)); 345135446Strhodes tree newid = NULL_TREE; 346135446Strhodes 347135446Strhodes if (lookup_attribute ("stdcall", type_attributes)) 348135446Strhodes newid = gen_stdcall_or_fastcall_suffix (decl, false); 349135446Strhodes else if (lookup_attribute ("fastcall", type_attributes)) 350135446Strhodes newid = gen_stdcall_or_fastcall_suffix (decl, true); 351135446Strhodes if (newid != NULL_TREE) 352135446Strhodes { 353135446Strhodes rtx rtlname = XEXP (rtl, 0); 354135446Strhodes if (GET_CODE (rtlname) == MEM) 355135446Strhodes rtlname = XEXP (rtlname, 0); 356135446Strhodes XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid); 357135446Strhodes /* These attributes must be present on first declaration, 358135446Strhodes change_decl_assembler_name will warn if they are added 359135446Strhodes later and the decl has been referenced, but duplicate_decls 360135446Strhodes should catch the mismatch before this is called. */ 361135446Strhodes change_decl_assembler_name (decl, newid); 362135446Strhodes } 363135446Strhodes } 364135446Strhodes 365135446Strhodes /* Mark the decl so we can tell from the rtl whether the object is 366135446Strhodes dllexport'd or dllimport'd. tree.c: merge_dllimport_decl_attributes 367135446Strhodes handles dllexport/dllimport override semantics. */ 368135446Strhodes 369135446Strhodes if (i386_pe_dllexport_p (decl)) 370218384Sdougb i386_pe_mark_dllexport (decl); 371218384Sdougb else if (i386_pe_dllimport_p (decl)) 372135446Strhodes i386_pe_mark_dllimport (decl); 373135446Strhodes /* It might be that DECL has been declared as dllimport, but a 374135446Strhodes subsequent definition nullified that. Assert that 375135446Strhodes tree.c: merge_dllimport_decl_attributes has removed the attribute 376135446Strhodes before the RTL name was marked with the DLL_IMPORT_PREFIX. */ 377135446Strhodes else 378135446Strhodes gcc_assert (!((TREE_CODE (decl) == FUNCTION_DECL 379135446Strhodes || TREE_CODE (decl) == VAR_DECL) 380135446Strhodes && rtl != NULL_RTX 381135446Strhodes && GET_CODE (rtl) == MEM 382135446Strhodes && GET_CODE (XEXP (rtl, 0)) == MEM 383135446Strhodes && GET_CODE (XEXP (XEXP (rtl, 0), 0)) == SYMBOL_REF 384135446Strhodes && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (rtl, 0), 0), 0)))); 385135446Strhodes} 386135446Strhodes 387135446Strhodes/* Strip only the leading encoding, leaving the stdcall suffix and fastcall 388135446Strhodes prefix if it exists. */ 389135446Strhodes 390135446Strhodesconst char * 391135446Strhodesi386_pe_strip_name_encoding (const char *str) 392135446Strhodes{ 393135446Strhodes if (strncmp (str, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX)) 394135446Strhodes == 0) 395135446Strhodes str += strlen (DLL_IMPORT_PREFIX); 396135446Strhodes else if (strncmp (str, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX)) 397135446Strhodes == 0) 398135446Strhodes str += strlen (DLL_EXPORT_PREFIX); 399135446Strhodes if (*str == '*') 400135446Strhodes str += 1; 401135446Strhodes return str; 402135446Strhodes} 403254897Serwin 404254897Serwin/* Also strip the fastcall prefix and stdcall suffix. */ 405135446Strhodes 406135446Strhodesconst char * 407135446Strhodesi386_pe_strip_name_encoding_full (const char *str) 408135446Strhodes{ 409135446Strhodes const char *p; 410135446Strhodes const char *name = i386_pe_strip_name_encoding (str); 411135446Strhodes 412135446Strhodes /* Strip leading '@' on fastcall symbols. */ 413254897Serwin if (*name == '@') 414135446Strhodes name++; 415254897Serwin 416135446Strhodes /* Strip trailing "@n". */ 417254897Serwin p = strchr (name, '@'); 418254897Serwin if (p) 419254897Serwin return ggc_alloc_string (name, p - name); 420135446Strhodes 421254897Serwin return name; 422254897Serwin} 423254897Serwin 424186462Sdougb/* Output a reference to a label. Fastcall symbols are prefixed with @, 425254897Serwin whereas symbols for functions using other calling conventions don't 426254897Serwin have a prefix (unless they are marked dllimport or dllexport). */ 427254897Serwin 428135446Strhodesvoid i386_pe_output_labelref (FILE *stream, const char *name) 429135446Strhodes{ 430135446Strhodes if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX)) 431135446Strhodes == 0) 432135446Strhodes /* A dll import */ 433135446Strhodes { 434186462Sdougb if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX) 435135446Strhodes /* A dllimport fastcall symbol. */ 436135446Strhodes { 437135446Strhodes fprintf (stream, "__imp_%s", 438135446Strhodes i386_pe_strip_name_encoding (name)); 439135446Strhodes } 440135446Strhodes else 441135446Strhodes /* A dllimport non-fastcall symbol. */ 442135446Strhodes { 443135446Strhodes fprintf (stream, "__imp__%s", 444135446Strhodes i386_pe_strip_name_encoding (name)); 445135446Strhodes } 446135446Strhodes } 447135446Strhodes else if ((name[0] == FASTCALL_PREFIX) 448135446Strhodes || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX)) 449135446Strhodes == 0 450135446Strhodes && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX)) 451135446Strhodes /* A fastcall symbol. */ 452254897Serwin { 453254897Serwin fprintf (stream, "%s", 454254897Serwin i386_pe_strip_name_encoding (name)); 455254897Serwin } 456135446Strhodes else 457135446Strhodes /* Everything else. */ 458135446Strhodes { 459135446Strhodes fprintf (stream, "%s%s", USER_LABEL_PREFIX, 460135446Strhodes i386_pe_strip_name_encoding (name)); 461135446Strhodes } 462135446Strhodes} 463135446Strhodes 464135446Strhodesvoid 465135446Strhodesi386_pe_unique_section (tree decl, int reloc) 466135446Strhodes{ 467254897Serwin int len; 468135446Strhodes const char *name, *prefix; 469135446Strhodes char *string; 470254897Serwin 471254897Serwin name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 472254897Serwin name = i386_pe_strip_name_encoding_full (name); 473135446Strhodes 474254897Serwin /* The object is put in, for example, section .text$foo. 475254897Serwin The linker will then ultimately place them in .text 476254897Serwin (everything from the $ on is stripped). Don't put 477186462Sdougb read-only data in .rdata section to avoid a PE linker 478254897Serwin bug when .rdata$* grouped sections are used in code 479254897Serwin without a .rdata section. */ 480254897Serwin if (TREE_CODE (decl) == FUNCTION_DECL) 481135446Strhodes prefix = ".text$"; 482135446Strhodes else if (decl_readonly_section (decl, reloc)) 483135446Strhodes prefix = ".rdata$"; 484135446Strhodes else 485135446Strhodes prefix = ".data$"; 486135446Strhodes len = strlen (name) + strlen (prefix); 487135446Strhodes string = alloca (len + 1); 488135446Strhodes sprintf (string, "%s%s", prefix, name); 489135446Strhodes 490135446Strhodes DECL_SECTION_NAME (decl) = build_string (len, string); 491135446Strhodes} 492135446Strhodes 493135446Strhodes/* Select a set of attributes for section NAME based on the properties 494135446Strhodes of DECL and whether or not RELOC indicates that DECL's initializer 495135446Strhodes might contain runtime relocations. 496135446Strhodes 497224092Sdougb We make the section read-only and executable for a function decl, 498224092Sdougb read-only for a const data decl, and writable for a non-const data decl. 499224092Sdougb 500135446Strhodes If the section has already been defined, to not allow it to have 501135446Strhodes different attributes, as (1) this is ambiguous since we're not seeing 502135446Strhodes all the declarations up front and (2) some assemblers (e.g. SVR4) 503135446Strhodes do not recognize section redefinitions. */ 504135446Strhodes/* ??? This differs from the "standard" PE implementation in that we 505135446Strhodes handle the SHARED variable attribute. Should this be done for all 506135446Strhodes PE targets? */ 507135446Strhodes 508135446Strhodes#define SECTION_PE_SHARED SECTION_MACH_DEP 509135446Strhodes 510135446Strhodesunsigned int 511135446Strhodesi386_pe_section_type_flags (tree decl, const char *name, int reloc) 512135446Strhodes{ 513135446Strhodes static htab_t htab; 514135446Strhodes unsigned int flags; 515135446Strhodes unsigned int **slot; 516135446Strhodes 517193149Sdougb /* The names we put in the hashtable will always be the unique 518193149Sdougb versions given to us by the stringtable, so we can just use 519135446Strhodes their addresses as the keys. */ 520135446Strhodes if (!htab) 521135446Strhodes htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL); 522135446Strhodes 523135446Strhodes if (decl && TREE_CODE (decl) == FUNCTION_DECL) 524135446Strhodes flags = SECTION_CODE; 525135446Strhodes else if (decl && decl_readonly_section (decl, reloc)) 526135446Strhodes flags = 0; 527135446Strhodes else 528135446Strhodes { 529135446Strhodes flags = SECTION_WRITE; 530135446Strhodes 531135446Strhodes if (decl && TREE_CODE (decl) == VAR_DECL 532135446Strhodes && lookup_attribute ("shared", DECL_ATTRIBUTES (decl))) 533135446Strhodes flags |= SECTION_PE_SHARED; 534135446Strhodes } 535218384Sdougb 536218384Sdougb if (decl && DECL_ONE_ONLY (decl)) 537135446Strhodes flags |= SECTION_LINKONCE; 538135446Strhodes 539135446Strhodes /* See if we already have an entry for this section. */ 540135446Strhodes slot = (unsigned int **) htab_find_slot (htab, name, INSERT); 541135446Strhodes if (!*slot) 542135446Strhodes { 543135446Strhodes *slot = (unsigned int *) xmalloc (sizeof (unsigned int)); 544170222Sdougb **slot = flags; 545170222Sdougb } 546170222Sdougb else 547170222Sdougb { 548170222Sdougb if (decl && **slot != flags) 549170222Sdougb error ("%q+D causes a section type conflict", decl); 550135446Strhodes } 551254402Serwin 552254402Serwin return flags; 553254402Serwin} 554254402Serwin 555254402Serwinvoid 556262706Serwini386_pe_asm_named_section (const char *name, unsigned int flags, 557262706Serwin tree decl) 558262706Serwin{ 559170222Sdougb char flagchars[8], *f = flagchars; 560262706Serwin 561170222Sdougb if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0) 562135446Strhodes /* readonly data */ 563135446Strhodes { 564135446Strhodes *f++ ='d'; /* This is necessary for older versions of gas. */ 565135446Strhodes *f++ ='r'; 566135446Strhodes } 567135446Strhodes else 568135446Strhodes { 569135446Strhodes if (flags & SECTION_CODE) 570135446Strhodes *f++ = 'x'; 571135446Strhodes if (flags & SECTION_WRITE) 572135446Strhodes *f++ = 'w'; 573135446Strhodes if (flags & SECTION_PE_SHARED) 574135446Strhodes *f++ = 's'; 575135446Strhodes } 576135446Strhodes 577135446Strhodes *f = '\0'; 578135446Strhodes 579135446Strhodes fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars); 580135446Strhodes 581135446Strhodes if (flags & SECTION_LINKONCE) 582135446Strhodes { 583135446Strhodes /* Functions may have been compiled at various levels of 584135446Strhodes optimization so we can't use `same_size' here. 585135446Strhodes Instead, have the linker pick one, without warning. 586135446Strhodes If 'selectany' attribute has been specified, MS compiler 587135446Strhodes sets 'discard' characteristic, rather than telling linker 588135446Strhodes to warn of size or content mismatch, so do the same. */ 589135446Strhodes bool discard = (flags & SECTION_CODE) 590135446Strhodes || lookup_attribute ("selectany", 591135446Strhodes DECL_ATTRIBUTES (decl)); 592135446Strhodes fprintf (asm_out_file, "\t.linkonce %s\n", 593135446Strhodes (discard ? "discard" : "same_size")); 594135446Strhodes } 595135446Strhodes} 596135446Strhodes 597135446Strhodes/* The Microsoft linker requires that every function be marked as 598135446Strhodes DT_FCN. When using gas on cygwin, we must emit appropriate .type 599135446Strhodes directives. */ 600135446Strhodes 601135446Strhodes#include "gsyms.h" 602135446Strhodes 603135446Strhodes/* Mark a function appropriately. This should only be called for 604135446Strhodes functions for which we are not emitting COFF debugging information. 605135446Strhodes FILE is the assembler output file, NAME is the name of the 606135446Strhodes function, and PUBLIC is nonzero if the function is globally 607135446Strhodes visible. */ 608135446Strhodes 609135446Strhodesvoid 610135446Strhodesi386_pe_declare_function_type (FILE *file, const char *name, int public) 611135446Strhodes{ 612135446Strhodes fprintf (file, "\t.def\t"); 613135446Strhodes assemble_name (file, name); 614135446Strhodes fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n", 615135446Strhodes public ? (int) C_EXT : (int) C_STAT, 616135446Strhodes (int) DT_FCN << N_BTSHFT); 617135446Strhodes} 618135446Strhodes 619135446Strhodes/* Keep a list of external functions. */ 620135446Strhodes 621135446Strhodesstruct extern_list GTY(()) 622135446Strhodes{ 623135446Strhodes struct extern_list *next; 624135446Strhodes tree decl; 625135446Strhodes const char *name; 626135446Strhodes}; 627135446Strhodes 628135446Strhodesstatic GTY(()) struct extern_list *extern_head; 629135446Strhodes 630135446Strhodes/* Assemble an external function reference. We need to keep a list of 631135446Strhodes these, so that we can output the function types at the end of the 632135446Strhodes assembly. We can't output the types now, because we might see a 633135446Strhodes definition of the function later on and emit debugging information 634135446Strhodes for it then. */ 635135446Strhodes 636135446Strhodesvoid 637135446Strhodesi386_pe_record_external_function (tree decl, const char *name) 638135446Strhodes{ 639135446Strhodes struct extern_list *p; 640135446Strhodes 641135446Strhodes p = (struct extern_list *) ggc_alloc (sizeof *p); 642135446Strhodes p->next = extern_head; 643135446Strhodes p->decl = decl; 644135446Strhodes p->name = name; 645135446Strhodes extern_head = p; 646135446Strhodes} 647135446Strhodes 648135446Strhodes/* Keep a list of exported symbols. */ 649135446Strhodes 650153816Sdougbstruct export_list GTY(()) 651135446Strhodes{ 652135446Strhodes struct export_list *next; 653135446Strhodes const char *name; 654135446Strhodes int is_data; /* used to type tag exported symbols. */ 655135446Strhodes}; 656135446Strhodes 657135446Strhodesstatic GTY(()) struct export_list *export_head; 658135446Strhodes 659135446Strhodes/* Assemble an export symbol entry. We need to keep a list of 660135446Strhodes these, so that we can output the export list at the end of the 661135446Strhodes assembly. We used to output these export symbols in each function, 662135446Strhodes but that causes problems with GNU ld when the sections are 663135446Strhodes linkonce. */ 664170222Sdougb 665135446Strhodesvoid 666135446Strhodesi386_pe_record_exported_symbol (const char *name, int is_data) 667135446Strhodes{ 668135446Strhodes struct export_list *p; 669135446Strhodes 670135446Strhodes p = (struct export_list *) ggc_alloc (sizeof *p); 671135446Strhodes p->next = export_head; 672135446Strhodes p->name = name; 673135446Strhodes p->is_data = is_data; 674135446Strhodes export_head = p; 675135446Strhodes} 676135446Strhodes 677135446Strhodes/* This is called at the end of assembly. For each external function 678135446Strhodes which has not been defined, we output a declaration now. We also 679135446Strhodes output the .drectve section. */ 680135446Strhodes 681135446Strhodesvoid 682135446Strhodesi386_pe_file_end (void) 683135446Strhodes{ 684135446Strhodes struct extern_list *p; 685135446Strhodes 686135446Strhodes ix86_file_end (); 687135446Strhodes 688135446Strhodes for (p = extern_head; p != NULL; p = p->next) 689143731Sdougb { 690143731Sdougb tree decl; 691143731Sdougb 692143731Sdougb decl = p->decl; 693143731Sdougb 694143731Sdougb /* Positively ensure only one declaration for any given symbol. */ 695143731Sdougb if (! TREE_ASM_WRITTEN (decl) 696143731Sdougb && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) 697143731Sdougb { 698135446Strhodes TREE_ASM_WRITTEN (decl) = 1; 699186462Sdougb i386_pe_declare_function_type (asm_out_file, p->name, 700193149Sdougb TREE_PUBLIC (decl)); 701193149Sdougb } 702193149Sdougb } 703135446Strhodes 704135446Strhodes if (export_head) 705135446Strhodes { 706135446Strhodes struct export_list *q; 707135446Strhodes drectve_section (); 708135446Strhodes for (q = export_head; q != NULL; q = q->next) 709135446Strhodes { 710135446Strhodes fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n", 711170222Sdougb i386_pe_strip_name_encoding (q->name), 712135446Strhodes (q->is_data) ? ",data" : ""); 713135446Strhodes } 714135446Strhodes } 715135446Strhodes} 716135446Strhodes 717135446Strhodes#include "gt-winnt.h" 718135446Strhodes