aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2007-03-29 14:54:35 -0700
committerRichard Henderson <rth@gcc.gnu.org>2007-03-29 14:54:35 -0700
commitda489f7340623783872629a4ebd595d93fc3dced (patch)
treeeb98f4ede31001adc419d6556b98962ff353afb5 /gcc/config
parent0c9bce0b5cfe0a037bdabd00cc783a37ff1f159c (diff)
downloadgcc-da489f7340623783872629a4ebd595d93fc3dced.zip
gcc-da489f7340623783872629a4ebd595d93fc3dced.tar.gz
gcc-da489f7340623783872629a4ebd595d93fc3dced.tar.bz2
varasm.c (initializer_constant_valid_p): Don't deny DECL_DLLIMPORT_P on functions.
* varasm.c (initializer_constant_valid_p): Don't deny DECL_DLLIMPORT_P on functions. * config/i386/cygming.h: Remove function declarations. (SUBTARGET_ENCODE_SECTION_INFO): Don't undef first. (ASM_OUTPUT_LABELREF): Remove. (COMMON_ASM_OP): Remove. (ASM_OUTPUT_COMMON): Remove. (ASM_OUTPUT_ALIGNED_DECL_COMMON): New. (ASM_DECLARE_OBJECT_NAME): Use i386_pe_maybe_record_exported_symbol. (ASM_DECLARE_FUNCTION_NAME): Likewise. * config/i386/i386-interix.h (SUBTARGET_ENCODE_SECTION_INFO): Rename from TARGET_ENCODE_SECTION_INFO. * config/i386/netware.h: Likewise. * config/i386/i386-protos.h: Update. * config/i386/i386.c (ix86_function_ok_for_sibcall): Turn ifdef of TARGET_DLLIMPORT_DECL_ATTRIBUTES into straight if. (legitimate_constant_p): Reject dllimports. (dllimport_map, get_dllimport_decl): New. (legitimize_dllimport_symbol): New. (legitimize_address, ix86_expand_move): Use it. (TARGET_BINDS_LOCAL_P): Redefine for TARGET_DLLIMPORT_DECL_ATTRIBUTES. * config/i386/i386.h (DLL_IMPORT_EXPORT_PREFIX): Remove. (SYMBOL_FLAG_DLLIMPORT, SYMBOL_REF_DLLIMPORT_P): New. (SYMBOL_FLAG_DLLEXPORT, SYMBOL_REF_DLLEXPORT_P): New. * config/i386/predicates.md (constant_call_address_operand): Only accept symbols; reject dllimport_p symbols. * config/i386/uwin.h (ASM_DECLARE_FUNCTION_NAME): Use i386_pe_maybe_record_exported_symbol. * config/i386/winnt.c (DLL_IMPORT_PREFIX, DLL_EXPORT_PREFIX): Remove. (i386_pe_determine_dllexport_p): Rename from i386_pe_dllexport_p. (i386_pe_determine_dllimport_p): Rename from i386_pe_dllimport_p; trust the setting of DECL_DLLIMPORT_P. (i386_pe_dllexport_name_p, i386_pe_dllimport_name_p): Remove. (i386_pe_mark_dllexport, i386_pe_mark_dllimport): Remove. (gen_stdcall_or_fastcall_suffix): Return NULL if no change required; tidy the argument scanning loop. (i386_pe_encode_section_info): Set SYMBOL_FLAG_DLLIMPORT and SYMBOL_FLAG_DLLEXPORT in SYMBOL_REF_FLAGS. (i386_pe_strip_name_encoding): Remove. (i386_pe_binds_local_p): New. (i386_pe_strip_name_encoding_full): Use default_strip_name_encoding. (i386_pe_output_labelref): Remove. (i386_pe_asm_output_aligned_decl_common): New. (i386_pe_maybe_record_exported_symbol): Rename from i386_pe_record_exported_symbol; check for dllexported symbols. From-SVN: r123344
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/cygming.h43
-rw-r--r--gcc/config/i386/i386-interix.h3
-rw-r--r--gcc/config/i386/i386-protos.h17
-rw-r--r--gcc/config/i386/i386.c135
-rw-r--r--gcc/config/i386/i386.h13
-rw-r--r--gcc/config/i386/netware.h3
-rw-r--r--gcc/config/i386/predicates.md11
-rw-r--r--gcc/config/i386/uwin.h3
-rw-r--r--gcc/config/i386/winnt.c466
9 files changed, 335 insertions, 359 deletions
diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index 9b0cd7f..aa4ca2a 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -148,39 +148,20 @@ do { \
section and we need to set DECL_SECTION_NAME so we do that here.
Note that we can be called twice on the same decl. */
-#undef SUBTARGET_ENCODE_SECTION_INFO
#define SUBTARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
#undef TARGET_STRIP_NAME_ENCODING
#define TARGET_STRIP_NAME_ENCODING i386_pe_strip_name_encoding_full
-
-/* Output a reference to a label. */
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF i386_pe_output_labelref
-
-#undef COMMON_ASM_OP
-#define COMMON_ASM_OP "\t.comm\t"
/* Output a common block. */
-#undef ASM_OUTPUT_COMMON
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
-do { \
- if (i386_pe_dllexport_name_p (NAME)) \
- i386_pe_record_exported_symbol (NAME, 1); \
- if (! i386_pe_dllimport_name_p (NAME)) \
- { \
- fprintf ((STREAM), "\t.comm\t"); \
- assemble_name ((STREAM), (NAME)); \
- fprintf ((STREAM), ", %d\t%s %d\n", \
- (int)(ROUNDED), ASM_COMMENT_START, (int)(SIZE)); \
- } \
-} while (0)
+#undef ASM_OUTPUT_ALIGNED_DECL_COMMON
+#define ASM_OUTPUT_ALIGNED_DECL_COMMON \
+ i386_pe_asm_output_aligned_decl_common
/* Output the label for an initialized variable. */
#undef ASM_DECLARE_OBJECT_NAME
#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
do { \
- if (i386_pe_dllexport_name_p (NAME)) \
- i386_pe_record_exported_symbol (NAME, 1); \
+ i386_pe_maybe_record_exported_symbol (DECL, NAME, 1); \
ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
} while (0)
@@ -210,7 +191,6 @@ do { \
/* Windows uses explicit import from shared libraries. */
#define MULTIPLE_SYMBOL_SPACES 1
-extern void i386_pe_unique_section (TREE, int);
#define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section
#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
@@ -229,8 +209,7 @@ extern void i386_pe_unique_section (TREE, int);
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do \
{ \
- if (i386_pe_dllexport_name_p (NAME)) \
- i386_pe_record_exported_symbol (NAME, 0); \
+ i386_pe_maybe_record_exported_symbol (DECL, NAME, 0); \
if (write_symbols != SDB_DEBUG) \
i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL)); \
ASM_OUTPUT_LABEL (FILE, NAME); \
@@ -289,15 +268,6 @@ extern void i386_pe_unique_section (TREE, int);
build_tree_list (get_identifier ("stdcall"), \
NULL))
-/* External function declarations. */
-
-extern void i386_pe_record_external_function (tree, const char *);
-extern void i386_pe_declare_function_type (FILE *, const char *, int);
-extern void i386_pe_record_exported_symbol (const char *, int);
-extern void i386_pe_file_end (void);
-extern int i386_pe_dllexport_name_p (const char *);
-extern int i386_pe_dllimport_name_p (const char *);
-
/* For Win32 ABI compatibility */
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 0
@@ -315,10 +285,10 @@ extern int i386_pe_dllimport_name_p (const char *);
machine. Use this macro to limit the alignment which can be
specified using the `__attribute__ ((aligned (N)))' construct. If
not defined, the default value is `BIGGEST_ALIGNMENT'. */
-#undef MAX_OFILE_ALIGNMENT
/* IMAGE_SCN_ALIGN_8192BYTES is the largest section alignment flag
specified in the PECOFF60 spec. Native MS compiler also limits
user-specified alignment to 8192 bytes. */
+#undef MAX_OFILE_ALIGNMENT
#define MAX_OFILE_ALIGNMENT (8192 * 8)
/* Native complier aligns internal doubles in structures on dword boundaries. */
@@ -334,6 +304,7 @@ extern int i386_pe_dllimport_name_p (const char *);
#ifndef SET_ASM_OP
#define SET_ASM_OP "\t.set\t"
#endif
+
/* This implements the `alias' attribute, keeping any stdcall or
fastcall decoration. */
#undef ASM_OUTPUT_DEF_FROM_DECLS
diff --git a/gcc/config/i386/i386-interix.h b/gcc/config/i386/i386-interix.h
index 5e9f7da..fa75376 100644
--- a/gcc/config/i386/i386-interix.h
+++ b/gcc/config/i386/i386-interix.h
@@ -326,8 +326,7 @@ while (0)
differently depending on something about the variable or
function named by the symbol (such as what section it is in). */
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
+#define SUBTARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
#undef TARGET_STRIP_NAME_ENCODING
#define TARGET_STRIP_NAME_ENCODING i386_pe_strip_name_encoding_full
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index aad4724..a379011 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -191,9 +191,6 @@ extern int ix86_local_alignment (tree, int);
extern int ix86_constant_alignment (tree, int);
extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *);
-
-extern unsigned int i386_pe_section_type_flags (tree, const char *, int);
-extern void i386_pe_asm_named_section (const char *, unsigned int, tree);
extern int x86_field_alignment (tree, int);
#endif
@@ -206,18 +203,22 @@ extern void ix86_expand_vector_extract (bool, rtx, rtx, int);
extern void ix86_expand_reduc_v4sf (rtx (*)(rtx, rtx, rtx), rtx, rtx);
/* In winnt.c */
-extern int i386_pe_dllexport_name_p (const char *);
-extern int i386_pe_dllimport_name_p (const char *);
extern void i386_pe_unique_section (tree, int);
extern void i386_pe_declare_function_type (FILE *, const char *, int);
extern void i386_pe_record_external_function (tree, const char *);
-extern void i386_pe_record_exported_symbol (const char *, int);
+extern void i386_pe_maybe_record_exported_symbol (tree, const char *, int);
extern void i386_pe_asm_file_end (FILE *);
extern void i386_pe_encode_section_info (tree, rtx, int);
-extern const char *i386_pe_strip_name_encoding (const char *);
+extern bool i386_pe_binds_local_p (tree);
extern const char *i386_pe_strip_name_encoding_full (const char *);
-extern void i386_pe_output_labelref (FILE *, const char *);
extern bool i386_pe_valid_dllimport_attribute_p (tree);
+extern unsigned int i386_pe_section_type_flags (tree, const char *, int);
+extern void i386_pe_asm_named_section (const char *, unsigned int, tree);
+extern void i386_pe_asm_output_aligned_decl_common (FILE *, tree,
+ const char *,
+ HOST_WIDE_INT,
+ HOST_WIDE_INT);
+extern void i386_pe_file_end (void);
/* In winnt-cxx.c and winnt-stubs.c */
extern void i386_pe_adjust_class_at_definition (tree);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 40ffcc8..ed25402 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2569,12 +2569,11 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
}
}
-#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
/* Dllimport'd functions are also called indirectly. */
- if (decl && DECL_DLLIMPORT_P (decl)
+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && decl && DECL_DLLIMPORT_P (decl)
&& ix86_function_regparm (TREE_TYPE (decl), NULL) >= 3)
return false;
-#endif
/* If we forced aligned the stack, then sibcalling would unalign the
stack, which may break the called function. */
@@ -6332,6 +6331,11 @@ legitimate_constant_p (rtx x)
/* TLS symbols are never valid. */
if (SYMBOL_REF_TLS_MODEL (x))
return false;
+
+ /* DLLIMPORT symbols are never valid. */
+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && SYMBOL_REF_DLLIMPORT_P (x))
+ return false;
break;
case CONST_DOUBLE:
@@ -7189,6 +7193,90 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
return dest;
}
+/* Create or return the unique __imp_DECL dllimport symbol corresponding
+ to symbol DECL. */
+
+static GTY((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
+ htab_t dllimport_map;
+
+static tree
+get_dllimport_decl (tree decl)
+{
+ struct tree_map *h, in;
+ void **loc;
+ const char *name;
+ const char *prefix;
+ size_t namelen, prefixlen;
+ char *imp_name;
+ tree to;
+ rtx rtl;
+
+ if (!dllimport_map)
+ dllimport_map = htab_create_ggc (512, tree_map_hash, tree_map_eq, 0);
+
+ in.hash = htab_hash_pointer (decl);
+ in.base.from = decl;
+ loc = htab_find_slot_with_hash (dllimport_map, &in, in.hash, INSERT);
+ h = *loc;
+ if (h)
+ return h->to;
+
+ *loc = h = ggc_alloc (sizeof (struct tree_map));
+ h->hash = in.hash;
+ h->base.from = decl;
+ h->to = to = build_decl (VAR_DECL, NULL, ptr_type_node);
+ DECL_ARTIFICIAL (to) = 1;
+ DECL_IGNORED_P (to) = 1;
+ DECL_EXTERNAL (to) = 1;
+ TREE_READONLY (to) = 1;
+
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ name = targetm.strip_name_encoding (name);
+ if (name[0] == FASTCALL_PREFIX)
+ {
+ name++;
+ prefix = "*__imp_";
+ }
+ else
+ prefix = "*__imp__";
+
+ namelen = strlen (name);
+ prefixlen = strlen (prefix);
+ imp_name = alloca (namelen + prefixlen + 1);
+ memcpy (imp_name, prefix, prefixlen);
+ memcpy (imp_name + prefixlen, name, namelen + 1);
+
+ name = ggc_alloc_string (imp_name, namelen + prefixlen);
+ rtl = gen_rtx_SYMBOL_REF (Pmode, name);
+ SET_SYMBOL_REF_DECL (rtl, to);
+ SYMBOL_REF_FLAGS (rtl) = SYMBOL_FLAG_LOCAL;
+
+ rtl = gen_const_mem (Pmode, rtl);
+ set_mem_alias_set (rtl, ix86_GOT_alias_set ());
+
+ SET_DECL_RTL (to, rtl);
+
+ return to;
+}
+
+/* Expand SYMBOL into its corresponding dllimport symbol. WANT_REG is
+ true if we require the result be a register. */
+
+static rtx
+legitimize_dllimport_symbol (rtx symbol, bool want_reg)
+{
+ tree imp_decl;
+ rtx x;
+
+ gcc_assert (SYMBOL_REF_DECL (symbol));
+ imp_decl = get_dllimport_decl (SYMBOL_REF_DECL (symbol));
+
+ x = DECL_RTL (imp_decl);
+ if (want_reg)
+ x = force_reg (Pmode, x);
+ return x;
+}
+
/* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address.
This macro is used in only one place: `memory_address' in explow.c.
@@ -7231,6 +7319,20 @@ legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
if (flag_pic && SYMBOLIC_CONST (x))
return legitimize_pic_address (x, 0);
+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES)
+ {
+ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_DLLIMPORT_P (x))
+ return legitimize_dllimport_symbol (x, true);
+ if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+ && SYMBOL_REF_DLLIMPORT_P (XEXP (XEXP (x, 0), 0)))
+ {
+ rtx t = legitimize_dllimport_symbol (XEXP (XEXP (x, 0), 0), true);
+ return gen_rtx_PLUS (Pmode, t, XEXP (XEXP (x, 0), 1));
+ }
+ }
+
/* Canonicalize shifts by 0, 1, 2, 3 into multiply */
if (GET_CODE (x) == ASHIFT
&& CONST_INT_P (XEXP (x, 1))
@@ -9236,20 +9338,31 @@ ix86_expand_move (enum machine_mode mode, rtx operands[])
if (op1 == op0)
return;
}
+ else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && SYMBOL_REF_DLLIMPORT_P (op1))
+ op1 = legitimize_dllimport_symbol (op1, false);
}
else if (GET_CODE (op1) == CONST
&& GET_CODE (XEXP (op1, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (op1, 0), 0)) == SYMBOL_REF)
{
- model = SYMBOL_REF_TLS_MODEL (XEXP (XEXP (op1, 0), 0));
+ rtx addend = XEXP (XEXP (op1, 0), 1);
+ rtx symbol = XEXP (XEXP (op1, 0), 0);
+ rtx tmp = NULL;
+
+ model = SYMBOL_REF_TLS_MODEL (symbol);
if (model)
+ tmp = legitimize_tls_address (symbol, model, true);
+ else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && SYMBOL_REF_DLLIMPORT_P (symbol))
+ tmp = legitimize_dllimport_symbol (symbol, true);
+
+ if (tmp)
{
- rtx addend = XEXP (XEXP (op1, 0), 1);
- op1 = legitimize_tls_address (XEXP (XEXP (op1, 0), 0), model, true);
- op1 = force_operand (op1, NULL);
- op1 = expand_simple_binop (Pmode, PLUS, op1, addend,
+ tmp = force_operand (tmp, NULL);
+ tmp = expand_simple_binop (Pmode, PLUS, tmp, addend,
op0, 1, OPTAB_DIRECT);
- if (op1 == op0)
+ if (tmp == op0)
return;
}
}
@@ -21648,6 +21761,10 @@ static const struct attribute_spec ix86_attribute_table[] =
#undef TARGET_BINDS_LOCAL_P
#define TARGET_BINDS_LOCAL_P darwin_binds_local_p
#endif
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
+#undef TARGET_BINDS_LOCAL_P
+#define TARGET_BINDS_LOCAL_P i386_pe_binds_local_p
+#endif
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 4c62ce5..045741b 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2347,8 +2347,6 @@ enum ix86_stack_slot
(! IN_RANGE ((SRC), FIRST_STACK_REG, LAST_STACK_REG))
-#define DLL_IMPORT_EXPORT_PREFIX '#'
-
#define FASTCALL_PREFIX '@'
struct machine_function GTY(())
@@ -2398,6 +2396,17 @@ struct machine_function GTY(())
#define SYMBOL_FLAG_FAR_ADDR (SYMBOL_FLAG_MACH_DEP << 0)
#define SYMBOL_REF_FAR_ADDR_P(X) \
((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_FAR_ADDR) != 0)
+
+/* Flags to mark dllimport/dllexport. Used by PE ports, but handy to
+ have defined always, to avoid ifdefing. */
+#define SYMBOL_FLAG_DLLIMPORT (SYMBOL_FLAG_MACH_DEP << 1)
+#define SYMBOL_REF_DLLIMPORT_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_DLLIMPORT) != 0)
+
+#define SYMBOL_FLAG_DLLEXPORT (SYMBOL_FLAG_MACH_DEP << 2)
+#define SYMBOL_REF_DLLEXPORT_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_DLLEXPORT) != 0)
+
/*
Local variables:
version-control: t
diff --git a/gcc/config/i386/netware.h b/gcc/config/i386/netware.h
index 3630765..ed3ab3c 100644
--- a/gcc/config/i386/netware.h
+++ b/gcc/config/i386/netware.h
@@ -150,7 +150,6 @@ Boston, MA 02110-1301, USA. */
the number of registers used, and an atsign (@). */
void i386_nlm_encode_section_info (tree, rtx, int);
const char *i386_nlm_strip_name_encoding (const char *);
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO i386_nlm_encode_section_info
+#define SUBTARGET_ENCODE_SECTION_INFO i386_nlm_encode_section_info
#undef TARGET_STRIP_NAME_ENCODING
#define TARGET_STRIP_NAME_ENCODING i386_nlm_strip_name_encoding
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 97deda6..efa5c98 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -484,9 +484,14 @@
;; Test for a pc-relative call operand
(define_predicate "constant_call_address_operand"
- (and (ior (match_code "symbol_ref")
- (match_operand 0 "local_symbolic_operand"))
- (match_test "ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC")))
+ (match_code "symbol_ref")
+{
+ if (ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
+ return false;
+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P (op))
+ return false;
+ return true;
+})
;; True for any non-virtual or eliminable register. Used in places where
;; instantiation of such a register may cause the pattern to not be recognized.
diff --git a/gcc/config/i386/uwin.h b/gcc/config/i386/uwin.h
index 38d218e..a87d1e7 100644
--- a/gcc/config/i386/uwin.h
+++ b/gcc/config/i386/uwin.h
@@ -77,8 +77,7 @@ Boston, MA 02110-1301, USA. */
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do \
{ \
- if (i386_pe_dllexport_name_p (NAME)) \
- i386_pe_record_exported_symbol (NAME, 0); \
+ i386_pe_maybe_record_exported_symbol (DECL, NAME, 0); \
/* UWIN binutils bug workaround. */ \
if (0 && write_symbols != SDB_DEBUG) \
i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL)); \
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index a46fc5b..a36fd08 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -34,6 +34,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "toplev.h"
#include "hashtab.h"
#include "ggc.h"
+#include "target.h"
/* i386/PE specific attribute support.
@@ -46,22 +47,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
multiple times.
*/
-static tree associated_type (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);
-
-/* This is we how mark internal identifiers with dllimport or dllexport
- attributes. */
-#ifndef DLL_IMPORT_PREFIX
-#define DLL_IMPORT_PREFIX "#i."
-#endif
-#ifndef DLL_EXPORT_PREFIX
-#define DLL_EXPORT_PREFIX "#e."
-#endif
-
/* Handle a "shared" attribute;
arguments as in struct attribute_spec.handler. */
tree
@@ -108,67 +93,59 @@ ix86_handle_selectany_attribute (tree *node, tree name,
static tree
associated_type (tree decl)
{
- return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
- ? DECL_CONTEXT (decl) : NULL_TREE;
+ return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))
+ ? DECL_CONTEXT (decl) : NULL_TREE);
}
-
-/* Return true if DECL is a dllexport'd object. */
+/* Return true if DECL should be a dllexport'd object. */
static bool
-i386_pe_dllexport_p (tree decl)
+i386_pe_determine_dllexport_p (tree decl)
{
- if (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
+ tree assoc;
+
+ if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
return false;
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))))
+ assoc = associated_type (decl);
+ if (assoc && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (assoc)))
return i386_pe_type_dllexport_p (decl);
return false;
}
+/* Return true if DECL should be a dllimport'd object. */
+
static bool
-i386_pe_dllimport_p (tree decl)
+i386_pe_determine_dllimport_p (tree decl)
{
- if (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
+ tree assoc;
+
+ 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)
- && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))
- {
- /* Make a final check to see if this is a definition before we generate
- RTL for an indirect reference. */
- if (!DECL_EXTERNAL (decl))
- {
- error ("%q+D: definition is marked as dllimport", decl);
- DECL_DLLIMPORT_P (decl) = 0;
- return false;
- }
- return true;
- }
+ 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. */
- else if (associated_type (decl)
- && lookup_attribute ("dllimport",
- TYPE_ATTRIBUTES (associated_type (decl))))
+ assoc = associated_type (decl);
+ if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc)))
return i386_pe_type_dllimport_p (decl);
return false;
}
/* Handle the -mno-fun-dllimport target switch. */
+
bool
i386_pe_valid_dllimport_attribute_p (tree decl)
{
@@ -177,247 +154,157 @@ i386_pe_valid_dllimport_attribute_p (tree decl)
return true;
}
-/* Return nonzero if SYMBOL is marked as being dllexport'd. */
-
-int
-i386_pe_dllexport_name_p (const char *symbol)
-{
- return (strncmp (DLL_EXPORT_PREFIX, symbol,
- strlen (DLL_EXPORT_PREFIX)) == 0);
-}
-
-/* Return nonzero if SYMBOL is marked as being dllimport'd. */
-
-int
-i386_pe_dllimport_name_p (const char *symbol)
-{
- return (strncmp (DLL_IMPORT_PREFIX, symbol,
- strlen (DLL_IMPORT_PREFIX)) == 0);
-}
-
-/* Mark a DECL as being dllexport'd.
- Note that we override the previous setting (e.g.: dllimport). */
-
-static void
-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) == MEM)
- rtlname = XEXP (rtlname, 0);
- gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
- oldname = XSTR (rtlname, 0);
- if (i386_pe_dllimport_name_p (oldname))
- {
- warning (0, "inconsistent dll linkage for %q+D, dllexport assumed",
- decl);
- /* Remove DLL_IMPORT_PREFIX. */
- oldname += strlen (DLL_IMPORT_PREFIX);
- }
- else if (i386_pe_dllexport_name_p (oldname))
- return; /* already done */
-
- newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
- sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
-
- /* We pass newname through get_identifier to ensure it has a unique
- address. RTL processing can sometimes peek inside the symbol ref
- and compare the string's addresses to see if two symbols are
- identical. */
- idp = get_identifier (newname);
-
- 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. */
-
-static void
-i386_pe_mark_dllimport (tree decl)
-{
- const char *oldname;
- char *newname;
- tree idp;
- rtx rtlname, newrtl;
- rtx symref;
-
- rtlname = XEXP (DECL_RTL (decl), 0);
- 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 ("%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. */
- gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)
- && DECL_DLLIMPORT_P (decl));
- return;
- }
-
- newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
- sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
-
- /* We pass newname through get_identifier to ensure it has a unique
- address. RTL processing can sometimes peek inside the symbol ref
- and compare the string's addresses to see if two symbols are
- identical. */
- idp = get_identifier (newname);
-
- 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;
-
- 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. If FASTCALL is true, also add the FASTCALL_PREFIX. */
+ arguments. If FASTCALL is true, also add the FASTCALL_PREFIX.
+ Return NULL if no change required. */
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));
- char *newsym;
- char *p;
+ HOST_WIDE_INT total = 0;
+ const char *asm_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ char *new_str, *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 (*asm_str == '*' || strchr (asm_str, '@'))
+ return NULL_TREE;
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);\
- }
- }
+ 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);
+ }
/* Assume max of 8 base 10 digits in the suffix. */
- newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1);
- p = newsym;
+ p = new_str = alloca (1 + strlen (asm_str) + 1 + 8 + 1);
if (fastcall)
*p++ = FASTCALL_PREFIX;
- sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT);
- return get_identifier (newsym);
+ sprintf (p, "%s@" HOST_WIDE_INT_PRINT_DEC, asm_str, total);
+
+ return get_identifier (new_str);
}
void
i386_pe_encode_section_info (tree decl, rtx rtl, int first)
{
+ rtx symbol;
+ int flags;
+
+ /* Do this last, due to our frobbing of DECL_DLLIMPORT_P above. */
default_encode_section_info (decl, rtl, first);
- if (first && TREE_CODE (decl) == FUNCTION_DECL)
+ /* Careful not to prod global register variables. */
+ if (!MEM_P (rtl))
+ return;
+
+ symbol = XEXP (rtl, 0);
+ gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
+
+ switch (TREE_CODE (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)
+ case FUNCTION_DECL:
+ if (first)
{
- 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);
+ 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)
+ {
+ XSTR (symbol, 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);
+ }
}
- }
+ break;
- else if (TREE_CODE (decl) == VAR_DECL
- && lookup_attribute ("selectany", DECL_ATTRIBUTES (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);
+ case VAR_DECL:
+ if (lookup_attribute ("selectany", DECL_ATTRIBUTES (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);
+ }
+ break;
+
+ default:
+ return;
}
/* Mark the decl so we can tell from the rtl whether the object is
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 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))));
+ flags = (SYMBOL_REF_FLAGS (symbol) &
+ ~(SYMBOL_FLAG_DLLIMPORT | SYMBOL_FLAG_DLLEXPORT));
+ 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;
+ }
+ }
+ SYMBOL_REF_FLAGS (symbol) = flags;
}
-/* Strip only the leading encoding, leaving the stdcall suffix and fastcall
- prefix if it exists. */
-
-const char *
-i386_pe_strip_name_encoding (const char *str)
+bool
+i386_pe_binds_local_p (tree exp)
{
- if (strncmp (str, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
- == 0)
- str += strlen (DLL_IMPORT_PREFIX);
- else if (strncmp (str, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
- == 0)
- str += strlen (DLL_EXPORT_PREFIX);
- if (*str == '*')
- str += 1;
- return str;
+ /* PE does not do dynamic binding. Indeed, the only kind of
+ non-local reference comes from a dllimport'd symbol. */
+ if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
+ && DECL_DLLIMPORT_P (exp))
+ return false;
+
+ return true;
}
/* Also strip the fastcall prefix and stdcall suffix. */
@@ -426,7 +313,7 @@ const char *
i386_pe_strip_name_encoding_full (const char *str)
{
const char *p;
- const char *name = i386_pe_strip_name_encoding (str);
+ const char *name = default_strip_name_encoding (str);
/* Strip leading '@' on fastcall symbols. */
if (*name == '@')
@@ -440,46 +327,6 @@ i386_pe_strip_name_encoding_full (const char *str)
return name;
}
-/* Output a reference to a label. Fastcall symbols are prefixed with @,
- whereas symbols for functions using other calling conventions don't
- have a prefix (unless they are marked dllimport or dllexport). */
-
-void i386_pe_output_labelref (FILE *stream, const char *name)
-{
- if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
- == 0)
- /* A dll import */
- {
- if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX)
- /* A dllimport fastcall symbol. */
- {
- fprintf (stream, "__imp_%s",
- i386_pe_strip_name_encoding (name));
- }
- else
- /* A dllimport non-fastcall symbol. */
- {
- fprintf (stream, "__imp__%s",
- i386_pe_strip_name_encoding (name));
- }
- }
- else if ((name[0] == FASTCALL_PREFIX)
- || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
- == 0
- && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX))
- /* A fastcall symbol. */
- {
- fprintf (stream, "%s",
- i386_pe_strip_name_encoding (name));
- }
- else
- /* Everything else. */
- {
- fprintf (stream, "%s%s", USER_LABEL_PREFIX,
- i386_pe_strip_name_encoding (name));
- }
-}
-
void
i386_pe_unique_section (tree decl, int reloc)
{
@@ -612,6 +459,29 @@ i386_pe_asm_named_section (const char *name, unsigned int flags,
(discard ? "discard" : "same_size"));
}
}
+
+void
+i386_pe_asm_output_aligned_decl_common (FILE *stream, tree decl,
+ const char *name, HOST_WIDE_INT size,
+ HOST_WIDE_INT align ATTRIBUTE_UNUSED)
+{
+ HOST_WIDE_INT rounded;
+
+ /* Compute as in assemble_noswitch_variable, since we don't actually
+ support aligned common. */
+ rounded = size ? size : 1;
+ rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
+ rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
+ * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
+
+ i386_pe_maybe_record_exported_symbol (decl, name, 1);
+
+ 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);
+}
/* The Microsoft linker requires that every function be marked as
DT_FCN. When using gas on cygwin, we must emit appropriate .type
@@ -682,10 +552,16 @@ static GTY(()) struct export_list *export_head;
linkonce. */
void
-i386_pe_record_exported_symbol (const char *name, int is_data)
+i386_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_data)
{
+ rtx symbol;
struct export_list *p;
+ symbol = XEXP (DECL_RTL (decl), 0);
+ gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
+ if (!SYMBOL_REF_DLLEXPORT_P (symbol))
+ return;
+
p = (struct export_list *) ggc_alloc (sizeof *p);
p->next = export_head;
p->name = name;
@@ -727,8 +603,8 @@ i386_pe_file_end (void)
for (q = export_head; q != NULL; q = q->next)
{
fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n",
- i386_pe_strip_name_encoding (q->name),
- (q->is_data) ? ",data" : "");
+ targetm.strip_name_encoding (q->name),
+ (q->is_data ? ",data" : ""));
}
}
}