* Patch for COMPLEX support (part 2)
@ 1998-02-10 3:34 Weiwen Liu
0 siblings, 0 replies; 2+ messages in thread
From: Weiwen Liu @ 1998-02-10 3:34 UTC (permalink / raw)
To: egcs
Wed Jan 7 17:30:00 1998 Weiwen Liu <liu@hepunix.physics.yale.edu>
* machmode.h: define COMPLEX_MODE_P, COMPLEX_SUBMODE.
* regs.h (REG_SIZE): Consider complex modes.
* calls.c (arg_data): Add partial_real and partial_imag to
record the number of registers used for real/imaginary part.
* combine.c (expand_field_assignment): Exclude SUBREG of a
COMPLEX.
* explow.c (hard_function_value): Promote COMPLEX return
value if required.
* calls.c (expand_call): Deal with arguments of complex modes.
(store_one_arg): Likewise.
* emit-rtl.c (gen_lowpart_common): Likewise.
(gen_highpart): Likewise.
* expr.c (store_expr): Likewise.
(expand_expr): Likewise.
* function.c (aggregate_value_p): Likewise.
(assign_parms): Likewise.
(locate_and_pad_parm): Likewise.
(expand_function_start): Likewise.
* integrate.c (expand_inline_function): Likewise.
* reload.c (find_reloads): Likewise.
* stmt.c (expand_value_return): Likewise.
--- gcc/calls.c.orig Wed Dec 24 16:39:40 1997
+++ gcc/calls.c Wed Jan 7 10:57:01 1998
@@ -71,6 +71,10 @@ struct arg_data
/* Number of registers to use. 0 means put the whole arg in registers.
Also 0 if not passed in registers. */
int partial;
+ /* Number of registers to use for real part. */
+ int partial_real;
+ /* Number of registers to use for imaginary part. */
+ int partial_imag;
/* Non-zero if argument must be passed on stack.
Note that some arguments may be passed on the stack
even though pass_on_stack is zero, just because FUNCTION_ARG says so.
@@ -1012,7 +1016,9 @@ expand_call (exp, target, ignore)
tree type = TREE_TYPE (TREE_VALUE (p));
int unsignedp;
enum machine_mode mode;
-
+ enum machine_mode submode;
+ tree subtype;
+
args[i].tree_value = TREE_VALUE (p);
/* Replace erroneous argument with constant zero. */
@@ -1044,8 +1050,13 @@ expand_call (exp, target, ignore)
&& contains_placeholder_p (TYPE_SIZE (type)))
|| TREE_ADDRESSABLE (type)
#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
- || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, TYPE_MODE (type),
- type, argpos < n_named_args)
+ || FUNCTION_ARG_PASS_BY_REFERENCE
+ (args_so_far,
+ (! COMPLEX_MODE_P (TYPE_MODE (type)))?
+ TYPE_MODE (type) : COMPLEX_SUBMODE (TYPE_MODE (type)),
+ (! COMPLEX_MODE_P (TYPE_MODE (type)))?
+ type : type_for_mode (COMPLEX_SUBMODE (TYPE_MODE (type)), 0),
+ argpos < n_named_args)
#endif
)
{
@@ -1053,8 +1064,14 @@ expand_call (exp, target, ignore)
references instead of making a copy. */
if (current_function_is_thunk
#ifdef FUNCTION_ARG_CALLEE_COPIES
- || (FUNCTION_ARG_CALLEE_COPIES (args_so_far, TYPE_MODE (type),
- type, argpos < n_named_args)
+ || (FUNCTION_ARG_CALLEE_COPIES
+ (args_so_far,
+ COMPLEX_MODE_P (TYPE_MODE (type))?
+ COMPLEX_SUBMODE (TYPE_MODE (type)) : TYPE_MODE (type),
+ COMPLEX_MODE_P (TYPE_MODE (type))?
+ type_for_mode (COMPLEX_SUBMODE (TYPE_MODE (type)), 0)
+ : type,
+ argpos < n_named_args)
/* If it's in a register, we must make a copy of it too. */
/* ??? Is this a sufficient test? Is there a better one? */
&& !(TREE_CODE (args[i].tree_value) == VAR_DECL
@@ -1117,21 +1134,81 @@ expand_call (exp, target, ignore)
mode = TYPE_MODE (type);
unsignedp = TREE_UNSIGNED (type);
-
+ if (COMPLEX_MODE_P (mode))
+ {
+ submode = COMPLEX_SUBMODE (mode);
+ subtype = type_for_mode (submode, unsignedp);
+ }
+
#ifdef PROMOTE_FUNCTION_ARGS
- mode = promote_mode (type, mode, &unsignedp, 1);
+ if (! COMPLEX_MODE_P (mode))
+ {
+ mode = promote_mode (type, mode, &unsignedp, 1);
+ }
+ else
+ {
+ submode = promote_mode (subtype, submode, &unsignedp, 1);
+ subtype = type_for_mode (submode, unsignedp);
+ mode = mode_for_size (2 * GET_MODE_SIZE (submode) * BITS_PER_UNIT,
+ GET_MODE_CLASS (mode), 0);
+ }
#endif
args[i].unsignedp = unsignedp;
args[i].mode = mode;
- args[i].reg = FUNCTION_ARG (args_so_far, mode, type,
- argpos < n_named_args);
+ if (! COMPLEX_MODE_P (mode))
+ {
+ args[i].reg = FUNCTION_ARG (args_so_far, mode, type,
+ argpos < n_named_args);
#ifdef FUNCTION_ARG_PARTIAL_NREGS
- if (args[i].reg)
- args[i].partial
- = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, type,
- argpos < n_named_args);
+ if (args[i].reg)
+ args[i].partial
+ = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, type,
+ argpos < n_named_args);
#endif
+ /* Increment ARGS_SO_FAR, which has info about which arg-registers
+ have been used, etc. */
+ FUNCTION_ARG_ADVANCE (args_so_far, TYPE_MODE (type), type,
+ argpos < n_named_args);
+ }
+ else
+ {
+ rtx realpart;
+ rtx imagpart;
+
+ realpart = FUNCTION_ARG (args_so_far, submode, subtype,
+ argpos < n_named_args);
+#ifdef FUNCTION_ARG_PARTIAL_NREGS
+ args[i].partial_real = 0;
+ if (realpart)
+ {
+ args[i].partial_real
+ = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, submode, subtype,
+ argpos < n_named_args);
+ args[i].partial = args[i].partial_real;
+ }
+#endif
+ FUNCTION_ARG_ADVANCE (args_so_far, submode,
+ type, argpos < n_named_args);
+ imagpart = FUNCTION_ARG (args_so_far, submode, subtype,
+ argpos < n_named_args);
+#ifdef FUNCTION_ARG_PARTIAL_NREGS
+ args[i].partial_imag = 0;
+ if (imagpart)
+ {
+ args[i].partial_imag
+ = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, submode, subtype,
+ argpos < n_named_args);
+ args[i].partial = args[i].partial_imag;
+ }
+#endif
+ FUNCTION_ARG_ADVANCE (args_so_far, submode,
+ type, argpos < n_named_args);
+ if (realpart != 0)
+ args[i].reg = gen_rtx (CONCAT, mode, realpart, imagpart);
+ else
+ args[i].reg = 0;
+ }
args[i].pass_on_stack = MUST_PASS_IN_STACK (mode, type);
@@ -1158,19 +1235,45 @@ expand_call (exp, target, ignore)
/* Compute the stack-size of this argument. */
if (args[i].reg == 0 || args[i].partial != 0
+ /* Allocate stack for a complex argument if its real part is
+ passed in register and its imaginary part is not. */
+ || (COMPLEX_MODE_P (mode) && XEXP (args[i].reg, 1) == 0)
#ifdef REG_PARM_STACK_SPACE
|| reg_parm_stack_space > 0
#endif
|| args[i].pass_on_stack)
- locate_and_pad_parm (mode, type,
+ {
+ enum machine_mode passed_mode = mode;
+ tree passed_type = type;
+ rtx reg = args[i].reg;
+
+ if (COMPLEX_MODE_P (mode) && args[i].reg != 0
+#if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE)
+ && REG_PARM_STACK_SPACE (fndecl) == 0
+#endif
+ )
+ {
+ /* If we do not need to allocate stack space for
+ arguments passing in register, and the real part
+ of a complex argument is passing in register,
+ we only allocate stack space for the imaginary part. */
+ if (XEXP (args[i].reg, 0) != 0 && args[i].partial_real == 0)
+ {
+ passed_mode = submode;
+ passed_type = subtype;
+ reg = XEXP (args[i].reg, 1);
+ }
+ }
+ locate_and_pad_parm (passed_mode, passed_type,
#ifdef STACK_PARMS_IN_REG_PARM_AREA
- 1,
+ 1,
#else
- args[i].reg != 0,
+ reg != 0,
#endif
- fndecl, &args_size, &args[i].offset,
- &args[i].size);
-
+ fndecl, &args_size, &args[i].offset,
+ &args[i].size);
+ }
+
#ifndef ARGS_GROW_DOWNWARD
args[i].slot_offset = args_size;
#endif
@@ -1203,12 +1306,6 @@ expand_call (exp, target, ignore)
SUB_PARM_SIZE (args[i].slot_offset, args_size.var);
}
#endif
-
- /* Increment ARGS_SO_FAR, which has info about which arg-registers
- have been used, etc. */
-
- FUNCTION_ARG_ADVANCE (args_so_far, TYPE_MODE (type), type,
- argpos < n_named_args);
}
#ifdef FINAL_REG_PARM_STACK_SPACE
@@ -1375,10 +1472,33 @@ expand_call (exp, target, ignore)
= protect_from_queue (args[i].initial_value, 0);
if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
- args[i].value
- = convert_modes (args[i].mode,
- TYPE_MODE (TREE_TYPE (args[i].tree_value)),
- args[i].value, args[i].unsignedp);
+ {
+ if (! COMPLEX_MODE_P (args[i].mode))
+ args[i].value
+ = convert_modes (args[i].mode,
+ TYPE_MODE (TREE_TYPE (args[i].tree_value)),
+ args[i].value, args[i].unsignedp);
+ else
+ {
+ enum machine_mode submode_orig
+ = COMPLEX_SUBMODE (TYPE_MODE
+ (TREE_TYPE (args[i].tree_value)));
+ enum machine_mode submode_final
+ = COMPLEX_SUBMODE (args[i].mode);
+ rtx realpart;
+ rtx imagpart;
+ realpart = convert_modes (submode_final, submode_orig,
+ gen_realpart (submode_orig,
+ args[i].value),
+ args[i].unsignedp);
+ imagpart = convert_modes (submode_final, submode_orig,
+ gen_imagpart (submode_orig,
+ args[i].value),
+ args[i].unsignedp);
+ args[i].value = gen_rtx (CONCAT, args[i].mode,
+ realpart, imagpart);
+ }
+ }
}
/* Now we are about to start emitting insns that can be deleted
@@ -1665,10 +1785,33 @@ expand_call (exp, target, ignore)
do it now. */
if (args[i].mode != TYPE_MODE (TREE_TYPE (args[i].tree_value)))
- args[i].value
- = convert_modes (args[i].mode,
- TYPE_MODE (TREE_TYPE (args[i].tree_value)),
- args[i].value, args[i].unsignedp);
+ {
+ if (! COMPLEX_MODE_P (args[i].mode))
+ args[i].value
+ = convert_modes (args[i].mode,
+ TYPE_MODE (TREE_TYPE (args[i].tree_value)),
+ args[i].value, args[i].unsignedp);
+ else
+ {
+ enum machine_mode submode_orig
+ = COMPLEX_SUBMODE (TYPE_MODE
+ (TREE_TYPE (args[i].tree_value)));
+ enum machine_mode submode_final
+ = COMPLEX_SUBMODE (args[i].mode);
+ rtx realpart;
+ rtx imagpart;
+ realpart = convert_modes (submode_final, submode_orig,
+ gen_realpart (submode_orig,
+ args[i].value),
+ args[i].unsignedp);
+ imagpart = convert_modes (submode_final, submode_orig,
+ gen_imagpart (submode_orig,
+ args[i].value),
+ args[i].unsignedp);
+ args[i].value = gen_rtx (CONCAT, args[i].mode,
+ realpart, imagpart);
+ }
+ }
/* If the value is expensive, and we are inside an appropriately
short loop, put the value into a pseudo and then put the pseudo
@@ -1758,7 +1901,12 @@ expand_call (exp, target, ignore)
but we do preallocate space here if they want that. */
for (i = 0; i < num_actuals; i++)
- if (args[i].reg == 0 || args[i].pass_on_stack)
+ if (args[i].reg == 0 || args[i].pass_on_stack
+ /* Deal with the imaginary part of a complex argument
+ that is passed in stack. */
+ || (COMPLEX_MODE_P (args[i].mode)
+ && args[i].reg != 0 && args[i].partial == 0
+ && XEXP (args[i].reg, 1) == 0))
store_one_arg (&args[i], argblock, may_be_alloca,
args_size.var != 0, fndecl, reg_parm_stack_space);
@@ -1919,8 +2067,22 @@ expand_call (exp, target, ignore)
load the register(s) from memory. */
else if (nregs == -1)
- emit_move_insn (reg, args[i].value);
-
+ {
+ if (GET_CODE (reg) != CONCAT)
+ emit_move_insn (reg, args[i].value);
+ else
+ {
+ enum machine_mode submode
+ = COMPLEX_SUBMODE (args[i].value->mode);
+ if (XEXP (reg, 0))
+ emit_move_insn (XEXP (reg, 0),
+ gen_realpart (submode, args[i].value));
+ if (XEXP (reg, 1))
+ emit_move_insn (XEXP (reg, 1),
+ gen_imagpart (submode, args[i].value));
+ }
+ }
+
/* If we have pre-computed the values to put in the registers in
the case of non-aligned structures, copy them in now. */
@@ -1939,9 +2101,31 @@ expand_call (exp, target, ignore)
if (GET_CODE (reg) == PARALLEL)
use_group_regs (&call_fusage, reg);
else if (nregs == -1)
- use_reg (&call_fusage, reg);
+ {
+ if (GET_CODE (reg) != CONCAT)
+ use_reg (&call_fusage, reg);
+ else
+ {
+ if (XEXP (reg, 0))
+ use_reg (&call_fusage, XEXP (reg, 0));
+ if (XEXP (reg, 1))
+ use_reg (&call_fusage, XEXP (reg, 1));
+ }
+ }
else
- use_regs (&call_fusage, REGNO (reg), nregs == 0 ? 1 : nregs);
+ {
+ if (GET_CODE (reg) != CONCAT)
+ use_regs (&call_fusage, REGNO (reg), nregs == 0 ? 1 : nregs);
+ else
+ {
+ if (args[i].partial_real)
+ use_regs (&call_fusage, REGNO (XEXP (reg, 0)),
+ args[i].partial_real);
+ else
+ use_regs (&call_fusage, REGNO (XEXP (reg, 1)),
+ args[i].partial_imag);
+ }
+ }
}
}
@@ -2193,6 +2377,41 @@ expand_call (exp, target, ignore)
SUBREG_PROMOTED_VAR_P (target) = 1;
SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp;
}
+ else if (GET_CODE (target) == CONCAT
+ && GET_CODE (XEXP (target, 0)) == REG
+ && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
+ && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
+ {
+ tree type = TREE_TYPE (exp);
+ int unsignedp = TREE_UNSIGNED (type);
+ enum machine_mode submode_orig = COMPLEX_SUBMODE (TYPE_MODE (type));
+ enum machine_mode submode_final;
+ enum machine_mode promoted_mode;
+ rtx realpart;
+ rtx imagpart;
+
+ submode_final = promote_mode (type_for_mode (submode_orig, unsignedp),
+ submode_orig, &unsignedp, 1);
+ promoted_mode = mode_for_size (2 * GET_MODE_SIZE (submode_final)
+ * BITS_PER_UNIT,
+ GET_MODE_CLASS (GET_MODE (target)), 0);
+
+ /* If we don't promote as expected, something is wrong. */
+ if (GET_MODE (target) != promoted_mode )
+ abort ();
+
+ realpart = gen_rtx (SUBREG, submode_orig,
+ gen_realpart (submode_final, target), 0);
+ SUBREG_PROMOTED_VAR_P (realpart) = 1;
+ SUBREG_PROMOTED_UNSIGNED_P (realpart) = unsignedp;
+
+ imagpart = gen_rtx (SUBREG, submode_orig,
+ gen_imagpart (submode_final, target), 0);
+ SUBREG_PROMOTED_VAR_P (imagpart) = 1;
+ SUBREG_PROMOTED_UNSIGNED_P (imagpart) = unsignedp;
+
+ target = gen_rtx (CONCAT, TYPE_MODE (type), realpart, imagpart);
+ }
#endif
/* If size of args is variable or this was a constructor call for a stack
@@ -3512,8 +3737,13 @@ store_one_arg (arg, argblock, may_be_all
/* If this isn't going to be placed on both the stack and in registers,
set up the register and number of words. */
if (! arg->pass_on_stack)
- reg = arg->reg, partial = arg->partial;
-
+ {
+ reg = arg->reg, partial = arg->partial;
+ if (reg && COMPLEX_MODE_P (reg->mode) && partial == 0)
+ /* Deal with the imaginary part passing in stack. */
+ reg = 0;
+ }
+
if (reg != 0 && partial == 0)
/* Being passed entirely in a register. We shouldn't be called in
this case. */
@@ -3560,8 +3790,31 @@ store_one_arg (arg, argblock, may_be_all
doesn't agree, convert the mode. */
if (arg->mode != TYPE_MODE (TREE_TYPE (pval)))
- arg->value = convert_modes (arg->mode, TYPE_MODE (TREE_TYPE (pval)),
- arg->value, arg->unsignedp);
+ {
+ if (! COMPLEX_MODE_P (arg->mode))
+ arg->value
+ = convert_modes (arg->mode, TYPE_MODE (TREE_TYPE (pval)),
+ arg->value, arg->unsignedp);
+ else
+ {
+ enum machine_mode submode_orig
+ = COMPLEX_SUBMODE (TYPE_MODE (TREE_TYPE (pval)));
+ enum machine_mode submode_final
+ = COMPLEX_SUBMODE (arg->mode);
+ rtx realpart;
+ rtx imagpart;
+ realpart = convert_modes (submode_final, submode_orig,
+ gen_realpart (submode_orig,
+ arg->value),
+ arg->unsignedp);
+ imagpart = convert_modes (submode_final, submode_orig,
+ gen_imagpart (submode_orig,
+ arg->value),
+ arg->unsignedp);
+ arg->value = gen_rtx (CONCAT, arg->mode,
+ realpart, imagpart);
+ }
+ }
#ifdef ACCUMULATE_OUTGOING_ARGS
if (arg->pass_on_stack)
@@ -3593,6 +3846,11 @@ store_one_arg (arg, argblock, may_be_all
else if (arg->mode != BLKmode)
{
register int size;
+ enum machine_mode mode
+ = (!COMPLEX_MODE_P (arg->mode)) ?
+ arg->mode : COMPLEX_SUBMODE (arg->mode);
+ tree type = (!COMPLEX_MODE_P (arg->mode))?
+ TREE_TYPE (pval) : TREE_TYPE (TREE_TYPE (pval));
/* Argument is a scalar, not entirely passed in registers.
(If part is passed in registers, arg->partial says how much
@@ -3604,7 +3862,7 @@ store_one_arg (arg, argblock, may_be_all
Note that in C the default argument promotions
will prevent such mismatches. */
- size = GET_MODE_SIZE (arg->mode);
+ size = GET_MODE_SIZE (mode);
/* Compute how much space the push instruction will push.
On many machines, pushing a byte will advance the stack
pointer by a halfword. */
@@ -3615,16 +3873,57 @@ store_one_arg (arg, argblock, may_be_all
/* Compute how much space the argument should get:
round up to a multiple of the alignment for arguments. */
- if (none != FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)))
+ if (none != FUNCTION_ARG_PADDING (mode, type))
used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
/ (PARM_BOUNDARY / BITS_PER_UNIT))
* (PARM_BOUNDARY / BITS_PER_UNIT));
/* This isn't already where we want it on the stack, so put it there.
This can either be done with push or copy insns. */
- emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX,
- 0, partial, reg, used - size,
- argblock, ARGS_SIZE_RTX (arg->offset));
+ if (! COMPLEX_MODE_P (arg->mode))
+ emit_push_insn (arg->value, arg->mode, type, NULL_RTX,
+ 0, partial, reg, used - size,
+ argblock, ARGS_SIZE_RTX (arg->offset));
+ else
+ {
+ struct args_size offset;
+ offset.constant = arg->offset.constant;
+ offset.var = arg->offset.var;
+ if (arg->partial_real > 0
+ || arg->reg == 0
+ || XEXP (arg->reg, 0) == 0)
+ emit_push_insn (gen_realpart (mode, arg->value),
+ mode, type, NULL_RTX,
+ 0, arg->partial_real,
+ reg ? XEXP (arg->reg, 0) : reg, used - size,
+ argblock, ARGS_SIZE_RTX (offset));
+
+ if (!(arg->reg
+#if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE)
+ && REG_PARM_STACK_SPACE (fndecl) == 0
+#endif
+ && XEXP (arg->reg, 0) != 0 && arg->partial_real == 0)
+#ifdef ARGS_GROW_DOWNWARD
+ /* If the real part is passing in register, the imaginary
+ part in stack only, and ARGS_GROW_DOWNWARD is defined,
+ allocate the stack space for the imaginary part close to
+ next argument. */
+ && !(arg->reg
+ && XEXP (arg->reg, 0) != 0 && arg->partial_real == 0
+ && (XEXP (arg->reg, 1) == 0 || arg->partial_imag > 0))
+#endif
+ )
+ offset.constant += arg->size.constant / 2;
+
+ if (arg->partial_imag > 0
+ || arg->reg == 0
+ || XEXP (arg->reg, 1) == 0)
+ emit_push_insn (gen_imagpart (mode, arg->value),
+ mode, type, NULL_RTX,
+ 0, arg->partial_imag,
+ reg ? XEXP (arg->reg, 1) : reg, used - size,
+ argblock, ARGS_SIZE_RTX (offset));
+ }
}
else
{
@@ -3666,7 +3965,10 @@ store_one_arg (arg, argblock, may_be_all
??? Note that this can change arg->value from arg->stack to
arg->stack_slot and it matters when they are not the same.
It isn't totally clear that this is correct in all cases. */
- if (partial == 0)
+ if (partial == 0
+ /* Do not include the case where the real/imaginary part is
+ not partially in register. */
+ && arg->reg == 0)
arg->value = arg->stack_slot;
/* Once we have pushed something, pops can't safely
--- gcc/combine.c.orig Sat Dec 20 06:31:23 1997
+++ gcc/combine.c Tue Jan 6 17:26:53 1998
@@ -5297,8 +5297,10 @@ expand_field_assignment (x)
}
/* A SUBREG between two modes that occupy the same numbers of words
- can be done by moving the SUBREG to the source. */
+ can be done by moving the SUBREG to the source.
+ But a SUBREG of a COMPLEX should not be done. */
else if (GET_CODE (SET_DEST (x)) == SUBREG
+ && ! COMPLEX_MODE_P (GET_MODE (SUBREG_REG (SET_DEST (x))))
&& (((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
--- gcc/emit-rtl.c.orig Sat Dec 20 06:31:27 1997
+++ gcc/emit-rtl.c Tue Jan 6 17:42:46 1998
@@ -499,8 +499,7 @@ gen_reg_rtx (mode)
if (reload_in_progress || reload_completed)
abort ();
- if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
- || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
+ if (COMPLEX_MODE_P (mode))
{
/* For complex modes, don't make a single pseudo.
Instead, make a CONCAT of two pseudos.
@@ -637,10 +636,16 @@ gen_lowpart_common (mode, x)
/ UNITS_PER_WORD)))
return 0;
- if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
- word = ((GET_MODE_SIZE (GET_MODE (x))
- - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
- / UNITS_PER_WORD);
+ if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > 0)
+ {
+ if (!COMPLEX_MODE_P (GET_MODE (x)))
+ word = ((GET_MODE_SIZE (GET_MODE (x))
+ - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
+ / UNITS_PER_WORD);
+ else
+ word = 2 * HARD_REGNO_NREGS (REGNO (x), COMPLEX_SUBMODE (GET_MODE (x)))
+ - HARD_REGNO_NREGS (REGNO (x), mode);
+ }
if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
&& (GET_MODE_CLASS (mode) == MODE_INT
@@ -1017,10 +1022,17 @@ gen_highpart (mode, x)
int word = 0;
if (! WORDS_BIG_ENDIAN
- && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
- word = ((GET_MODE_SIZE (GET_MODE (x))
- - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
- / UNITS_PER_WORD);
+ && GET_MODE_SIZE (GET_MODE (x)) > 0)
+ {
+ if (!COMPLEX_MODE_P (GET_MODE (x)))
+ word = ((GET_MODE_SIZE (GET_MODE (x))
+ - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
+ / UNITS_PER_WORD);
+ else
+ word = 2 * HARD_REGNO_NREGS (REGNO (x),
+ COMPLEX_SUBMODE (GET_MODE (x)))
+ - HARD_REGNO_NREGS (REGNO (x), mode);
+ }
/*
* ??? This fails miserably for complex values being passed in registers
--- gcc/explow.c.orig Sat Dec 6 12:19:52 1997
+++ gcc/explow.c Wed Jan 7 16:34:26 1998
@@ -1322,7 +1322,29 @@ hard_function_value (valtype, func)
tree valtype;
tree func;
{
- rtx val = FUNCTION_VALUE (valtype, func);
+ rtx val;
+ enum machine_mode complex_mode = TYPE_MODE (valtype);
+
+ if (COMPLEX_MODE_P (complex_mode))
+ {
+ enum machine_mode orig_word_mode = word_mode;
+ enum machine_mode submode = COMPLEX_SUBMODE (complex_mode);
+ int unsignedp = TREE_UNSIGNED (valtype);
+ word_mode = submode;
+ val = FUNCTION_VALUE (type_for_mode (submode, unsignedp), func);
+ word_mode = orig_word_mode;
+#ifdef PROMOTE_FUNCTION_RETURN
+ submode = promote_mode (type_for_mode (submode, unsignedp),
+ submode, &unsignedp, 0);
+ complex_mode = mode_for_size (2 * GET_MODE_SIZE (submode)
+ * BITS_PER_UNIT,
+ GET_MODE_CLASS (complex_mode), 0);
+#endif
+ val = gen_rtx (REG, complex_mode, REGNO (val));
+ }
+ else
+ val = FUNCTION_VALUE (valtype, func);
+
if (GET_CODE (val) == REG
&& GET_MODE (val) == BLKmode)
{
--- gcc/expr.c.orig Fri Dec 19 11:41:58 1997
+++ gcc/expr.c Wed Jan 7 16:53:23 1998
@@ -2262,12 +2262,8 @@ emit_move_insn_1 (x, y)
emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
/* Expand complex moves by moving real part and imag part, if possible. */
- else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
- && BLKmode != (submode = mode_for_size ((GET_MODE_UNIT_SIZE (mode)
- * BITS_PER_UNIT),
- (class == MODE_COMPLEX_INT
- ? MODE_INT : MODE_FLOAT),
- 0))
+ else if (COMPLEX_MODE_P (mode)
+ && BLKmode != (submode = COMPLEX_SUBMODE (mode))
&& (mov_optab->handlers[(int) submode].insn_code
!= CODE_FOR_nothing))
{
@@ -3296,6 +3292,81 @@ store_expr (exp, target, want_value)
SUBREG_PROMOTED_UNSIGNED_P (target));
return want_value ? temp : NULL_RTX;
}
+ else if (GET_CODE (target) == CONCAT
+ && COMPLEX_MODE_P (GET_MODE (target))
+ && GET_CODE (XEXP (target, 0)) == SUBREG
+ && SUBREG_PROMOTED_VAR_P (XEXP (target, 0)))
+ /* Do the same as for the previous case. */
+ {
+ rtx realpart;
+ rtx imagpart;
+ if (! want_value && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (exp)))
+ && TREE_TYPE (TREE_TYPE (TREE_TYPE (exp))) == 0)
+ {
+ enum machine_mode mode;
+ tree type;
+
+ if (TREE_UNSIGNED (TREE_TYPE (exp))
+ != SUBREG_PROMOTED_UNSIGNED_P (XEXP (target, 0)))
+ exp
+ = convert
+ (signed_or_unsigned_type (SUBREG_PROMOTED_UNSIGNED_P
+ (XEXP (target, 0)),
+ TREE_TYPE (exp)),
+ exp);
+
+ mode = GET_MODE (SUBREG_REG (XEXP (target, 0)));
+ mode = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT * 2,
+ GET_MODE_CLASS (GET_MODE (target)),
+ 0);
+
+ exp = convert (type_for_mode (mode,
+ SUBREG_PROMOTED_UNSIGNED_P
+ (XEXP (target, 0))),
+ exp);
+ }
+
+ temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
+
+ realpart = gen_realpart (COMPLEX_SUBMODE (GET_MODE (temp)), temp);
+ imagpart = gen_imagpart (COMPLEX_SUBMODE (GET_MODE (temp)), temp);
+ if (GET_CODE (realpart) == MEM && want_value
+ && (MEM_VOLATILE_P (realpart)
+ || reg_mentioned_p (SUBREG_REG (XEXP (target, 0)),
+ XEXP (realpart, 0))))
+ realpart = copy_to_reg (realpart);
+ if (GET_CODE (imagpart) == MEM && want_value
+ && (MEM_VOLATILE_P (imagpart)
+ || reg_mentioned_p (SUBREG_REG (XEXP (target, 1)),
+ XEXP (imagpart, 0))))
+ imagpart = copy_to_reg (imagpart);
+
+ if (CONSTANT_P (realpart) && GET_MODE (realpart) == VOIDmode)
+ realpart = convert_modes (GET_MODE (SUBREG_REG
+ (XEXP (target, 0))),
+ COMPLEX_SUBMODE (TYPE_MODE
+ (TREE_TYPE (exp))),
+ realpart,
+ SUBREG_PROMOTED_UNSIGNED_P
+ (XEXP (target, 0)));
+ if (CONSTANT_P (imagpart) && GET_MODE (imagpart) == VOIDmode)
+ imagpart = convert_modes (GET_MODE (SUBREG_REG
+ (XEXP (target, 1))),
+ COMPLEX_SUBMODE (TYPE_MODE
+ (TREE_TYPE (exp))),
+ imagpart,
+ SUBREG_PROMOTED_UNSIGNED_P
+ (XEXP (target, 1)));
+
+ convert_move (SUBREG_REG (XEXP (target, 0)), realpart,
+ SUBREG_PROMOTED_UNSIGNED_P (XEXP (target, 0)));
+ convert_move (SUBREG_REG (XEXP (target, 1)), imagpart,
+ SUBREG_PROMOTED_UNSIGNED_P (XEXP (target, 1)));
+ temp = gen_rtx (CONCAT, TYPE_MODE (TREE_TYPE (exp)),
+ realpart, imagpart);
+
+ return want_value ? temp : NULL_RTX;
+ }
else
{
temp = expand_expr (exp, target, GET_MODE (target), 0);
@@ -4978,10 +5049,21 @@ expand_expr (exp, target, tmode, modifie
and 2) otherwise cse could produce an insn the machine
cannot support. */
- if (! cse_not_expected && mode != BLKmode && target
- && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER))
- target = subtarget;
+ if (! cse_not_expected && mode != BLKmode && target)
+ {
+ int flag = 1;
+
+ if (GET_CODE (target) == REG && REGNO (target) > FIRST_PSEUDO_REGISTER)
+ flag = 0;
+ else if (GET_CODE (target) == CONCAT
+ && GET_CODE (XEXP (target, 0)) == REG
+ && REGNO (XEXP (target, 0)) > FIRST_PSEUDO_REGISTER)
+ flag = 0;
+ if (flag)
+ target = subtarget;
+ }
+
switch (code)
{
case LABEL_DECL:
@@ -5160,6 +5242,38 @@ expand_expr (exp, target, tmode, modifie
return temp;
}
+ if (GET_CODE (DECL_RTL (exp)) == CONCAT
+ && COMPLEX_MODE_P (GET_MODE (DECL_RTL (exp)))
+ && GET_MODE (DECL_RTL (exp)) != mode)
+ {
+ rtx realpart;
+ rtx imagpart;
+ enum machine_mode submode_orig = COMPLEX_SUBMODE (mode);
+ enum machine_mode submode_final
+ = promote_mode (type_for_mode (submode_orig,
+ TREE_UNSIGNED (type)),
+ submode_orig, &unsignedp, 0);
+ enum machine_mode promoted_mode
+ = mode_for_size (2 * GET_MODE_SIZE (submode_final)
+ * BITS_PER_UNIT, GET_MODE_CLASS (mode), 0);
+ /* Get the signedness used for this variable. Ensure we get the
+ same mode we got when the variable was declared. */
+ if (GET_MODE (DECL_RTL (exp)) != promoted_mode)
+ abort ();
+
+ realpart = gen_rtx (SUBREG, submode_orig,
+ XEXP (DECL_RTL (exp), 0), 0);
+ imagpart = gen_rtx (SUBREG, submode_orig,
+ XEXP (DECL_RTL (exp), 1), 0);
+ SUBREG_PROMOTED_VAR_P (realpart) = 1;
+ SUBREG_PROMOTED_UNSIGNED_P (realpart) = unsignedp;
+ SUBREG_PROMOTED_VAR_P (imagpart) = 1;
+ SUBREG_PROMOTED_UNSIGNED_P (imagpart) = unsignedp;
+
+ temp = gen_rtx (CONCAT, mode, realpart, imagpart);
+ return temp;
+ }
+
return DECL_RTL (exp);
case INTEGER_CST:
@@ -5789,8 +5903,7 @@ expand_expr (exp, target, tmode, modifie
|| (modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER
&& ((mode1 != BLKmode && ! direct_load[(int) mode1]
- && GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
- && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
+ && ! COMPLEX_MODE_P (mode))
/* If the field isn't aligned enough to fetch as a memref,
fetch it as a bit field. */
|| (SLOW_UNALIGNED_ACCESS
@@ -6493,8 +6606,7 @@ expand_expr (exp, target, tmode, modifie
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
/* Handle complex values specially. */
- if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
- || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
+ if (COMPLEX_MODE_P (mode))
return expand_complex_abs (mode, op0, target, unsignedp);
/* Unsigned abs is simply the operand. Testing here means we don't
@@ -10396,8 +10508,7 @@ do_jump (exp, if_false_label, if_true_la
if (integer_zerop (TREE_OPERAND (exp, 1)))
do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
- else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_FLOAT
- || GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_INT)
+ else if (COMPLEX_MODE_P (TYPE_MODE (inner_type)))
do_jump
(fold
(build (TRUTH_ANDIF_EXPR, TREE_TYPE (exp),
@@ -10430,8 +10541,7 @@ do_jump (exp, if_false_label, if_true_la
if (integer_zerop (TREE_OPERAND (exp, 1)))
do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
- else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_FLOAT
- || GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_COMPLEX_INT)
+ else if (COMPLEX_MODE_P (TYPE_MODE (inner_type)))
do_jump
(fold
(build (TRUTH_ORIF_EXPR, TREE_TYPE (exp),
--- gcc/function.c.orig Mon Dec 15 02:04:57 1997
+++ gcc/function.c Wed Jan 7 16:42:46 1998
@@ -3523,7 +3523,9 @@ aggregate_value_p (exp)
else
type = TREE_TYPE (exp);
- if (RETURN_IN_MEMORY (type))
+ if (RETURN_IN_MEMORY (COMPLEX_MODE_P (TYPE_MODE (type))?
+ type_for_mode (COMPLEX_SUBMODE (TYPE_MODE (type)), 0)
+ : type))
return 1;
/* Types that are TREE_ADDRESSABLE must be constructed in memory,
and thus can't be returned in registers. */
@@ -3541,7 +3543,10 @@ aggregate_value_p (exp)
return 0;
regno = REGNO (reg);
- nregs = HARD_REGNO_NREGS (regno, TYPE_MODE (type));
+ if (! COMPLEX_MODE_P (GET_MODE (reg)))
+ nregs = HARD_REGNO_NREGS (regno, TYPE_MODE (type));
+ else
+ nregs = 2*HARD_REGNO_NREGS (regno, COMPLEX_SUBMODE (TYPE_MODE (type)));
for (i = 0; i < nregs; i++)
if (! call_used_regs[regno + i])
return 1;
@@ -3661,7 +3666,13 @@ assign_parms (fndecl, second_time)
int did_conversion = 0;
tree passed_type = DECL_ARG_TYPE (parm);
tree nominal_type = TREE_TYPE (parm);
-
+ enum machine_mode submode;
+ tree subtype;
+ int nregs = 0;
+ int nregs_real = 0;
+ int nregs_imag = 0;
+ int in_regs;
+
/* Set LAST_NAMED if this is last named arg before some
anonymous args. We treat it as if it were anonymous too. */
int last_named = ((TREE_CHAIN (parm) == 0
@@ -3714,8 +3725,14 @@ assign_parms (fndecl, second_time)
&& contains_placeholder_p (TYPE_SIZE (passed_type)))
|| TREE_ADDRESSABLE (passed_type)
#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
- || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, passed_mode,
- passed_type, ! last_named)
+ || FUNCTION_ARG_PASS_BY_REFERENCE
+ (args_so_far,
+ (! COMPLEX_MODE_P (passed_mode))?
+ passed_mode : COMPLEX_SUBMODE (passed_mode),
+ (! COMPLEX_MODE_P (passed_mode))?
+ passed_type : type_for_mode (COMPLEX_SUBMODE (passed_mode),
+ 0),
+ ! last_named)
#endif
)
{
@@ -3725,25 +3742,31 @@ assign_parms (fndecl, second_time)
}
promoted_mode = passed_mode;
+ unsignedp = TREE_UNSIGNED (passed_type);
+ if (COMPLEX_MODE_P (promoted_mode))
+ {
+ submode = COMPLEX_SUBMODE (promoted_mode);
+ subtype = type_for_mode (submode, unsignedp);
+ }
+
#ifdef PROMOTE_FUNCTION_ARGS
/* Compute the mode in which the arg is actually extended to. */
- promoted_mode = promote_mode (passed_type, promoted_mode, &unsignedp, 1);
-#endif
-
- /* Let machine desc say which reg (if any) the parm arrives in.
- 0 means it arrives on the stack. */
-#ifdef FUNCTION_INCOMING_ARG
- entry_parm = FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
- passed_type, ! last_named);
-#else
- entry_parm = FUNCTION_ARG (args_so_far, promoted_mode,
- passed_type, ! last_named);
+ if (! COMPLEX_MODE_P (promoted_mode))
+ {
+ promoted_mode = promote_mode (passed_type, promoted_mode,
+ &unsignedp, 1);
+ }
+ else
+ {
+ submode = promote_mode (subtype, submode, &unsignedp, 1);
+ subtype = type_for_mode (submode, unsignedp);
+ promoted_mode = mode_for_size (2 * GET_MODE_SIZE (submode)
+ * BITS_PER_UNIT,
+ GET_MODE_CLASS (promoted_mode), 0);
+ }
#endif
- if (entry_parm == 0)
- promoted_mode = passed_mode;
-
#ifdef SETUP_INCOMING_VARARGS
/* If this is the last named parameter, do any required setup for
varargs or stdargs. We need to know about the case of this being an
@@ -3764,6 +3787,121 @@ assign_parms (fndecl, second_time)
}
#endif
+ if (! COMPLEX_MODE_P (promoted_mode))
+ {
+ /* Let machine desc say which reg (if any) the parm arrives in.
+ 0 means it arrives on the stack. */
+#ifdef FUNCTION_INCOMING_ARG
+ entry_parm = FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
+ passed_type, ! last_named);
+#else
+ entry_parm = FUNCTION_ARG (args_so_far, promoted_mode,
+ passed_type, ! last_named);
+#endif
+
+#ifdef FUNCTION_ARG_PARTIAL_NREGS
+ if (entry_parm)
+ nregs = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode,
+ passed_type, ! last_named);
+#endif
+
+#ifdef STACK_PARMS_IN_REG_PARM_AREA
+ in_regs = 1;
+#else
+#ifdef FUNCTION_INCOMING_ARG
+ in_regs = FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
+ passed_type,
+ (! last_named
+ || varargs_setup)) != 0;
+#else
+ in_regs = FUNCTION_ARG (args_so_far, promoted_mode,
+ passed_type,
+ ! last_named || varargs_setup) != 0;
+#endif
+#endif
+
+ /* Update info on where next arg arrives in registers. */
+ FUNCTION_ARG_ADVANCE (args_so_far, promoted_mode,
+ passed_type, ! last_named);
+ }
+ else
+ {
+ rtx realpart;
+ rtx imagpart;
+ int in_regs_real;
+ int in_regs_imag;
+
+#ifdef FUNCTION_INCOMING_ARG
+ realpart = FUNCTION_INCOMING_ARG (args_so_far, submode,
+ subtype, ! last_named);
+#else
+ realpart = FUNCTION_ARG (args_so_far, submode,
+ subtype, ! last_named);
+#endif
+
+#ifdef FUNCTION_ARG_PARTIAL_NREGS
+ if (realpart)
+ nregs_real = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, submode,
+ subtype, ! last_named);
+#endif
+#ifdef STACK_PARMS_IN_REG_PARM_AREA
+ in_regs_real = 1;
+#else
+#ifdef FUNCTION_INCOMING_ARG
+ in_regs_real = FUNCTION_INCOMING_ARG (args_so_far, submode, subtype,
+ (! last_named
+ || varargs_setup)) != 0;
+#else
+ in_regs_real = FUNCTION_ARG (args_so_far, submode, subtype,
+ ! last_named || varargs_setup) != 0;
+#endif
+#endif
+
+ FUNCTION_ARG_ADVANCE (args_so_far, submode,
+ subtype, !last_named);
+#ifdef FUNCTION_INCOMING_ARG
+ imagpart = FUNCTION_INCOMING_ARG (args_so_far, submode,
+ subtype, ! last_named);
+#else
+ imagpart = FUNCTION_ARG (args_so_far, submode,
+ subtype, ! last_named);
+#endif
+#ifdef FUNCTION_ARG_PARTIAL_NREGS
+ if (imagpart)
+ nregs_imag = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, submode,
+ subtype, ! last_named);
+#endif
+#ifdef STACK_PARMS_IN_REG_PARM_AREA
+ in_regs_imag = 1;
+#else
+#ifdef FUNCTION_INCOMING_ARG
+ in_regs_imag = FUNCTION_INCOMING_ARG (args_so_far, submode, subtype,
+ (! last_named
+ || varargs_setup)) != 0;
+#else
+ in_regs_imag = FUNCTION_ARG (args_so_far, submode, subtype,
+ ! last_named || varargs_setup) != 0;
+#endif
+#endif
+
+ FUNCTION_ARG_ADVANCE (args_so_far, submode,
+ subtype, !last_named);
+ if (realpart == 0 && imagpart == 0)
+ in_regs = in_regs_real;
+ else if (imagpart)
+ in_regs = in_regs_imag;
+ else if (realpart)
+ in_regs = in_regs_real;
+
+ if (realpart != 0)
+ entry_parm = gen_rtx (CONCAT, promoted_mode, realpart, imagpart);
+ else
+ entry_parm = 0;
+ }
+
+ if (entry_parm == 0)
+ promoted_mode = passed_mode;
+
/* Determine parm's home in the stack,
in case it arrives in the stack or we should pretend it did.
@@ -3777,40 +3915,114 @@ assign_parms (fndecl, second_time)
In this case, we call FUNCTION_ARG with NAMED set to 1 instead of
0 as it was the previous time. */
- locate_and_pad_parm (promoted_mode, passed_type,
-#ifdef STACK_PARMS_IN_REG_PARM_AREA
- 1,
-#else
-#ifdef FUNCTION_INCOMING_ARG
- FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
- passed_type,
- (! last_named
- || varargs_setup)) != 0,
-#else
- FUNCTION_ARG (args_so_far, promoted_mode,
- passed_type,
- ! last_named || varargs_setup) != 0,
-#endif
+ {
+ enum machine_mode pad_mode = promoted_mode;
+ tree pad_type = passed_type;
+
+ if (COMPLEX_MODE_P (promoted_mode) && entry_parm != 0
+#if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE)
+ && REG_PARM_STACK_SPACE (fndecl) == 0
#endif
- fndecl, &stack_args_size, &stack_offset, &arg_size);
-
- if (! second_time)
- {
- rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
+ )
+ {
+ /* If we do not need to allocate stack space for
+ arguments passing in register, and the real part
+ of a complex argument is passing in register,
+ we only allocate stack space for the imaginary part. */
+ if (XEXP (entry_parm, 0) != 0 && nregs_real == 0
+ && (XEXP (entry_parm, 1) == 0 || nregs_imag > 0))
+ {
+ pad_mode = COMPLEX_SUBMODE (passed_mode);
+ pad_type = type_for_mode (pad_mode, unsignedp);
+ }
+ }
+ locate_and_pad_parm (pad_mode, pad_type, in_regs,
+ fndecl, &stack_args_size, &stack_offset,
+ &arg_size);
+
+ if (! second_time)
+ {
+ rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
- if (offset_rtx == const0_rtx)
- stack_parm = gen_rtx (MEM, promoted_mode, internal_arg_pointer);
- else
- stack_parm = gen_rtx (MEM, promoted_mode,
- gen_rtx (PLUS, Pmode,
- internal_arg_pointer, offset_rtx));
+ if (! COMPLEX_MODE_P (promoted_mode))
+ {
+ if (offset_rtx == const0_rtx)
+ stack_parm = gen_rtx (MEM, promoted_mode,
+ internal_arg_pointer);
+ else
+ stack_parm = gen_rtx (MEM, promoted_mode,
+ gen_rtx (PLUS, Pmode,
+ internal_arg_pointer,
+ offset_rtx));
+
+ /* If this is a memory ref that contains aggregate components,
+ mark it as such for cse and loop optimize. Likewise if it
+ is readonly. */
+ MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ RTX_UNCHANGING_P (stack_parm) = TREE_READONLY (parm);
+ }
+ else
+ {
+ rtx realpart;
+ rtx imagpart;
+ int imag_offset;
+ enum machine_mode stack_mode = promoted_mode;
+ enum machine_mode sub_stack_mode;
+
+ if (entry_parm
+ && XEXP (entry_parm, 0) != 0 && nregs_real == 0)
+ stack_mode = passed_mode;
+ sub_stack_mode = COMPLEX_SUBMODE (stack_mode);
+
+ if (offset_rtx == const0_rtx)
+ realpart = gen_rtx (MEM, sub_stack_mode,
+ internal_arg_pointer);
+ else
+ realpart = gen_rtx (MEM, sub_stack_mode,
+ gen_rtx (PLUS, Pmode,
+ internal_arg_pointer,
+ offset_rtx));
+ MEM_IN_STRUCT_P (realpart) = aggregate;
+ RTX_UNCHANGING_P (realpart) = TREE_READONLY (parm);
- /* If this is a memory ref that contains aggregate components,
- mark it as such for cse and loop optimize. Likewise if it
- is readonly. */
- MEM_IN_STRUCT_P (stack_parm) = aggregate;
- RTX_UNCHANGING_P (stack_parm) = TREE_READONLY (parm);
- }
+ if (COMPLEX_MODE_P (pad_mode))
+ {
+ imag_offset = arg_size.constant / 2;
+ stack_offset.constant += imag_offset;
+
+ offset_rtx = ARGS_SIZE_RTX (stack_offset);
+ imagpart = gen_rtx (MEM, sub_stack_mode,
+ gen_rtx (PLUS, Pmode,
+ internal_arg_pointer,
+ offset_rtx));
+ MEM_IN_STRUCT_P (imagpart) = aggregate;
+ RTX_UNCHANGING_P (imagpart) = TREE_READONLY (parm);
+ }
+ else
+ imagpart = 0;
+#ifdef ARGS_GROW_DOWNWARD
+ /* If the real part is passing in register, the imaginary
+ part in stack only, and ARGS_GROW_DOWNWARD is defined,
+ allocate the stack space for the imaginary part close to
+ next argument. */
+ if (COMPLEX_MODE_P (promoted_mode) && entry_parm != 0
+ && XEXP (entry_parm, 0) != 0 && nregs_real == 0
+ && (XEXP (entry_parm, 1) == 0 || nregs_imag > 0))
+ {
+ rtx tmp = realpart;
+ realpart = imagpart;
+ imagpart = tmp;
+ }
+#endif
+ if (COMPLEX_MODE_P (pad_mode))
+ stack_parm = gen_rtx (CONCAT, stack_mode,
+ realpart, imagpart);
+ else
+ stack_parm = gen_rtx (CONCAT, stack_mode,
+ imagpart, realpart);
+ }
+ }
+ }
/* If this parameter was passed both in registers and in the stack,
use the copy on the stack. */
@@ -3826,15 +4038,49 @@ assign_parms (fndecl, second_time)
we could put it together in a pseudoreg directly,
but for now that's not worth bothering with. */
- if (entry_parm)
+ if (entry_parm != 0 && GET_CODE (entry_parm) == CONCAT
+ && COMPLEX_MODE_P (GET_MODE (entry_parm)))
{
- int nregs = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode,
- passed_type, ! last_named);
+ if (nregs_real > 0 || nregs_imag > 0
+ || (XEXP (entry_parm, 0) && XEXP (entry_parm, 1) == 0))
+ {
+ if (nregs_real > 0 || nregs_imag > 0)
+ {
+ current_function_pretend_args_size
+ = ((((nregs_real + nregs_imag) * UNITS_PER_WORD)
+ + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
+ / (PARM_BOUNDARY / BITS_PER_UNIT)
+ * (PARM_BOUNDARY / BITS_PER_UNIT));
+ }
+ if (! second_time)
+ {
+ if (nregs_real > 0)
+ move_block_from_reg (REGNO (XEXP (entry_parm, 0)),
+ validize_mem (XEXP (stack_parm, 0)),
+ nregs_real,
+ int_size_in_bytes (DECL_ARG_TYPE
+ (parm))/2);
+ else if (nregs_imag > 0)
+ move_block_from_reg (REGNO (XEXP (entry_parm, 1)),
+ validize_mem (XEXP (stack_parm, 1)),
+ nregs_imag,
+ int_size_in_bytes (DECL_ARG_TYPE
+ (parm))/2);
+ }
+ if (XEXP (entry_parm, 0) && nregs_real == 0)
+ XEXP (entry_parm, 1) = stack_parm ? XEXP (stack_parm, 1) : 0;
+ else
+ entry_parm = stack_parm;
+ }
+ }
+ else if (entry_parm)
+ {
if (nregs > 0)
{
current_function_pretend_args_size
- = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
+ = (((nregs * UNITS_PER_WORD)
+ + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
/ (PARM_BOUNDARY / BITS_PER_UNIT)
* (PARM_BOUNDARY / BITS_PER_UNIT));
@@ -3869,6 +4115,8 @@ assign_parms (fndecl, second_time)
to indicate there is no preallocated stack slot for the parm. */
if (entry_parm == stack_parm
+ || (COMPLEX_MODE_P (promoted_mode) && entry_parm && stack_parm
+ && XEXP (entry_parm, 1) == XEXP (stack_parm, 1))
#if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE)
/* On some machines, even if a parm value arrives in a register
there is still an (uninitialized) stack slot allocated for it.
@@ -3891,11 +4139,6 @@ assign_parms (fndecl, second_time)
/* No stack slot was pushed for this parm. */
stack_parm = 0;
- /* Update info on where next arg arrives in registers. */
-
- FUNCTION_ARG_ADVANCE (args_so_far, promoted_mode,
- passed_type, ! last_named);
-
/* If this is our second time through, we are done with this parm. */
if (second_time)
continue;
@@ -3970,6 +4213,16 @@ assign_parms (fndecl, second_time)
if (GET_CODE (entry_parm) == REG && !(hide_last_arg && last_named))
emit_insn (gen_rtx (USE, GET_MODE (entry_parm), entry_parm));
+ else if (GET_CODE (entry_parm) == CONCAT
+ && !(hide_last_arg && last_named))
+ {
+ if (GET_CODE (XEXP (entry_parm, 0)) == REG)
+ emit_insn (gen_rtx (USE, GET_MODE (XEXP (entry_parm, 0)),
+ XEXP (entry_parm, 0)));
+ if (GET_CODE (XEXP (entry_parm, 1)) == REG)
+ emit_insn (gen_rtx (USE, GET_MODE (XEXP (entry_parm, 1)),
+ XEXP (entry_parm, 1)));
+ }
#endif
/* ENTRY_PARM is an RTX for the parameter as it arrives,
@@ -4056,12 +4309,38 @@ assign_parms (fndecl, second_time)
unsignedp = TREE_UNSIGNED (TREE_TYPE (parm));
- promoted_nominal_mode
- = promote_mode (TREE_TYPE (parm), nominal_mode, &unsignedp, 0);
-
- parmreg = gen_reg_rtx (promoted_nominal_mode);
- mark_user_reg (parmreg);
-
+ if (! COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (parm))))
+ {
+ promoted_nominal_mode
+ = promote_mode (TREE_TYPE (parm), nominal_mode, &unsignedp, 0);
+
+ parmreg = gen_reg_rtx (promoted_nominal_mode);
+ mark_user_reg (parmreg);
+ }
+ else
+ {
+ enum machine_mode submode_nominal
+ = COMPLEX_SUBMODE (nominal_mode);
+ rtx realpart;
+ rtx imagpart;
+
+ submode_nominal
+ = promote_mode (type_for_mode (submode_nominal, unsignedp),
+ submode_nominal, &unsignedp, 0);
+ promoted_nominal_mode
+ = mode_for_size (2 * GET_MODE_SIZE (submode_nominal)
+ * BITS_PER_UNIT,
+ GET_MODE_CLASS (nominal_mode), 0);
+
+ realpart = gen_reg_rtx (submode_nominal);
+ imagpart = gen_reg_rtx (submode_nominal);
+
+ parmreg = gen_rtx (CONCAT, promoted_nominal_mode,
+ realpart, imagpart);
+ mark_user_reg (realpart);
+ mark_user_reg (imagpart);
+ }
+
/* If this was an item that we received a pointer to, set DECL_RTL
appropriately. */
if (passed_pointer)
@@ -4075,7 +4354,10 @@ assign_parms (fndecl, second_time)
/* Copy the value into the register. */
if (nominal_mode != passed_mode
- || promoted_nominal_mode != promoted_mode)
+ || promoted_nominal_mode != promoted_mode
+ || (COMPLEX_MODE_P (passed_mode)
+ && GET_MODE (XEXP (entry_parm, 0))
+ != GET_MODE (XEXP (entry_parm, 1))))
{
/* ENTRY_PARM has been converted to PROMOTED_MODE, its
mode, by the caller. We now have to convert it to
@@ -4096,22 +4378,60 @@ assign_parms (fndecl, second_time)
a pseudo reg here, and save the conversion until after all
parameters have been moved. */
- rtx tempreg = gen_reg_rtx (GET_MODE (entry_parm));
+ if (! COMPLEX_MODE_P (GET_MODE (entry_parm)))
+ {
+ rtx tempreg = gen_reg_rtx (GET_MODE (entry_parm));
- emit_move_insn (tempreg, validize_mem (entry_parm));
+ emit_move_insn (tempreg, validize_mem (entry_parm));
- push_to_sequence (conversion_insns);
- tempreg = convert_to_mode (nominal_mode, tempreg, unsignedp);
+ push_to_sequence (conversion_insns);
+ tempreg = convert_to_mode (nominal_mode, tempreg, unsignedp);
- expand_assignment (parm,
- make_tree (nominal_type, tempreg), 0, 0);
- conversion_insns = get_insns ();
- did_conversion = 1;
- end_sequence ();
+ expand_assignment (parm,
+ make_tree (nominal_type, tempreg), 0, 0);
+ conversion_insns = get_insns ();
+ did_conversion = 1;
+ end_sequence ();
+ }
+ else
+ {
+ rtx realpart = gen_reg_rtx (GET_MODE (XEXP (entry_parm, 0)));
+ rtx imagpart = gen_reg_rtx (GET_MODE (XEXP (entry_parm, 1)));
+ enum machine_mode submode_nominal
+ = COMPLEX_SUBMODE (nominal_mode);
+ rtx tempreg;
+
+ emit_move_insn (realpart,
+ validize_mem (XEXP (entry_parm, 0)));
+ emit_move_insn (imagpart,
+ validize_mem (XEXP (entry_parm, 1)));
+
+ push_to_sequence (conversion_insns);
+ realpart = convert_to_mode (submode_nominal, realpart, unsignedp);
+ imagpart = convert_to_mode (submode_nominal, imagpart, unsignedp);
+ tempreg = gen_rtx (CONCAT, nominal_mode,
+ realpart, imagpart);
+
+ expand_assignment (parm,
+ make_tree (nominal_type, tempreg), 0, 0);
+ conversion_insns = get_insns ();
+ did_conversion = 1;
+ end_sequence ();
+ }
}
else
- emit_move_insn (parmreg, validize_mem (entry_parm));
-
+ {
+ if (! COMPLEX_MODE_P (GET_MODE (entry_parm)))
+ emit_move_insn (parmreg, validize_mem (entry_parm));
+ else
+ {
+ emit_move_insn (XEXP (parmreg, 0),
+ validize_mem (XEXP (entry_parm, 0)));
+ emit_move_insn (XEXP (parmreg, 1),
+ validize_mem (XEXP (entry_parm, 1)));
+ }
+ }
+
/* If we were passed a pointer but the actual value
can safely live in a register, put it in one. */
if (passed_pointer && TYPE_MODE (TREE_TYPE (parm)) != BLKmode
@@ -4145,10 +4465,16 @@ assign_parms (fndecl, second_time)
modified, don't do the copy. */
else if (passed_pointer
- && FUNCTION_ARG_CALLEE_COPIES (args_so_far,
- TYPE_MODE (DECL_ARG_TYPE (parm)),
- DECL_ARG_TYPE (parm),
- ! last_named)
+ && FUNCTION_ARG_CALLEE_COPIES
+ (args_so_far,
+ (! COMPLEX_MODE_P (TYPE_MODE (DECL_ARG_TYPE (parm))))?
+ TYPE_MODE (DECL_ARG_TYPE (parm))
+ : COMPLEX_SUBMODE (TYPE_MODE (DECL_ARG_TYPE (parm))),
+ (! COMPLEX_MODE_P (TYPE_MODE (DECL_ARG_TYPE (parm))))?
+ DECL_ARG_TYPE (parm)
+ : type_for_mode (COMPLEX_SUBMODE (TYPE_MODE (DECL_ARG_TYPE (parm))),
+ 0),
+ ! last_named)
&& ! TREE_ADDRESSABLE (DECL_ARG_TYPE (parm)))
{
rtx copy;
@@ -4219,15 +4545,13 @@ assign_parms (fndecl, second_time)
{
enum machine_mode submode = GET_MODE (XEXP (parmreg, 0));
- regnor = REGNO (gen_realpart (submode, parmreg));
- regnoi = REGNO (gen_imagpart (submode, parmreg));
+ regnor = REGNO (XEXP (parmreg, 0));
+ regnoi = REGNO (XEXP (parmreg, 1));
if (stack_parm != 0)
{
- parm_reg_stack_loc[regnor]
- = gen_realpart (submode, stack_parm);
- parm_reg_stack_loc[regnoi]
- = gen_imagpart (submode, stack_parm);
+ parm_reg_stack_loc[regnor] = XEXP (stack_parm, 0);
+ parm_reg_stack_loc[regnoi] = XEXP (stack_parm, 1);
}
else
{
@@ -4294,53 +4618,157 @@ assign_parms (fndecl, second_time)
/* Value must be stored in the stack slot STACK_PARM
during function execution. */
- if (promoted_mode != nominal_mode)
+ if (! COMPLEX_MODE_P (promoted_mode))
{
- /* Conversion is required. */
- rtx tempreg = gen_reg_rtx (GET_MODE (entry_parm));
-
- emit_move_insn (tempreg, validize_mem (entry_parm));
+ if (promoted_mode != nominal_mode)
+ {
+ /* Conversion is required. */
+ rtx tempreg = gen_reg_rtx (GET_MODE (entry_parm));
+
+ emit_move_insn (tempreg, validize_mem (entry_parm));
+
+ push_to_sequence (conversion_insns);
+ entry_parm
+ = convert_to_mode (nominal_mode, tempreg,
+ TREE_UNSIGNED (TREE_TYPE (parm)));
+ if (stack_parm)
+ {
+ /* ??? This may need a big-endian conversion on sparc64. */
+ stack_parm = change_address (stack_parm, nominal_mode,
+ NULL_RTX);
+ }
+ conversion_insns = get_insns ();
+ did_conversion = 1;
+ end_sequence ();
+ }
+ }
+ else
+ {
+ enum machine_mode submode_nominal
+ = COMPLEX_SUBMODE (nominal_mode);
+ rtx realpart;
+ rtx imagpart;
+ int unsignedp1 = TREE_UNSIGNED (TREE_TYPE (parm));
- push_to_sequence (conversion_insns);
- entry_parm = convert_to_mode (nominal_mode, tempreg,
- TREE_UNSIGNED (TREE_TYPE (parm)));
- if (stack_parm)
+ if (GET_MODE (XEXP (entry_parm, 0)) != submode_nominal)
{
- /* ??? This may need a big-endian conversion on sparc64. */
- stack_parm = change_address (stack_parm, nominal_mode,
- NULL_RTX);
+ realpart = gen_reg_rtx (submode);
+ emit_move_insn (realpart,
+ validize_mem (XEXP (entry_parm, 0)));
+ push_to_sequence (conversion_insns);
+ realpart = convert_to_mode (submode_nominal, realpart,
+ unsignedp1);
+ conversion_insns = get_insns ();
+ did_conversion = 1;
+ end_sequence ();
}
- conversion_insns = get_insns ();
- did_conversion = 1;
- end_sequence ();
+ else
+ realpart = XEXP (entry_parm, 0);
+
+ if (GET_MODE (XEXP (entry_parm, 1)) != submode_nominal)
+ {
+ imagpart = gen_reg_rtx (submode);
+ emit_move_insn (imagpart,
+ validize_mem (XEXP (entry_parm, 1)));
+ push_to_sequence (conversion_insns);
+ imagpart = convert_to_mode (submode_nominal, imagpart,
+ unsignedp1);
+ conversion_insns = get_insns ();
+ did_conversion = 1;
+ end_sequence ();
+ }
+ else
+ imagpart = XEXP (entry_parm, 1);
+
+ if (GET_MODE (XEXP (entry_parm, 0)) != submode_nominal
+ || GET_MODE (XEXP (entry_parm, 1)) != submode_nominal)
+ entry_parm = gen_rtx (CONCAT, nominal_mode,
+ realpart, imagpart);
}
if (entry_parm != stack_parm)
{
- if (stack_parm == 0)
+ enum machine_mode entry_mode = GET_MODE (entry_parm);
+
+ if (! COMPLEX_MODE_P (entry_mode))
{
- stack_parm
- = assign_stack_local (GET_MODE (entry_parm),
- GET_MODE_SIZE (GET_MODE (entry_parm)), 0);
- /* If this is a memory ref that contains aggregate components,
- mark it as such for cse and loop optimize. */
- MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ if (stack_parm == 0)
+ {
+ stack_parm
+ = assign_stack_local (GET_MODE (entry_parm),
+ GET_MODE_SIZE (GET_MODE
+ (entry_parm)), 0);
+ /* If this is a memory ref that contains aggregate components,
+ mark it as such for cse and loop optimize. */
+ MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ }
+ }
+ else
+ {
+ rtx realpart;
+ rtx imagpart;
+ enum machine_mode submode
+ = COMPLEX_SUBMODE (entry_mode);
+
+ if (stack_parm == 0 || XEXP (stack_parm, 0) == 0)
+ {
+ realpart
+ = assign_stack_local (submode,
+ GET_MODE_SIZE (submode), 0);
+ MEM_IN_STRUCT_P (realpart) = aggregate;
+ }
+ if (stack_parm == 0 || XEXP (stack_parm, 1) == 0)
+ {
+ imagpart
+ = assign_stack_local (submode,
+ GET_MODE_SIZE (submode), 0);
+ MEM_IN_STRUCT_P (imagpart) = aggregate;
+ }
+ if (stack_parm == 0)
+ stack_parm = gen_rtx (CONCAT, entry_mode,
+ realpart, imagpart);
+ else if (XEXP (stack_parm, 0) == 0)
+ XEXP (stack_parm, 0) = realpart;
+ else if (XEXP (stack_parm, 1) == 0)
+ XEXP (stack_parm, 1) = imagpart;
}
-
if (promoted_mode != nominal_mode)
{
push_to_sequence (conversion_insns);
- emit_move_insn (validize_mem (stack_parm),
- validize_mem (entry_parm));
+ if (! COMPLEX_MODE_P (entry_mode))
+ {
+ emit_move_insn (validize_mem (stack_parm),
+ validize_mem (entry_parm));
+ }
+ else
+ {
+ emit_move_insn (validize_mem (XEXP (stack_parm, 0)),
+ validize_mem (XEXP (entry_parm, 0)));
+ emit_move_insn (validize_mem (XEXP (stack_parm, 1)),
+ validize_mem (XEXP (entry_parm, 1)));
+ }
+
conversion_insns = get_insns ();
end_sequence ();
}
else
- emit_move_insn (validize_mem (stack_parm),
- validize_mem (entry_parm));
+ {
+ if (! COMPLEX_MODE_P (entry_mode))
+ {
+ emit_move_insn (validize_mem (stack_parm),
+ validize_mem (entry_parm));
+ }
+ else
+ {
+ emit_move_insn (validize_mem (XEXP (stack_parm, 0)),
+ validize_mem (XEXP (entry_parm, 0)));
+ emit_move_insn (validize_mem (XEXP (stack_parm, 1)),
+ validize_mem (XEXP (entry_parm, 1)));
+ }
+ }
}
- if (flag_check_memory_usage)
- {
+ if (flag_check_memory_usage)
+ {
push_to_sequence (conversion_insns);
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
XEXP (stack_parm, 0), ptr_mode,
@@ -4511,12 +4939,32 @@ locate_and_pad_parm (passed_mode, type,
struct args_size *offset_ptr;
struct args_size *arg_size_ptr;
{
- tree sizetree
- = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
- enum direction where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
- int boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
- int boundary_in_bytes = boundary / BITS_PER_UNIT;
+ tree sizetree;
+ enum direction where_pad;
+ enum machine_mode mode;
+ int boundary;
+ int boundary_in_bytes;
int reg_parm_stack_space = 0;
+ int i;
+
+ if (! COMPLEX_MODE_P (passed_mode))
+ {
+ sizetree = type ? size_in_bytes (type)
+ : size_int (GET_MODE_SIZE (passed_mode));
+ where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
+ boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
+ mode = passed_mode;
+ }
+ else
+ {
+ tree subtype;
+ mode = COMPLEX_SUBMODE (passed_mode);
+ subtype = type_for_mode (mode, 0);
+ sizetree = size_int (GET_MODE_SIZE (mode));
+ where_pad = FUNCTION_ARG_PADDING (mode, subtype);
+ boundary = FUNCTION_ARG_BOUNDARY (mode, subtype);
+ }
+ boundary_in_bytes = boundary / BITS_PER_UNIT;
#ifdef REG_PARM_STACK_SPACE
/* If we have found a stack parm before we reach the end of the
@@ -4562,7 +5010,13 @@ locate_and_pad_parm (passed_mode, type,
&& (TREE_CODE (sizetree) != INTEGER_CST
|| ((TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)))
sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
- SUB_PARM_SIZE (*offset_ptr, sizetree);
+ if (COMPLEX_MODE_P (passed_mode))
+ {
+ SUB_PARM_SIZE (*offset_ptr, sizetree);
+ SUB_PARM_SIZE (*offset_ptr, sizetree);
+ }
+ else
+ SUB_PARM_SIZE (*offset_ptr, sizetree);
if (where_pad != downward)
pad_to_arg_alignment (offset_ptr, boundary);
if (initial_offset_ptr->var)
@@ -4593,14 +5047,20 @@ locate_and_pad_parm (passed_mode, type,
/* However, BLKmode args passed in regs have their padding done elsewhere.
The stack slot must be able to hold the entire register. */
&& !(in_regs && passed_mode == BLKmode))
- pad_below (offset_ptr, passed_mode, sizetree);
+ pad_below (offset_ptr, mode, sizetree);
if (where_pad != none
&& (TREE_CODE (sizetree) != INTEGER_CST
|| ((TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)))
sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
- ADD_PARM_SIZE (*arg_size_ptr, sizetree);
+ if (COMPLEX_MODE_P (passed_mode))
+ {
+ ADD_PARM_SIZE (*arg_size_ptr, sizetree);
+ ADD_PARM_SIZE (*arg_size_ptr, sizetree);
+ }
+ else
+ ADD_PARM_SIZE (*arg_size_ptr, sizetree);
#endif /* ARGS_GROW_DOWNWARD */
}
@@ -5586,10 +6046,61 @@ expand_function_start (subr, parms_have_
tree type = TREE_TYPE (DECL_RESULT (subr));
int unsignedp = TREE_UNSIGNED (type);
- mode = promote_mode (type, mode, &unsignedp, 1);
+ if (! COMPLEX_MODE_P (mode))
+ {
+ mode = promote_mode (type, mode, &unsignedp, 1);
+ }
+ else
+ {
+ enum machine_mode submode = COMPLEX_SUBMODE (mode);
+ submode = promote_mode (type_for_mode (submode,
+ TREE_UNSIGNED (type)),
+ submode, &unsignedp, 1);
+ mode = mode_for_size (2 * GET_MODE_SIZE (submode) * BITS_PER_UNIT,
+ GET_MODE_CLASS (mode), 0);
+ }
#endif
DECL_RTL (DECL_RESULT (subr)) = gen_reg_rtx (mode);
+ }
+ else if (COMPLEX_MODE_P (DECL_MODE (DECL_RESULT (subr))))
+ /* To return a complex value, using two registers. */
+ {
+ enum machine_mode mode = DECL_MODE (DECL_RESULT (subr));
+ enum machine_mode submode = COMPLEX_SUBMODE (mode);
+ rtx realpart;
+ int unsignedp = TREE_UNSIGNED (TREE_TYPE (DECL_RESULT (subr)));
+ tree parttree = type_for_mode (submode, unsignedp);
+
+#ifdef FUNCTION_OUTGOING_VALUE
+ realpart = FUNCTION_OUTGOING_VALUE (parttree, subr);
+#else
+ realpart = FUNCTION_VALUE (parttree, subr);
+#endif
+
+ if (GET_CODE (realpart) == REG)
+ {
+#ifdef PROMOTE_FUNCTION_RETURN
+ submode = promote_mode (type_for_mode (submode, unsignedp),
+ submode, &unsignedp, 1);
+ mode = mode_for_size (2 * GET_MODE_SIZE (submode)
+ * BITS_PER_UNIT,
+ GET_MODE_CLASS (mode), 0);
+#endif
+ DECL_RTL (DECL_RESULT (subr))
+ = gen_rtx (REG, mode, REGNO (realpart));
+ }
+ else
+ abort ();
+
+ /* Mark this reg as the function's return value. */
+ if (GET_CODE (DECL_RTL (DECL_RESULT (subr))) == REG)
+ {
+ REG_FUNCTION_VALUE_P (DECL_RTL (DECL_RESULT (subr))) = 1;
+ /* Needed because we may need to move this to memory
+ in case it's a named return value whose address is taken. */
+ DECL_REGISTER (DECL_RESULT (subr)) = 1;
+ }
}
else
/* Scalar, returned in a register. */
--- gcc/integrate.c.orig Thu Dec 18 17:42:35 1997
+++ gcc/integrate.c Wed Jan 7 16:45:26 1998
@@ -1382,11 +1382,32 @@ expand_inline_function (fndecl, parms, t
if (GET_MODE (loc) != TYPE_MODE (TREE_TYPE (arg)))
/* The mode if LOC and ARG can differ if LOC was a variable
that had its mode promoted via PROMOTED_MODE. */
- arg_vals[i] = convert_modes (GET_MODE (loc),
- TYPE_MODE (TREE_TYPE (arg)),
- expand_expr (arg, NULL_RTX, mode,
- EXPAND_SUM),
- TREE_UNSIGNED (TREE_TYPE (formal)));
+ {
+ if (! COMPLEX_MODE_P (GET_MODE (loc)))
+ arg_vals[i]
+ = convert_modes (GET_MODE (loc),
+ TYPE_MODE (TREE_TYPE (arg)),
+ expand_expr (arg, NULL_RTX, mode,
+ EXPAND_SUM),
+ TREE_UNSIGNED (TREE_TYPE (formal)));
+ else
+ {
+ rtx temp = expand_expr (arg, NULL_RTX, mode, EXPAND_SUM);
+ enum machine_mode mode_orig
+ = COMPLEX_SUBMODE (TYPE_MODE (TREE_TYPE (arg)));
+ enum machine_mode mode_final
+ = COMPLEX_SUBMODE (GET_MODE (loc));
+ rtx realpart = gen_realpart (mode_orig, temp);
+ rtx imagpart = gen_imagpart (mode_orig, temp);
+
+ realpart = convert_modes (mode_final, mode_orig, realpart,
+ TREE_UNSIGNED (TREE_TYPE (formal)));
+ imagpart = convert_modes (mode_final, mode_orig, imagpart,
+ TREE_UNSIGNED (TREE_TYPE (formal)));
+ arg_vals[i] = gen_rtx (CONCAT, GET_MODE (loc),
+ realpart, imagpart);
+ }
+ }
else
arg_vals[i] = expand_expr (arg, NULL_RTX, mode, EXPAND_SUM);
}
@@ -1750,7 +1771,8 @@ expand_inline_function (fndecl, parms, t
/* If function's value was promoted before return,
avoid machine mode mismatch when we substitute INLINE_TARGET.
But TARGET is what we will return to the caller. */
- if (arriving_mode != departing_mode)
+ if (arriving_mode != departing_mode
+ && ! COMPLEX_MODE_P (arriving_mode))
{
/* Avoid creating a paradoxical subreg wider than
BITS_PER_WORD, since that is illegal. */
@@ -1765,6 +1787,41 @@ expand_inline_function (fndecl, parms, t
}
else
reg_to_map = gen_rtx (SUBREG, arriving_mode, target, 0);
+ }
+ else if (arriving_mode != departing_mode)
+ {
+ /* Deal with complex return. */
+ enum machine_mode submode = COMPLEX_SUBMODE (departing_mode);
+ enum machine_mode promoted_submode
+ = COMPLEX_SUBMODE (arriving_mode);
+ rtx realpart;
+ rtx imagpart;
+
+ /* Avoid creating a paradoxical subreg wider than
+ BITS_PER_WORD, since that is illegal. */
+ if (GET_MODE_BITSIZE (promoted_submode) > BITS_PER_WORD)
+ {
+ if (!TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (submode),
+ GET_MODE_BITSIZE (promoted_submode)))
+ /* Maybe could be handled by using convert_move () ? */
+ abort ();
+ reg_to_map = gen_reg_rtx (arriving_mode);
+ realpart = gen_lowpart (submode,
+ gen_realpart (promoted_submode,
+ reg_to_map));
+ imagpart = gen_lowpart (submode,
+ gen_imagpart (promoted_submode,
+ reg_to_map));
+ target = gen_rtx (CONCAT, departing_mode, realpart, imagpart);
+ }
+ else
+ {
+ realpart = gen_rtx (SUBREG, promoted_submode,
+ gen_realpart (submode, target), 0);
+ imagpart = gen_rtx (SUBREG, promoted_submode,
+ gen_imagpart (submode, target), 0);
+ reg_to_map = gen_rtx (CONCAT, arriving_mode, realpart, imagpart);
+ }
}
else
reg_to_map = target;
--- gcc/machmode.h.orig Mon Aug 11 11:57:11 1997
+++ gcc/machmode.h Wed Jan 7 11:48:11 1998
@@ -164,6 +164,17 @@ extern enum mode_class mode_class[];
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
+/* Nonzero if MODE is a complex mode. */
+#define COMPLEX_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
+ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
+
+/* Determine the mode for the imaginary and real part of a complex MODE. */
+#define COMPLEX_SUBMODE(MODE) \
+mode_for_size (GET_MODE_UNIT_SIZE(MODE)*BITS_PER_UNIT, \
+ (GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT)? \
+ MODE_INT:MODE_FLOAT, 0)
+
/* Get the size in bytes of an object of mode MODE. */
extern int mode_size[];
--- gcc/recog.c.orig Sat Dec 6 12:21:30 1997
+++ gcc/recog.c Tue Jan 6 17:27:00 1998
@@ -898,8 +898,7 @@ register_operand (op, mode)
REGNO (SUBREG_REG (op)))
&& (GET_MODE_SIZE (mode)
!= GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
- && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_INT
- && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_FLOAT)
+ && ! COMPLEX_MODE_P (GET_MODE (SUBREG_REG (op))))
return 0;
#endif
--- gcc/regs.h.orig Sun Nov 2 03:40:47 1997
+++ gcc/regs.h Tue Jan 6 17:27:01 1998
@@ -27,7 +27,10 @@ Boston, MA 02111-1307, USA. */
valid way to get this value. You cannot get it from the regno. */
#define REG_SIZE(R) \
- ((mode_size[(int) GET_MODE (R)] + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+ (GET_MODE_SIZE (GET_MODE (R)) == 0? \
+ 0:(((GET_MODE_UNIT_SIZE (GET_MODE (R)) + (UNITS_PER_WORD - 1)) \
+ / UNITS_PER_WORD) * (GET_MODE_SIZE (GET_MODE (R)) \
+ / GET_MODE_UNIT_SIZE (GET_MODE (R)))))
#ifndef SMALL_REGISTER_CLASSES
#define SMALL_REGISTER_CLASSES 0
--- gcc/reload.c.orig Mon Dec 15 12:55:27 1997
+++ gcc/reload.c Tue Jan 6 23:30:05 1998
@@ -2370,6 +2370,21 @@ find_reloads (insn, replace, ind_levels,
&& REGISTER_MOVE_COST (REGNO_REG_CLASS (REGNO (SET_SRC (body))),
REGNO_REG_CLASS (REGNO (SET_DEST (body)))) == 2)
return;
+ if (GET_CODE (SET_DEST (body)) == SUBREG
+ && GET_CODE (SUBREG_REG (SET_DEST (body))) == REG
+ && COMPLEX_MODE_P (GET_MODE (SUBREG_REG (SET_DEST (body)))))
+ {
+ rtx complex_dest = SUBREG_REG (SET_DEST (body));
+ int regno = REGNO (complex_dest) + SUBREG_WORD (SET_DEST (body));
+
+ if (regno < FIRST_PSEUDO_REGISTER
+ && GET_CODE (SET_SRC (body)) == REG
+ && REGNO (SET_SRC (body)) < FIRST_PSEUDO_REGISTER
+ && REGISTER_MOVE_COST (REGNO_REG_CLASS (REGNO (SET_SRC (body))),
+ REGNO_REG_CLASS (regno)) == 2)
+ return;
+ }
+
case PARALLEL:
case ASM_OPERANDS:
reload_n_operands = noperands = asm_noperands (body);
@@ -2768,6 +2783,7 @@ find_reloads (insn, replace, ind_levels,
or which would handle that mode in the wrong number of
registers for subregging to work. */
|| (GET_CODE (operand) == REG
+ && !COMPLEX_MODE_P (GET_MODE (operand))
&& REGNO (operand) < FIRST_PSEUDO_REGISTER
&& ((GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (operand))
--- gcc/stmt.c.orig Fri Dec 19 11:41:53 1997
+++ gcc/stmt.c Wed Jan 7 16:47:02 1998
@@ -2620,19 +2620,59 @@ expand_value_return (val)
#ifdef PROMOTE_FUNCTION_RETURN
tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
int unsignedp = TREE_UNSIGNED (type);
- enum machine_mode mode
- = promote_mode (type, DECL_MODE (DECL_RESULT (current_function_decl)),
- &unsignedp, 1);
+ enum machine_mode mode_orig
+ = DECL_MODE (DECL_RESULT (current_function_decl));
+ enum machine_mode mode;
+ enum machine_mode submode;
+ enum machine_mode promoted_submode;
+ if (! COMPLEX_MODE_P (mode_orig))
+ {
+ mode = promote_mode (type, mode_orig, &unsignedp, 1);
+ }
+ else
+ {
+ submode = COMPLEX_SUBMODE (mode_orig);
+ promoted_submode
+ = promote_mode (type_for_mode (submode, unsignedp),
+ submode, &unsignedp, 1);
+ mode = mode_for_size (2 * GET_MODE_SIZE (promoted_submode)
+ * BITS_PER_UNIT,
+ GET_MODE_CLASS (mode_orig), 0);
+ }
+
if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
- convert_move (return_reg, val, unsignedp);
+ {
+ if (! COMPLEX_MODE_P (mode))
+ convert_move (return_reg, val, unsignedp);
+ else
+ {
+ convert_move (gen_realpart (promoted_submode, return_reg),
+ gen_realpart (submode, val), unsignedp);
+ convert_move (gen_imagpart (promoted_submode, return_reg),
+ gen_imagpart (submode, val), unsignedp);
+ }
+ }
else
#endif
emit_move_insn (return_reg, val);
}
if (GET_CODE (return_reg) == REG
&& REGNO (return_reg) < FIRST_PSEUDO_REGISTER)
- emit_insn (gen_rtx (USE, VOIDmode, return_reg));
+ {
+ if (! COMPLEX_MODE_P (GET_MODE (return_reg)))
+ emit_insn (gen_rtx (USE, VOIDmode, return_reg));
+ else
+ {
+ enum machine_mode submode = COMPLEX_SUBMODE (GET_MODE (return_reg));
+ int n = 2 * HARD_REGNO_NREGS (REGNO (return_reg), submode);
+ int k;
+
+ for (k = 0; k < n; k ++)
+ emit_insn (gen_rtx (USE, VOIDmode,
+ gen_rtx (REG, submode, REGNO (return_reg) + k)));
+ }
+ }
/* Handle calls that return values in multiple non-contiguous locations.
The Irix 6 ABI has examples of this. */
else if (GET_CODE (return_reg) == PARALLEL)
^ permalink raw reply [flat|nested] 2+ messages in thread
* Patch for COMPLEX support (part 2)
@ 1998-01-08 6:05 Weiwen Liu
0 siblings, 0 replies; 2+ messages in thread
From: Weiwen Liu @ 1998-01-08 6:05 UTC (permalink / raw)
To: egcs
I sent part 2 of this patch yesterday, but it never shows up.
Is there a limit on the length of a message enforced on egcs mailing list?
I am sending part 2 now after it is gzipped.
Wed Jan 7 17:30:00 1998 Weiwen Liu <liu@hepunix.physics.yale.edu>
* machmode.h: define COMPLEX_MODE_P, COMPLEX_SUBMODE.
* regs.h (REG_SIZE): Consider complex modes.
* calls.c (arg_data): Add partial_real and partial_imag to
record the number of registers used for real/imaginary part.
* combine.c (expand_field_assignment): Exclude SUBREG of a
COMPLEX.
* explow.c (hard_function_value): Promote COMPLEX return
value if required.
* calls.c (expand_call): Deal with arguments of complex modes.
(store_one_arg): Likewise.
* emit-rtl.c (gen_lowpart_common): Likewise.
(gen_highpart): Likewise.
* expr.c (store_expr): Likewise.
(expand_expr): Likewise.
* function.c (aggregate_value_p): Likewise.
(assign_parms): Likewise.
(locate_and_pad_parm): Likewise.
(expand_function_start): Likewise.
* integrate.c (expand_inline_function): Likewise.
* reload.c (find_reloads): Likewise.
* stmt.c (expand_value_return): Likewise.
begin 600 patch2.gz
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
M-GDIWG^\N&2M]/@TO+@<O?EWON685Y&1@&7-X6XWV`-9LS\8=K>A-X,=O
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
CE#4\_A*AN)_QTX0DTVJ^IPI*#F.52-MY]O\`0>7"5^L2`0`<
`
end
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~1998-02-10 3:34 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-02-10 3:34 Patch for COMPLEX support (part 2) Weiwen Liu
-- strict thread matches above, loose matches on Subject: below --
1998-01-08 6:05 Weiwen Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).