Patchwork [i386,windows] : Fix PR/52790 also required for workig upcoming cygwin x64 target

login
register
mail settings
Submitter Kai Tietz
Date March 22, 2013, 9:27 a.m.
Message ID <CAEwic4a29_oyZdWL7S97gX+6Q5rYjnNO1BckZJ7S1peNA6wung@mail.gmail.com>
Download mbox | patch
Permalink /patch/229933/
State New
Headers show

Comments

Kai Tietz - March 22, 2013, 9:27 a.m.
Hi,

this patch fixes PR/52790 and supports for x64 Windows targets the use
of large and medium code-model.
This feature is required for upcoming new cygwin x64 target, which
uses full 48-bit available address-space of x64 Windows.
The cygwin-target depends on pseudo-relocation-feature, which operates
on instruction relocations.  This can lead for x86_64 to issues, due
instructions are in general signed-32bit-pc-relative relocated.  So
distances can become too wide for pseudo-relocation.
Due for functions we generate anyway on pe-coff targets jump-stubs, we
just need to make sure that variables are accessed via
reference-pointer-variables.  So we add for them in medium model
.refptr-variables.
In large model we using for external (therefore possibly
pseudo-relocated) symbols also indirect-addressing via refptr-stubs.

To avoid same issues as we noticed on cygwin64, I want to change
code-model default to medium also for native-windows x64 target.

ChangeLog

2013-03-22  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.

This patch is tested for x86_64-pc-cygwin, x86_64-w64-mingw32.
Additional tested for x86_64-unknown-linux-gnu to see that no
regression were introduced by this patch.

Ok for apply?

Regards,
Kai
Kai Tietz - March 28, 2013, 1:35 p.m.
Ping
Kai Tietz - April 2, 2013, 1:28 p.m.
Ping ^2

----- Original Message -----
> From: "Kai Tietz" <ktietz70@googlemail.com>
> To: "GCC Patches" <gcc-patches@gcc.gnu.org>
> Cc: "Richard Henderson" <rth@redhat.com>
> Sent: Thursday, March 28, 2013 2:35:15 PM
> Subject: Re: [patch i386 windows]: Fix PR/52790 also required for workig upcoming cygwin x64 target
> 
> Ping
>
Richard Henderson - April 2, 2013, 5:18 p.m.
On 2013-03-22 02:27, Kai Tietz wrote:
> Hi,
>
> this patch fixes PR/52790 and supports for x64 Windows targets the use
> of large and medium code-model.
> This feature is required for upcoming new cygwin x64 target, which
> uses full 48-bit available address-space of x64 Windows.
> The cygwin-target depends on pseudo-relocation-feature, which operates
> on instruction relocations.  This can lead for x86_64 to issues, due
> instructions are in general signed-32bit-pc-relative relocated.  So
> distances can become too wide for pseudo-relocation.
> Due for functions we generate anyway on pe-coff targets jump-stubs, we
> just need to make sure that variables are accessed via
> reference-pointer-variables.  So we add for them in medium model
> .refptr-variables.
> In large model we using for external (therefore possibly
> pseudo-relocated) symbols also indirect-addressing via refptr-stubs.
>
> To avoid same issues as we noticed on cygwin64, I want to change
> code-model default to medium also for native-windows x64 target.
>
> ChangeLog
>
> 2013-03-22  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.

Ok.


r~

Patch

Index: gcc/config/i386/cygming.h
===================================================================
--- gcc/config/i386/cygming.h	(Revision 196898)
+++ gcc/config/i386/cygming.h	(Arbeitskopie)
@@ -474,5 +474,8 @@  do {						\
 #undef TARGET_ASM_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.  */
 #define STACK_CHECK_STATIC_BUILTIN 1
Index: gcc/config/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h	(Revision 196898)
+++ gcc/config/i386/i386-protos.h	(Arbeitskopie)
@@ -260,6 +260,7 @@  extern void i386_pe_end_function (FILE *, const ch
 extern void i386_pe_assemble_visibility (tree, int);
 extern tree i386_pe_mangle_decl_assembler_name (tree, tree);
 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_end_prologue (FILE *);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(Revision 196898)
+++ gcc/config/i386/i386.c	(Arbeitskopie)
@@ -64,6 +64,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-flow.h"

 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
 #define CHECK_STACK_LIMIT (-1)
@@ -3233,9 +3235,7 @@  ix86_option_override_internal (bool main_args_p)
 	 use of rip-relative addressing.  This eliminates fixups that
 	 would otherwise be needed if this object is to be placed in a
 	 DLL, and is essentially just as efficient as direct addressing.  */
-      if (TARGET_64BIT && DEFAULT_ABI == MS_ABI)
-	ix86_cmodel = CM_SMALL_PIC, flag_pic = 1;
-      else if (TARGET_64BIT && TARGET_RDOS)
+      if (TARGET_64BIT && (TARGET_RDOS || DEFAULT_ABI == MS_ABI))
 	ix86_cmodel = CM_MEDIUM_PIC, flag_pic = 1;
       else if (TARGET_64BIT)
 	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
@@ -10575,7 +10575,9 @@  ix86_expand_prologue (void)
     ix86_emit_save_sse_regs_using_mov (frame.sse_reg_save_offset);

   pic_reg_used = false;
+  /* We don't use pic-register for pe-coff target.  */
   if (pic_offset_table_rtx
+      && DEFAULT_ABI != MS_ABI
       && (df_regs_ever_live_p (REAL_PIC_OFFSET_TABLE_REGNUM)
 	  || crtl->profile))
     {
@@ -11380,7 +11382,8 @@  ix86_expand_split_stack_prologue (void)
 	  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;

@@ -11998,7 +12001,20 @@  ix86_cannot_force_const_mem (enum machine_mode mod
   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
    when generating PIC code.  It is given that flag_pic is on and
    that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
@@ -12086,11 +12102,39 @@  legitimate_pic_address_disp_p (rtx disp)
 	  /* FALLTHRU */

 	case SYMBOL_REF:
-	  /* TLS references should always be enclosed in UNSPEC.  */
-	  if (SYMBOL_REF_TLS_MODEL (op0))
+	  /* TLS references should always be enclosed in UNSPEC.
+	     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;
-	  if (!SYMBOL_REF_FAR_ADDR_P (op0) && SYMBOL_REF_LOCAL_P (op0)
-	      && ix86_cmodel != CM_LARGE_PIC)
+
+	  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)
 	    return true;
 	  break;

@@ -12151,7 +12195,7 @@  legitimate_pic_address_disp_p (rtx disp)
       if ((GET_CODE (XVECEXP (disp, 0, 0)) == SYMBOL_REF
 	   || GET_CODE (XVECEXP (disp, 0, 0)) == LABEL_REF)
 	  && !TARGET_64BIT)
-        return gotoff_operand (XVECEXP (disp, 0, 0), Pmode);
+        return DEFAULT_ABI != MS_ABI && gotoff_operand (XVECEXP
(disp, 0, 0), Pmode);
       return false;
     case UNSPEC_GOTTPOFF:
     case UNSPEC_GOTNTPOFF:
@@ -12486,11 +12530,17 @@  legitimize_pic_address (rtx orig, rtx reg)
     }
 #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))
     new_rtx = addr;
-  else if (TARGET_64BIT
-	   && ix86_cmodel != CM_SMALL_PIC
-	   && gotoff_operand (addr, Pmode))
+  else if (TARGET_64BIT && DEFAULT_ABI != MS_ABI
+	   && ix86_cmodel != CM_SMALL_PIC && gotoff_operand (addr, Pmode))
     {
       rtx tmpreg;
       /* This symbol may be referenced via a displacement from the PIC
@@ -12521,9 +12571,10 @@  legitimize_pic_address (rtx orig, rtx reg)
 					 tmpreg, 1, OPTAB_DIRECT);
 	  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
 	 base address (@GOTOFF).  */
@@ -12554,31 +12605,22 @@  legitimize_pic_address (rtx orig, rtx reg)
 	      see gotoff_operand.  */
 	   || (TARGET_VXWORKS_RTP && GET_CODE (addr) == LABEL_REF))
     {
-      if (TARGET_DLLIMPORT_DECL_ATTRIBUTES)
-        {
-          if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_DLLIMPORT_P (addr))
-            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));
-            }
-        }
+      rtx tmp = legitimize_pe_coff_symbol (addr, true);
+      if (tmp)
+        return tmp;

       /* For x64 PE-COFF there is no GOT table.  So we use address
          directly.  */
       if (TARGET_64BIT && DEFAULT_ABI == MS_ABI)
-      {
+	{
 	  new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PCREL);
 	  new_rtx = gen_rtx_CONST (Pmode, new_rtx);

 	  if (reg == 0)
 	    reg = gen_reg_rtx (Pmode);
-  	  emit_move_insn (reg, new_rtx);
+	  emit_move_insn (reg, new_rtx);
 	  new_rtx = reg;
-      }
+	}
       else if (TARGET_64BIT && ix86_cmodel != CM_LARGE_PIC)
 	{
 	  new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTPCREL);
@@ -12647,7 +12689,7 @@  legitimize_pic_address (rtx orig, rtx reg)

 	  /* Check first to see if this is a constant offset from a @GOTOFF
 	     symbol reference.  */
-	  if (gotoff_operand (op0, Pmode)
+	  if (DEFAULT_ABI != MS_ABI && gotoff_operand (op0, Pmode)
 	      && CONST_INT_P (op1))
 	    {
 	      if (!TARGET_64BIT)
@@ -12791,7 +12833,7 @@  legitimize_tls_address (rtx x, enum tls_model mode

       if (!TARGET_64BIT)
 	{
-	  if (flag_pic)
+	  if (flag_pic && DEFAULT_ABI != MS_ABI)
 	    pic = pic_offset_table_rtx;
 	  else
 	    {
@@ -13000,13 +13042,14 @@  legitimize_tls_address (rtx x, enum tls_model mode
 }

 /* 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)))
   htab_t dllimport_map;

 static tree
-get_dllimport_decl (tree decl)
+get_dllimport_decl (tree decl, bool beimport)
 {
   struct tree_map *h, in;
   void **loc;
@@ -13039,8 +13082,11 @@  static tree

   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   name = targetm.strip_name_encoding (name);
-  prefix = name[0] == FASTCALL_PREFIX || user_label_prefix[0] == 0
-    ? "*__imp_" : "*__imp__";
+  if (beimport)
+    prefix = name[0] == FASTCALL_PREFIX || user_label_prefix[0] == 0
+      ? "*__imp_" : "*__imp__";
+  else
+    prefix = user_label_prefix[0] == 0 ? "*.refptr." : "*refptr.";
   namelen = strlen (name);
   prefixlen = strlen (prefix);
   imp_name = (char *) alloca (namelen + prefixlen + 1);
@@ -13050,7 +13096,14 @@  static tree
   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;
+  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);
   set_mem_alias_set (rtl, ix86_GOT_alias_set ());
@@ -13061,6 +13114,24 @@  static tree
   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
    true if we require the result be a register.  */

@@ -13071,7 +13142,7 @@  legitimize_dllimport_symbol (rtx symbol, bool want
   rtx x;

   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);
   if (want_reg)
@@ -13079,6 +13150,50 @@  legitimize_dllimport_symbol (rtx symbol, bool want
   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
    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.
@@ -13119,16 +13234,9 @@  ix86_legitimize_address (rtx x, rtx oldx ATTRIBUTE

   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));
-	}
+      rtx tmp = legitimize_pe_coff_symbol (x, true);
+      if (tmp)
+        return tmp;
     }

   if (flag_pic && SYMBOLIC_CONST (x))
@@ -15944,6 +16052,8 @@  ix86_expand_move (enum machine_mode mode, rtx oper

   if (GET_CODE (op1) == SYMBOL_REF)
     {
+      rtx tmp;
+
       model = SYMBOL_REF_TLS_MODEL (op1);
       if (model)
 	{
@@ -15953,9 +16063,8 @@  ix86_expand_move (enum machine_mode mode, rtx oper
 	    return;
 	  op1 = convert_to_mode (mode, op1, 1);
 	}
-      else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
-	       && SYMBOL_REF_DLLIMPORT_P (op1))
-	op1 = legitimize_dllimport_symbol (op1, false);
+      else if ((tmp = legitimize_pe_coff_symbol (op1, false)) != NULL_RTX)
+	op1 = tmp;
     }
   else if (GET_CODE (op1) == CONST
 	   && GET_CODE (XEXP (op1, 0)) == PLUS
@@ -15963,14 +16072,13 @@  ix86_expand_move (enum machine_mode mode, rtx oper
     {
       rtx addend = XEXP (XEXP (op1, 0), 1);
       rtx symbol = XEXP (XEXP (op1, 0), 0);
-      rtx tmp = NULL;
+      rtx tmp;

       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);
+      else
+        tmp = legitimize_pe_coff_symbol (symbol, true);

       if (tmp)
 	{
@@ -23576,7 +23684,7 @@  construct_plt_address (rtx symbol)
   rtx tmp, unspec;

   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);

   tmp = gen_reg_rtx (Pmode);
@@ -23618,7 +23726,8 @@  ix86_expand_call (rtx retval, rtx fnaddr, rtx call
   else
     {
       /* 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
 	  && ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0)))
 	use_reg (&use, pic_offset_table_rtx);
@@ -23632,6 +23741,7 @@  ix86_expand_call (rtx retval, rtx fnaddr, rtx call
     }

   if (ix86_cmodel == CM_LARGE_PIC
+      && DEFAULT_ABI != MS_ABI
       && MEM_P (fnaddr)
       && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
       && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
@@ -34959,7 +35069,7 @@  x86_output_mi_thunk (FILE *file,
   if (TARGET_64BIT)
     {
       if (!flag_pic || targetm.binds_local_p (function)
-	  || cfun->machine->call_abi == MS_ABI)
+	  || DEFAULT_ABI == MS_ABI)
 	;
       else
 	{
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	(Revision 196898)
+++ gcc/config/i386/i386.h	(Arbeitskopie)
@@ -1179,7 +1179,8 @@  enum target_cpu_default
 #define REAL_PIC_OFFSET_TABLE_REGNUM  BX_REG

 #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			\
    : reload_completed ? REGNO (pic_offset_table_rtx)	\
    : REAL_PIC_OFFSET_TABLE_REGNUM)
@@ -2379,6 +2380,10 @@  struct GTY(()) machine_function {
 #define SYMBOL_REF_DLLEXPORT_P(X) \
 	((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_dispatch_window (int);

Index: gcc/config/i386/winnt.c
===================================================================
--- gcc/config/i386/winnt.c	(Revision 196898)
+++ gcc/config/i386/winnt.c	(Arbeitskopie)
@@ -554,6 +554,7 @@  i386_pe_asm_named_section (const char *name, unsig
     }
 }

+
 /* Beware, DECL may be NULL if compile_file() is emitting the LTO marker.  */

 void
@@ -646,8 +647,18 @@  struct GTY(()) export_list
   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 stub_list *stub_head;
+
 /* Assemble an export symbol entry.  We need to keep a list of
    these, so that we can output the export list at the end of the
    assembly.  We used to output these export symbols in each function,
@@ -678,6 +689,30 @@  i386_pe_maybe_record_exported_symbol (tree decl, c
   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

 /*  Hash table equality helper function.  */
@@ -781,6 +819,30 @@  i386_pe_file_end (void)
 		   (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);
+	}
+    }
 }