Commit 82c0e1a0 by Kai Tietz Committed by Kai Tietz

re PR target/52790 (Problems using x86_64-w64-mingw-w32-gfortran with mcmodel=large and medium)

	PR target/52790
	* config/i386/cygming.h (SUB_TARGET_RECORD_STUB): New sub-target macro.
	* config/i386/i386-protos.h (i386_pe_record_stub): Add new prototype.
	* config/i386/i386.c (legitimize_pe_coff_extern_decl): New static
	function.
	(legitimize_pe_coff_symbol): Likewise.
	(is_imported_p): New helper-function.
	(ix86_option_override_internal): Make MEDIUM_PIC the default code-model
	for Windows x64 targets.
	(ix86_expand_prologue): Optimize for pe-coff targets.
	(ix86_expand_split_stack_prologue): Adjust for pe-coff targets.
	(legitimate_pic_address_disp_p): Adjust for x64 pe-coff to support
	medium/large code-model.
	(legitimize_pic_address): Likewise.
	(legitimize_tls_address): Likewise.
	(ix86_expand_call): Likewise.
	(x86_output_mi_thunk): Likewise.
	(get_dllimport_decl): Add new beimport argument.
	(construct_plt_address): Don't assert for x64 pe-coff targets.
	* config/i386/i386.h (PIC_OFFSET_TABLE_REGNUM): Adjust for x64 pe-coff
	targets.
	(SYMBOL_FLAG_STUBVAR): New macro.
	(SYMBOL_REF_STUBVAR_P): Likewise.
	* config/i386/winnt.c (stub_list): New structure.
	(stub_head): New local variable.
	(i386_pe_record_stub): New function.
	(i386_pe_file_end): Emit refptr-stubs.

From-SVN: r197373
parent 09bb4c99
2013-04-02 Kai Tietz <ktietz@redhat.com>
PR target/52790
* config/i386/cygming.h (SUB_TARGET_RECORD_STUB): New sub-target macro.
* config/i386/i386-protos.h (i386_pe_record_stub): Add new prototype.
* config/i386/i386.c (legitimize_pe_coff_extern_decl): New static function.
(legitimize_pe_coff_symbol): Likewise.
(is_imported_p): New helper-function.
(ix86_option_override_internal): Make MEDIUM_PIC the default code-model
for Windows x64 targets.
(ix86_expand_prologue): Optimize for pe-coff targets.
(ix86_expand_split_stack_prologue): Adjust for pe-coff targets.
(legitimate_pic_address_disp_p): Adjust for x64 pe-coff to support
medium/large code-model.
(legitimize_pic_address): Likewise.
(legitimize_tls_address): Likewise.
(ix86_expand_call): Likewise.
(x86_output_mi_thunk): Likewise.
(get_dllimport_decl): Add new beimport argument.
(construct_plt_address): Don't assert for x64 pe-coff targets.
* config/i386/i386.h (PIC_OFFSET_TABLE_REGNUM): Adjust for x64 pe-coff
targets.
(SYMBOL_FLAG_STUBVAR): New macro.
(SYMBOL_REF_STUBVAR_P): Likewise.
* config/i386/winnt.c (stub_list): New structure.
(stub_head): New local variable.
(i386_pe_record_stub): New function.
(i386_pe_file_end): Emit refptr-stubs.
2013-04-02 Jakub Jelinek <jakub@redhat.com> 2013-04-02 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/56745 PR rtl-optimization/56745
......
...@@ -474,5 +474,8 @@ do { \ ...@@ -474,5 +474,8 @@ do { \
#undef TARGET_ASM_ASSEMBLE_VISIBILITY #undef TARGET_ASM_ASSEMBLE_VISIBILITY
#define TARGET_ASM_ASSEMBLE_VISIBILITY i386_pe_assemble_visibility #define TARGET_ASM_ASSEMBLE_VISIBILITY i386_pe_assemble_visibility
#undef SUB_TARGET_RECORD_STUB
#define SUB_TARGET_RECORD_STUB i386_pe_record_stub
/* Static stack checking is supported by means of probes. */ /* Static stack checking is supported by means of probes. */
#define STACK_CHECK_STATIC_BUILTIN 1 #define STACK_CHECK_STATIC_BUILTIN 1
...@@ -260,6 +260,7 @@ extern void i386_pe_end_function (FILE *, const char *, tree); ...@@ -260,6 +260,7 @@ extern void i386_pe_end_function (FILE *, const char *, tree);
extern void i386_pe_assemble_visibility (tree, int); extern void i386_pe_assemble_visibility (tree, int);
extern tree i386_pe_mangle_decl_assembler_name (tree, tree); extern tree i386_pe_mangle_decl_assembler_name (tree, tree);
extern tree i386_pe_mangle_assembler_name (const char *); extern tree i386_pe_mangle_assembler_name (const char *);
extern void i386_pe_record_stub (const char *);
extern void i386_pe_seh_init (FILE *); extern void i386_pe_seh_init (FILE *);
extern void i386_pe_seh_end_prologue (FILE *); extern void i386_pe_seh_end_prologue (FILE *);
......
...@@ -64,6 +64,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -64,6 +64,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-flow.h" #include "tree-flow.h"
static rtx legitimize_dllimport_symbol (rtx, bool); static rtx legitimize_dllimport_symbol (rtx, bool);
static rtx legitimize_pe_coff_extern_decl (rtx, bool);
static rtx legitimize_pe_coff_symbol (rtx, bool);
#ifndef CHECK_STACK_LIMIT #ifndef CHECK_STACK_LIMIT
#define CHECK_STACK_LIMIT (-1) #define CHECK_STACK_LIMIT (-1)
...@@ -3233,9 +3235,7 @@ ix86_option_override_internal (bool main_args_p) ...@@ -3233,9 +3235,7 @@ ix86_option_override_internal (bool main_args_p)
use of rip-relative addressing. This eliminates fixups that use of rip-relative addressing. This eliminates fixups that
would otherwise be needed if this object is to be placed in a would otherwise be needed if this object is to be placed in a
DLL, and is essentially just as efficient as direct addressing. */ DLL, and is essentially just as efficient as direct addressing. */
if (TARGET_64BIT && DEFAULT_ABI == MS_ABI) if (TARGET_64BIT && (TARGET_RDOS || DEFAULT_ABI == MS_ABI))
ix86_cmodel = CM_SMALL_PIC, flag_pic = 1;
else if (TARGET_64BIT && TARGET_RDOS)
ix86_cmodel = CM_MEDIUM_PIC, flag_pic = 1; ix86_cmodel = CM_MEDIUM_PIC, flag_pic = 1;
else if (TARGET_64BIT) else if (TARGET_64BIT)
ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL; ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
...@@ -10575,7 +10575,9 @@ ix86_expand_prologue (void) ...@@ -10575,7 +10575,9 @@ ix86_expand_prologue (void)
ix86_emit_save_sse_regs_using_mov (frame.sse_reg_save_offset); ix86_emit_save_sse_regs_using_mov (frame.sse_reg_save_offset);
pic_reg_used = false; pic_reg_used = false;
/* We don't use pic-register for pe-coff target. */
if (pic_offset_table_rtx if (pic_offset_table_rtx
&& DEFAULT_ABI != MS_ABI
&& (df_regs_ever_live_p (REAL_PIC_OFFSET_TABLE_REGNUM) && (df_regs_ever_live_p (REAL_PIC_OFFSET_TABLE_REGNUM)
|| crtl->profile)) || crtl->profile))
{ {
...@@ -11380,7 +11382,8 @@ ix86_expand_split_stack_prologue (void) ...@@ -11380,7 +11382,8 @@ ix86_expand_split_stack_prologue (void)
use_reg (&call_fusage, rax); use_reg (&call_fusage, rax);
} }
if (ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC) if ((ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
&& DEFAULT_ABI != MS_ABI)
{ {
HOST_WIDE_INT argval; HOST_WIDE_INT argval;
...@@ -11998,6 +12001,19 @@ ix86_cannot_force_const_mem (enum machine_mode mode, rtx x) ...@@ -11998,6 +12001,19 @@ ix86_cannot_force_const_mem (enum machine_mode mode, rtx x)
return !ix86_legitimate_constant_p (mode, x); return !ix86_legitimate_constant_p (mode, x);
} }
/* Nonzero if the symbol is marked as dllimport, or as stub-variable,
otherwise zero. */
static bool
is_imported_p (rtx x)
{
if (!TARGET_DLLIMPORT_DECL_ATTRIBUTES
|| GET_CODE (x) != SYMBOL_REF)
return false;
return SYMBOL_REF_DLLIMPORT_P (x) || SYMBOL_REF_STUBVAR_P (x);
}
/* Nonzero if the constant value X is a legitimate general operand /* Nonzero if the constant value X is a legitimate general operand
when generating PIC code. It is given that flag_pic is on and when generating PIC code. It is given that flag_pic is on and
...@@ -12086,10 +12102,38 @@ legitimate_pic_address_disp_p (rtx disp) ...@@ -12086,10 +12102,38 @@ legitimate_pic_address_disp_p (rtx disp)
/* FALLTHRU */ /* FALLTHRU */
case SYMBOL_REF: case SYMBOL_REF:
/* TLS references should always be enclosed in UNSPEC. */ /* TLS references should always be enclosed in UNSPEC.
if (SYMBOL_REF_TLS_MODEL (op0)) The dllimported symbol needs always to be resolved. */
if (SYMBOL_REF_TLS_MODEL (op0)
|| (TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P (op0)))
return false; return false;
if (!SYMBOL_REF_FAR_ADDR_P (op0) && SYMBOL_REF_LOCAL_P (op0)
if (DEFAULT_ABI == MS_ABI)
{
if (is_imported_p (op0))
return true;
if (SYMBOL_REF_FAR_ADDR_P (op0)
|| !SYMBOL_REF_LOCAL_P (op0))
break;
/* Function-symbols need to be resolved only for
large-model.
For the small-model we don't need to resolve anything
here. */
if ((ix86_cmodel != CM_LARGE_PIC
&& SYMBOL_REF_FUNCTION_P (op0))
|| ix86_cmodel == CM_SMALL_PIC)
return true;
/* Non-external symbols don't need to be resolved for
large, and medium-model. */
if ((ix86_cmodel == CM_LARGE_PIC
|| ix86_cmodel == CM_MEDIUM_PIC)
&& !SYMBOL_REF_EXTERNAL_P (op0))
return true;
}
else if (!SYMBOL_REF_FAR_ADDR_P (op0)
&& SYMBOL_REF_LOCAL_P (op0)
&& ix86_cmodel != CM_LARGE_PIC) && ix86_cmodel != CM_LARGE_PIC)
return true; return true;
break; break;
...@@ -12151,7 +12195,7 @@ legitimate_pic_address_disp_p (rtx disp) ...@@ -12151,7 +12195,7 @@ legitimate_pic_address_disp_p (rtx disp)
if ((GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF if ((GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF
|| GET_CODE (XVECEXP (disp, 0, 0)) == LABEL_REF) || GET_CODE (XVECEXP (disp, 0, 0)) == LABEL_REF)
&& !TARGET_64BIT) && !TARGET_64BIT)
return gotoff_operand (XVECEXP (disp, 0, 0), Pmode); return DEFAULT_ABI != MS_ABI && gotoff_operand (XVECEXP (disp, 0, 0), Pmode);
return false; return false;
case UNSPEC_GOTTPOFF: case UNSPEC_GOTTPOFF:
case UNSPEC_GOTNTPOFF: case UNSPEC_GOTNTPOFF:
...@@ -12486,11 +12530,17 @@ legitimize_pic_address (rtx orig, rtx reg) ...@@ -12486,11 +12530,17 @@ legitimize_pic_address (rtx orig, rtx reg)
} }
#endif #endif
if (TARGET_64BIT && TARGET_DLLIMPORT_DECL_ATTRIBUTES)
{
rtx tmp = legitimize_pe_coff_symbol (addr, true);
if (tmp)
return tmp;
}
if (TARGET_64BIT && legitimate_pic_address_disp_p (addr)) if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
new_rtx = addr; new_rtx = addr;
else if (TARGET_64BIT else if (TARGET_64BIT && DEFAULT_ABI != MS_ABI
&& ix86_cmodel != CM_SMALL_PIC && ix86_cmodel != CM_SMALL_PIC && gotoff_operand (addr, Pmode))
&& gotoff_operand (addr, Pmode))
{ {
rtx tmpreg; rtx tmpreg;
/* This symbol may be referenced via a displacement from the PIC /* This symbol may be referenced via a displacement from the PIC
...@@ -12521,9 +12571,10 @@ legitimize_pic_address (rtx orig, rtx reg) ...@@ -12521,9 +12571,10 @@ legitimize_pic_address (rtx orig, rtx reg)
tmpreg, 1, OPTAB_DIRECT); tmpreg, 1, OPTAB_DIRECT);
new_rtx = reg; new_rtx = reg;
} }
else new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmpreg); else
new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmpreg);
} }
else if (!TARGET_64BIT && gotoff_operand (addr, Pmode)) else if (!TARGET_64BIT && DEFAULT_ABI != MS_ABI && gotoff_operand (addr, Pmode))
{ {
/* This symbol may be referenced via a displacement from the PIC /* This symbol may be referenced via a displacement from the PIC
base address (@GOTOFF). */ base address (@GOTOFF). */
...@@ -12554,18 +12605,9 @@ legitimize_pic_address (rtx orig, rtx reg) ...@@ -12554,18 +12605,9 @@ legitimize_pic_address (rtx orig, rtx reg)
see gotoff_operand. */ see gotoff_operand. */
|| (TARGET_VXWORKS_RTP && GET_CODE (addr) == LABEL_REF)) || (TARGET_VXWORKS_RTP && GET_CODE (addr) == LABEL_REF))
{ {
if (TARGET_DLLIMPORT_DECL_ATTRIBUTES) rtx tmp = legitimize_pe_coff_symbol (addr, true);
{ if (tmp)
if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_DLLIMPORT_P (addr)) return tmp;
return legitimize_dllimport_symbol (addr, true);
if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF
&& SYMBOL_REF_DLLIMPORT_P (XEXP (XEXP (addr, 0), 0)))
{
rtx t = legitimize_dllimport_symbol (XEXP (XEXP (addr, 0), 0), true);
return gen_rtx_PLUS (Pmode, t, XEXP (XEXP (addr, 0), 1));
}
}
/* For x64 PE-COFF there is no GOT table. So we use address /* For x64 PE-COFF there is no GOT table. So we use address
directly. */ directly. */
...@@ -12647,7 +12689,7 @@ legitimize_pic_address (rtx orig, rtx reg) ...@@ -12647,7 +12689,7 @@ legitimize_pic_address (rtx orig, rtx reg)
/* Check first to see if this is a constant offset from a @GOTOFF /* Check first to see if this is a constant offset from a @GOTOFF
symbol reference. */ symbol reference. */
if (gotoff_operand (op0, Pmode) if (DEFAULT_ABI != MS_ABI && gotoff_operand (op0, Pmode)
&& CONST_INT_P (op1)) && CONST_INT_P (op1))
{ {
if (!TARGET_64BIT) if (!TARGET_64BIT)
...@@ -12791,7 +12833,7 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) ...@@ -12791,7 +12833,7 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
if (!TARGET_64BIT) if (!TARGET_64BIT)
{ {
if (flag_pic) if (flag_pic && DEFAULT_ABI != MS_ABI)
pic = pic_offset_table_rtx; pic = pic_offset_table_rtx;
else else
{ {
...@@ -13000,13 +13042,14 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) ...@@ -13000,13 +13042,14 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
} }
/* Create or return the unique __imp_DECL dllimport symbol corresponding /* Create or return the unique __imp_DECL dllimport symbol corresponding
to symbol DECL. */ to symbol DECL if BEIMPORT is true. Otherwise create or return the
unique refptr-DECL symbol corresponding to symbol DECL. */
static GTY((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) static GTY((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
htab_t dllimport_map; htab_t dllimport_map;
static tree static tree
get_dllimport_decl (tree decl) get_dllimport_decl (tree decl, bool beimport)
{ {
struct tree_map *h, in; struct tree_map *h, in;
void **loc; void **loc;
...@@ -13039,8 +13082,11 @@ get_dllimport_decl (tree decl) ...@@ -13039,8 +13082,11 @@ get_dllimport_decl (tree decl)
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
name = targetm.strip_name_encoding (name); name = targetm.strip_name_encoding (name);
if (beimport)
prefix = name[0] == FASTCALL_PREFIX || user_label_prefix[0] == 0 prefix = name[0] == FASTCALL_PREFIX || user_label_prefix[0] == 0
? "*__imp_" : "*__imp__"; ? "*__imp_" : "*__imp__";
else
prefix = user_label_prefix[0] == 0 ? "*.refptr." : "*refptr.";
namelen = strlen (name); namelen = strlen (name);
prefixlen = strlen (prefix); prefixlen = strlen (prefix);
imp_name = (char *) alloca (namelen + prefixlen + 1); imp_name = (char *) alloca (namelen + prefixlen + 1);
...@@ -13050,7 +13096,14 @@ get_dllimport_decl (tree decl) ...@@ -13050,7 +13096,14 @@ get_dllimport_decl (tree decl)
name = ggc_alloc_string (imp_name, namelen + prefixlen); name = ggc_alloc_string (imp_name, namelen + prefixlen);
rtl = gen_rtx_SYMBOL_REF (Pmode, name); rtl = gen_rtx_SYMBOL_REF (Pmode, name);
SET_SYMBOL_REF_DECL (rtl, to); SET_SYMBOL_REF_DECL (rtl, to);
SYMBOL_REF_FLAGS (rtl) = SYMBOL_FLAG_LOCAL; SYMBOL_REF_FLAGS (rtl) = SYMBOL_FLAG_LOCAL | SYMBOL_FLAG_STUBVAR;
if (!beimport)
{
SYMBOL_REF_FLAGS (rtl) |= SYMBOL_FLAG_EXTERNAL;
#ifdef SUB_TARGET_RECORD_STUB
SUB_TARGET_RECORD_STUB (name);
#endif
}
rtl = gen_const_mem (Pmode, rtl); rtl = gen_const_mem (Pmode, rtl);
set_mem_alias_set (rtl, ix86_GOT_alias_set ()); set_mem_alias_set (rtl, ix86_GOT_alias_set ());
...@@ -13061,6 +13114,24 @@ get_dllimport_decl (tree decl) ...@@ -13061,6 +13114,24 @@ get_dllimport_decl (tree decl)
return to; return to;
} }
/* Expand SYMBOL into its corresponding far-addresse symbol.
WANT_REG is true if we require the result be a register. */
static rtx
legitimize_pe_coff_extern_decl (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), false);
x = DECL_RTL (imp_decl);
if (want_reg)
x = force_reg (Pmode, x);
return x;
}
/* Expand SYMBOL into its corresponding dllimport symbol. WANT_REG is /* Expand SYMBOL into its corresponding dllimport symbol. WANT_REG is
true if we require the result be a register. */ true if we require the result be a register. */
...@@ -13071,7 +13142,7 @@ legitimize_dllimport_symbol (rtx symbol, bool want_reg) ...@@ -13071,7 +13142,7 @@ legitimize_dllimport_symbol (rtx symbol, bool want_reg)
rtx x; rtx x;
gcc_assert (SYMBOL_REF_DECL (symbol)); gcc_assert (SYMBOL_REF_DECL (symbol));
imp_decl = get_dllimport_decl (SYMBOL_REF_DECL (symbol)); imp_decl = get_dllimport_decl (SYMBOL_REF_DECL (symbol), true);
x = DECL_RTL (imp_decl); x = DECL_RTL (imp_decl);
if (want_reg) if (want_reg)
...@@ -13079,6 +13150,50 @@ legitimize_dllimport_symbol (rtx symbol, bool want_reg) ...@@ -13079,6 +13150,50 @@ legitimize_dllimport_symbol (rtx symbol, bool want_reg)
return x; return x;
} }
/* Expand SYMBOL into its corresponding dllimport or refptr symbol. WANT_REG
is true if we require the result be a register. */
static rtx
legitimize_pe_coff_symbol (rtx addr, bool inreg)
{
if (DEFAULT_ABI != MS_ABI)
return NULL_RTX;
if (TARGET_DLLIMPORT_DECL_ATTRIBUTES)
{
if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_DLLIMPORT_P (addr))
return legitimize_dllimport_symbol (addr, inreg);
if (GET_CODE (addr) == CONST
&& GET_CODE (XEXP (addr, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF
&& SYMBOL_REF_DLLIMPORT_P (XEXP (XEXP (addr, 0), 0)))
{
rtx t = legitimize_dllimport_symbol (XEXP (XEXP (addr, 0), 0), inreg);
return gen_rtx_PLUS (Pmode, t, XEXP (XEXP (addr, 0), 1));
}
}
if (ix86_cmodel != CM_LARGE_PIC && ix86_cmodel != CM_MEDIUM_PIC)
return NULL_RTX;
if (GET_CODE (addr) == SYMBOL_REF
&& !is_imported_p (addr)
&& SYMBOL_REF_EXTERNAL_P (addr)
&& SYMBOL_REF_DECL (addr))
return legitimize_pe_coff_extern_decl (addr, inreg);
if (GET_CODE (addr) == CONST
&& GET_CODE (XEXP (addr, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF
&& !is_imported_p (XEXP (XEXP (addr, 0), 0))
&& SYMBOL_REF_EXTERNAL_P (XEXP (XEXP (addr, 0), 0))
&& SYMBOL_REF_DECL (XEXP (XEXP (addr, 0), 0)))
{
rtx t = legitimize_pe_coff_extern_decl (XEXP (XEXP (addr, 0), 0), inreg);
return gen_rtx_PLUS (Pmode, t, XEXP (XEXP (addr, 0), 1));
}
return NULL_RTX;
}
/* 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.
...@@ -13119,16 +13234,9 @@ ix86_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -13119,16 +13234,9 @@ ix86_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (TARGET_DLLIMPORT_DECL_ATTRIBUTES) if (TARGET_DLLIMPORT_DECL_ATTRIBUTES)
{ {
if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_DLLIMPORT_P (x)) rtx tmp = legitimize_pe_coff_symbol (x, true);
return legitimize_dllimport_symbol (x, true); if (tmp)
if (GET_CODE (x) == CONST return tmp;
&& 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));
}
} }
if (flag_pic && SYMBOLIC_CONST (x)) if (flag_pic && SYMBOLIC_CONST (x))
...@@ -15944,6 +16052,8 @@ ix86_expand_move (enum machine_mode mode, rtx operands[]) ...@@ -15944,6 +16052,8 @@ ix86_expand_move (enum machine_mode mode, rtx operands[])
if (GET_CODE (op1) == SYMBOL_REF) if (GET_CODE (op1) == SYMBOL_REF)
{ {
rtx tmp;
model = SYMBOL_REF_TLS_MODEL (op1); model = SYMBOL_REF_TLS_MODEL (op1);
if (model) if (model)
{ {
...@@ -15953,9 +16063,8 @@ ix86_expand_move (enum machine_mode mode, rtx operands[]) ...@@ -15953,9 +16063,8 @@ ix86_expand_move (enum machine_mode mode, rtx operands[])
return; return;
op1 = convert_to_mode (mode, op1, 1); op1 = convert_to_mode (mode, op1, 1);
} }
else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES else if ((tmp = legitimize_pe_coff_symbol (op1, false)) != NULL_RTX)
&& SYMBOL_REF_DLLIMPORT_P (op1)) op1 = tmp;
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
...@@ -15963,14 +16072,13 @@ ix86_expand_move (enum machine_mode mode, rtx operands[]) ...@@ -15963,14 +16072,13 @@ ix86_expand_move (enum machine_mode mode, rtx operands[])
{ {
rtx addend = XEXP (XEXP (op1, 0), 1); rtx addend = XEXP (XEXP (op1, 0), 1);
rtx symbol = XEXP (XEXP (op1, 0), 0); rtx symbol = XEXP (XEXP (op1, 0), 0);
rtx tmp = NULL; rtx tmp;
model = SYMBOL_REF_TLS_MODEL (symbol); model = SYMBOL_REF_TLS_MODEL (symbol);
if (model) if (model)
tmp = legitimize_tls_address (symbol, model, true); tmp = legitimize_tls_address (symbol, model, true);
else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES else
&& SYMBOL_REF_DLLIMPORT_P (symbol)) tmp = legitimize_pe_coff_symbol (symbol, true);
tmp = legitimize_dllimport_symbol (symbol, true);
if (tmp) if (tmp)
{ {
...@@ -23576,7 +23684,7 @@ construct_plt_address (rtx symbol) ...@@ -23576,7 +23684,7 @@ construct_plt_address (rtx symbol)
rtx tmp, unspec; rtx tmp, unspec;
gcc_assert (GET_CODE (symbol) == SYMBOL_REF); gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
gcc_assert (ix86_cmodel == CM_LARGE_PIC); gcc_assert (ix86_cmodel == CM_LARGE_PIC && DEFAULT_ABI != MS_ABI);
gcc_assert (Pmode == DImode); gcc_assert (Pmode == DImode);
tmp = gen_reg_rtx (Pmode); tmp = gen_reg_rtx (Pmode);
...@@ -23618,7 +23726,8 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, ...@@ -23618,7 +23726,8 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
else else
{ {
/* Static functions and indirect calls don't need the pic register. */ /* Static functions and indirect calls don't need the pic register. */
if (flag_pic && (!TARGET_64BIT || ix86_cmodel == CM_LARGE_PIC) if (flag_pic && (!TARGET_64BIT
|| (ix86_cmodel == CM_LARGE_PIC && DEFAULT_ABI != MS_ABI))
&& GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
&& ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0))) && ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0)))
use_reg (&use, pic_offset_table_rtx); use_reg (&use, pic_offset_table_rtx);
...@@ -23632,6 +23741,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, ...@@ -23632,6 +23741,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
} }
if (ix86_cmodel == CM_LARGE_PIC if (ix86_cmodel == CM_LARGE_PIC
&& DEFAULT_ABI != MS_ABI
&& MEM_P (fnaddr) && MEM_P (fnaddr)
&& GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
&& !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode)) && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
...@@ -34970,7 +35080,7 @@ x86_output_mi_thunk (FILE *file, ...@@ -34970,7 +35080,7 @@ x86_output_mi_thunk (FILE *file,
if (TARGET_64BIT) if (TARGET_64BIT)
{ {
if (!flag_pic || targetm.binds_local_p (function) if (!flag_pic || targetm.binds_local_p (function)
|| cfun->machine->call_abi == MS_ABI) || DEFAULT_ABI == MS_ABI)
; ;
else else
{ {
...@@ -1179,7 +1179,8 @@ enum target_cpu_default ...@@ -1179,7 +1179,8 @@ enum target_cpu_default
#define REAL_PIC_OFFSET_TABLE_REGNUM BX_REG #define REAL_PIC_OFFSET_TABLE_REGNUM BX_REG
#define PIC_OFFSET_TABLE_REGNUM \ #define PIC_OFFSET_TABLE_REGNUM \
((TARGET_64BIT && ix86_cmodel == CM_SMALL_PIC) \ ((TARGET_64BIT && (ix86_cmodel == CM_SMALL_PIC \
|| DEFAULT_ABI == MS_ABI)) \
|| !flag_pic ? INVALID_REGNUM \ || !flag_pic ? INVALID_REGNUM \
: reload_completed ? REGNO (pic_offset_table_rtx) \ : reload_completed ? REGNO (pic_offset_table_rtx) \
: REAL_PIC_OFFSET_TABLE_REGNUM) : REAL_PIC_OFFSET_TABLE_REGNUM)
...@@ -2379,6 +2380,10 @@ struct GTY(()) machine_function { ...@@ -2379,6 +2380,10 @@ struct GTY(()) machine_function {
#define SYMBOL_REF_DLLEXPORT_P(X) \ #define SYMBOL_REF_DLLEXPORT_P(X) \
((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_DLLEXPORT) != 0) ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_DLLEXPORT) != 0)
#define SYMBOL_FLAG_STUBVAR (SYMBOL_FLAG_MACH_DEP << 4)
#define SYMBOL_REF_STUBVAR_P(X) \
((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_STUBVAR) != 0)
extern void debug_ready_dispatch (void); extern void debug_ready_dispatch (void);
extern void debug_dispatch_window (int); extern void debug_dispatch_window (int);
......
...@@ -646,8 +646,18 @@ struct GTY(()) export_list ...@@ -646,8 +646,18 @@ struct GTY(()) export_list
int is_data; /* used to type tag exported symbols. */ int is_data; /* used to type tag exported symbols. */
}; };
/* Keep a list of stub symbols. */
struct GTY(()) stub_list
{
struct stub_list *next;
const char *name;
};
static GTY(()) struct export_list *export_head; static GTY(()) struct export_list *export_head;
static GTY(()) struct stub_list *stub_head;
/* Assemble an export symbol entry. We need to keep a list of /* 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 these, so that we can output the export list at the end of the
assembly. We used to output these export symbols in each function, assembly. We used to output these export symbols in each function,
...@@ -678,6 +688,30 @@ i386_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_data) ...@@ -678,6 +688,30 @@ i386_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_data)
export_head = p; export_head = p;
} }
void
i386_pe_record_stub (const char *name)
{
struct stub_list *p;
if (!name || *name == 0)
return;
p = stub_head;
while (p != NULL)
{
if (p->name[0] == *name
&& !strcmp (p->name, name))
return;
p = p->next;
}
p = ggc_alloc_stub_list ();
p->next = stub_head;
p->name = name;
stub_head = p;
}
#ifdef CXX_WRAP_SPEC_LIST #ifdef CXX_WRAP_SPEC_LIST
/* Hash table equality helper function. */ /* Hash table equality helper function. */
...@@ -781,6 +815,30 @@ i386_pe_file_end (void) ...@@ -781,6 +815,30 @@ i386_pe_file_end (void)
(q->is_data ? ",data" : "")); (q->is_data ? ",data" : ""));
} }
} }
if (stub_head)
{
struct stub_list *q;
for (q = stub_head; q != NULL; q = q->next)
{
const char *name = q->name;
const char *oname;
if (name[0] == '*')
++name;
oname = name;
if (name[0] == '.')
++name;
if (strncmp (name, "refptr.", 7) != 0)
continue;
name += 7;
fprintf (asm_out_file, "\t.section\t.rdata$%s, \"dr\"\n"
"\t.globl\t%s\n"
"\t.linkonce\tdiscard\n", oname, oname);
fprintf (asm_out_file, "%s:\n\t.quad\t%s\n", oname, name);
}
}
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment