+2004-03-13 Alan Modra <amodra@bigpond.net.au>
+
+ PR target/14567
+ * config/rs6000/rs6000.h (UNITS_PER_ARG, RS6000_ARG_SIZE): Delete.
+ (HARD_REGNO_MODE_OK): Disallow TFmode for fp31.
+ * config/rs6000/rs6000.c (rs6000_arg_size): New function.
+ Update all users of RS6000_ARG_SIZE.
+ (function_arg_advance): Count fregno using mode size.
+ (function_arg): Handle long double split over regs and memory.
+ (function_arg_partial_nregs): Likewise.
+ (rs6000_va_arg): Repackage complex args.
+
2004-03-13 Dean Ferreyra <dferreyra@igc.org>
PR target/14047
that corresponds to this FDE.
(FRAME_BEGIN_LABEL): Allow target to override default label.
(output_call_frame_info): If FDEs are linknonce, then use extra
- indirection for FDE encoding, output a label for each FDE, and
+ indirection for FDE encoding, output a label for each FDE, and
output an empty label for each function without an FDE.
(dwarf2out_begin_prologue): Set up decl field when creating an FDE.
* varasm.c (globalize_decl): Call ASM_MAKE_LABEL_LINKONCE for
* target.h (struct gcc_target): Move calls substructure before
booleans. Add split_complex_arg.
* function.c (assign_parms, split_complex_args): Use it.
- * calls.c (expand_call): Likewise.
- (split_complex_values): Likewise. Check for splittable types
- before allocating memory.
- (split_complex_types): Likewise.
+ * calls.c (expand_call): Likewise.
+ (split_complex_values): Likewise. Check for splittable types
+ before allocating memory.
+ (split_complex_types): Likewise.
* system.h (SPLIT_COMPLEX_ARGS): Poison.
* expr.h (SPLIT_COMPLEX_ARGS): Remove.
* target-def.h (TARGET_SPLIT_COMPLEX_ARG): New.
(set_frame_base_location): Unshare variable if needed.
(set_variable_part): Init the refcount of new variable.
Unshare the variables if needed.
- (delete_variable_part): Unshare the variables if needed.
+ (delete_variable_part): Unshare the variables if needed.
(emit_notes_for_differences_1): Init the refcount of new variable.
(vt_add_function_parameters): Do not add function parameters to
IN set of ENTRY_BLOCK_PTR because it is unused anyway.
and gt_pch_use_address.
* config/host-linux.c, config/host-solaris.c: New files.
* config/x-linux, config/x-solaris: New files.
- * config/rs6000/host-darwin.c darwin_rs6000_gt_pch_get_address):
+ * config/rs6000/host-darwin.c (darwin_rs6000_gt_pch_get_address):
Update for changed definition.
(darwin_rs6000_gt_pch_use_address): Likewise.
* doc/hostconfig.texi: Update docs.
PR bootstrap/12371
* config/m68k/m68k.h (FIXED_REGISTERS): Add arg pointer.
(CALL_USED_REGISTERS): Likewise.
- (REG_CLASS_CONTENTS): Likewise.
+ (REG_CLASS_CONTENTS): Likewise.
(REG_ALLOC_ORDER): New.
(REGNO_REG_CLASS): Use regno_reg_class.
* config/m68k/m68k.c: Add regno_reg_class array.
* toplev.c (dump_file_tbl): Rename from dump_file.
* bb-reorder.c, bt-load.c, cfgcleanup.c, cfglayout.c, cfgloopanal.c,
- cfgloopmanip.c, cfgrtl.c, config/arm/arm.c, config/frv/frv.c,
+ cfgloopmanip.c, cfgrtl.c, config/arm/arm.c, config/frv/frv.c,
config/i386/i386.c, config/ia64/ia64.c, config/mips/mips.c,
config/sh/sh.c, cse.c, flow.c, ifcvt.c, loop-iv.c, loop-unroll.c,
loop-unswitch.c, output.h, predict.c, profile.c, ra-build.c,
2004-01-31 Paolo Bonzini <bonzini@gnu.org>
- * combine.c (cse_main): Set gen_lowpart to gen_lowpart_for_combine
+ * combine.c (cse_main): Set gen_lowpart to gen_lowpart_for_combine
and restore it to gen_lowpart_general on exit.
(gen_lowpart_for_combine): Adjust all callers to go through
gen_lowpart.
* fixinc/inclhack.def (alpha___extern_prefix,
alpha___extern_prefix_standards): New hacks to obey
- __PRAGMA_EXTERN_PREFIX.
+ __PRAGMA_EXTERN_PREFIX.
* fixinc/tests/base/testing.h [ALPHA___EXTERN_PREFIX_CHECK]: New
test.
* fixinc/tests/base/standards.h: Likewise.
else
return PARM_BOUNDARY;
}
+
+/* Compute the size (in words) of a function argument. */
+
+static unsigned long
+rs6000_arg_size (enum machine_mode mode, tree type)
+{
+ unsigned long size;
+
+ if (mode != BLKmode)
+ size = GET_MODE_SIZE (mode);
+ else
+ size = int_size_in_bytes (type);
+
+ if (TARGET_32BIT)
+ return (size + 3) >> 2;
+ else
+ return (size + 7) >> 3;
+}
\f
/* Update the data in CUM to advance over an argument
of mode MODE and data type TYPE.
align = ((6 - (cum->words & 3)) & 3);
else
align = cum->words & 1;
- cum->words += align + RS6000_ARG_SIZE (mode, type);
+ cum->words += align + rs6000_arg_size (mode, type);
if (TARGET_DEBUG_ARG)
{
{
if (mode == DFmode)
cum->words += cum->words & 1;
- cum->words += RS6000_ARG_SIZE (mode, type);
+ cum->words += rs6000_arg_size (mode, type);
}
}
else
|| mode == TFmode)
n_words = 1;
else
- n_words = RS6000_ARG_SIZE (mode, type);
+ n_words = rs6000_arg_size (mode, type);
/* Long long and SPE vectors are put in odd registers. */
if (n_words == 2 && (gregno & 1) == 0)
int align = (TARGET_32BIT && (cum->words & 1) != 0
&& function_arg_boundary (mode, type) == 64) ? 1 : 0;
- cum->words += align + RS6000_ARG_SIZE (mode, type);
+ cum->words += align + rs6000_arg_size (mode, type);
if (GET_MODE_CLASS (mode) == MODE_FLOAT
&& TARGET_HARD_FLOAT && TARGET_FPRS)
- cum->fregno += (mode == TFmode ? 2 : 1);
+ cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
if (TARGET_DEBUG_ARG)
{
if (cum->stdarg)
{
int gregno = cum->sysv_gregno;
- int n_words = RS6000_ARG_SIZE (mode, type);
+ int n_words = rs6000_arg_size (mode, type);
/* SPE vectors are put in odd registers. */
if (n_words == 2 && (gregno & 1) == 0)
gen_rtx_REG (mode,
cum->fregno),
const0_rtx)));
- else if (align_words + RS6000_ARG_SIZE (mode, type)
+ else if (align_words + rs6000_arg_size (mode, type)
> GP_ARG_NUM_REG)
/* If this is partially on the stack, then we only
include the portion actually in registers here. */
|| mode == TFmode)
n_words = 1;
else
- n_words = RS6000_ARG_SIZE (mode, type);
+ n_words = rs6000_arg_size (mode, type);
/* Long long and SPE vectors are put in odd registers. */
if (n_words == 2 && (gregno & 1) == 0)
gregno += 1;
- /* Long long do not split between registers and stack. */
+ /* Long long does not split between registers and stack. */
if (gregno + n_words - 1 <= GP_ARG_MAX_REG)
return gen_rtx_REG (mode, gregno);
else
if (USE_FP_FOR_ARG_P (cum, mode, type))
{
- if (! type
- || ((cum->nargs_prototype > 0)
- /* IBM AIX extended its linkage convention definition always
- to require FP args after register save area hole on the
- stack. */
- && (DEFAULT_ABI != ABI_AIX
- || ! TARGET_XL_CALL
- || (align_words < GP_ARG_NUM_REG))))
- return gen_rtx_REG (mode, cum->fregno);
+ rtx fpr[2];
+ rtx *r;
+ bool needs_psave;
+ enum machine_mode fmode = mode;
+ int n;
+ unsigned long n_fpreg = (GET_MODE_SIZE (mode) + 7) >> 3;
+
+ if (cum->fregno + n_fpreg > FP_ARG_MAX_REG + 1)
+ {
+ /* Long double split over regs and memory. */
+ if (fmode == TFmode)
+ fmode = DFmode;
+
+ /* Currently, we only ever need one reg here because complex
+ doubles are split. */
+ if (cum->fregno != FP_ARG_MAX_REG - 1)
+ abort ();
+ }
+ fpr[1] = gen_rtx_REG (fmode, cum->fregno);
+
+ /* Do we also need to pass this arg in the parameter save
+ area? */
+ needs_psave = (type
+ && (cum->nargs_prototype <= 0
+ || (DEFAULT_ABI == ABI_AIX
+ && TARGET_XL_CALL
+ && align_words >= GP_ARG_NUM_REG)));
+
+ if (!needs_psave && mode == fmode)
+ return fpr[1];
if (TARGET_32BIT && TARGET_POWERPC64
&& mode == DFmode && cum->stdarg)
return rs6000_mixed_function_arg (cum, mode, type, align_words);
- return gen_rtx_PARALLEL (mode,
- gen_rtvec (2,
- gen_rtx_EXPR_LIST (VOIDmode,
- ((align_words >= GP_ARG_NUM_REG)
- ? NULL_RTX
- : (align_words
- + RS6000_ARG_SIZE (mode, type)
- > GP_ARG_NUM_REG
- /* If this is partially on the stack, then
- we only include the portion actually
- in registers here. */
- ? gen_rtx_REG (Pmode,
- GP_ARG_MIN_REG + align_words)
- : gen_rtx_REG (mode,
- GP_ARG_MIN_REG + align_words))),
- const0_rtx),
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (mode, cum->fregno),
- const0_rtx)));
+ /* Describe where this piece goes. */
+ r = fpr + 1;
+ *r = gen_rtx_EXPR_LIST (VOIDmode, *r, const0_rtx);
+ n = 1;
+
+ if (needs_psave)
+ {
+ /* Now describe the part that goes in gprs or the stack.
+ This piece must come first, before the fprs. */
+ rtx reg = NULL_RTX;
+ if (align_words < GP_ARG_NUM_REG)
+ {
+ unsigned long n_words = rs6000_arg_size (mode, type);
+ enum machine_mode rmode = mode;
+
+ if (align_words + n_words > GP_ARG_NUM_REG)
+ /* If this is partially on the stack, then we only
+ include the portion actually in registers here.
+ We know this can only be one register because
+ complex doubles are splt. */
+ rmode = Pmode;
+ reg = gen_rtx_REG (rmode, GP_ARG_MIN_REG + align_words);
+ }
+ *--r = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx);
+ ++n;
+ }
+
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (n, r));
}
else if (align_words < GP_ARG_NUM_REG)
return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
tree type, int named)
{
+ int ret = 0;
+
if (DEFAULT_ABI == ABI_V4)
return 0;
- if (USE_FP_FOR_ARG_P (cum, mode, type)
- || USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
+ if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named)
+ && cum->nargs_prototype >= 0)
+ return 0;
+
+ if (USE_FP_FOR_ARG_P (cum, mode, type))
{
- if (cum->nargs_prototype >= 0)
+ if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) > FP_ARG_MAX_REG + 1)
+ ret = FP_ARG_MAX_REG - cum->fregno;
+ else if (cum->nargs_prototype >= 0)
return 0;
}
if (cum->words < GP_ARG_NUM_REG
- && GP_ARG_NUM_REG < (cum->words + RS6000_ARG_SIZE (mode, type)))
- {
- int ret = GP_ARG_NUM_REG - cum->words;
- if (ret && TARGET_DEBUG_ARG)
- fprintf (stderr, "function_arg_partial_nregs: %d\n", ret);
+ && GP_ARG_NUM_REG < cum->words + rs6000_arg_size (mode, type))
+ ret = GP_ARG_NUM_REG - cum->words;
- return ret;
- }
+ if (ret != 0 && TARGET_DEBUG_ARG)
+ fprintf (stderr, "function_arg_partial_nregs: %d\n", ret);
- return 0;
+ return ret;
}
\f
/* A C expression that indicates when an argument must be passed by
cfun->machine->sysv_varargs_p = 0;
if (MUST_PASS_IN_STACK (mode, type))
- first_reg_offset += RS6000_ARG_SIZE (TYPE_MODE (type), type);
+ first_reg_offset += rs6000_arg_size (TYPE_MODE (type), type);
}
set = get_varargs_alias_set ();
return expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
}
- else
- return std_expand_builtin_va_arg (valist, type);
+ if (SPLIT_COMPLEX_ARGS
+ && TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ tree elem_type = TREE_TYPE (type);
+ enum machine_mode elem_mode = TYPE_MODE (elem_type);
+ int elem_size = GET_MODE_SIZE (elem_mode);
+
+ if (elem_size < UNITS_PER_WORD)
+ {
+ rtx real_part, imag_part, dest_real, rr;
+
+ real_part = rs6000_va_arg (valist, elem_type);
+ imag_part = rs6000_va_arg (valist, elem_type);
+
+ /* We're not returning the value here, but the address.
+ real_part and imag_part are not contiguous, and we know
+ there is space available to pack real_part next to
+ imag_part. float _Complex is not promoted to
+ double _Complex by the default promotion rules that
+ promote float to double. */
+ if (2 * elem_size > UNITS_PER_WORD)
+ abort ();
+
+ real_part = gen_rtx_MEM (elem_mode, real_part);
+ imag_part = gen_rtx_MEM (elem_mode, imag_part);
+
+ dest_real = adjust_address (imag_part, elem_mode, -elem_size);
+ rr = gen_reg_rtx (elem_mode);
+ emit_move_insn (rr, real_part);
+ emit_move_insn (dest_real, rr);
+
+ return XEXP (dest_real, 0);
+ }
+ }
+
+ return std_expand_builtin_va_arg (valist, type);
}
f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));