Index: gcc/config/i386/predicates.md =================================================================== --- gcc/config/i386/predicates.md (revision 196791) +++ gcc/config/i386/predicates.md (working copy) @@ -137,6 +137,8 @@ switch (XINT (XEXP (op, 0), 1)) { case UNSPEC_GOTPCREL: + if (DEFAULT_ABI == MS_ABI) + break; case UNSPEC_DTPOFF: case UNSPEC_GOTNTPOFF: case UNSPEC_NTPOFF: @@ -436,6 +438,9 @@ if (SYMBOL_REF_TLS_MODEL (op)) return false; + /* Dll-imported symbols are always external. */ + if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P (op)) + return false; if (SYMBOL_REF_LOCAL_P (op)) return true; Index: gcc/config/i386/winnt.c =================================================================== --- gcc/config/i386/winnt.c (revision 196791) +++ gcc/config/i386/winnt.c (working copy) @@ -646,8 +646,18 @@ 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 +688,21 @@ export_head = p; } +void +i386_pe_record_stub (const char *name) +{ + struct stub_list *p; + + if (!name || *name == 0) + return; + + 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 +806,30 @@ (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); + } + } } Index: gcc/config/i386/xm-mingw32.h =================================================================== --- gcc/config/i386/xm-mingw32.h (revision 196791) +++ gcc/config/i386/xm-mingw32.h (working copy) @@ -29,6 +29,12 @@ /* The st_ino field of struct stat is always 0. */ #define HOST_LACKS_INODE_NUMBERS +#ifdef __MINGW32__ +#undef __USE_MINGW_ANSI_STDIO +#define __USE_MINGW_ANSI_STDIO 1 +#else /* MSVCRT does not support the "ll" format specifier for printing "long long" values. Instead, we use "I64". */ #define HOST_LONG_LONG_FORMAT "I64" +#endif + Index: gcc/config/i386/i386-protos.h =================================================================== --- gcc/config/i386/i386-protos.h (revision 196791) +++ gcc/config/i386/i386-protos.h (working copy) @@ -260,6 +260,7 @@ 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 196791) +++ gcc/config/i386/i386.c (working copy) @@ -64,6 +64,8 @@ #include "tree-flow.h" static rtx legitimize_dllimport_symbol (rtx, bool); +static rtx legitimize_faraddr_symbol (rtx, bool); +static rtx legitimize_pe_coff_symbol (rtx, bool); #ifndef CHECK_STACK_LIMIT #define CHECK_STACK_LIMIT (-1) @@ -3234,7 +3236,11 @@ 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; +#ifdef TARGET_CYGWIN64 + ix86_cmodel = CM_MEDIUM_PIC, flag_pic = 1; +#else + ix86_cmodel = CM_MEDIUM_PIC, flag_pic = 1; +#endif else if (TARGET_64BIT && TARGET_RDOS) ix86_cmodel = CM_MEDIUM_PIC, flag_pic = 1; else if (TARGET_64BIT) @@ -10575,7 +10581,9 @@ ix86_emit_save_sse_regs_using_mov (frame.sse_reg_save_offset); pic_reg_used = false; + /* We don't use pic-register for x64 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 +11388,8 @@ 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 +12007,20 @@ 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 +12108,39 @@ /* 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 +12201,7 @@ 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 +12536,17 @@ } #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 +12577,10 @@ 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 +12611,22 @@ 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 +12695,7 @@ /* 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 +12839,7 @@ if (!TARGET_64BIT) { - if (flag_pic) + if (flag_pic && DEFAULT_ABI != MS_ABI) pic = pic_offset_table_rtx; else { @@ -13006,7 +13054,7 @@ 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 +13087,11 @@ 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 +13101,14 @@ 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 +13119,24 @@ 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_faraddr_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), 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 +13147,7 @@ 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 +13155,47 @@ return x; } + +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_faraddr_symbol (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_faraddr_symbol (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 +13236,9 @@ 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 +16054,8 @@ if (GET_CODE (op1) == SYMBOL_REF) { + rtx tmp; + model = SYMBOL_REF_TLS_MODEL (op1); if (model) { @@ -15953,9 +16065,8 @@ 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 +16074,13 @@ { 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 +23686,7 @@ 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 +23728,8 @@ 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 +23743,7 @@ } 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 +35071,7 @@ 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 196791) +++ gcc/config/i386/i386.h (working copy) @@ -1179,7 +1179,8 @@ #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 @@ #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/cygming.h =================================================================== --- gcc/config/i386/cygming.h (revision 196791) +++ gcc/config/i386/cygming.h (working copy) @@ -474,5 +474,8 @@ #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