Hi Jan, Jan Hubicka wrote on 31.07.2007 23:40:40:
> > Hi Kai, > > > > so, could you resolve the remaining issues? Or have you kind of > > paused the project? > > > > Cheers, > > Nicolas > > > > > > On Jul 12, 2007, at 2:14 , Kai Tietz wrote: > > > > >Hi, > > > > > >I am nearly through :) The remaining macros left to be ported are > > >REGPARM_MAX and SSE_REGPARM_MAX. The sysv_abi uses 6 regs and 8 sses, > > >ms_abi uses 4 regs and 4 sse registers. The problem is for example > > >the use > > >in i386.md of SSE_REGPARM_MAX without any hint, how to choose the > > >required > > >abi. Do you have an idea how this could be done ? > > This shoul not be dificult - ix86_regparm is used in > ix86_function_regparm, init_cumulative_args, setup_incoming_varargs_64 > functions. In all those cases you know the function declaration and > thus you can take a look if it is call to different ABI and overwrite > the value. Ok, here is my update. Cheers, i.A. Kai Tietz | (\_/) This is Bunny. Copy and paste Bunny | (='.'=) into your signature to help him gain | (")_(") world domination. ------------------------------------------------------------------------------------------ OneVision Software Entwicklungs GmbH & Co. KG Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050 Handelsregister: HRA 6744, Amtsgericht Regensburg Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: Ulrike Döhler, Manuela Kluger
Index: gcc/gcc/calls.c =================================================================== --- gcc.orig/gcc/calls.c +++ gcc/gcc/calls.c @@ -1187,6 +1187,7 @@ initialize_argument_information (int num static int compute_argument_block_size (int reg_parm_stack_space, struct args_size *args_size, + tree fndecl, // $$$$ int preferred_stack_boundary ATTRIBUTE_UNUSED) { int unadjusted_args_size = args_size->constant; @@ -1224,7 +1225,7 @@ compute_argument_block_size (int reg_par /* The area corresponding to register parameters is not to count in the size of the block we need. So make the adjustment. */ - if (!OUTGOING_REG_PARM_STACK_SPACE) + if (!OUTGOING_REG_PARM_STACK_SPACE (fndecl)) args_size->var = size_binop (MINUS_EXPR, args_size->var, ssize_int (reg_parm_stack_space)); @@ -1245,7 +1246,7 @@ compute_argument_block_size (int reg_par args_size->constant = MAX (args_size->constant, reg_parm_stack_space); - if (!OUTGOING_REG_PARM_STACK_SPACE) + if (!OUTGOING_REG_PARM_STACK_SPACE (fndecl)) args_size->constant -= reg_parm_stack_space; } return unadjusted_args_size; @@ -2036,7 +2037,7 @@ expand_call (tree exp, rtx target, int i reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl); #endif - if (!OUTGOING_REG_PARM_STACK_SPACE && reg_parm_stack_space > 0 && PUSH_ARGS) + if (!OUTGOING_REG_PARM_STACK_SPACE (fndecl) && reg_parm_stack_space > 0 && PUSH_ARGS) must_preallocate = 1; /* Set up a place to return a structure. */ @@ -2442,7 +2443,7 @@ expand_call (tree exp, rtx target, int i /* Since we will be writing into the entire argument area, the map must be allocated for its entire size, not just the part that is the responsibility of the caller. */ - if (!OUTGOING_REG_PARM_STACK_SPACE) + if (!OUTGOING_REG_PARM_STACK_SPACE (fndecl)) needed += reg_parm_stack_space; #ifdef ARGS_GROW_DOWNWARD @@ -2541,7 +2542,7 @@ expand_call (tree exp, rtx target, int i { rtx push_size = GEN_INT (adjusted_args_size.constant - + (OUTGOING_REG_PARM_STACK_SPACE ? 0 + + (OUTGOING_REG_PARM_STACK_SPACE (fndecl) ? 0 : reg_parm_stack_space)); if (old_stack_level == 0) { @@ -2712,7 +2713,7 @@ expand_call (tree exp, rtx target, int i /* If register arguments require space on the stack and stack space was not preallocated, allocate stack space here for arguments passed in registers. */ - if (OUTGOING_REG_PARM_STACK_SPACE && !ACCUMULATE_OUTGOING_ARGS + if (OUTGOING_REG_PARM_STACK_SPACE (fndecl) && !ACCUMULATE_OUTGOING_ARGS && must_preallocate == 0 && reg_parm_stack_space > 0) anti_adjust_stack (GEN_INT (reg_parm_stack_space)); @@ -3537,7 +3538,7 @@ emit_library_call_value_1 (int retval, r args_size.constant = MAX (args_size.constant, reg_parm_stack_space); - if (!OUTGOING_REG_PARM_STACK_SPACE) + if (!OUTGOING_REG_PARM_STACK_SPACE (fndecl)) args_size.constant -= reg_parm_stack_space; if (args_size.constant > current_function_outgoing_args_size) @@ -3562,7 +3563,7 @@ emit_library_call_value_1 (int retval, r /* Since we will be writing into the entire argument area, the map must be allocated for its entire size, not just the part that is the responsibility of the caller. */ - if (!OUTGOING_REG_PARM_STACK_SPACE) + if (!OUTGOING_REG_PARM_STACK_SPACE (fndecl)) needed += reg_parm_stack_space; #ifdef ARGS_GROW_DOWNWARD Index: gcc/gcc/config/alpha/unicosmk.h =================================================================== --- gcc.orig/gcc/config/alpha/unicosmk.h +++ gcc/gcc/config/alpha/unicosmk.h @@ -116,7 +116,7 @@ Boston, MA 02110-1301, USA. */ in registers) are allocated. */ #define REG_PARM_STACK_SPACE(DECL) 48 -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 /* If an argument can't be passed in registers even though not all argument registers have been used yet, it is passed on the stack in the space Index: gcc/gcc/config/bfin/bfin.h =================================================================== --- gcc.orig/gcc/config/bfin/bfin.h +++ gcc/gcc/config/bfin/bfin.h @@ -211,7 +211,7 @@ extern const char *bfin_library_id_strin /* Define this if the above stack space is to be considered part of the * space allocated by the caller. */ -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 /* Define this if the maximum size of all the outgoing args is to be accumulated and pushed during the prologue. The amount can be Index: gcc/gcc/config/i386/cygming.h =================================================================== --- gcc.orig/gcc/config/i386/cygming.h +++ gcc/gcc/config/i386/cygming.h @@ -35,7 +35,10 @@ Boston, MA 02110-1301, USA. */ #endif #undef TARGET_64BIT_MS_ABI -#define TARGET_64BIT_MS_ABI TARGET_64BIT +#define TARGET_64BIT_MS_ABI (!cfun ? DEFAULT_USED_ABI == 1 : TARGET_64BIT && cfun->machine->used_abi == 1) + +#undef DEFAULT_USED_ABI +#define DEFAULT_USED_ABI (TARGET_64BIT ? 1 : 0) #undef DBX_REGISTER_NUMBER #define DBX_REGISTER_NUMBER(n) \ @@ -124,12 +127,6 @@ Boston, MA 02110-1301, USA. */ #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) Index: gcc/gcc/config/i386/i386-protos.h =================================================================== --- gcc.orig/gcc/config/i386/i386-protos.h +++ gcc/gcc/config/i386/i386-protos.h @@ -134,7 +134,7 @@ extern rtx ix86_libcall_value (enum mach extern bool ix86_function_value_regno_p (int); extern bool ix86_function_arg_regno_p (int); extern int ix86_function_arg_boundary (enum machine_mode, tree); -extern int ix86_return_in_memory (tree); +extern int ix86_return_in_memory (tree, tree); extern int ix86_sol10_return_in_memory (tree); extern void ix86_va_start (tree, rtx); extern rtx ix86_va_arg (tree, tree); Index: gcc/gcc/config/i386/i386.c =================================================================== --- gcc.orig/gcc/config/i386/i386.c +++ gcc/gcc/config/i386/i386.c @@ -1408,7 +1408,7 @@ rtx ix86_compare_op1 = NULL_RTX; rtx ix86_compare_emitted = NULL_RTX; /* Size of the register save area. */ -#define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16) +#define X86_64_VARARGS_SIZE (6 * UNITS_PER_WORD + 8 * 16) /* Define the structure for the machine field in struct function. */ @@ -1981,11 +1981,11 @@ override_options (void) } else { - /* For TARGET_64BIT_MS_ABI, force pic on, in order to enable the + /* For DEFAULT_USED_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) + if (DEFAULT_USED_ABI == 1) ix86_cmodel = CM_SMALL_PIC, flag_pic = 1; else if (TARGET_64BIT) ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL; @@ -2806,7 +2806,7 @@ ix86_handle_cconv_attribute (tree *node, if (TARGET_64BIT) { /* Do not warn when emulating the MS ABI. */ - if (!TARGET_64BIT_MS_ABI) + if (TREE_CODE (*node) != FUNCTION_TYPE || !ix86_get_abi_format (*node)) warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name)); *no_add_attrs = true; @@ -2906,7 +2906,11 @@ ix86_function_regparm (tree type, tree d int regparm = ix86_regparm; if (TARGET_64BIT) - return regparm; + { + if (ix86_get_abi_format () == DEFAULT_USED_ABI) + return regparm; + return DEFAULT_USED_ABI != 0 ? 6 : 4; + } attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type)); if (attr) @@ -3127,11 +3131,15 @@ ix86_function_arg_regno_p (int regno) return true; } + /* TODO: The function should depend on current function ABI but + builtins.c would need updating then. Therefore we use the + default ABI. */ + /* RAX is used as hidden argument to va_arg functions. */ - if (!TARGET_64BIT_MS_ABI && regno == 0) + if (DEFAULT_USED_ABI != 1 && regno == 0) return true; - if (TARGET_64BIT_MS_ABI) + if (DEFAULT_USED_ABI == 1) parm_regs = x86_64_ms_abi_int_parameter_registers; else parm_regs = x86_64_int_parameter_registers; @@ -3156,6 +3164,38 @@ ix86_must_pass_in_stack (enum machine_mo && type && TREE_CODE (type) != VECTOR_TYPE); } +/* It returns the size, in bytes, of the area reserved for arguments passed + in registers for the function represented by fndecl dependent to the used + abi format. */ +unsigned int +ix86_reg_parm_stack_space (tree fndecl) +{ + int used_abi = 0; + /* For libcalls it is possible that there is no fndecl at hand. + Therefore assume for this case the default abi of the target. */ + if (!fndecl) + used_abi = DEFAULT_USED_ABI; + else + used_abi = ix86_get_abi_format (TREE_TYPE (fndecl)); + if (used_abi == 1) + return 32; + return 0; +} + +/* Returns value 0 for sysv_abi and value 1 for ms_abi. */ +int +ix86_get_abi_format (tree fntype) +{ + if (TARGET_64BIT && fntype != NULL) + { + if (DEFAULT_USED_ABI == 0) + return lookup_attribute ("ms_abi", TYPE_ATTRIBUTES (fntype)) ? 1 : 0; + else + return lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (fntype)) ? 0 : 1; + } + return DEFAULT_USED_ABI; +} + /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. */ @@ -3168,10 +3208,23 @@ init_cumulative_args (CUMULATIVE_ARGS *c { memset (cum, 0, sizeof (*cum)); + cum->used_abi = ix86_get_abi_format (fntype); /* Set up the number of registers to use for passing arguments. */ - cum->nregs = ix86_regparm; + if (TARGET_64BIT) + { + cum->nregs = ix86_regparm; + if (cum->used_abi != DEFAULT_USED_ABI) + cum->nregs = DEFAULT_USED_ABI != 0 ? 6 : 4; + } if (TARGET_SSE) - cum->sse_nregs = SSE_REGPARM_MAX; + { + cum->sse_nregs = SSE_REGPARM_MAX; + if (TARGET_64BIT) + { + if (cum->used_abi != DEFAULT_USED_ABI) + cum->sse_nregs = DEFAULT_USED_ABI != 0 ? 8 : 4; + } + } if (TARGET_MMX) cum->mmx_nregs = MMX_REGPARM_MAX; cum->warn_sse = true; @@ -3947,7 +4000,7 @@ function_arg_advance (CUMULATIVE_ARGS *c if (type) mode = type_natural_mode (type); - if (TARGET_64BIT_MS_ABI) + if (cum->used_abi == 1) function_arg_advance_ms_64 (cum, bytes, words); else if (TARGET_64BIT) function_arg_advance_64 (cum, mode, type, words); @@ -4070,7 +4123,9 @@ function_arg_64 (CUMULATIVE_ARGS *cum, e if (mode == VOIDmode) return GEN_INT (cum->maybe_vaarg ? (cum->sse_nregs < 0 - ? SSE_REGPARM_MAX + ? ((!TARGET_64BIT + || cum->used_abi == DEFAULT_USED_ABI) ? SSE_REGPARM_MAX + : (DEFAULT_USED_ABI != 0 ? 8 : 4)) : cum->sse_regno) : -1); @@ -4136,7 +4191,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum if (type && TREE_CODE (type) == VECTOR_TYPE) mode = type_natural_mode (type); - if (TARGET_64BIT_MS_ABI) + if (cum->used_abi == 1) return function_arg_ms_64 (cum, mode, omode, named); else if (TARGET_64BIT) return function_arg_64 (cum, mode, omode, type); @@ -4151,11 +4206,11 @@ function_arg (CUMULATIVE_ARGS *cum, enum appropriate for passing a pointer to that type. */ static bool -ix86_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, +ix86_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode ATTRIBUTE_UNUSED, tree type, bool named ATTRIBUTE_UNUSED) { - if (TARGET_64BIT_MS_ABI) + if (cum->used_abi == 1) { if (type) { @@ -4281,7 +4336,10 @@ ix86_function_value_regno_p (int regno) return true; case FIRST_FLOAT_REG: - if (TARGET_64BIT_MS_ABI) + /* TODO: The function should depend on current function ABI but + builtins.c would need updating then. Therefore we use the + default ABI. */ + if (DEFAULT_USED_ABI == 1) return false; return TARGET_FLOAT_RETURNS_IN_80387; @@ -4372,7 +4430,7 @@ function_value_64 (enum machine_mode ori } ret = construct_container (mode, orig_mode, valtype, 1, - REGPARM_MAX, SSE_REGPARM_MAX, + 6, 8, x86_64_int_return_registers, 0); /* For zero sized structures, construct_container returns NULL, but we @@ -4410,7 +4468,7 @@ ix86_function_value_1 (tree valtype, tre fn = fntype_or_decl; fntype = fn ? TREE_TYPE (fn) : fntype_or_decl; - if (TARGET_64BIT_MS_ABI) + if (ix86_get_abi_format (fntype) == 1) return function_value_ms_64 (orig_mode, mode); else if (TARGET_64BIT) return function_value_64 (orig_mode, mode, valtype); @@ -4498,11 +4556,11 @@ return_in_memory_ms_64 (tree type, enum } int -ix86_return_in_memory (tree type) +ix86_return_in_memory (tree type, tree fntype) { enum machine_mode mode = type_natural_mode (type); - if (TARGET_64BIT_MS_ABI) + if (ix86_get_abi_format (fntype) == 1) return return_in_memory_ms_64 (type, mode); else if (TARGET_64BIT) return return_in_memory_64 (type, mode); @@ -4602,7 +4660,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 || TARGET_64BIT_MS_ABI) + if (!TARGET_64BIT || cfun->machine->used_abi == 1) return build_pointer_type (char_type_node); record = (*lang_hooks.types.make_type) (RECORD_TYPE); @@ -4650,6 +4708,10 @@ setup_incoming_varargs_64 (CUMULATIVE_AR rtx nsse_reg; int set; int i; + int regparm = ix86_regparm; + + if(cum->used_abi != DEFAULT_USED_ABI) + regparm = DEFAULT_USED_ABI != 0 ? 6 : 4; if (! cfun->va_list_gpr_size && ! cfun->va_list_fpr_size) return; @@ -4662,7 +4724,7 @@ setup_incoming_varargs_64 (CUMULATIVE_AR set = get_varargs_alias_set (); for (i = cum->regno; - i < ix86_regparm + i < regparm && i < cum->regno + cfun->va_list_gpr_size / UNITS_PER_WORD; i++) { @@ -4769,7 +4831,7 @@ ix86_setup_incoming_varargs (CUMULATIVE_ if (stdarg_p) function_arg_advance (&next_cum, mode, type, 1); - if (TARGET_64BIT_MS_ABI) + if (cum->used_abi == 1) setup_incoming_varargs_ms_64 (&next_cum); else setup_incoming_varargs_64 (&next_cum); @@ -4786,7 +4848,7 @@ ix86_va_start (tree valist, rtx nextarg) tree type; /* Only 64bit target needs something special. */ - if (!TARGET_64BIT || TARGET_64BIT_MS_ABI) + if (!TARGET_64BIT || cfun->machine->used_abi == 1) { std_expand_builtin_va_start (valist, nextarg); return; @@ -4865,7 +4927,7 @@ ix86_gimplify_va_arg (tree valist, tree enum machine_mode nat_mode; /* Only 64bit target needs something special. */ - if (!TARGET_64BIT || TARGET_64BIT_MS_ABI) + if (!TARGET_64BIT || cfun->machine->used_abi == 1) return std_gimplify_va_arg_expr (valist, type, pre_p, post_p); f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); @@ -4887,7 +4949,7 @@ ix86_gimplify_va_arg (tree valist, tree nat_mode = type_natural_mode (type); container = construct_container (nat_mode, TYPE_MODE (type), type, 0, - REGPARM_MAX, SSE_REGPARM_MAX, intreg, 0); + 6, 8, intreg, 0); /* Pull the value out of the saved registers. */ @@ -4965,7 +5027,7 @@ ix86_gimplify_va_arg (tree valist, tree if (needed_sseregs) { t = build_int_cst (TREE_TYPE (fpr), - (SSE_REGPARM_MAX - needed_sseregs + 1) * 16 + (8 - needed_sseregs + 1) * 16 + REGPARM_MAX * 8); t = build2 (GE_EXPR, boolean_type_node, fpr, t); t2 = build1 (GOTO_EXPR, void_type_node, lab_false); @@ -6065,9 +6127,9 @@ ix86_expand_prologue (void) bool eax_live; rtx t; - gcc_assert (!TARGET_64BIT || TARGET_64BIT_MS_ABI); + gcc_assert (!TARGET_64BIT || cfun->machine->used_abi == 1); - if (TARGET_64BIT_MS_ABI) + if (cfun->machine->used_abi == 1) eax_live = false; else eax_live = ix86_eax_live_at_start_p (); @@ -7250,7 +7312,7 @@ legitimize_pic_address (rtx orig, rtx re /* 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); + gcc_assert (cfun->machine->used_abi != 1); if (TARGET_64BIT && ix86_cmodel != CM_LARGE_PIC) { @@ -7874,7 +7936,7 @@ output_pic_addr_const (FILE *file, rtx x #endif assemble_name (file, name); } - if (!TARGET_MACHO && !TARGET_64BIT_MS_ABI + if (!TARGET_MACHO && cfun->machine->used_abi != 1 && code == 'P' && ! SYMBOL_REF_LOCAL_P (x)) fputs ("@PLT", file); break; @@ -15591,7 +15653,7 @@ ix86_init_machine_status (void) f = GGC_CNEW (struct machine_function); f->use_fast_prologue_epilogue_nregs = -1; f->tls_descriptor_call_expanded_p = 0; - + f->used_abi = DEFAULT_USED_ABI; return f; } @@ -21091,7 +21153,7 @@ x86_this_parameter (tree function) { const int *parm_regs; - if (TARGET_64BIT_MS_ABI) + if (ix86_get_abi_format (type) == 1) parm_regs = x86_64_ms_abi_int_parameter_registers; else parm_regs = x86_64_int_parameter_registers; @@ -21240,7 +21302,7 @@ x86_output_mi_thunk (FILE *file ATTRIBUT 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) + else if (cfun->machine->used_abi == 1) gcc_unreachable (); else { @@ -21323,7 +21385,7 @@ x86_function_profiler (FILE *file, int l fprintf (file, "\tleaq\t%sP%d@(%%rip),%%r11\n", LPREFIX, labelno); #endif - if (!TARGET_64BIT_MS_ABI && flag_pic) + if (!DEFAULT_USED_ABI && flag_pic) fprintf (file, "[EMAIL PROTECTED](%%rip)\n", MCOUNT_NAME); else fprintf (file, "\tcall\t%s\n", MCOUNT_NAME); Index: gcc/gcc/config/i386/i386.h =================================================================== --- gcc.orig/gcc/config/i386/i386.h +++ gcc/gcc/config/i386/i386.h @@ -415,7 +415,10 @@ extern tree x86_mfence; #define TARGET_MACHO 0 /* Likewise, for the Windows 64-bit ABI. */ -#define TARGET_64BIT_MS_ABI 0 +#define TARGET_64BIT_MS_ABI (!cfun ? DEFAULT_USED_ABI == 1 : TARGET_64BIT && cfun->machine->used_abi == 1) + +/* The default abi form used by target. */ +#define DEFAULT_USED_ABI 0 /* Subtargets may reset this to 1 in order to enable 96-bit long double with the rounding mode forced to 53 bits. */ @@ -982,6 +985,25 @@ extern const char *host_detect_local_cpu #define ORDER_REGS_FOR_LOCAL_ALLOC x86_order_regs_for_local_alloc () +extern int ix86_get_abi_format (tree fntype); + +#define OVERRIDE_ABI_FORMAT (FNDECL) \ +do { \ + if (FNDECL == NULL) \ + cfun->machine->used_abi = DEFAULT_USED_ABI; \ + else \ + cfun->machine->used_abi = ix86_get_abi_format (TREE_TYPE (FNDECL)); \ + if (cfun->machine->used_abi == 1) \ + { \ + call_used_regs[4 /*RSI*/] = 0; \ + call_used_regs[5 /*RDI*/] = 0; \ + } \ + else if (TARGET_64BIT) \ + { \ + call_used_regs[4 /*RSI*/] = 1; \ + call_used_regs[5 /*RDI*/] = 1; \ + } \ + } while (0) /* Macro to conditionally modify fixed_regs/call_used_regs. */ #define CONDITIONAL_REGISTER_USAGE \ @@ -1033,11 +1055,6 @@ 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 @@ -1227,8 +1244,8 @@ do { \ should always be returned in memory. You should instead use `DEFAULT_PCC_STRUCT_RETURN' to indicate this. */ -#define RETURN_IN_MEMORY(TYPE) \ - ix86_return_in_memory (TYPE) +#define RETURN_IN_MEMORY(TYPE, FNTYPE) \ + ix86_return_in_memory (TYPE, FNTYPE) /* This is overridden by <cygwin.h>. */ #define MS_AGGREGATE_RETURN 0 @@ -1576,7 +1593,11 @@ enum reg_class This space can be allocated by the caller, or be a part of the machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says which. */ -#define REG_PARM_STACK_SPACE(FNDECL) 0 +#define REG_PARM_STACK_SPACE(FNDECL) ix86_reg_parm_stack_space (FNDECL) + +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) ((FNDECL) && ix86_get_abi_format (TREE_TYPE (FNDECL)) == 1 ? 1 : 0) + +extern unsigned int ix86_reg_parm_stack_space (tree); /* Value is the number of bytes of arguments automatically popped when returning from a subroutine call. @@ -1638,6 +1659,8 @@ typedef struct ix86_args { int maybe_vaarg; /* true for calls to possibly vardic fncts. */ int float_in_sse; /* 1 if in 32-bit mode SFmode (2 for DFmode) should be passed in SSE registers. Otherwise 0. */ + int used_abi; /* Set to zero for sysv_abi. Otherwise + 1 for ms_abi. */ } CUMULATIVE_ARGS; /* Initialize a variable CUM of type CUMULATIVE_ARGS @@ -2420,6 +2443,9 @@ struct machine_function GTY(()) ix86_current_function_calls_tls_descriptor macro for a better approximation. */ int tls_descriptor_call_expanded_p; + /* This value is used for amd64 targets and specifies the current abi + to be used. One means ms_abi. Otherwise 0 means sysv_abi. */ + int used_abi; }; #define ix86_stack_locals (cfun->machine->stack_locals) Index: gcc/gcc/config/iq2000/iq2000.h =================================================================== --- gcc.orig/gcc/config/iq2000/iq2000.h +++ gcc/gcc/config/iq2000/iq2000.h @@ -375,7 +375,7 @@ enum reg_class #define REG_PARM_STACK_SPACE(FNDECL) 0 -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 Index: gcc/gcc/config/mips/mips.h =================================================================== --- gcc.orig/gcc/config/mips/mips.h +++ gcc/gcc/config/mips/mips.h @@ -1897,7 +1897,7 @@ extern const enum reg_class mips_regno_t If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect of this macro is to determine whether the space is included in `current_function_outgoing_args_size'. */ -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 #define STACK_BOUNDARY (TARGET_NEWABI ? 128 : 64) Index: gcc/gcc/config/mn10300/mn10300.h =================================================================== --- gcc.orig/gcc/config/mn10300/mn10300.h +++ gcc/gcc/config/mn10300/mn10300.h @@ -487,7 +487,7 @@ enum reg_class { /* We use d0/d1 for passing parameters, so allocate 8 bytes of space for a register flushback area. */ #define REG_PARM_STACK_SPACE(DECL) 8 -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 #define ACCUMULATE_OUTGOING_ARGS 1 /* So we can allocate space for return pointers once for the function Index: gcc/gcc/config/mt/mt.h =================================================================== --- gcc.orig/gcc/config/mt/mt.h +++ gcc/gcc/config/mt/mt.h @@ -533,7 +533,7 @@ extern struct mt_frame_info current_fram /* Define this if it is the responsibility of the caller to allocate the area reserved for arguments passed in registers. */ -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 /* The number of register assigned to holding function arguments. */ #define MT_NUM_ARG_REGS 4 Index: gcc/gcc/config/pa/pa.h =================================================================== --- gcc.orig/gcc/config/pa/pa.h +++ gcc/gcc/config/pa/pa.h @@ -560,7 +560,7 @@ extern struct rtx_def *hppa_pic_save_rtx /* Define this if the above stack space is to be considered part of the space allocated by the caller. */ -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 /* Keep the stack pointer constant throughout the function. This is both an optimization and a necessity: longjmp Index: gcc/gcc/config/rs6000/rs6000.h =================================================================== --- gcc.orig/gcc/config/rs6000/rs6000.h +++ gcc/gcc/config/rs6000/rs6000.h @@ -1257,7 +1257,7 @@ extern enum rs6000_abi rs6000_current_ab /* Define this if the above stack space is to be considered part of the space allocated by the caller. */ -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 /* This is the difference between the logical top of stack and the actual sp. Index: gcc/gcc/config/score/score.h =================================================================== --- gcc.orig/gcc/config/score/score.h +++ gcc/gcc/config/score/score.h @@ -546,7 +546,7 @@ enum reg_class If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect of this macro is to determine whether the space is included in `current_function_outgoing_args_size'. */ -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 #define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0 Index: gcc/gcc/config/spu/spu.h =================================================================== --- gcc.orig/gcc/config/spu/spu.h +++ gcc/gcc/config/spu/spu.h @@ -354,7 +354,7 @@ targetm.resolve_overloaded_builtin = spu #define REG_PARM_STACK_SPACE(FNDECL) 0 -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) (0) Index: gcc/gcc/config/v850/v850.h =================================================================== --- gcc.orig/gcc/config/v850/v850.h +++ gcc/gcc/config/v850/v850.h @@ -626,7 +626,7 @@ struct cum_arg { int nbytes; int anonymo /* Define this if the above stack space is to be considered part of the space allocated by the caller. */ -#define OUTGOING_REG_PARM_STACK_SPACE 1 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 1 /* 1 if N is a possible register number for function argument passing. */ Index: gcc/gcc/defaults.h =================================================================== --- gcc.orig/gcc/defaults.h +++ gcc/gcc/defaults.h @@ -905,7 +905,7 @@ along with GCC; see the file COPYING3. #endif #ifndef OUTGOING_REG_PARM_STACK_SPACE -#define OUTGOING_REG_PARM_STACK_SPACE 0 +#define OUTGOING_REG_PARM_STACK_SPACE(FNDECL) 0 #endif #endif /* ! GCC_DEFAULTS_H */ Index: gcc/gcc/expr.c =================================================================== --- gcc.orig/gcc/expr.c +++ gcc/gcc/expr.c @@ -1233,6 +1233,8 @@ emit_block_move (rtx x, rtx y, rtx size, static bool block_move_libcall_safe_for_call_parm (void) { + tree fn; + /* If arguments are pushed on the stack, then they're safe. */ if (PUSH_ARGS) return true; @@ -1240,13 +1242,9 @@ block_move_libcall_safe_for_call_parm (v /* If registers go on the stack anyway, any argument is sure to clobber an outgoing argument. */ #if defined (REG_PARM_STACK_SPACE) - if (OUTGOING_REG_PARM_STACK_SPACE) - { - tree fn; - fn = emit_block_move_libcall_fn (false); - if (REG_PARM_STACK_SPACE (fn) != 0) - return false; - } + fn = emit_block_move_libcall_fn (false); + if (OUTGOING_REG_PARM_STACK_SPACE (fn) && REG_PARM_STACK_SPACE (fn) != 0) + return false; #endif /* If any argument goes in memory, then it might clobber an outgoing Index: gcc/gcc/function.c =================================================================== --- gcc.orig/gcc/function.c +++ gcc/gcc/function.c @@ -1216,7 +1216,7 @@ static int cfa_offset; #define STACK_DYNAMIC_OFFSET(FNDECL) \ ((ACCUMULATE_OUTGOING_ARGS \ ? (current_function_outgoing_args_size \ - + (OUTGOING_REG_PARM_STACK_SPACE ? 0 : REG_PARM_STACK_SPACE (FNDECL))) \ + + (OUTGOING_REG_PARM_STACK_SPACE (FNDECL) ? 0 : REG_PARM_STACK_SPACE (FNDECL))) \ : 0) + (STACK_POINTER_OFFSET)) #else #define STACK_DYNAMIC_OFFSET(FNDECL) \ @@ -3813,12 +3813,15 @@ allocate_struct_function (tree fndecl) if (init_machine_status) cfun->machine = (*init_machine_status) (); +#ifdef OVERRIDE_ABI_FORM + OVERRIDE_ABI_FORMAT (fndecl); +#endif + if (fndecl == NULL) return; DECL_STRUCT_FUNCTION (fndecl) = cfun; cfun->decl = fndecl; - result = DECL_RESULT (fndecl); if (aggregate_value_p (result, fndecl)) { Index: gcc/gcc/targhooks.c =================================================================== --- gcc.orig/gcc/targhooks.c +++ gcc/gcc/targhooks.c @@ -90,7 +90,7 @@ default_return_in_memory (tree type, #ifndef RETURN_IN_MEMORY return (TYPE_MODE (type) == BLKmode); #else - return RETURN_IN_MEMORY (type); + return RETURN_IN_MEMORY (type, fntype); #endif } =