From ccf8e764e9ca5a530de57cdabdb7123734de2d4a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 30 Mar 2007 14:45:03 -0700 Subject: [PATCH] cygming.h (DWARF2_DEBUGGING_INFO): Enable by default for 64-bit. gcc/ * config/i386/cygming.h (DWARF2_DEBUGGING_INFO): Enable by default for 64-bit. (PREFERRED_DEBUGGING_TYPE): Prefer dwarf2 for 64-bit. (TARGET_64BIT_MS_ABI): New. (DBX_REGISTER_NUMBER): Handle 64-bit. (SIZE_TYPE, PTRDIFF_TYPE): Use long long for 64-bit. (LONG_TYPE_SIZE): Force to 32. (REG_PARM_STACK_SPACE): New. (OUTGOING_REG_PARM_STACK_SPACE): New. (REGPARM_MAX, SSE_REGPARM_MAX): New. (HANDLE_PRAGMA_PUSH_POP_MACRO): New. (STACK_BOUNDARY): Use 128 for 64-bit. * config/i386/cygwin.asm: Use push/ret to preserve call stack. Add 64-bit implementation. * config/i386/gthr-win32.c (__gthr_win32_key_create): Mark dtor argument unused. * config/i386/i386.c (x86_64_ms_abi_int_parameter_registers): New. (override_options): Set ix86_cmodel for TARGET_64BIT_MS_ABI. Warn for -mregparm, -mrtd in 64-bit mode; force ix86_regparm for 64-bit; use TARGET_SUBTARGET64_DEFAULT. (ix86_handle_cconv_attribute): Don't warn when ignoring if TARGET_64BIT_MS_ABI. (ix86_function_arg_regno_p): Handle TARGET_64BIT_MS_ABI. (ix86_pass_by_reference): Likewise. (ix86_function_value_regno_p): Likewise. (ix86_build_builtin_va_list): Likewise. (ix86_va_start, ix86_gimplify_va_arg): Likewise. (function_arg_advance_ms_64): New. (function_arg_advance): Call it. (function_arg_ms_64): New. (function_arg): Call it. (function_value_ms_64): New. (ix86_function_value_1): Call it. (return_in_memory_ms_64): New. (ix86_return_in_memory): Call it. (setup_incoming_varargs_ms_64): New. (ix86_setup_incoming_varargs): Call it. (ix86_expand_prologue): Handle 64-bit stack probing. (legitimize_pic_address): Handle TARGET_64BIT_MS_ABI. (output_pic_addr_const): Likewise. (x86_this_parameter): Likewise. (x86_output_mi_thunk): Likewise. (x86_function_profiler): Likewise. (TARGET_STRICT_ARGUMENT_NAMING): New. * config/i386/i386.h (TARGET_SUBTARGET64_DEFAULT): New. (TARGET_64BIT_MS_ABI): New. (CONDITIONAL_REGISTER_USAGE): Handle TARGET_64BIT_MS_ABI. * config/i386/i386.md (allocate_stack_worker): Remove. (allocate_stack_worker_32): Rename from allocate_stack_worker_1; describe the clobber of eax without a match_scratch. (allocate_stack_worker_postreload): Remove. (allocate_stack_worker_64): Rename from allocate_stack_worker_rex64; describe the clobbers of rax, r10, r11 properly; use __chkstk symbol. (allocate_stack_worker_rex64_postreload): Remove. (allocate_stack): Handle 64-bit. * config/i386/i386elf (TARGET_SUBTARGET_DEFAULT): Remove. * config/i386/mingw32.h (TARGET_VERSION): Set correctly for 64-bit. (EXTRA_OS_CPP_BUILTINS): Handle 64-bit. (STANDARD_INCLUDE_DIR): Handle TARGET_64BIT_DEFAULT. (STANDARD_STARTFILE_PREFIX_1): Likewise. * config/i386/unix.h (TARGET_SUBTARGET64_DEFAULT): New. * config.build (x86_64-*-mingw*): New host. * config.host (x86_64-*-mingw*): New host. * config.gcc (x86_64-*-mingw*): New target. * gthr-win32.h (__gthread_key_create): Mark dtor unused. libgcc/ * config.host (x86_64-*-mingw*): New target. Co-Authored-By: Kai Tietz From-SVN: r123372 --- gcc/ChangeLog | 77 +++++++++ gcc/config.build | 2 +- gcc/config.gcc | 2 +- gcc/config.host | 2 +- gcc/config/i386/cygming.h | 59 +++++-- gcc/config/i386/cygwin.asm | 71 ++++++-- gcc/config/i386/gthr-win32.c | 3 +- gcc/config/i386/i386.c | 311 +++++++++++++++++++++++++++-------- gcc/config/i386/i386.h | 80 +++++---- gcc/config/i386/i386.md | 96 ++++------- gcc/config/i386/i386elf.h | 5 - gcc/config/i386/mingw32.h | 25 ++- gcc/config/i386/unix.h | 7 +- gcc/gthr-win32.h | 3 +- libgcc/ChangeLog | 4 + libgcc/config.host | 2 +- 16 files changed, 542 insertions(+), 207 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1f01dac48ea..b048bc7532a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,80 @@ +2007-03-30 Richard Henderson + + * tree-ssa-loop-ivopts.c: Include target.h. + (produce_memory_decl_rtl): Pass the rtx through encode_section_info. + (get_address_cost): Force SYMBOL_FLAG_LOCAL set. + (force_expr_to_var_cost): Use produce_memory_decl_rtl. + * Makefile.in (tree-ssa-loop-ivopts.o): Depend on TARGET_H. + +2007-03-30 Richard Henderson + Kai Tietz + + * config/i386/cygming.h (DWARF2_DEBUGGING_INFO): Enable by + default for 64-bit. + (PREFERRED_DEBUGGING_TYPE): Prefer dwarf2 for 64-bit. + (TARGET_64BIT_MS_ABI): New. + (DBX_REGISTER_NUMBER): Handle 64-bit. + (SIZE_TYPE, PTRDIFF_TYPE): Use long long for 64-bit. + (LONG_TYPE_SIZE): Force to 32. + (REG_PARM_STACK_SPACE): New. + (OUTGOING_REG_PARM_STACK_SPACE): New. + (REGPARM_MAX, SSE_REGPARM_MAX): New. + (HANDLE_PRAGMA_PUSH_POP_MACRO): New. + (STACK_BOUNDARY): Use 128 for 64-bit. + * config/i386/cygwin.asm: Use push/ret to preserve call stack. + Add 64-bit implementation. + * config/i386/gthr-win32.c (__gthr_win32_key_create): Mark dtor + argument unused. + * config/i386/i386.c (x86_64_ms_abi_int_parameter_registers): New. + (override_options): Set ix86_cmodel for TARGET_64BIT_MS_ABI. + Warn for -mregparm, -mrtd in 64-bit mode; force ix86_regparm + for 64-bit; use TARGET_SUBTARGET64_DEFAULT. + (ix86_handle_cconv_attribute): Don't warn when ignoring if + TARGET_64BIT_MS_ABI. + (ix86_function_arg_regno_p): Handle TARGET_64BIT_MS_ABI. + (ix86_pass_by_reference): Likewise. + (ix86_function_value_regno_p): Likewise. + (ix86_build_builtin_va_list): Likewise. + (ix86_va_start, ix86_gimplify_va_arg): Likewise. + (function_arg_advance_ms_64): New. + (function_arg_advance): Call it. + (function_arg_ms_64): New. + (function_arg): Call it. + (function_value_ms_64): New. + (ix86_function_value_1): Call it. + (return_in_memory_ms_64): New. + (ix86_return_in_memory): Call it. + (setup_incoming_varargs_ms_64): New. + (ix86_setup_incoming_varargs): Call it. + (ix86_expand_prologue): Handle 64-bit stack probing. + (legitimize_pic_address): Handle TARGET_64BIT_MS_ABI. + (output_pic_addr_const): Likewise. + (x86_this_parameter): Likewise. + (x86_output_mi_thunk): Likewise. + (x86_function_profiler): Likewise. + (TARGET_STRICT_ARGUMENT_NAMING): New. + * config/i386/i386.h (TARGET_SUBTARGET64_DEFAULT): New. + (TARGET_64BIT_MS_ABI): New. + (CONDITIONAL_REGISTER_USAGE): Handle TARGET_64BIT_MS_ABI. + * config/i386/i386.md (allocate_stack_worker): Remove. + (allocate_stack_worker_32): Rename from allocate_stack_worker_1; + describe the clobber of eax without a match_scratch. + (allocate_stack_worker_postreload): Remove. + (allocate_stack_worker_64): Rename from allocate_stack_worker_rex64; + describe the clobbers of rax, r10, r11 properly; use __chkstk symbol. + (allocate_stack_worker_rex64_postreload): Remove. + (allocate_stack): Handle 64-bit. + * config/i386/i386elf (TARGET_SUBTARGET_DEFAULT): Remove. + * config/i386/mingw32.h (TARGET_VERSION): Set correctly for 64-bit. + (EXTRA_OS_CPP_BUILTINS): Handle 64-bit. + (STANDARD_INCLUDE_DIR): Handle TARGET_64BIT_DEFAULT. + (STANDARD_STARTFILE_PREFIX_1): Likewise. + * config/i386/unix.h (TARGET_SUBTARGET64_DEFAULT): New. + * config.build (x86_64-*-mingw*): New host. + * config.host (x86_64-*-mingw*): New host. + * config.gcc (x86_64-*-mingw*): New target. + * gthr-win32.h (__gthread_key_create): Mark dtor unused. + 2007-03-30 Richard Henderson Kai Tietz diff --git a/gcc/config.build b/gcc/config.build index 4a8f409e431..bfc0d435d09 100644 --- a/gcc/config.build +++ b/gcc/config.build @@ -77,7 +77,7 @@ case $build in build_xm_file=i386/xm-cygwin.h build_exeext=.exe ;; - i[34567]86-*-mingw32*) + i[34567]86-*-mingw32* | x86_64-*-mingw*) build_xm_file=i386/xm-mingw32.h build_exeext=.exe ;; diff --git a/gcc/config.gcc b/gcc/config.gcc index d1deffc92a4..7cf32997eaa 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -1343,7 +1343,7 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*) thread_file='posix' fi ;; -i[34567]86-*-mingw32*) +i[34567]86-*-mingw32* | x86_64-*-mingw32*) tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h" xm_file=i386/xm-mingw32.h tmake_file="i386/t-cygming i386/t-mingw32" diff --git a/gcc/config.host b/gcc/config.host index 8e6119ba10b..150a4336496 100644 --- a/gcc/config.host +++ b/gcc/config.host @@ -168,7 +168,7 @@ case ${host} in host_xmake_file="${host_xmake_file} i386/x-cygwin" host_exeext=.exe ;; - i[34567]86-*-mingw32*) + i[34567]86-*-mingw32* | x86_64-*-mingw*) host_xm_file=i386/xm-mingw32.h host_xmake_file="${host_xmake_file} i386/x-mingw32" host_exeext=.exe diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h index aa4ca2a925d..f7e8febb16e 100644 --- a/gcc/config/i386/cygming.h +++ b/gcc/config/i386/cygming.h @@ -21,18 +21,35 @@ along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#if TARGET_64BIT_DEFAULT +#ifndef DWARF2_DEBUGGING_INFO +#define DWARF2_DEBUGGING_INFO 1 +#endif +#ifndef DWARF2_UNWIND_INFO +#define DWARF2_UNWIND_INFO 1 +#endif +#endif + #define DBX_DEBUGGING_INFO 1 #define SDB_DEBUGGING_INFO 1 #undef PREFERRED_DEBUGGING_TYPE +#if TARGET_64BIT_DEFAULT +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG +#else #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG +#endif + +#undef TARGET_64BIT_MS_ABI +#define TARGET_64BIT_MS_ABI TARGET_64BIT #ifdef HAVE_GAS_PE_SECREL32_RELOC #define DWARF2_DEBUGGING_INFO 1 #undef DBX_REGISTER_NUMBER -#define DBX_REGISTER_NUMBER(n) (write_symbols == DWARF2_DEBUG \ - ? svr4_dbx_register_map[n] \ - : dbx_register_map[n]) +#define DBX_REGISTER_NUMBER(n) \ + (TARGET_64BIT ? dbx64_register_map[n] \ + : (write_symbols == DWARF2_DEBUG \ + ? svr4_dbx_register_map[n] : dbx_register_map[n])) /* Use section relative relocations for debugging offsets. Unlike other targets that fake this by putting the section VMA at 0, PE @@ -97,14 +114,32 @@ Boston, MA 02110-1301, USA. */ #undef MATH_LIBRARY #define MATH_LIBRARY "" -#define SIZE_TYPE "unsigned int" -#define PTRDIFF_TYPE "int" +#define SIZE_TYPE (TARGET_64BIT ? "long long unsigned int" : "unsigned int") +#define PTRDIFF_TYPE (TARGET_64BIT ? "long long int" : "int") + #define WCHAR_TYPE_SIZE 16 #define WCHAR_TYPE "short unsigned int" +/* Windows64 continues to use a 32-bit long type. */ +#undef LONG_TYPE_SIZE +#define LONG_TYPE_SIZE 32 + +#undef REG_PARM_STACK_SPACE +#define REG_PARM_STACK_SPACE(FNDECL) (TARGET_64BIT_MS_ABI ? 32 : 0) + +#undef OUTGOING_REG_PARM_STACK_SPACE +#define OUTGOING_REG_PARM_STACK_SPACE (TARGET_64BIT_MS_ABI ? 1 : 0) + +#undef REGPARM_MAX +#define REGPARM_MAX (TARGET_64BIT_MS_ABI ? 4 : 3) + +#undef SSE_REGPARM_MAX +#define SSE_REGPARM_MAX (TARGET_64BIT_MS_ABI ? 4 : TARGET_SSE ? 3 : 0) /* Enable parsing of #pragma pack(push,) and #pragma pack(pop). */ #define HANDLE_PRAGMA_PACK_PUSH_POP 1 +/* Enable push_macro & pop_macro */ +#define HANDLE_PRAGMA_PUSH_POP_MACRO 1 union tree_node; #define TREE union tree_node * @@ -166,19 +201,21 @@ do { \ } while (0) -/* Emit code to check the stack when allocating more that 4000 +/* Emit code to check the stack when allocating more than 4000 bytes in one go. */ - #define CHECK_STACK_LIMIT 4000 +#undef STACK_BOUNDARY +#define STACK_BOUNDARY (TARGET_64BIT_MS_ABI ? 128 : BITS_PER_WORD) + /* By default, target has a 80387, uses IEEE compatible arithmetic, returns float values in the 387 and needs stack probes. We also align doubles to 64-bits for MSVC default compatibility. */ #undef TARGET_SUBTARGET_DEFAULT #define TARGET_SUBTARGET_DEFAULT \ - (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE \ - | MASK_ALIGN_DOUBLE) + (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS \ + | MASK_STACK_PROBE | MASK_ALIGN_DOUBLE) /* This is how to output an assembler line that says to advance the location counter @@ -245,7 +282,9 @@ do { \ /* DWARF2 Unwinding doesn't work with exception handling yet. To make it work, we need to build a libgcc_s.dll, and dcrt0.o should be changed to call __register_frame_info/__deregister_frame_info. */ +#ifndef DWARF2_UNWIND_INFO #define DWARF2_UNWIND_INFO 0 +#endif /* Don't assume anything about the header files. */ #define NO_IMPLICIT_EXTERN_C @@ -346,8 +385,8 @@ do { \ #define TARGET_USE_LOCAL_THUNK_ALIAS_P(DECL) (!DECL_ONE_ONLY (DECL)) #define SUBTARGET_ATTRIBUTE_TABLE \ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ \ { "selectany", 0, 0, true, false, false, ix86_handle_selectany_attribute } + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ /* mcount() does not need a counter variable. */ #undef NO_PROFILE_COUNTERS diff --git a/gcc/config/i386/cygwin.asm b/gcc/config/i386/cygwin.asm index 5b656892d5f..371feae8864 100644 --- a/gcc/config/i386/cygwin.asm +++ b/gcc/config/i386/cygwin.asm @@ -42,27 +42,66 @@ .global ___chkstk .global __alloca +#ifndef _WIN64 ___chkstk: __alloca: - pushl %ecx /* save temp */ - movl %esp,%ecx /* get sp */ - addl $0x8,%ecx /* and point to return addr */ + pushl %ecx /* save temp */ + leal 8(%esp), %ecx /* point past return addr */ + cmpl $0x1000, %eax /* > 4k ?*/ + jb Ldone -probe: cmpl $0x1000,%eax /* > 4k ?*/ - jb done +Lprobe: + subl $0x1000, %ecx /* yes, move pointer down 4k*/ + orl $0x0, (%ecx) /* probe there */ + subl $0x1000, %eax /* decrement count */ + cmpl $0x1000, %eax + ja Lprobe /* and do it again */ - subl $0x1000,%ecx /* yes, move pointer down 4k*/ - orl $0x0,(%ecx) /* probe there */ - subl $0x1000,%eax /* decrement count */ - jmp probe /* and do it again */ +Ldone: + subl %eax, %ecx + orl $0x0, (%ecx) /* less than 4k, just peek here */ -done: subl %eax,%ecx - orl $0x0,(%ecx) /* less that 4k, just peek here */ + movl %esp, %eax /* save old stack pointer */ + movl %ecx, %esp /* decrement stack */ + movl (%eax), %ecx /* recover saved temp */ + movl 4(%eax), %eax /* recover return address */ - movl %esp,%eax - movl %ecx,%esp /* decrement stack */ + /* Push the return value back. Doing this instead of just + jumping to %eax preserves the cached call-return stack + used by most modern processors. */ + pushl %eax + ret +#else +/* __alloca is a normal function call, which uses %rcx as the argument. */ +__alloca: + movq %rcx, %rax + /* FALLTHRU */ - movl (%eax),%ecx /* recover saved temp */ - movl 4(%eax),%eax /* get return address */ - jmp *%eax +/* ___chkstk is a *special* function call, which uses %rax as the argument. + We avoid clobbering the 4 integer argument registers, %rcx, %rdx, + %r8 and %r9, which leaves us with %rax, %r10, and %r11 to use. */ +___chkstk: + popq %r11 /* pop return address */ + movq %rsp, %r10 /* get sp */ + cmpq $0x1000, %rax /* > 4k ?*/ + jb Ldone + +Lprobe: + subq $0x1000, %r10 /* yes, move pointer down 4k*/ + orl $0x0, (%r10) /* probe there */ + subq $0x1000, %rax /* decrement count */ + cmpq $0x1000, %rax + ja Lprobe /* and do it again */ + +Ldone: + subq %rax, %r10 + orl $0x0, (%r10) /* less than 4k, just peek here */ + movq %r10, %rsp /* decrement stack */ + + /* Push the return value back. Doing this instead of just + jumping to %r11 preserves the cached call-return stack + used by most modern processors. */ + pushq %r11 + ret +#endif #endif diff --git a/gcc/config/i386/gthr-win32.c b/gcc/config/i386/gthr-win32.c index d13b5398c69..c87a771ed8f 100644 --- a/gcc/config/i386/gthr-win32.c +++ b/gcc/config/i386/gthr-win32.c @@ -102,7 +102,8 @@ __gthr_win32_once (__gthread_once_t *once, void (*func) (void)) C++ EH. Mingw uses a thread-support DLL to work-around this problem. */ int -__gthr_win32_key_create (__gthread_key_t *key, void (*dtor) (void *)) +__gthr_win32_key_create (__gthread_key_t *key, + void (*dtor) (void *) __attribute__((unused))) { int status = 0; DWORD tls_index = TlsAlloc (); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index ed25402476a..7106e87eae7 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1308,9 +1308,15 @@ static int const x86_64_int_parameter_registers[6] = FIRST_REX_INT_REG /*R8 */, FIRST_REX_INT_REG + 1 /*R9 */ }; +static int const x86_64_ms_abi_int_parameter_registers[4] = +{ + 2 /*RCX*/, 1 /*RDX*/, + FIRST_REX_INT_REG /*R8 */, FIRST_REX_INT_REG + 1 /*R9 */ +}; + static int const x86_64_int_return_registers[4] = { - 0 /*RAX*/, 1 /*RDI*/, 5 /*RDI*/, 4 /*RSI*/ + 0 /*RAX*/, 1 /*RDX*/, 5 /*RDI*/, 4 /*RSI*/ }; /* The "default" register map used in 64bit mode. */ @@ -1857,9 +1863,16 @@ override_options (void) } else { - ix86_cmodel = CM_32; - if (TARGET_64BIT) + /* For TARGET_64BIT_MS_ABI, force pic on, in order to enable the + 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_MS_ABI) + ix86_cmodel = CM_SMALL_PIC, flag_pic = 1; + else if (TARGET_64BIT) ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL; + else + ix86_cmodel = CM_32; } if (ix86_asm_string != 0) { @@ -1981,15 +1994,16 @@ override_options (void) /* Validate -mregparm= value. */ if (ix86_regparm_string) { + if (TARGET_64BIT) + warning (0, "-mregparm is ignored in 64-bit mode"); i = atoi (ix86_regparm_string); if (i < 0 || i > REGPARM_MAX) error ("-mregparm=%d is not between 0 and %d", i, REGPARM_MAX); else ix86_regparm = i; } - else - if (TARGET_64BIT) - ix86_regparm = REGPARM_MAX; + if (TARGET_64BIT) + ix86_regparm = REGPARM_MAX; /* If the user has provided any of the -malign-* options, warn and use that value only if -falign-* is not set. @@ -2135,18 +2149,16 @@ override_options (void) if (TARGET_64BIT) { - if (TARGET_ALIGN_DOUBLE) - error ("-malign-double makes no sense in the 64bit mode"); if (TARGET_RTD) - error ("-mrtd calling convention not supported in the 64bit mode"); + warning (0, "-mrtd is ignored in 64bit mode"); /* Enable by default the SSE and MMX builtins. Do allow the user to explicitly disable any of these. In particular, disabling SSE and MMX for kernel code is extremely useful. */ target_flags - |= ((MASK_SSE2 | MASK_SSE | MASK_MMX | MASK_128BIT_LONG_DOUBLE) + |= ((MASK_SSE2 | MASK_SSE | MASK_MMX | TARGET_SUBTARGET64_DEFAULT) & ~target_flags_explicit); - } + } else { /* i386 ABI does not specify red zone. It still makes sense to use it @@ -2644,8 +2656,10 @@ ix86_handle_cconv_attribute (tree *node, tree name, if (TARGET_64BIT) { - warning (OPT_Wattributes, "%qs attribute ignored", - IDENTIFIER_POINTER (name)); + /* Do not warn when emulating the MS ABI. */ + if (!TARGET_64BIT_MS_ABI) + warning (OPT_Wattributes, "%qs attribute ignored", + IDENTIFIER_POINTER (name)); *no_add_attrs = true; return NULL_TREE; } @@ -2932,6 +2946,7 @@ bool ix86_function_arg_regno_p (int regno) { int i; + const int *parm_regs; if (!TARGET_64BIT) { @@ -2959,11 +2974,15 @@ ix86_function_arg_regno_p (int regno) } /* RAX is used as hidden argument to va_arg functions. */ - if (regno == 0) + if (!TARGET_64BIT_MS_ABI && regno == 0) return true; + if (TARGET_64BIT_MS_ABI) + parm_regs = x86_64_ms_abi_int_parameter_registers; + else + parm_regs = x86_64_int_parameter_registers; for (i = 0; i < REGPARM_MAX; i++) - if (regno == x86_64_int_parameter_registers[i]) + if (regno == parm_regs[i]) return true; return false; } @@ -3741,6 +3760,21 @@ function_arg_advance_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode, cum->words += words; } +static void +function_arg_advance_ms_64 (CUMULATIVE_ARGS *cum, HOST_WIDE_INT bytes, + HOST_WIDE_INT words) +{ + /* Otherwise, this should be passed indirect. */ + gcc_assert (bytes == 1 || bytes == 2 || bytes == 4 || bytes == 8); + + cum->words += words; + if (cum->nregs > 0) + { + cum->nregs -= 1; + cum->regno += 1; + } +} + void function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named ATTRIBUTE_UNUSED) @@ -3756,7 +3790,9 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, if (type) mode = type_natural_mode (type); - if (TARGET_64BIT) + if (TARGET_64BIT_MS_ABI) + function_arg_advance_ms_64 (cum, bytes, words); + else if (TARGET_64BIT) function_arg_advance_64 (cum, mode, type, words); else function_arg_advance_32 (cum, mode, type, bytes, words); @@ -3887,9 +3923,47 @@ function_arg_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode, cum->sse_regno); } +static rtx +function_arg_ms_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode, + enum machine_mode orig_mode, int named) +{ + unsigned int regno; + + /* Avoid the AL settings for the Unix64 ABI. */ + if (mode == VOIDmode) + return constm1_rtx; + + /* If we've run out of registers, it goes on the stack. */ + if (cum->nregs == 0) + return NULL_RTX; + + regno = x86_64_ms_abi_int_parameter_registers[cum->regno]; + + /* Only floating point modes are passed in anything but integer regs. */ + if (TARGET_SSE && (mode == SFmode || mode == DFmode)) + { + if (named) + regno = cum->regno + FIRST_SSE_REG; + else + { + rtx t1, t2; + + /* Unnamed floating parameters are passed in both the + SSE and integer registers. */ + t1 = gen_rtx_REG (mode, cum->regno + FIRST_SSE_REG); + t2 = gen_rtx_REG (mode, regno); + t1 = gen_rtx_EXPR_LIST (VOIDmode, t1, const0_rtx); + t2 = gen_rtx_EXPR_LIST (VOIDmode, t2, const0_rtx); + return gen_rtx_PARALLEL (mode, gen_rtvec (2, t1, t2)); + } + } + + return gen_reg_or_parallel (mode, orig_mode, regno); +} + rtx function_arg (CUMULATIVE_ARGS *cum, enum machine_mode omode, - tree type, int named ATTRIBUTE_UNUSED) + tree type, int named) { enum machine_mode mode = omode; HOST_WIDE_INT bytes, words; @@ -3905,7 +3979,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode omode, if (type && TREE_CODE (type) == VECTOR_TYPE) mode = type_natural_mode (type); - if (TARGET_64BIT) + if (TARGET_64BIT_MS_ABI) + return function_arg_ms_64 (cum, mode, omode, named); + else if (TARGET_64BIT) return function_arg_64 (cum, mode, omode, type); else return function_arg_32 (cum, mode, omode, type, bytes, words); @@ -3922,7 +3998,30 @@ ix86_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED, tree type, bool named ATTRIBUTE_UNUSED) { - if (TARGET_64BIT && type && int_size_in_bytes (type) == -1) + if (TARGET_64BIT_MS_ABI) + { + if (type) + { + /* Arrays are passed by reference. */ + if (TREE_CODE (type) == ARRAY_TYPE) + return true; + + if (AGGREGATE_TYPE_P (type)) + { + /* Structs/unions of sizes other than 8, 16, 32, or 64 bits + are passed by reference. */ + int el2 = exact_log2 (int_size_in_bytes (type)); + return !(el2 >= 0 && el2 <= 3); + } + } + + /* __m128 is passed by reference. */ + /* ??? How to handle complex? For now treat them as structs, + and pass them by reference if they're too large. */ + if (GET_MODE_SIZE (mode) > 8) + return true; + } + else if (TARGET_64BIT && type && int_size_in_bytes (type) == -1) return 1; return 0; @@ -4025,6 +4124,8 @@ ix86_function_value_regno_p (int regno) return true; case FIRST_FLOAT_REG: + if (TARGET_64BIT_MS_ABI) + return false; return TARGET_FLOAT_RETURNS_IN_80387; case FIRST_SSE_REG: @@ -4131,6 +4232,22 @@ function_value_64 (enum machine_mode orig_mode, enum machine_mode mode, return ret; } +static rtx +function_value_ms_64 (enum machine_mode orig_mode, enum machine_mode mode) +{ + unsigned int regno = 0; + + if (TARGET_SSE) + { + if (mode == SFmode || mode == DFmode) + regno = FIRST_SSE_REG; + else if (VECTOR_MODE_P (mode) || GET_MODE_SIZE (mode) == 16) + regno = FIRST_SSE_REG; + } + + return gen_rtx_REG (orig_mode, regno); +} + static rtx ix86_function_value_1 (tree valtype, tree fntype_or_decl, enum machine_mode orig_mode, enum machine_mode mode) @@ -4142,7 +4259,9 @@ ix86_function_value_1 (tree valtype, tree fntype_or_decl, fn = fntype_or_decl; fntype = fn ? TREE_TYPE (fn) : fntype_or_decl; - if (TARGET_64BIT) + if (TARGET_64BIT_MS_ABI) + return function_value_ms_64 (orig_mode, mode); + else if (TARGET_64BIT) return function_value_64 (orig_mode, mode, valtype); else return function_value_32 (orig_mode, mode, fntype, fn); @@ -4214,12 +4333,27 @@ return_in_memory_64 (tree type, enum machine_mode mode) return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs); } +static int +return_in_memory_ms_64 (tree type, enum machine_mode mode) +{ + HOST_WIDE_INT size = int_size_in_bytes (type); + + /* __m128 and friends are returned in xmm0. */ + if (size == 16 && VECTOR_MODE_P (mode)) + return 0; + + /* Otherwise, the size must be exactly in [1248]. */ + return (size != 1 && size != 2 && size != 4 && size != 8); +} + int ix86_return_in_memory (tree type) { enum machine_mode mode = type_natural_mode (type); - if (TARGET_64BIT) + if (TARGET_64BIT_MS_ABI) + return return_in_memory_ms_64 (type, mode); + else if (TARGET_64BIT) return return_in_memory_64 (type, mode); else return return_in_memory_32 (type, mode); @@ -4280,7 +4414,7 @@ ix86_build_builtin_va_list (void) tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl; /* For i386 we use plain pointer to argument area. */ - if (!TARGET_64BIT) + if (!TARGET_64BIT || TARGET_64BIT_MS_ABI) return build_pointer_type (char_type_node); record = (*lang_hooks.types.make_type) (RECORD_TYPE); @@ -4399,6 +4533,27 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum) } } +static void +setup_incoming_varargs_ms_64 (CUMULATIVE_ARGS *cum) +{ + int set = get_varargs_alias_set (); + int i; + + for (i = cum->regno; i < REGPARM_MAX; i++) + { + rtx reg, mem; + + mem = gen_rtx_MEM (Pmode, + plus_constant (virtual_incoming_args_rtx, + i * UNITS_PER_WORD)); + MEM_NOTRAP_P (mem) = 1; + set_mem_alias_set (mem, set); + + reg = gen_rtx_REG (Pmode, x86_64_ms_abi_int_parameter_registers[i]); + emit_move_insn (mem, reg); + } +} + static void ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int *pretend_size ATTRIBUTE_UNUSED, @@ -4426,7 +4581,10 @@ ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, if (stdarg_p) function_arg_advance (&next_cum, mode, type, 1); - setup_incoming_varargs_64 (&next_cum); + if (TARGET_64BIT_MS_ABI) + setup_incoming_varargs_ms_64 (&next_cum); + else + setup_incoming_varargs_64 (&next_cum); } /* Implement va_start. */ @@ -4440,7 +4598,7 @@ ix86_va_start (tree valist, rtx nextarg) tree type; /* Only 64bit target needs something special. */ - if (!TARGET_64BIT) + if (!TARGET_64BIT || TARGET_64BIT_MS_ABI) { std_expand_builtin_va_start (valist, nextarg); return; @@ -4519,7 +4677,7 @@ ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) enum machine_mode nat_mode; /* Only 64bit target needs something special. */ - if (!TARGET_64BIT) + if (!TARGET_64BIT || TARGET_64BIT_MS_ABI) return std_gimplify_va_arg_expr (valist, type, pre_p, post_p); f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); @@ -5711,21 +5869,30 @@ ix86_expand_prologue (void) else { /* Only valid for Win32. */ - rtx eax = gen_rtx_REG (SImode, 0); - bool eax_live = ix86_eax_live_at_start_p (); + rtx eax = gen_rtx_REG (Pmode, 0); + bool eax_live; rtx t; - gcc_assert (!TARGET_64BIT); + gcc_assert (!TARGET_64BIT || TARGET_64BIT_MS_ABI); + + if (TARGET_64BIT_MS_ABI) + eax_live = false; + else + eax_live = ix86_eax_live_at_start_p (); if (eax_live) { emit_insn (gen_push (eax)); - allocate -= 4; + allocate -= UNITS_PER_WORD; } emit_move_insn (eax, GEN_INT (allocate)); - insn = emit_insn (gen_allocate_stack_worker (eax)); + if (TARGET_64BIT) + insn = gen_allocate_stack_worker_64 (eax); + else + insn = gen_allocate_stack_worker_32 (eax); + insn = emit_insn (insn); RTX_FRAME_RELATED_P (insn) = 1; t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-allocate)); t = gen_rtx_SET (VOIDmode, stack_pointer_rtx, t); @@ -5741,7 +5908,7 @@ ix86_expand_prologue (void) - frame.nregs * UNITS_PER_WORD); else t = plus_constant (stack_pointer_rtx, allocate); - emit_move_insn (eax, gen_rtx_MEM (SImode, t)); + emit_move_insn (eax, gen_rtx_MEM (Pmode, t)); } } @@ -5995,7 +6162,7 @@ ix86_expand_epilogue (int style) { rtx ecx = gen_rtx_REG (SImode, 2); - /* There is no "pascal" calling convention in 64bit ABI. */ + /* There is no "pascal" calling convention in any 64bit ABI. */ gcc_assert (!TARGET_64BIT); emit_insn (gen_popsi1 (ecx)); @@ -6848,7 +7015,8 @@ legitimize_pic_address (rtx orig, rtx reg) addr = XEXP (addr, 0); if (GET_CODE (addr) == PLUS) { - new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), UNSPEC_GOTOFF); + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), + UNSPEC_GOTOFF); new = gen_rtx_PLUS (Pmode, new, XEXP (addr, 1)); } else @@ -6879,7 +7047,8 @@ legitimize_pic_address (rtx orig, rtx reg) addr = XEXP (addr, 0); if (GET_CODE (addr) == PLUS) { - new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), UNSPEC_GOTOFF); + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), + UNSPEC_GOTOFF); new = gen_rtx_PLUS (Pmode, new, XEXP (addr, 1)); } else @@ -6898,6 +7067,11 @@ legitimize_pic_address (rtx orig, rtx reg) see gotoff_operand. */ || (TARGET_VXWORKS_RTP && GET_CODE (addr) == LABEL_REF)) { + /* Given that we've already handled dllimport variables separately + in legitimize_address, and all other variables should satisfy + legitimate_pic_address_disp_p, we should never arrive here. */ + gcc_assert (!TARGET_64BIT_MS_ABI); + if (TARGET_64BIT && ix86_cmodel != CM_LARGE_PIC) { new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTPCREL); @@ -7505,7 +7679,8 @@ output_pic_addr_const (FILE *file, rtx x, int code) { const char *name = XSTR (x, 0); - /* Mark the decl as referenced so that cgraph will output the function. */ + /* Mark the decl as referenced so that cgraph will + output the function. */ if (SYMBOL_REF_DECL (x)) mark_decl_referenced (SYMBOL_REF_DECL (x)); @@ -7516,7 +7691,8 @@ output_pic_addr_const (FILE *file, rtx x, int code) #endif assemble_name (file, name); } - if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_LOCAL_P (x)) + if (!TARGET_MACHO && !TARGET_64BIT_MS_ABI + && code == 'P' && ! SYMBOL_REF_LOCAL_P (x)) fputs ("@PLT", file); break; @@ -9291,7 +9467,6 @@ ix86_expand_clear (rtx dest) /* Avoid HImode and its attendant prefix byte. */ if (GET_MODE_SIZE (GET_MODE (dest)) < 4) dest = gen_rtx_REG (SImode, REGNO (dest)); - tmp = gen_rtx_SET (VOIDmode, dest, const0_rtx); /* This predicate should match that for movsi_xor and movdi_xor_rex64. */ @@ -19508,37 +19683,29 @@ static rtx x86_this_parameter (tree function) { tree type = TREE_TYPE (function); + bool aggr = aggregate_value_p (TREE_TYPE (type), type) != 0; if (TARGET_64BIT) { - int n = aggregate_value_p (TREE_TYPE (type), type) != 0; - return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]); + const int *parm_regs; + + if (TARGET_64BIT_MS_ABI) + parm_regs = x86_64_ms_abi_int_parameter_registers; + else + parm_regs = x86_64_int_parameter_registers; + return gen_rtx_REG (DImode, parm_regs[aggr]); } - if (ix86_function_regparm (type, function) > 0) + if (ix86_function_regparm (type, function) > 0 + && !type_has_variadic_args_p (type)) { - tree parm; - - parm = TYPE_ARG_TYPES (type); - /* Figure out whether or not the function has a variable number of - arguments. */ - for (; parm; parm = TREE_CHAIN (parm)) - if (TREE_VALUE (parm) == void_type_node) - break; - /* If not, the this parameter is in the first argument. */ - if (parm) - { - int regno = 0; - if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type))) - regno = 2; - return gen_rtx_REG (SImode, regno); - } + int regno = 0; + if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type))) + regno = 2; + return gen_rtx_REG (SImode, regno); } - if (aggregate_value_p (TREE_TYPE (type), type)) - return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8)); - else - return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4)); + return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, aggr ? 8 : 4)); } /* Determine whether x86_output_mi_thunk can succeed. */ @@ -19627,7 +19794,7 @@ x86_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED, { int tmp_regno = 2 /* ECX */; if (lookup_attribute ("fastcall", - TYPE_ATTRIBUTES (TREE_TYPE (function)))) + TYPE_ATTRIBUTES (TREE_TYPE (function)))) tmp_regno = 0 /* EAX */; tmp = gen_rtx_REG (SImode, tmp_regno); } @@ -19669,6 +19836,10 @@ x86_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED, { if (!flag_pic || (*targetm.binds_local_p) (function)) output_asm_insn ("jmp\t%P0", xops); + /* All thunks should be in the same object as their target, + and thus binds_local_p should be true. */ + else if (TARGET_64BIT_MS_ABI) + gcc_unreachable (); else { tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xops[0]), UNSPEC_GOTPCREL); @@ -19745,20 +19916,16 @@ void x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) { if (TARGET_64BIT) - if (flag_pic) - { + { #ifndef NO_PROFILE_COUNTERS - fprintf (file, "\tleaq\t%sP%d@(%%rip),%%r11\n", LPREFIX, labelno); + fprintf (file, "\tleaq\t%sP%d@(%%rip),%%r11\n", LPREFIX, labelno); #endif + + if (!TARGET_64BIT_MS_ABI && flag_pic) fprintf (file, "\tcall\t*%s@GOTPCREL(%%rip)\n", MCOUNT_NAME); - } - else - { -#ifndef NO_PROFILE_COUNTERS - fprintf (file, "\tmovq\t$%sP%d,%%r11\n", LPREFIX, labelno); -#endif + else fprintf (file, "\tcall\t%s\n", MCOUNT_NAME); - } + } else if (flag_pic) { #ifndef NO_PROFILE_COUNTERS @@ -21817,6 +21984,8 @@ static const struct attribute_spec ix86_attribute_table[] = #define TARGET_INTERNAL_ARG_POINTER ix86_internal_arg_pointer #undef TARGET_DWARF_HANDLE_FRAME_UNSPEC #define TARGET_DWARF_HANDLE_FRAME_UNSPEC ix86_dwarf_handle_frame_unspec +#undef TARGET_STRICT_ARGUMENT_NAMING +#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR ix86_gimplify_va_arg diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 045741b4c4f..e86bb7273fe 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -20,40 +20,6 @@ along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "config/vxworks-dummy.h" - -/* Algorithm to expand string function with. */ -enum stringop_alg -{ - no_stringop, - libcall, - rep_prefix_1_byte, - rep_prefix_4_byte, - rep_prefix_8_byte, - loop_1_byte, - loop, - unrolled_loop -}; -#define NAX_STRINGOP_ALGS 4 -/* Specify what algorithm to use for stringops on known size. - When size is unknown, the UNKNOWN_SIZE alg is used. When size is - known at compile time or estimated via feedback, the SIZE array - is walked in order until MAX is greater then the estimate (or -1 - means infinity). Corresponding ALG is used then. - For example initializer: - {{256, loop}, {-1, rep_prefix_4_byte}} - will use loop for blocks smaller or equal to 256 bytes, rep prefix will - be used otherwise. -*/ -struct stringop_algs -{ - const enum stringop_alg unknown_size; - const struct stringop_strategy { - const int max; - const enum stringop_alg alg; - } size [NAX_STRINGOP_ALGS]; -}; - /* The purpose of this file is to define the characteristics of the i386, independent of assembler syntax or operating system. @@ -69,6 +35,41 @@ struct stringop_algs ADDR_BEG, ADDR_END, PRINT_IREG, PRINT_SCALE, PRINT_B_I_S, and many that start with ASM_ or end in ASM_OP. */ +#include "config/vxworks-dummy.h" + +/* Algorithm to expand string function with. */ +enum stringop_alg +{ + no_stringop, + libcall, + rep_prefix_1_byte, + rep_prefix_4_byte, + rep_prefix_8_byte, + loop_1_byte, + loop, + unrolled_loop +}; + +#define NAX_STRINGOP_ALGS 4 + +/* Specify what algorithm to use for stringops on known size. + When size is unknown, the UNKNOWN_SIZE alg is used. When size is + known at compile time or estimated via feedback, the SIZE array + is walked in order until MAX is greater then the estimate (or -1 + means infinity). Corresponding ALG is used then. + For example initializer: + {{256, loop}, {-1, rep_prefix_4_byte}} + will use loop for blocks smaller or equal to 256 bytes, rep prefix will + be used otherwise. */ +struct stringop_algs +{ + const enum stringop_alg unknown_size; + const struct stringop_strategy { + const int max; + const enum stringop_alg alg; + } size [NAX_STRINGOP_ALGS]; +}; + /* Define the specific costs for a given cpu */ struct processor_costs { @@ -372,11 +373,17 @@ extern int x86_prefetch_sse; the frame pointer in leaf functions. */ #define TARGET_DEFAULT 0 +/* Extra bits to force on w/ 64-bit mode. */ +#define TARGET_SUBTARGET64_DEFAULT 0 + /* This is not really a target flag, but is done this way so that it's analogous to similar code for Mach-O on PowerPC. darwin.h redefines this to 1. */ #define TARGET_MACHO 0 +/* Likewise, for the Windows 64-bit ABI. */ +#define TARGET_64BIT_MS_ABI 0 + /* Subtargets may reset this to 1 in order to enable 96-bit long double with the rounding mode forced to 53 bits. */ #define TARGET_96_ROUND_53_LONG_DOUBLE 0 @@ -998,6 +1005,11 @@ do { \ for (i = FIRST_REX_SSE_REG; i <= LAST_REX_SSE_REG; i++) \ reg_names[i] = ""; \ } \ + if (TARGET_64BIT_MS_ABI) \ + { \ + call_used_regs[4 /*RSI*/] = 0; \ + call_used_regs[5 /*RDI*/] = 0; \ + } \ } while (0) /* Return number of consecutive hard regs needed starting at reg REGNO diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index fddd1c2d258..2fc4f5f1072 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -19611,86 +19611,56 @@ [(set_attr "type" "alu,lea") (set_attr "mode" "DI")]) -(define_expand "allocate_stack_worker" - [(match_operand:SI 0 "register_operand" "")] - "TARGET_STACK_PROBE" -{ - if (reload_completed) - { - if (TARGET_64BIT) - emit_insn (gen_allocate_stack_worker_rex64_postreload (operands[0])); - else - emit_insn (gen_allocate_stack_worker_postreload (operands[0])); - } - else - { - if (TARGET_64BIT) - emit_insn (gen_allocate_stack_worker_rex64 (operands[0])); - else - emit_insn (gen_allocate_stack_worker_1 (operands[0])); - } - DONE; -}) - -(define_insn "allocate_stack_worker_1" - [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")] - UNSPECV_STACK_PROBE) +(define_insn "allocate_stack_worker_32" + [(set (match_operand:SI 0 "register_operand" "+a") + (unspec_volatile:SI [(match_dup 0)] UNSPECV_STACK_PROBE)) (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0))) - (clobber (match_scratch:SI 1 "=0")) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT && TARGET_STACK_PROBE" "call\t__alloca" [(set_attr "type" "multi") (set_attr "length" "5")]) -(define_expand "allocate_stack_worker_postreload" - [(parallel [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")] - UNSPECV_STACK_PROBE) - (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0))) - (clobber (match_dup 0)) - (clobber (reg:CC FLAGS_REG))])] - "" - "") - -(define_insn "allocate_stack_worker_rex64" - [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")] - UNSPECV_STACK_PROBE) +(define_insn "allocate_stack_worker_64" + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec_volatile:DI [(match_dup 0)] UNSPECV_STACK_PROBE)) (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0))) - (clobber (match_scratch:DI 1 "=0")) + (clobber (reg:DI R10_REG)) + (clobber (reg:DI R11_REG)) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && TARGET_STACK_PROBE" - "call\t__alloca" + "call\t___chkstk" [(set_attr "type" "multi") (set_attr "length" "5")]) -(define_expand "allocate_stack_worker_rex64_postreload" - [(parallel [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")] - UNSPECV_STACK_PROBE) - (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0))) - (clobber (match_dup 0)) - (clobber (reg:CC FLAGS_REG))])] - "" - "") - (define_expand "allocate_stack" - [(parallel [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (reg:SI SP_REG) - (match_operand:SI 1 "general_operand" ""))) - (clobber (reg:CC FLAGS_REG))]) - (parallel [(set (reg:SI SP_REG) - (minus:SI (reg:SI SP_REG) (match_dup 1))) - (clobber (reg:CC FLAGS_REG))])] + [(match_operand 0 "register_operand" "") + (match_operand 1 "general_operand" "")] "TARGET_STACK_PROBE" { -#ifdef CHECK_STACK_LIMIT - if (CONST_INT_P (operands[1]) - && INTVAL (operands[1]) < CHECK_STACK_LIMIT) - emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, - operands[1])); - else + rtx x; + +#ifndef CHECK_STACK_LIMIT +#define CHECK_STACK_LIMIT 0 #endif - emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode, - operands[1]))); + + if (CHECK_STACK_LIMIT && CONST_INT_P (operands[1]) + && INTVAL (operands[1]) < CHECK_STACK_LIMIT) + { + x = expand_simple_binop (Pmode, MINUS, stack_pointer_rtx, operands[1], + stack_pointer_rtx, 0, OPTAB_DIRECT); + if (x != stack_pointer_rtx) + emit_move_insn (stack_pointer_rtx, x); + } + else + { + x = copy_to_mode_reg (Pmode, operands[1]); + if (TARGET_64BIT) + x = gen_allocate_stack_worker_64 (x); + else + x = gen_allocate_stack_worker_32 (x); + emit_insn (x); + } emit_move_insn (operands[0], virtual_stack_dynamic_rtx); DONE; diff --git a/gcc/config/i386/i386elf.h b/gcc/config/i386/i386elf.h index d99fe62392a..15078cc19c4 100644 --- a/gcc/config/i386/i386elf.h +++ b/gcc/config/i386/i386elf.h @@ -27,11 +27,6 @@ Boston, MA 02110-1301, USA. */ #define TARGET_VERSION fprintf (stderr, " (i386 bare ELF target)"); -/* By default, target has a 80387, uses IEEE compatible arithmetic, - and returns float values in the 387. */ - -#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS) - /* The ELF ABI for the i386 says that records and unions are returned in memory. */ diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h index 28c2fb9fbb8..c608826be11 100644 --- a/gcc/config/i386/mingw32.h +++ b/gcc/config/i386/mingw32.h @@ -21,7 +21,11 @@ the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #undef TARGET_VERSION -#define TARGET_VERSION fprintf (stderr, " (x86 MinGW)"); +#if TARGET_64BIT_DEFAULT +#define TARGET_VERSION fprintf (stderr,"(x86_64 MinGW"); +#else +#define TARGET_VERSION fprintf (stderr," (x86 MinGW)"); +#endif /* See i386/crtdll.h for an alternative definition. */ #define EXTRA_OS_CPP_BUILTINS() \ @@ -32,13 +36,28 @@ Boston, MA 02110-1301, USA. */ builtin_define ("_WIN32"); \ builtin_define_std ("WIN32"); \ builtin_define_std ("WINNT"); \ + if (TARGET_64BIT_MS_ABI) \ + { \ + builtin_define ("__MINGW64__"); \ + builtin_define_with_value("_INTEGRAL_MAX_BITS","64",0); \ + builtin_define_std ("WIN64"); \ + builtin_define_std ("_WIN64"); \ + } \ + else \ + { \ + builtin_define_with_value("_INTEGRAL_MAX_BITS","32",0); \ + } \ } \ while (0) /* Override the standard choice of /usr/include as the default prefix to try when searching for header files. */ #undef STANDARD_INCLUDE_DIR +#if TARGET_64BIT_DEFAULT +#define STANDARD_INCLUDE_DIR "/mingw/include64" +#else #define STANDARD_INCLUDE_DIR "/mingw/include" +#endif #undef STANDARD_INCLUDE_COMPONENT #define STANDARD_INCLUDE_COMPONENT "MINGW" @@ -71,8 +90,12 @@ Boston, MA 02110-1301, USA. */ /* Override startfile prefix defaults. */ #ifndef STANDARD_STARTFILE_PREFIX_1 +#if TARGET_64BIT_DEFAULT +#define STANDARD_STARTFILE_PREFIX_1 "/mingw/lib64/" +#else #define STANDARD_STARTFILE_PREFIX_1 "/mingw/lib/" #endif +#endif #ifndef STANDARD_STARTFILE_PREFIX_2 #define STANDARD_STARTFILE_PREFIX_2 "" #endif diff --git a/gcc/config/i386/unix.h b/gcc/config/i386/unix.h index abb4e054038..d27fd1c085b 100644 --- a/gcc/config/i386/unix.h +++ b/gcc/config/i386/unix.h @@ -61,5 +61,10 @@ Boston, MA 02110-1301, USA. */ /* By default, target has a 80387, uses IEEE compatible arithmetic, and returns float values in the 387. */ +#define TARGET_SUBTARGET_DEFAULT \ + (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS) -#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS) +/* By default, 64-bit mode uses 128-bit long double. */ +#undef TARGET_SUBTARGET64_DEFAULT +#define TARGET_SUBTARGET64_DEFAULT \ + MASK_128BIT_LONG_DOUBLE diff --git a/gcc/gthr-win32.h b/gcc/gthr-win32.h index a27dccf7126..80b2b71c9e7 100644 --- a/gcc/gthr-win32.h +++ b/gcc/gthr-win32.h @@ -562,7 +562,8 @@ __gthread_once (__gthread_once_t *once, void (*func) (void)) leaks, especially in threaded applications making extensive use of C++ EH. Mingw uses a thread-support DLL to work-around this problem. */ static inline int -__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) +__gthread_key_create (__gthread_key_t *key, + void (*dtor) (void *) __attribute__((unused))) { int status = 0; DWORD tls_index = TlsAlloc (); diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 4271a4018b5..de59b9d56da 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,7 @@ +2007-02-30 Kai Tietz + + * config.host (x86_64-*-mingw*): New target. + 2007-03-23 Michael Meissner H.J. Lu diff --git a/libgcc/config.host b/libgcc/config.host index 389fec200ba..f5fff370941 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -364,7 +364,7 @@ i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae) ;; i[34567]86-*-pe | i[34567]86-*-cygwin*) ;; -i[34567]86-*-mingw32*) +i[34567]86-*-mingw32* | x86_64-*-mingw*) ;; i[34567]86-*-uwin*) ;;