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
This commit is contained in:
Richard Henderson 2007-03-29 14:54:35 -07:00 committed by Richard Henderson
parent 0c9bce0b5c
commit da489f7340
11 changed files with 386 additions and 362 deletions

View File

@ -1,3 +1,52 @@
2007-03-29 Richard Henderson <rth@redhat.com>
* 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.
2007-03-29 Zack Weinberg <zack@mrtock.ucsd.edu> 2007-03-29 Zack Weinberg <zack@mrtock.ucsd.edu>
* gengtype.c (oprintf): Mostly revert changes from 2007-03-26; * gengtype.c (oprintf): Mostly revert changes from 2007-03-26;

View File

@ -148,39 +148,20 @@ do { \
section and we need to set DECL_SECTION_NAME so we do that here. 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. */ 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 #define SUBTARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
#undef TARGET_STRIP_NAME_ENCODING #undef TARGET_STRIP_NAME_ENCODING
#define TARGET_STRIP_NAME_ENCODING i386_pe_strip_name_encoding_full #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. */ /* Output a common block. */
#undef ASM_OUTPUT_COMMON #undef ASM_OUTPUT_ALIGNED_DECL_COMMON
#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \ #define ASM_OUTPUT_ALIGNED_DECL_COMMON \
do { \ i386_pe_asm_output_aligned_decl_common
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)
/* Output the label for an initialized variable. */ /* Output the label for an initialized variable. */
#undef ASM_DECLARE_OBJECT_NAME #undef ASM_DECLARE_OBJECT_NAME
#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \ #define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
do { \ do { \
if (i386_pe_dllexport_name_p (NAME)) \ i386_pe_maybe_record_exported_symbol (DECL, NAME, 1); \
i386_pe_record_exported_symbol (NAME, 1); \
ASM_OUTPUT_LABEL ((STREAM), (NAME)); \ ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
} while (0) } while (0)
@ -210,7 +191,6 @@ do { \
/* Windows uses explicit import from shared libraries. */ /* Windows uses explicit import from shared libraries. */
#define MULTIPLE_SYMBOL_SPACES 1 #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_UNIQUE_SECTION i386_pe_unique_section
#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_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) \ #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do \ do \
{ \ { \
if (i386_pe_dllexport_name_p (NAME)) \ i386_pe_maybe_record_exported_symbol (DECL, NAME, 0); \
i386_pe_record_exported_symbol (NAME, 0); \
if (write_symbols != SDB_DEBUG) \ if (write_symbols != SDB_DEBUG) \
i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL)); \ i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL)); \
ASM_OUTPUT_LABEL (FILE, NAME); \ ASM_OUTPUT_LABEL (FILE, NAME); \
@ -289,15 +268,6 @@ extern void i386_pe_unique_section (TREE, int);
build_tree_list (get_identifier ("stdcall"), \ build_tree_list (get_identifier ("stdcall"), \
NULL)) 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 */ /* For Win32 ABI compatibility */
#undef DEFAULT_PCC_STRUCT_RETURN #undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 0 #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 machine. Use this macro to limit the alignment which can be
specified using the `__attribute__ ((aligned (N)))' construct. If specified using the `__attribute__ ((aligned (N)))' construct. If
not defined, the default value is `BIGGEST_ALIGNMENT'. */ not defined, the default value is `BIGGEST_ALIGNMENT'. */
#undef MAX_OFILE_ALIGNMENT
/* IMAGE_SCN_ALIGN_8192BYTES is the largest section alignment flag /* IMAGE_SCN_ALIGN_8192BYTES is the largest section alignment flag
specified in the PECOFF60 spec. Native MS compiler also limits specified in the PECOFF60 spec. Native MS compiler also limits
user-specified alignment to 8192 bytes. */ user-specified alignment to 8192 bytes. */
#undef MAX_OFILE_ALIGNMENT
#define MAX_OFILE_ALIGNMENT (8192 * 8) #define MAX_OFILE_ALIGNMENT (8192 * 8)
/* Native complier aligns internal doubles in structures on dword boundaries. */ /* 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 #ifndef SET_ASM_OP
#define SET_ASM_OP "\t.set\t" #define SET_ASM_OP "\t.set\t"
#endif #endif
/* This implements the `alias' attribute, keeping any stdcall or /* This implements the `alias' attribute, keeping any stdcall or
fastcall decoration. */ fastcall decoration. */
#undef ASM_OUTPUT_DEF_FROM_DECLS #undef ASM_OUTPUT_DEF_FROM_DECLS

View File

@ -326,8 +326,7 @@ while (0)
differently depending on something about the variable or differently depending on something about the variable or
function named by the symbol (such as what section it is in). */ function named by the symbol (such as what section it is in). */
#undef TARGET_ENCODE_SECTION_INFO #define SUBTARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
#define TARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
#undef TARGET_STRIP_NAME_ENCODING #undef TARGET_STRIP_NAME_ENCODING
#define TARGET_STRIP_NAME_ENCODING i386_pe_strip_name_encoding_full #define TARGET_STRIP_NAME_ENCODING i386_pe_strip_name_encoding_full

View File

@ -191,9 +191,6 @@ extern int ix86_local_alignment (tree, int);
extern int ix86_constant_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_shared_attribute (tree *, tree, tree, int, bool *);
extern tree ix86_handle_selectany_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); extern int x86_field_alignment (tree, int);
#endif #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); extern void ix86_expand_reduc_v4sf (rtx (*)(rtx, rtx, rtx), rtx, rtx);
/* In winnt.c */ /* 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_unique_section (tree, int);
extern void i386_pe_declare_function_type (FILE *, const char *, 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_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_asm_file_end (FILE *);
extern void i386_pe_encode_section_info (tree, rtx, int); 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 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 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 */ /* In winnt-cxx.c and winnt-stubs.c */
extern void i386_pe_adjust_class_at_definition (tree); extern void i386_pe_adjust_class_at_definition (tree);

View File

@ -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. */ /* 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) && ix86_function_regparm (TREE_TYPE (decl), NULL) >= 3)
return false; return false;
#endif
/* If we forced aligned the stack, then sibcalling would unalign the /* If we forced aligned the stack, then sibcalling would unalign the
stack, which may break the called function. */ stack, which may break the called function. */
@ -6332,6 +6331,11 @@ legitimate_constant_p (rtx x)
/* TLS symbols are never valid. */ /* TLS symbols are never valid. */
if (SYMBOL_REF_TLS_MODEL (x)) if (SYMBOL_REF_TLS_MODEL (x))
return false; return false;
/* DLLIMPORT symbols are never valid. */
if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
&& SYMBOL_REF_DLLIMPORT_P (x))
return false;
break; break;
case CONST_DOUBLE: case CONST_DOUBLE:
@ -7189,6 +7193,90 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
return dest; 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 /* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid 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. 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)) if (flag_pic && SYMBOLIC_CONST (x))
return legitimize_pic_address (x, 0); 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 */ /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
if (GET_CODE (x) == ASHIFT if (GET_CODE (x) == ASHIFT
&& CONST_INT_P (XEXP (x, 1)) && CONST_INT_P (XEXP (x, 1))
@ -9236,20 +9338,31 @@ ix86_expand_move (enum machine_mode mode, rtx operands[])
if (op1 == op0) if (op1 == op0)
return; return;
} }
else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
&& SYMBOL_REF_DLLIMPORT_P (op1))
op1 = legitimize_dllimport_symbol (op1, false);
} }
else if (GET_CODE (op1) == CONST else if (GET_CODE (op1) == CONST
&& GET_CODE (XEXP (op1, 0)) == PLUS && GET_CODE (XEXP (op1, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (op1, 0), 0)) == SYMBOL_REF) && 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) 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); tmp = force_operand (tmp, NULL);
op1 = legitimize_tls_address (XEXP (XEXP (op1, 0), 0), model, true); tmp = expand_simple_binop (Pmode, PLUS, tmp, addend,
op1 = force_operand (op1, NULL);
op1 = expand_simple_binop (Pmode, PLUS, op1, addend,
op0, 1, OPTAB_DIRECT); op0, 1, OPTAB_DIRECT);
if (op1 == op0) if (tmp == op0)
return; return;
} }
} }
@ -21648,6 +21761,10 @@ static const struct attribute_spec ix86_attribute_table[] =
#undef TARGET_BINDS_LOCAL_P #undef TARGET_BINDS_LOCAL_P
#define TARGET_BINDS_LOCAL_P darwin_binds_local_p #define TARGET_BINDS_LOCAL_P darwin_binds_local_p
#endif #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 #undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk #define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk

View File

@ -2347,8 +2347,6 @@ enum ix86_stack_slot
(! IN_RANGE ((SRC), FIRST_STACK_REG, LAST_STACK_REG)) (! IN_RANGE ((SRC), FIRST_STACK_REG, LAST_STACK_REG))
#define DLL_IMPORT_EXPORT_PREFIX '#'
#define FASTCALL_PREFIX '@' #define FASTCALL_PREFIX '@'
struct machine_function GTY(()) struct machine_function GTY(())
@ -2398,6 +2396,17 @@ struct machine_function GTY(())
#define SYMBOL_FLAG_FAR_ADDR (SYMBOL_FLAG_MACH_DEP << 0) #define SYMBOL_FLAG_FAR_ADDR (SYMBOL_FLAG_MACH_DEP << 0)
#define SYMBOL_REF_FAR_ADDR_P(X) \ #define SYMBOL_REF_FAR_ADDR_P(X) \
((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_FAR_ADDR) != 0) ((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: Local variables:
version-control: t version-control: t

View File

@ -150,7 +150,6 @@ Boston, MA 02110-1301, USA. */
the number of registers used, and an atsign (@). */ the number of registers used, and an atsign (@). */
void i386_nlm_encode_section_info (tree, rtx, int); void i386_nlm_encode_section_info (tree, rtx, int);
const char *i386_nlm_strip_name_encoding (const char *); const char *i386_nlm_strip_name_encoding (const char *);
#undef TARGET_ENCODE_SECTION_INFO #define SUBTARGET_ENCODE_SECTION_INFO i386_nlm_encode_section_info
#define TARGET_ENCODE_SECTION_INFO i386_nlm_encode_section_info
#undef TARGET_STRIP_NAME_ENCODING #undef TARGET_STRIP_NAME_ENCODING
#define TARGET_STRIP_NAME_ENCODING i386_nlm_strip_name_encoding #define TARGET_STRIP_NAME_ENCODING i386_nlm_strip_name_encoding

View File

@ -484,9 +484,14 @@
;; Test for a pc-relative call operand ;; Test for a pc-relative call operand
(define_predicate "constant_call_address_operand" (define_predicate "constant_call_address_operand"
(and (ior (match_code "symbol_ref") (match_code "symbol_ref")
(match_operand 0 "local_symbolic_operand")) {
(match_test "ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"))) 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 ;; 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. ;; instantiation of such a register may cause the pattern to not be recognized.

View File

@ -77,8 +77,7 @@ Boston, MA 02110-1301, USA. */
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do \ do \
{ \ { \
if (i386_pe_dllexport_name_p (NAME)) \ i386_pe_maybe_record_exported_symbol (DECL, NAME, 0); \
i386_pe_record_exported_symbol (NAME, 0); \
/* UWIN binutils bug workaround. */ \ /* UWIN binutils bug workaround. */ \
if (0 && write_symbols != SDB_DEBUG) \ if (0 && write_symbols != SDB_DEBUG) \
i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL)); \ i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL)); \

View File

@ -34,6 +34,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "toplev.h" #include "toplev.h"
#include "hashtab.h" #include "hashtab.h"
#include "ggc.h" #include "ggc.h"
#include "target.h"
/* i386/PE specific attribute support. /* i386/PE specific attribute support.
@ -46,22 +47,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
multiple times. 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; /* Handle a "shared" attribute;
arguments as in struct attribute_spec.handler. */ arguments as in struct attribute_spec.handler. */
tree tree
@ -108,67 +93,59 @@ ix86_handle_selectany_attribute (tree *node, tree name,
static tree static tree
associated_type (tree decl) associated_type (tree decl)
{ {
return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))
? DECL_CONTEXT (decl) : NULL_TREE; ? DECL_CONTEXT (decl) : NULL_TREE);
} }
/* Return true if DECL should be a dllexport'd object. */
/* Return true if DECL is a dllexport'd object. */
static bool static bool
i386_pe_dllexport_p (tree decl) i386_pe_determine_dllexport_p (tree decl)
{ {
if (TREE_CODE (decl) != VAR_DECL tree assoc;
&& TREE_CODE (decl) != FUNCTION_DECL)
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
return false; return false;
if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
return true; return true;
/* Also mark class members of exported classes with dllexport. */ /* Also mark class members of exported classes with dllexport. */
if (associated_type (decl) assoc = associated_type (decl);
&& lookup_attribute ("dllexport", if (assoc && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (assoc)))
TYPE_ATTRIBUTES (associated_type (decl))))
return i386_pe_type_dllexport_p (decl); return i386_pe_type_dllexport_p (decl);
return false; return false;
} }
/* Return true if DECL should be a dllimport'd object. */
static bool static bool
i386_pe_dllimport_p (tree decl) i386_pe_determine_dllimport_p (tree decl)
{ {
if (TREE_CODE (decl) != VAR_DECL tree assoc;
&& TREE_CODE (decl) != FUNCTION_DECL)
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
return false; return false;
/* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag. /* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag.
We may need to override an earlier decision. */ We may need to override an earlier decision. */
if (DECL_DLLIMPORT_P (decl) if (DECL_DLLIMPORT_P (decl))
&& lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))) return true;
{
/* 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;
}
/* The DECL_DLLIMPORT_P flag was set for decls in the class definition /* The DECL_DLLIMPORT_P flag was set for decls in the class definition
by targetm.cxx.adjust_class_at_definition. Check again to emit by targetm.cxx.adjust_class_at_definition. Check again to emit
warnings if the class attribute has been overridden by an warnings if the class attribute has been overridden by an
out-of-class definition. */ out-of-class definition. */
else if (associated_type (decl) assoc = associated_type (decl);
&& lookup_attribute ("dllimport", if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc)))
TYPE_ATTRIBUTES (associated_type (decl))))
return i386_pe_type_dllimport_p (decl); return i386_pe_type_dllimport_p (decl);
return false; return false;
} }
/* Handle the -mno-fun-dllimport target switch. */ /* Handle the -mno-fun-dllimport target switch. */
bool bool
i386_pe_valid_dllimport_attribute_p (tree decl) i386_pe_valid_dllimport_attribute_p (tree decl)
{ {
@ -177,247 +154,157 @@ i386_pe_valid_dllimport_attribute_p (tree decl)
return true; 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 /* Return string which is the former assembler name modified with a
suffix consisting of an atsign (@) followed by the number of bytes of 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 static tree
gen_stdcall_or_fastcall_suffix (tree decl, bool fastcall) gen_stdcall_or_fastcall_suffix (tree decl, bool fastcall)
{ {
int total = 0; HOST_WIDE_INT total = 0;
/* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead const char *asm_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
of DECL_ASSEMBLER_NAME. */ char *new_str, *p;
const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
char *newsym;
char *p;
tree formal_type; tree formal_type;
/* Do not change the identifier if a verbatim asmspec or already done. */ /* Do not change the identifier if a verbatim asmspec or already done. */
if (*asmname == '*' || strchr (asmname, '@')) if (*asm_str == '*' || strchr (asm_str, '@'))
return DECL_ASSEMBLER_NAME (decl); return NULL_TREE;
formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
if (formal_type != NULL_TREE) if (formal_type != NULL_TREE)
{ while (1)
/* These attributes are ignored for variadic functions in {
i386.c:ix86_return_pops_args. For compatibility with MS HOST_WIDE_INT parm_size;
compiler do not add @0 suffix here. */ HOST_WIDE_INT parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT;
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 /* We got to the end of the list without seeing void_list_node,
by convert_arguments in c-typeck.c or cp/typeck.c. */ which means the function is variadic. The suffix is to be
while (TREE_VALUE (formal_type) != void_type_node ignored in that case. */
&& COMPLETE_TYPE_P (TREE_VALUE (formal_type))) if (formal_type == NULL_TREE)
{ return NULL_TREE;
int parm_size
= TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); /* End of arguments, non-varargs marker. */
/* Must round up to include padding. This is done the same if (formal_type == void_list_node)
way as in store_one_arg. */ break;
parm_size = ((parm_size + PARM_BOUNDARY - 1)
/ PARM_BOUNDARY * PARM_BOUNDARY); /* Quit if we hit an incomplete type. Error is reported
total += parm_size; by convert_arguments in c-typeck.c or cp/typeck.c. */
formal_type = TREE_CHAIN (formal_type);\ 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. */ /* Assume max of 8 base 10 digits in the suffix. */
newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1); p = new_str = alloca (1 + strlen (asm_str) + 1 + 8 + 1);
p = newsym;
if (fastcall) if (fastcall)
*p++ = FASTCALL_PREFIX; *p++ = FASTCALL_PREFIX;
sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT); sprintf (p, "%s@" HOST_WIDE_INT_PRINT_DEC, asm_str, total);
return get_identifier (newsym);
return get_identifier (new_str);
} }
void void
i386_pe_encode_section_info (tree decl, rtx rtl, int first) 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); 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))
tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl)); return;
tree newid = NULL_TREE;
if (lookup_attribute ("stdcall", type_attributes)) symbol = XEXP (rtl, 0);
newid = gen_stdcall_or_fastcall_suffix (decl, false); gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
else if (lookup_attribute ("fastcall", type_attributes))
newid = gen_stdcall_or_fastcall_suffix (decl, true); switch (TREE_CODE (decl))
if (newid != NULL_TREE) {
case FUNCTION_DECL:
if (first)
{ {
rtx rtlname = XEXP (rtl, 0); tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
if (GET_CODE (rtlname) == MEM) tree newid = NULL_TREE;
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 if (lookup_attribute ("stdcall", type_attributes))
&& lookup_attribute ("selectany", DECL_ATTRIBUTES (decl))) newid = gen_stdcall_or_fastcall_suffix (decl, false);
{ else if (lookup_attribute ("fastcall", type_attributes))
if (DECL_INITIAL (decl) newid = gen_stdcall_or_fastcall_suffix (decl, true);
/* If an object is initialized with a ctor, the static if (newid != NULL_TREE)
initialization and destruction code for it is present in {
each unit defining the object. The code that calls the XSTR (symbol, 0) = IDENTIFIER_POINTER (newid);
ctor is protected by a link-once guard variable, so that /* These attributes must be present on first declaration,
the object still has link-once semantics, */ change_decl_assembler_name will warn if they are added
|| TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) later and the decl has been referenced, but duplicate_decls
make_decl_one_only (decl); should catch the mismatch before this is called. */
else change_decl_assembler_name (decl, newid);
error ("%q+D:'selectany' attribute applies only to initialized objects", }
decl); }
break;
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 /* 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 dllexport'd or dllimport'd. tree.c: merge_dllimport_decl_attributes
handles dllexport/dllimport override semantics. */ handles dllexport/dllimport override semantics. */
flags = (SYMBOL_REF_FLAGS (symbol) &
if (i386_pe_dllexport_p (decl)) ~(SYMBOL_FLAG_DLLIMPORT | SYMBOL_FLAG_DLLEXPORT));
i386_pe_mark_dllexport (decl); if (i386_pe_determine_dllexport_p (decl))
else if (i386_pe_dllimport_p (decl)) flags |= SYMBOL_FLAG_DLLEXPORT;
i386_pe_mark_dllimport (decl); else if (i386_pe_determine_dllimport_p (decl))
/* It might be that DECL has been declared as dllimport, but a {
subsequent definition nullified that. Assert that flags |= SYMBOL_FLAG_DLLIMPORT;
tree.c: merge_dllimport_decl_attributes has removed the attribute /* If we went through the associated_type path, this won't already
before the RTL name was marked with the DLL_IMPORT_PREFIX. */ be set. Though, frankly, this seems wrong, and should be fixed
else elsewhere. */
gcc_assert (!((TREE_CODE (decl) == FUNCTION_DECL if (!DECL_DLLIMPORT_P (decl))
|| TREE_CODE (decl) == VAR_DECL) {
&& rtl != NULL_RTX DECL_DLLIMPORT_P (decl) = 1;
&& GET_CODE (rtl) == MEM flags &= ~SYMBOL_FLAG_LOCAL;
&& 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)))); SYMBOL_REF_FLAGS (symbol) = flags;
} }
/* Strip only the leading encoding, leaving the stdcall suffix and fastcall bool
prefix if it exists. */ i386_pe_binds_local_p (tree exp)
const char *
i386_pe_strip_name_encoding (const char *str)
{ {
if (strncmp (str, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX)) /* PE does not do dynamic binding. Indeed, the only kind of
== 0) non-local reference comes from a dllimport'd symbol. */
str += strlen (DLL_IMPORT_PREFIX); if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
else if (strncmp (str, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX)) && DECL_DLLIMPORT_P (exp))
== 0) return false;
str += strlen (DLL_EXPORT_PREFIX);
if (*str == '*') return true;
str += 1;
return str;
} }
/* Also strip the fastcall prefix and stdcall suffix. */ /* Also strip the fastcall prefix and stdcall suffix. */
@ -426,7 +313,7 @@ const char *
i386_pe_strip_name_encoding_full (const char *str) i386_pe_strip_name_encoding_full (const char *str)
{ {
const char *p; 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. */ /* Strip leading '@' on fastcall symbols. */
if (*name == '@') if (*name == '@')
@ -440,46 +327,6 @@ i386_pe_strip_name_encoding_full (const char *str)
return name; 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 void
i386_pe_unique_section (tree decl, int reloc) 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")); (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 /* The Microsoft linker requires that every function be marked as
DT_FCN. When using gas on cygwin, we must emit appropriate .type DT_FCN. When using gas on cygwin, we must emit appropriate .type
@ -682,10 +552,16 @@ static GTY(()) struct export_list *export_head;
linkonce. */ linkonce. */
void 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; 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 = (struct export_list *) ggc_alloc (sizeof *p);
p->next = export_head; p->next = export_head;
p->name = name; p->name = name;
@ -727,8 +603,8 @@ i386_pe_file_end (void)
for (q = export_head; q != NULL; q = q->next) for (q = export_head; q != NULL; q = q->next)
{ {
fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n", fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n",
i386_pe_strip_name_encoding (q->name), targetm.strip_name_encoding (q->name),
(q->is_data) ? ",data" : ""); (q->is_data ? ",data" : ""));
} }
} }
} }

View File

@ -4063,9 +4063,8 @@ initializer_constant_valid_p (tree value, tree endtype)
return null_pointer_node; return null_pointer_node;
/* Taking the address of a nested function involves a trampoline. */ /* Taking the address of a nested function involves a trampoline. */
if (TREE_CODE (value) == FUNCTION_DECL if (TREE_CODE (value) == FUNCTION_DECL
&& ((decl_function_context (value) && decl_function_context (value)
&& !DECL_NO_STATIC_CHAIN (value)) && !DECL_NO_STATIC_CHAIN (value))
|| DECL_DLLIMPORT_P (value)))
return NULL_TREE; return NULL_TREE;
/* "&{...}" requires a temporary to hold the constructed /* "&{...}" requires a temporary to hold the constructed
object. */ object. */