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
}
=