aboutsummaryrefslogtreecommitdiff
path: root/contrib/gcc/config/i386/winnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/config/i386/winnt.c')
-rw-r--r--contrib/gcc/config/i386/winnt.c297
1 files changed, 187 insertions, 110 deletions
diff --git a/contrib/gcc/config/i386/winnt.c b/contrib/gcc/config/i386/winnt.c
index 24d8617f8dfa..9d955df2f48e 100644
--- a/contrib/gcc/config/i386/winnt.c
+++ b/contrib/gcc/config/i386/winnt.c
@@ -1,6 +1,6 @@
/* Subroutines for insn-output.c for Windows NT.
Contributed by Douglas Rupp (drupp@cs.washington.edu)
- Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -27,6 +27,9 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "tree.h"
#include "flags.h"
+#include "tm_p.h"
+#include "toplev.h"
+#include "hashtab.h"
/* i386/PE specific attribute support.
@@ -39,102 +42,61 @@ Boston, MA 02111-1307, USA. */
multiple times.
*/
-/* Return nonzero if ATTR is a valid attribute for DECL.
- ATTRIBUTES are any existing attributes and ARGS are the arguments
- supplied with ATTR. */
+static tree associated_type PARAMS ((tree));
+const char * gen_stdcall_suffix PARAMS ((tree));
+int i386_pe_dllexport_p PARAMS ((tree));
+int i386_pe_dllimport_p PARAMS ((tree));
+void i386_pe_mark_dllexport PARAMS ((tree));
+void i386_pe_mark_dllimport PARAMS ((tree));
-int
-i386_pe_valid_decl_attribute_p (decl, attributes, attr, args)
- tree decl;
- tree attributes;
- tree attr;
- tree args;
-{
- if (args == NULL_TREE)
- {
- if (is_attribute_p ("dllexport", attr))
- return 1;
- if (is_attribute_p ("dllimport", attr))
- return 1;
- }
-
- return i386_valid_decl_attribute_p (decl, attributes, attr, args);
-}
-
-/* Return nonzero if ATTR is a valid attribute for TYPE.
- ATTRIBUTES are any existing attributes and ARGS are the arguments
- supplied with ATTR. */
-
-int
-i386_pe_valid_type_attribute_p (type, attributes, attr, args)
- tree type;
- tree attributes;
- tree attr;
+/* Handle a "dllimport" or "dllexport" attribute;
+ arguments as in struct attribute_spec.handler. */
+tree
+ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
tree args;
+ int flags;
+ bool *no_add_attrs;
{
- if (args == NULL_TREE
- && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
+ /* These attributes may apply to structure and union types being created,
+ but otherwise should pass to the declaration involved. */
+ if (!DECL_P (*node))
{
- if (is_attribute_p ("dllexport", attr))
- return 1;
- if (is_attribute_p ("dllimport", attr))
- return 1;
+ 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 i386_valid_type_attribute_p (type, attributes, attr, args);
+ return NULL_TREE;
}
-/* Merge attributes in decls OLD and NEW.
-
- This handles the following situation:
-
- __declspec (dllimport) int foo;
- int foo;
-
- The second instance of `foo' nullifies the dllimport. */
-
+/* Handle a "shared" attribute;
+ arguments as in struct attribute_spec.handler. */
tree
-i386_pe_merge_decl_attributes (old, new)
- tree old, new;
+ix86_handle_shared_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
{
- tree a;
- int delete_dllimport_p;
-
- old = DECL_MACHINE_ATTRIBUTES (old);
- new = DECL_MACHINE_ATTRIBUTES (new);
-
- /* What we need to do here is remove from `old' dllimport if it doesn't
- appear in `new'. dllimport behaves like extern: if a declaration is
- marked dllimport and a definition appears later, then the object
- is not dllimport'd. */
-
- if (lookup_attribute ("dllimport", old) != NULL_TREE
- && lookup_attribute ("dllimport", new) == NULL_TREE)
- delete_dllimport_p = 1;
- else
- delete_dllimport_p = 0;
-
- a = merge_attributes (old, new);
-
- if (delete_dllimport_p)
+ if (TREE_CODE (*node) != VAR_DECL)
{
- tree prev,t;
-
- /* Scan the list for dllimport and delete it. */
- for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
- {
- if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
- {
- if (prev == NULL_TREE)
- a = TREE_CHAIN (a);
- else
- TREE_CHAIN (prev) = TREE_CHAIN (t);
- break;
- }
- }
+ warning ("`%s' attribute only applies to variables",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
}
- return a;
+ return NULL_TREE;
}
/* Return the type that we should use to determine if DECL is
@@ -173,7 +135,7 @@ i386_pe_dllexport_p (decl)
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
- exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl));
+ exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
if (exp)
return 1;
@@ -204,7 +166,7 @@ i386_pe_dllimport_p (decl)
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
- imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl));
+ imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
if (imp)
return 1;
@@ -224,7 +186,7 @@ i386_pe_dllimport_p (decl)
int
i386_pe_dllexport_name_p (symbol)
- char *symbol;
+ const char *symbol;
{
return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.';
}
@@ -233,7 +195,7 @@ i386_pe_dllexport_name_p (symbol)
int
i386_pe_dllimport_name_p (symbol)
- char *symbol;
+ const char *symbol;
{
return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.';
}
@@ -245,7 +207,8 @@ void
i386_pe_mark_dllexport (decl)
tree decl;
{
- char *oldname, *newname;
+ const char *oldname;
+ char *newname;
rtx rtlname;
tree idp;
@@ -281,7 +244,8 @@ void
i386_pe_mark_dllimport (decl)
tree decl;
{
- char *oldname, *newname;
+ const char *oldname;
+ char *newname;
tree idp;
rtx rtlname, newrtl;
@@ -295,7 +259,7 @@ i386_pe_mark_dllimport (decl)
abort ();
if (i386_pe_dllexport_name_p (oldname))
{
- error ("`%s' declared as both exported to and imported from a DLL.",
+ error ("`%s' declared as both exported to and imported from a DLL",
IDENTIFIER_POINTER (DECL_NAME (decl)));
return;
}
@@ -368,14 +332,14 @@ i386_pe_mark_dllimport (decl)
suffix consisting of an atsign (@) followed by the number of bytes of
arguments */
-char *
+const char *
gen_stdcall_suffix (decl)
tree decl;
{
int total = 0;
/* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
of DECL_ASSEMBLER_NAME. */
- char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
char *newsym;
if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
@@ -442,7 +406,7 @@ i386_pe_encode_section_info (decl)
&& 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)))
{
- char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
+ const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
tree idp = get_identifier (oldname + 9);
rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
@@ -463,7 +427,8 @@ i386_pe_unique_section (decl, reloc)
int reloc;
{
int len;
- char *name,*string,*prefix;
+ const char *name, *prefix;
+ char *string;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
/* Strip off any encoding in fnname. */
@@ -477,6 +442,9 @@ i386_pe_unique_section (decl, reloc)
without a .rdata section. */
if (TREE_CODE (decl) == FUNCTION_DECL)
prefix = ".text$";
+/* else if (DECL_INITIAL (decl) == 0
+ || DECL_INITIAL (decl) == error_mark_node)
+ prefix = ".bss"; */
else if (DECL_READONLY_SECTION (decl, reloc))
#ifdef READONLY_DATA_SECTION
prefix = ".rdata$";
@@ -491,6 +459,98 @@ i386_pe_unique_section (decl, reloc)
DECL_SECTION_NAME (decl) = build_string (len, string);
}
+
+/* Select a set of attributes for section NAME based on the properties
+ of DECL and whether or not RELOC indicates that DECL's initializer
+ might contain runtime relocations.
+
+ We make the section read-only and executable for a function decl,
+ read-only for a const data decl, and writable for a non-const data decl.
+
+ If the section has already been defined, to not allow it to have
+ different attributes, as (1) this is ambiguous since we're not seeing
+ all the declarations up front and (2) some assemblers (e.g. SVR4)
+ do not recoginize section redefinitions. */
+/* ??? This differs from the "standard" PE implementation in that we
+ handle the SHARED variable attribute. Should this be done for all
+ PE targets? */
+
+#define SECTION_PE_SHARED SECTION_MACH_DEP
+
+unsigned int
+i386_pe_section_type_flags (decl, name, reloc)
+ tree decl;
+ const char *name;
+ int reloc;
+{
+ static htab_t htab;
+ unsigned int flags;
+ 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
+ their addresses as the keys. */
+ if (!htab)
+ htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL);
+
+ if (decl && TREE_CODE (decl) == FUNCTION_DECL)
+ flags = SECTION_CODE;
+ else if (decl && DECL_READONLY_SECTION (decl, reloc))
+ flags = 0;
+ else
+ {
+ flags = SECTION_WRITE;
+
+ if (decl && TREE_CODE (decl) == VAR_DECL
+ && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
+ flags |= SECTION_PE_SHARED;
+ }
+
+ if (decl && DECL_ONE_ONLY (decl))
+ flags |= SECTION_LINKONCE;
+
+ /* See if we already have an entry for this section. */
+ slot = (unsigned int **) htab_find_slot (htab, name, INSERT);
+ if (!*slot)
+ {
+ *slot = (unsigned int *) xmalloc (sizeof (unsigned int));
+ **slot = flags;
+ }
+ else
+ {
+ if (decl && **slot != flags)
+ error_with_decl (decl, "%s causes a section type conflict");
+ }
+
+ return flags;
+}
+
+void
+i386_pe_asm_named_section (name, flags)
+ const char *name;
+ unsigned int flags;
+{
+ char flagchars[8], *f = flagchars;
+
+ if (flags & SECTION_CODE)
+ *f++ = 'x';
+ if (flags & SECTION_WRITE)
+ *f++ = 'w';
+ if (flags & SECTION_PE_SHARED)
+ *f++ = 's';
+ *f = '\0';
+
+ fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
+
+ 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. */
+ fprintf (asm_out_file, "\t.linkonce %s\n",
+ (flags & SECTION_CODE ? "discard" : "same_size"));
+ }
+}
/* The Microsoft linker requires that every function be marked as
DT_FCN. When using gas on cygwin, we must emit appropriate .type
@@ -507,7 +567,7 @@ i386_pe_unique_section (decl, reloc)
void
i386_pe_declare_function_type (file, name, public)
FILE *file;
- char *name;
+ const char *name;
int public;
{
fprintf (file, "\t.def\t");
@@ -522,7 +582,7 @@ i386_pe_declare_function_type (file, name, public)
struct extern_list
{
struct extern_list *next;
- char *name;
+ const char *name;
};
static struct extern_list *extern_head;
@@ -535,7 +595,7 @@ static struct extern_list *extern_head;
void
i386_pe_record_external_function (name)
- char *name;
+ const char *name;
{
struct extern_list *p;
@@ -545,7 +605,16 @@ i386_pe_record_external_function (name)
extern_head = p;
}
-static struct extern_list *exports_head;
+/* Keep a list of exported symbols. */
+
+struct export_list
+{
+ struct export_list *next;
+ const char *name;
+ int is_data; /* used to type tag exported symbols. */
+};
+
+static 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
@@ -554,15 +623,17 @@ static struct extern_list *exports_head;
linkonce. */
void
-i386_pe_record_exported_symbol (name)
- char *name;
+i386_pe_record_exported_symbol (name, is_data)
+ const char *name;
+ int is_data;
{
- struct extern_list *p;
+ struct export_list *p;
- p = (struct extern_list *) permalloc (sizeof *p);
- p->next = exports_head;
+ p = (struct export_list *) permalloc (sizeof *p);
+ p->next = export_head;
p->name = name;
- exports_head = p;
+ p->is_data = is_data;
+ export_head = p;
}
/* This is called at the end of assembly. For each external function
@@ -575,6 +646,8 @@ i386_pe_asm_file_end (file)
{
struct extern_list *p;
+ ix86_asm_file_end (file);
+
for (p = extern_head; p != NULL; p = p->next)
{
tree decl;
@@ -589,12 +662,16 @@ i386_pe_asm_file_end (file)
}
}
- if (exports_head)
- drectve_section ();
- for (p = exports_head; p != NULL; p = p->next)
+ if (export_head)
{
- fprintf (file, "\t.ascii \" -export:%s\"\n",
- I386_PE_STRIP_ENCODING (p->name));
+ struct export_list *q;
+ drectve_section ();
+ for (q = export_head; q != NULL; q = q->next)
+ {
+ fprintf (file, "\t.ascii \" -export:%s%s\"\n",
+ I386_PE_STRIP_ENCODING (q->name),
+ (q->is_data) ? ",data" : "");
+ }
}
}