/* 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,
- 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GCC.
#include "tm_p.h"
#include "toplev.h"
#include "hashtab.h"
+#include "langhooks.h"
#include "ggc.h"
#include "target.h"
{
if (TREE_CODE (*node) != VAR_DECL)
{
- warning (OPT_Wattributes, "%qs attribute only applies to variables",
- IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute only applies to variables",
+ name);
*no_add_attrs = true;
}
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));
+ error ("%qE attribute applies only to initialized variables"
+ " with external linkage", name);
*no_add_attrs = true;
}
static bool
i386_pe_determine_dllexport_p (tree decl)
{
- tree assoc;
-
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
return false;
+ /* Don't export local clones of dllexports. */
+ if (!TREE_PUBLIC (decl))
+ return false;
+
if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
return true;
- /* Also mark class members of exported classes with dllexport. */
- assoc = associated_type (decl);
- if (assoc && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (assoc)))
- return i386_pe_type_dllexport_p (decl);
-
return false;
}
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
return false;
- /* 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))
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. */
+ error message if the class attribute has been overridden by an
+ out-of-class definition of static data. */
assoc = associated_type (decl);
- if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc)))
- return i386_pe_type_dllimport_p (decl);
+ if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc))
+ && TREE_CODE (decl) == VAR_DECL
+ && TREE_STATIC (decl) && TREE_PUBLIC (decl)
+ && !DECL_EXTERNAL (decl)
+ /* vtable's are linkonce constants, so defining a vtable is not
+ an error as long as we don't try to import it too. */
+ && !DECL_VIRTUAL_P (decl))
+ error ("definition of static data member %q+D of "
+ "dllimport'd class", decl);
return false;
}
HOST_WIDE_INT total = 0;
const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl));
char *new_str, *p;
- tree formal_type;
+ tree type = TREE_TYPE (decl);
+ tree arg;
+ function_args_iterator args_iter;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
- formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
- if (formal_type != NULL_TREE)
- while (1)
- {
- HOST_WIDE_INT parm_size;
- HOST_WIDE_INT parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT;
-
- /* We got to the end of the list without seeing void_list_node,
- which means the function is variadic. The suffix is to be
- ignored in that case. */
- if (formal_type == NULL_TREE)
- return NULL_TREE;
-
- /* End of arguments, non-varargs marker. */
- if (formal_type == void_list_node)
- break;
-
- /* Quit if we hit an incomplete type. Error is reported
- by convert_arguments in c-typeck.c or cp/typeck.c. */
- parm_size = int_size_in_bytes (TREE_VALUE (formal_type));
- if (parm_size < 0)
- break;
-
- /* Must round up to include padding. This is done the same
- way as in store_one_arg. */
- parm_size = ((parm_size + parm_boundary_bytes - 1)
- / parm_boundary_bytes * parm_boundary_bytes);
- total += parm_size;
-
- formal_type = TREE_CHAIN (formal_type);
+ if (prototype_p (type))
+ {
+ /* This attribute is ignored for variadic functions. */
+ if (stdarg_p (type))
+ return NULL_TREE;
+
+ /* Quit if we hit an incomplete type. Error is reported
+ by convert_arguments in c-typeck.c or cp/typeck.c. */
+ FOREACH_FUNCTION_ARGS(type, arg, args_iter)
+ {
+ HOST_WIDE_INT parm_size;
+ HOST_WIDE_INT parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT;
+
+ if (! COMPLETE_TYPE_P (arg))
+ break;
+
+ parm_size = int_size_in_bytes (arg);
+ if (parm_size < 0)
+ break;
+
+ /* Must round up to include padding. This is done the same
+ way as in store_one_arg. */
+ parm_size = ((parm_size + parm_boundary_bytes - 1)
+ / parm_boundary_bytes * parm_boundary_bytes);
+ total += parm_size;
+ }
}
/* Assume max of 8 base 10 digits in the suffix. */
- p = new_str = alloca (1 + strlen (old_str) + 1 + 8 + 1);
+ p = new_str = XALLOCAVEC (char, 1 + strlen (old_str) + 1 + 8 + 1);
if (fastcall)
*p++ = FASTCALL_PREFIX;
sprintf (p, "%s@" HOST_WIDE_INT_PRINT_DEC, old_str, total);
switch (TREE_CODE (decl))
{
case FUNCTION_DECL:
- if (first)
+ /* FIXME: Imported stdcall names are not modified by the Ada frontend.
+ Check and decorate the RTL name now. */
+ if (strcmp (lang_hooks.name, "GNU Ada") == 0)
{
- /* FIXME: In Ada, and perhaps other language frontends,
- imported stdcall names may not yet have been modified.
- Check and do it know. */
- tree new_id;
- tree old_id = DECL_ASSEMBLER_NAME (decl);
- const char* asm_str = IDENTIFIER_POINTER (old_id);
- /* Do not change the identifier if a verbatim asmspec
+ tree new_id;
+ tree old_id = DECL_ASSEMBLER_NAME (decl);
+ const char* asm_str = IDENTIFIER_POINTER (old_id);
+ /* Do not change the identifier if a verbatim asmspec
or if stdcall suffix already added. */
- if (*asm_str == '*' || strchr (asm_str, '@'))
- break;
- if ((new_id = i386_pe_maybe_mangle_decl_assembler_name (decl, old_id)))
- {
- /* 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 first. */
- change_decl_assembler_name (decl, new_id);
- XSTR (symbol, 0) = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- }
+ if (!(*asm_str == '*' || strchr (asm_str, '@'))
+ && (new_id = i386_pe_maybe_mangle_decl_assembler_name (decl,
+ old_id)))
+ XSTR (symbol, 0) = IDENTIFIER_POINTER (new_id);
}
break;
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);
+ make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
else
error ("%q+D:'selectany' attribute applies only to "
"initialized objects", decl);
if (i386_pe_determine_dllexport_p (decl))
flags |= SYMBOL_FLAG_DLLEXPORT;
else if (i386_pe_determine_dllimport_p (decl))
- {
- flags |= SYMBOL_FLAG_DLLIMPORT;
- /* If we went through the associated_type path, this won't already
- be set. Though, frankly, this seems wrong, and should be fixed
- elsewhere. */
- if (!DECL_DLLIMPORT_P (decl))
- {
- DECL_DLLIMPORT_P (decl) = 1;
- flags &= ~SYMBOL_FLAG_LOCAL;
- }
- }
+ flags |= SYMBOL_FLAG_DLLIMPORT;
+
SYMBOL_REF_FLAGS (symbol) = flags;
}
else
prefix = ".data$";
len = strlen (name) + strlen (prefix);
- string = alloca (len + 1);
+ string = XALLOCAVEC (char, len + 1);
sprintf (string, "%s%s", prefix, name);
DECL_SECTION_NAME (decl) = build_string (len, string);
flags = SECTION_CODE;
else if (decl && decl_readonly_section (decl, reloc))
flags = 0;
+ else if (current_function_decl
+ && cfun
+ && crtl->subsections.unlikely_text_section_name
+ && strcmp (name, crtl->subsections.unlikely_text_section_name) == 0)
+ flags = SECTION_CODE;
+ else if (!decl
+ && (!current_function_decl || !cfun)
+ && strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
+ flags = SECTION_CODE;
else
{
flags = SECTION_WRITE;
{
HOST_WIDE_INT rounded;
- /* Compute as in assemble_noswitch_variable, since we don't actually
- support aligned common. */
+ /* Compute as in assemble_noswitch_variable, since we don't have
+ support for aligned common on older binutils. We must also
+ avoid emitting a common symbol of size zero, as this is the
+ overloaded representation that indicates an undefined external
+ symbol in the PE object file format. */
rounded = size ? size : 1;
rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
fprintf (stream, "\t.comm\t");
assemble_name (stream, name);
- fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START
- " " HOST_WIDE_INT_PRINT_DEC "\n",
- rounded, size);
+ if (use_pe_aligned_common)
+ fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC ", %d\n",
+ size ? size : (HOST_WIDE_INT) 1,
+ exact_log2 (align) - exact_log2 (CHAR_BIT));
+ else
+ fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START
+ " " HOST_WIDE_INT_PRINT_DEC "\n", rounded, size);
}
\f
/* The Microsoft linker requires that every function be marked as
/* Mark a function appropriately. This should only be called for
functions for which we are not emitting COFF debugging information.
FILE is the assembler output file, NAME is the name of the
- function, and PUBLIC is nonzero if the function is globally
+ function, and PUB is nonzero if the function is globally
visible. */
void
-i386_pe_declare_function_type (FILE *file, const char *name, int public)
+i386_pe_declare_function_type (FILE *file, const char *name, int pub)
{
fprintf (file, "\t.def\t");
assemble_name (file, name);
fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
- public ? (int) C_EXT : (int) C_STAT,
+ pub ? (int) C_EXT : (int) C_STAT,
(int) DT_FCN << N_BTSHFT);
}
/* Keep a list of external functions. */
-struct extern_list GTY(())
+struct GTY(()) extern_list
{
struct extern_list *next;
tree decl;
/* Keep a list of exported symbols. */
-struct export_list GTY(())
+struct GTY(()) export_list
{
struct export_list *next;
const char *name;
if (!SYMBOL_REF_DLLEXPORT_P (symbol))
return;
+ gcc_assert (TREE_PUBLIC (decl));
+
p = (struct export_list *) ggc_alloc (sizeof *p);
p->next = export_head;
p->name = name;
export_head = p;
}
+#ifdef CXX_WRAP_SPEC_LIST
+
+/* Hash table equality helper function. */
+
+static int
+wrapper_strcmp (const void *x, const void *y)
+{
+ return !strcmp ((const char *) x, (const char *) y);
+}
+
+/* Search for a function named TARGET in the list of library wrappers
+ we are using, returning a pointer to it if found or NULL if not.
+ This function might be called on quite a few symbols, and we only
+ have the list of names of wrapped functions available to us as a
+ spec string, so first time round we lazily initialise a hash table
+ to make things quicker. */
+
+static const char *
+i386_find_on_wrapper_list (const char *target)
+{
+ static char first_time = 1;
+ static htab_t wrappers;
+
+ if (first_time)
+ {
+ /* Beware that this is not a complicated parser, it assumes
+ that any sequence of non-whitespace beginning with an
+ underscore is one of the wrapped symbols. For now that's
+ adequate to distinguish symbols from spec substitutions
+ and command-line options. */
+ static char wrapper_list_buffer[] = CXX_WRAP_SPEC_LIST;
+ char *bufptr;
+ /* Breaks up the char array into separated strings
+ strings and enter them into the hash table. */
+ wrappers = htab_create_alloc (8, htab_hash_string, wrapper_strcmp,
+ 0, xcalloc, free);
+ for (bufptr = wrapper_list_buffer; *bufptr; ++bufptr)
+ {
+ char *found = NULL;
+ if (ISSPACE (*bufptr))
+ continue;
+ if (*bufptr == '_')
+ found = bufptr;
+ while (*bufptr && !ISSPACE (*bufptr))
+ ++bufptr;
+ if (*bufptr)
+ *bufptr = 0;
+ if (found)
+ *htab_find_slot (wrappers, found, INSERT) = found;
+ }
+ first_time = 0;
+ }
+
+ return (const char *) htab_find (wrappers, target);
+}
+
+#endif /* CXX_WRAP_SPEC_LIST */
+
/* This is called at the end of assembly. For each external function
which has not been defined, we output a declaration now. We also
output the .drectve section. */
if (! TREE_ASM_WRITTEN (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
{
+#ifdef CXX_WRAP_SPEC_LIST
+ /* To ensure the DLL that provides the corresponding real
+ functions is still loaded at runtime, we must reference
+ the real function so that an (unused) import is created. */
+ const char *realsym = i386_find_on_wrapper_list (p->name);
+ if (realsym)
+ i386_pe_declare_function_type (asm_out_file,
+ concat ("__real_", realsym, NULL), TREE_PUBLIC (decl));
+#endif /* CXX_WRAP_SPEC_LIST */
TREE_ASM_WRITTEN (decl) = 1;
i386_pe_declare_function_type (asm_out_file, p->name,
TREE_PUBLIC (decl));