diff options
author | kan <kan@FreeBSD.org> | 2007-05-19 01:19:51 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2007-05-19 01:19:51 +0000 |
commit | 1f9ea4d0a40cca64d60cf4dab152349da7b9dddf (patch) | |
tree | 0cb530c9c38af219e6dda2994c078b6b2b9ad853 /contrib/gcc/config/i386/winnt.c | |
parent | 4895159b2b4f648051c1f139faa7b6dc50c2bfcb (diff) | |
download | FreeBSD-src-1f9ea4d0a40cca64d60cf4dab152349da7b9dddf.zip FreeBSD-src-1f9ea4d0a40cca64d60cf4dab152349da7b9dddf.tar.gz |
GCC 4.2.0 release.
Diffstat (limited to 'contrib/gcc/config/i386/winnt.c')
-rw-r--r-- | contrib/gcc/config/i386/winnt.c | 574 |
1 files changed, 226 insertions, 348 deletions
diff --git a/contrib/gcc/config/i386/winnt.c b/contrib/gcc/config/i386/winnt.c index f8621b4..a46fc5b 100644 --- a/contrib/gcc/config/i386/winnt.c +++ b/contrib/gcc/config/i386/winnt.c @@ -1,7 +1,7 @@ /* Subroutines for insn-output.c for Windows NT. Contributed by Douglas Rupp (drupp@cs.washington.edu) - Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + 2005, 2006 Free Software Foundation, Inc. This file is part of GCC. @@ -17,8 +17,8 @@ for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ #include "config.h" #include "system.h" @@ -47,10 +47,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA */ static tree associated_type (tree); -static const char * gen_stdcall_suffix (tree); -static const char * gen_fastcall_suffix (tree); -static int i386_pe_dllexport_p (tree); -static int i386_pe_dllimport_p (tree); +static tree gen_stdcall_or_fastcall_suffix (tree, bool); +static bool i386_pe_dllexport_p (tree); +static bool i386_pe_dllimport_p (tree); static void i386_pe_mark_dllexport (tree); static void i386_pe_mark_dllimport (tree); @@ -63,96 +62,45 @@ static void i386_pe_mark_dllimport (tree); #define DLL_EXPORT_PREFIX "#e." #endif -/* Handle a "dllimport" or "dllexport" attribute; +/* Handle a "shared" attribute; arguments as in struct attribute_spec.handler. */ tree -ix86_handle_dll_attribute (tree * pnode, tree name, tree args, int flags, - bool *no_add_attrs) +ix86_handle_shared_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) { - tree node = *pnode; - - /* These attributes may apply to structure and union types being created, - but otherwise should pass to the declaration involved. */ - if (!DECL_P (node)) - { - if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT - | (int) ATTR_FLAG_ARRAY_NEXT)) - { - *no_add_attrs = true; - return tree_cons (name, args, NULL_TREE); - } - if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) - { - warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } - - return NULL_TREE; - } - - /* Report error on dllimport ambiguities seen now before they cause - any damage. */ - else if (is_attribute_p ("dllimport", name)) - { - /* Like MS, treat definition of dllimported variables and - non-inlined functions on declaration as syntax errors. - We allow the attribute for function definitions if declared - inline, but just ignore it in i386_pe_dllimport_p. */ - if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node) - && !DECL_INLINE (node)) - { - error ("%Jfunction `%D' definition is marked dllimport.", node, node); - *no_add_attrs = true; - } - - else if (TREE_CODE (node) == VAR_DECL) - { - if (DECL_INITIAL (node)) - { - error ("%Jvariable `%D' definition is marked dllimport.", - node, node); - *no_add_attrs = true; - } - - /* `extern' needn't be specified with dllimport. - Specify `extern' now and hope for the best. Sigh. */ - DECL_EXTERNAL (node) = 1; - /* Also, implicitly give dllimport'd variables declared within - a function global scope, unless declared static. */ - if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) - TREE_PUBLIC (node) = 1; - } - } - - /* Report error if symbol is not accessible at global scope. */ - if (!TREE_PUBLIC (node) - && (TREE_CODE (node) == VAR_DECL - || TREE_CODE (node) == FUNCTION_DECL)) + if (TREE_CODE (*node) != VAR_DECL) { - error ("%Jexternal linkage required for symbol '%D' because of " - "'%s' attribute.", node, node, IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qs attribute only applies to variables", + IDENTIFIER_POINTER (name)); *no_add_attrs = true; } return NULL_TREE; } -/* Handle a "shared" attribute; +/* Handle a "selectany" attribute; arguments as in struct attribute_spec.handler. */ tree -ix86_handle_shared_attribute (tree *node, tree name, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +ix86_handle_selectany_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) { - if (TREE_CODE (*node) != VAR_DECL) - { - warning ("`%s' attribute only applies to variables", - IDENTIFIER_POINTER (name)); + /* The attribute applies only to objects that are initialized and have + external linkage. However, we may not know about initialization + until the language frontend has processed the decl. We'll check for + initialization later in encode_section_info. */ + if (TREE_CODE (*node) != VAR_DECL || !TREE_PUBLIC (*node)) + { + error ("%qs attribute applies only to initialized variables" + " with external linkage", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } return NULL_TREE; } + /* Return the type that we should use to determine if DECL is imported or exported. */ @@ -160,132 +108,73 @@ ix86_handle_shared_attribute (tree *node, tree name, static tree associated_type (tree decl) { - tree t = NULL_TREE; - - /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer - to the containing class. So we look at the 'this' arg. */ - if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) - { - /* Artificial methods are not affected by the import/export status - of their class unless they are COMDAT. Implicit copy ctor's and - dtor's are not affected by class status but virtual and - non-virtual thunks are. */ - if (!DECL_ARTIFICIAL (decl) || DECL_COMDAT (decl)) - t = TYPE_MAIN_VARIANT - (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))))); - } - else if (DECL_CONTEXT (decl) - && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') - t = DECL_CONTEXT (decl); - - return t; + return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) + ? DECL_CONTEXT (decl) : NULL_TREE; } -/* Return nonzero if DECL is a dllexport'd object. */ -static int +/* Return true if DECL is a dllexport'd object. */ + +static bool i386_pe_dllexport_p (tree decl) { - tree exp; - if (TREE_CODE (decl) != VAR_DECL - && TREE_CODE (decl) != FUNCTION_DECL) - return 0; - exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)); - if (exp) - return 1; - - /* Class members get the dllexport status of their class. */ - if (associated_type (decl)) - { - exp = lookup_attribute ("dllexport", - TYPE_ATTRIBUTES (associated_type (decl))); - if (exp) - return 1; - } + && TREE_CODE (decl) != FUNCTION_DECL) + return false; - return 0; -} + if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) + return true; + + /* Also mark class members of exported classes with dllexport. */ + if (associated_type (decl) + && lookup_attribute ("dllexport", + TYPE_ATTRIBUTES (associated_type (decl)))) + return i386_pe_type_dllexport_p (decl); -/* Return nonzero if DECL is a dllimport'd object. */ + return false; +} -static int +static bool i386_pe_dllimport_p (tree decl) { - tree imp; - int context_imp = 0; - - if (TREE_CODE (decl) == FUNCTION_DECL - && TARGET_NOP_FUN_DLLIMPORT) - return 0; - if (TREE_CODE (decl) != VAR_DECL - && TREE_CODE (decl) != FUNCTION_DECL) - return 0; + && TREE_CODE (decl) != FUNCTION_DECL) + return false; - imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); - - /* Class members get the dllimport status of their class. */ - if (!imp && associated_type (decl)) - { - imp = lookup_attribute ("dllimport", - TYPE_ATTRIBUTES (associated_type (decl))); - if (imp) - context_imp = 1; - } - - if (imp) + /* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag. + We may need to override an earlier decision. */ + if (DECL_DLLIMPORT_P (decl) + && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))) { - /* Don't mark defined functions as dllimport. If the definition - itself was marked with dllimport, than ix86_handle_dll_attribute - reports an error. This handles the case when the definition - overrides an earlier declaration. */ - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) - && !DECL_INLINE (decl)) + /* Make a final check to see if this is a definition before we generate + RTL for an indirect reference. */ + if (!DECL_EXTERNAL (decl)) { - /* Don't warn about artificial methods. */ - if (!DECL_ARTIFICIAL (decl)) - warning ("%Jfunction '%D' is defined after prior declaration " - "as dllimport: attribute ignored", decl, decl); - return 0; - } - - /* We ignore the dllimport attribute for inline member functions. - This differs from MSVC behavior which treats it like GNUC - 'extern inline' extension. */ - else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl)) - { - if (extra_warnings) - warning ("%Jinline function '%D' is declared as dllimport: " - "attribute ignored.", decl, decl); - return 0; - } - - /* Don't allow definitions of static data members in dllimport class, - Just ignore attribute for vtable data. */ - else if (TREE_CODE (decl) == VAR_DECL - && TREE_STATIC (decl) && TREE_PUBLIC (decl) - && !DECL_EXTERNAL (decl) && context_imp) - { - if (!DECL_VIRTUAL_P (decl)) - error ("%Jdefinition of static data member '%D' of " - "dllimport'd class.", decl, decl); - return 0; - } - - /* Since we can't treat a pointer to a dllimport'd symbol as a - constant address, we turn off the attribute on C++ virtual - methods to allow creation of vtables using thunks. Don't mark - artificial methods either (in associated_type, only COMDAT - artificial method get import status from class context). */ - else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE - && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl))) - return 0; - - return 1; + error ("%q+D: definition is marked as dllimport", decl); + DECL_DLLIMPORT_P (decl) = 0; + return false; + } + return true; } + /* The DECL_DLLIMPORT_P flag was set for decls in the class definition + by targetm.cxx.adjust_class_at_definition. Check again to emit + warnings if the class attribute has been overridden by an + out-of-class definition. */ + else if (associated_type (decl) + && lookup_attribute ("dllimport", + TYPE_ATTRIBUTES (associated_type (decl)))) + return i386_pe_type_dllimport_p (decl); + + return false; +} - return 0; +/* Handle the -mno-fun-dllimport target switch. */ +bool +i386_pe_valid_dllimport_attribute_p (tree decl) +{ + if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL) + return false; + return true; } /* Return nonzero if SYMBOL is marked as being dllexport'd. */ @@ -307,7 +196,7 @@ i386_pe_dllimport_name_p (const char *symbol) } /* Mark a DECL as being dllexport'd. - Note that we override the previous setting (eg: dllimport). */ + Note that we override the previous setting (e.g.: dllimport). */ static void i386_pe_mark_dllexport (tree decl) @@ -315,23 +204,20 @@ i386_pe_mark_dllexport (tree decl) const char *oldname; char *newname; rtx rtlname; + rtx symref; tree idp; rtlname = XEXP (DECL_RTL (decl), 0); - if (GET_CODE (rtlname) == SYMBOL_REF) - oldname = XSTR (rtlname, 0); - else if (GET_CODE (rtlname) == MEM - && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) - oldname = XSTR (XEXP (rtlname, 0), 0); - else - abort (); + if (GET_CODE (rtlname) == MEM) + rtlname = XEXP (rtlname, 0); + gcc_assert (GET_CODE (rtlname) == SYMBOL_REF); + oldname = XSTR (rtlname, 0); if (i386_pe_dllimport_name_p (oldname)) { - warning ("%Jinconsistent dll linkage for '%D', dllexport assumed.", - decl, decl); + warning (0, "inconsistent dll linkage for %q+D, dllexport assumed", + decl); /* Remove DLL_IMPORT_PREFIX. */ oldname += strlen (DLL_IMPORT_PREFIX); - DECL_NON_ADDR_CONST_P (decl) = 0; } else if (i386_pe_dllexport_name_p (oldname)) return; /* already done */ @@ -345,8 +231,9 @@ i386_pe_mark_dllexport (tree decl) identical. */ idp = get_identifier (newname); - XEXP (DECL_RTL (decl), 0) = - gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); + symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); + SET_SYMBOL_REF_DECL (symref, decl); + XEXP (DECL_RTL (decl), 0) = symref; } /* Mark a DECL as being dllimport'd. */ @@ -358,30 +245,25 @@ i386_pe_mark_dllimport (tree decl) char *newname; tree idp; rtx rtlname, newrtl; + rtx symref; rtlname = XEXP (DECL_RTL (decl), 0); - if (GET_CODE (rtlname) == SYMBOL_REF) - oldname = XSTR (rtlname, 0); - else if (GET_CODE (rtlname) == MEM - && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) - oldname = XSTR (XEXP (rtlname, 0), 0); - else - abort (); + if (GET_CODE (rtlname) == MEM) + rtlname = XEXP (rtlname, 0); + gcc_assert (GET_CODE (rtlname) == SYMBOL_REF); + oldname = XSTR (rtlname, 0); if (i386_pe_dllexport_name_p (oldname)) { - error ("`%s' declared as both exported to and imported from a DLL", + error ("%qs declared as both exported to and imported from a DLL", IDENTIFIER_POINTER (DECL_NAME (decl))); return; } else if (i386_pe_dllimport_name_p (oldname)) { - /* Already done, but do a sanity check to prevent assembler errors. */ - if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)) - { - error ("%Jfailure in redeclaration of '%D': dllimport'd " - "symbol lacks external linkage.", decl, decl); - abort(); - } + /* Already done, but do a sanity check to prevent assembler + errors. */ + gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl) + && DECL_DLLIMPORT_P (decl)); return; } @@ -394,93 +276,65 @@ i386_pe_mark_dllimport (tree decl) identical. */ idp = get_identifier (newname); - newrtl = gen_rtx (MEM, Pmode, - gen_rtx (SYMBOL_REF, Pmode, - IDENTIFIER_POINTER (idp))); + symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); + SET_SYMBOL_REF_DECL (symref, decl); + newrtl = gen_rtx_MEM (Pmode,symref); XEXP (DECL_RTL (decl), 0) = newrtl; - /* Can't treat a pointer to this as a constant address */ - DECL_NON_ADDR_CONST_P (decl) = 1; -} - -/* Return string which is the former assembler name modified with a - prefix consisting of FASTCALL_PREFIX and a suffix consisting of an - atsign (@) followed by the number of bytes of arguments. */ - -static const char * -gen_fastcall_suffix (tree decl) -{ - int total = 0; - const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - char *newsym; - - if (TYPE_ARG_TYPES (TREE_TYPE (decl))) - if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl)))) - == void_type_node) - { - tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); - - /* Quit if we hit an incomplete type. Error is reported - by convert_arguments in c-typeck.c or cp/typeck.c. */ - while (TREE_VALUE (formal_type) != void_type_node - && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) - { - int parm_size - = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); - /* Must round up to include padding. This is done the same - way as in store_one_arg. */ - parm_size = ((parm_size + PARM_BOUNDARY - 1) - / PARM_BOUNDARY * PARM_BOUNDARY); - total += parm_size; - formal_type = TREE_CHAIN (formal_type); - } - } - - /* Assume max of 8 base 10 digits in the suffix. */ - newsym = xmalloc (1 + strlen (asmname) + 1 + 8 + 1); - sprintf (newsym, "%c%s@%d", FASTCALL_PREFIX, asmname, total/BITS_PER_UNIT); - return IDENTIFIER_POINTER (get_identifier (newsym)); + DECL_DLLIMPORT_P (decl) = 1; } /* Return string which is the former assembler name modified with a suffix consisting of an atsign (@) followed by the number of bytes of - arguments */ + arguments. If FASTCALL is true, also add the FASTCALL_PREFIX. */ -static const char * -gen_stdcall_suffix (tree decl) +static tree +gen_stdcall_or_fastcall_suffix (tree decl, bool fastcall) { int total = 0; /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead of DECL_ASSEMBLER_NAME. */ - const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); char *newsym; + char *p; + tree formal_type; + + /* Do not change the identifier if a verbatim asmspec or already done. */ + if (*asmname == '*' || strchr (asmname, '@')) + return DECL_ASSEMBLER_NAME (decl); - if (TYPE_ARG_TYPES (TREE_TYPE (decl))) - if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl)))) - == void_type_node) - { - tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); - - /* Quit if we hit an incomplete type. Error is reported - by convert_arguments in c-typeck.c or cp/typeck.c. */ - while (TREE_VALUE (formal_type) != void_type_node - && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) - { - int parm_size - = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); + formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); + if (formal_type != NULL_TREE) + { + /* These attributes are ignored for variadic functions in + i386.c:ix86_return_pops_args. For compatibility with MS + compiler do not add @0 suffix here. */ + if (TREE_VALUE (tree_last (formal_type)) != void_type_node) + return DECL_ASSEMBLER_NAME (decl); + + /* Quit if we hit an incomplete type. Error is reported + by convert_arguments in c-typeck.c or cp/typeck.c. */ + while (TREE_VALUE (formal_type) != void_type_node + && COMPLETE_TYPE_P (TREE_VALUE (formal_type))) + { + int parm_size + = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); /* Must round up to include padding. This is done the same way as in store_one_arg. */ - parm_size = ((parm_size + PARM_BOUNDARY - 1) - / PARM_BOUNDARY * PARM_BOUNDARY); - total += parm_size; - formal_type = TREE_CHAIN (formal_type); - } - } + parm_size = ((parm_size + PARM_BOUNDARY - 1) + / PARM_BOUNDARY * PARM_BOUNDARY); + total += parm_size; + formal_type = TREE_CHAIN (formal_type);\ + } + } /* Assume max of 8 base 10 digits in the suffix. */ - newsym = xmalloc (strlen (asmname) + 1 + 8 + 1); - sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT); - return IDENTIFIER_POINTER (get_identifier (newsym)); + newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1); + p = newsym; + if (fastcall) + *p++ = FASTCALL_PREFIX; + sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT); + return get_identifier (newsym); } void @@ -488,58 +342,65 @@ i386_pe_encode_section_info (tree decl, rtx rtl, int first) { default_encode_section_info (decl, rtl, first); - if (TREE_CODE (decl) == FUNCTION_DECL) + if (first && TREE_CODE (decl) == FUNCTION_DECL) + { + tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl)); + tree newid = NULL_TREE; + + if (lookup_attribute ("stdcall", type_attributes)) + newid = gen_stdcall_or_fastcall_suffix (decl, false); + else if (lookup_attribute ("fastcall", type_attributes)) + newid = gen_stdcall_or_fastcall_suffix (decl, true); + if (newid != NULL_TREE) + { + rtx rtlname = XEXP (rtl, 0); + if (GET_CODE (rtlname) == MEM) + rtlname = XEXP (rtlname, 0); + XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid); + /* These attributes must be present on first declaration, + change_decl_assembler_name will warn if they are added + later and the decl has been referenced, but duplicate_decls + should catch the mismatch before this is called. */ + change_decl_assembler_name (decl, newid); + } + } + + else if (TREE_CODE (decl) == VAR_DECL + && lookup_attribute ("selectany", DECL_ATTRIBUTES (decl))) { - if (lookup_attribute ("stdcall", - TYPE_ATTRIBUTES (TREE_TYPE (decl)))) - XEXP (DECL_RTL (decl), 0) = - gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl)); - else if (lookup_attribute ("fastcall", - TYPE_ATTRIBUTES (TREE_TYPE (decl)))) - XEXP (DECL_RTL (decl), 0) = - gen_rtx (SYMBOL_REF, Pmode, gen_fastcall_suffix (decl)); + if (DECL_INITIAL (decl) + /* If an object is initialized with a ctor, the static + initialization and destruction code for it is present in + each unit defining the object. The code that calls the + ctor is protected by a link-once guard variable, so that + the object still has link-once semantics, */ + || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) + make_decl_one_only (decl); + else + error ("%q+D:'selectany' attribute applies only to initialized objects", + decl); } /* Mark the decl so we can tell from the rtl whether the object is - dllexport'd or dllimport'd. This also handles dllexport/dllimport - override semantics. */ + dllexport'd or dllimport'd. tree.c: merge_dllimport_decl_attributes + handles dllexport/dllimport override semantics. */ if (i386_pe_dllexport_p (decl)) i386_pe_mark_dllexport (decl); else if (i386_pe_dllimport_p (decl)) i386_pe_mark_dllimport (decl); - /* It might be that DECL has already been marked as dllimport, but a - subsequent definition nullified that. The attribute is gone but - DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove - that. Ditto for the DECL_NON_ADDR_CONST_P flag. */ - else if ((TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == VAR_DECL) - && DECL_RTL (decl) != NULL_RTX - && GET_CODE (DECL_RTL (decl)) == MEM - && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM - && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF - && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0))) - { - const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0); - - /* Remove DLL_IMPORT_PREFIX. */ - tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX)); - rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); - - if (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl)) - warning ("%J'%D' defined locally after being " - "referenced with dllimport linkage", decl, decl); - else - warning ("%J'%D' redeclared without dllimport attribute " - "after being referenced with dllimport linkage", decl, decl); - - XEXP (DECL_RTL (decl), 0) = newrtl; - - DECL_NON_ADDR_CONST_P (decl) = 0; - - /* We previously set TREE_PUBLIC and DECL_EXTERNAL. - We leave these alone for now. */ - } + /* It might be that DECL has been declared as dllimport, but a + subsequent definition nullified that. Assert that + tree.c: merge_dllimport_decl_attributes has removed the attribute + before the RTL name was marked with the DLL_IMPORT_PREFIX. */ + else + gcc_assert (!((TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == VAR_DECL) + && rtl != NULL_RTX + && GET_CODE (rtl) == MEM + && GET_CODE (XEXP (rtl, 0)) == MEM + && GET_CODE (XEXP (XEXP (rtl, 0), 0)) == SYMBOL_REF + && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (rtl, 0), 0), 0)))); } /* Strip only the leading encoding, leaving the stdcall suffix and fastcall @@ -559,7 +420,7 @@ i386_pe_strip_name_encoding (const char *str) return str; } -/* Also strip the stdcall suffix. */ +/* Also strip the fastcall prefix and stdcall suffix. */ const char * i386_pe_strip_name_encoding_full (const char *str) @@ -567,6 +428,11 @@ i386_pe_strip_name_encoding_full (const char *str) const char *p; const char *name = i386_pe_strip_name_encoding (str); + /* Strip leading '@' on fastcall symbols. */ + if (*name == '@') + name++; + + /* Strip trailing "@n". */ p = strchr (name, '@'); if (p) return ggc_alloc_string (name, p - name); @@ -598,9 +464,9 @@ void i386_pe_output_labelref (FILE *stream, const char *name) } } else if ((name[0] == FASTCALL_PREFIX) - || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX) + || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX)) == 0 - && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX))) + && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX)) /* A fastcall symbol. */ { fprintf (stream, "%s", @@ -668,7 +534,7 @@ i386_pe_section_type_flags (tree decl, const char *name, int reloc) unsigned int **slot; /* The names we put in the hashtable will always be the unique - versions gived to us by the stringtable, so we can just use + versions given to us by the stringtable, so we can just use their addresses as the keys. */ if (!htab) htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL); @@ -699,14 +565,15 @@ i386_pe_section_type_flags (tree decl, const char *name, int reloc) else { if (decl && **slot != flags) - error ("%J'%D' causes a section type conflict", decl, decl); + error ("%q+D causes a section type conflict", decl); } return flags; } void -i386_pe_asm_named_section (const char *name, unsigned int flags) +i386_pe_asm_named_section (const char *name, unsigned int flags, + tree decl) { char flagchars[8], *f = flagchars; @@ -733,10 +600,16 @@ i386_pe_asm_named_section (const char *name, unsigned int flags) if (flags & SECTION_LINKONCE) { /* Functions may have been compiled at various levels of - optimization so we can't use `same_size' here. - Instead, have the linker pick one. */ + optimization so we can't use `same_size' here. + Instead, have the linker pick one, without warning. + If 'selectany' attribute has been specified, MS compiler + sets 'discard' characteristic, rather than telling linker + to warn of size or content mismatch, so do the same. */ + bool discard = (flags & SECTION_CODE) + || lookup_attribute ("selectany", + DECL_ATTRIBUTES (decl)); fprintf (asm_out_file, "\t.linkonce %s\n", - (flags & SECTION_CODE ? "discard" : "same_size")); + (discard ? "discard" : "same_size")); } } @@ -764,13 +637,14 @@ i386_pe_declare_function_type (FILE *file, const char *name, int public) /* Keep a list of external functions. */ -struct extern_list +struct extern_list GTY(()) { struct extern_list *next; + tree decl; const char *name; }; -static struct extern_list *extern_head; +static GTY(()) struct extern_list *extern_head; /* Assemble an external function reference. We need to keep a list of these, so that we can output the function types at the end of the @@ -779,26 +653,27 @@ static struct extern_list *extern_head; for it then. */ void -i386_pe_record_external_function (const char *name) +i386_pe_record_external_function (tree decl, const char *name) { struct extern_list *p; - p = (struct extern_list *) xmalloc (sizeof *p); + p = (struct extern_list *) ggc_alloc (sizeof *p); p->next = extern_head; + p->decl = decl; p->name = name; extern_head = p; } /* Keep a list of exported symbols. */ -struct export_list +struct export_list GTY(()) { struct export_list *next; const char *name; int is_data; /* used to type tag exported symbols. */ }; -static struct export_list *export_head; +static GTY(()) struct export_list *export_head; /* Assemble an export symbol entry. We need to keep a list of these, so that we can output the export list at the end of the @@ -811,7 +686,7 @@ i386_pe_record_exported_symbol (const char *name, int is_data) { struct export_list *p; - p = (struct export_list *) xmalloc (sizeof *p); + p = (struct export_list *) ggc_alloc (sizeof *p); p->next = export_head; p->name = name; p->is_data = is_data; @@ -833,10 +708,11 @@ i386_pe_file_end (void) { tree decl; - decl = get_identifier (p->name); + decl = p->decl; /* Positively ensure only one declaration for any given symbol. */ - if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl)) + if (! TREE_ASM_WRITTEN (decl) + && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) { TREE_ASM_WRITTEN (decl) = 1; i386_pe_declare_function_type (asm_out_file, p->name, @@ -856,3 +732,5 @@ i386_pe_file_end (void) } } } + +#include "gt-winnt.h" |