current_function_decl = p->decl;
reg_renumber = 0;
- restore_emit_status (p);
-
lang_hooks.function.leave_nested (p);
/* Reset variables that have known state during rtx generation. */
static struct temp_slot **
temp_slots_at_level (int level)
{
- level++;
if (!used_temp_slots)
VARRAY_GENERIC_PTR_INIT (used_temp_slots, 3, "used_temp_slots");
done for BLKmode slots because we can be sure that we won't have alignment
problems in this case. */
-void
+static void
combine_temp_slots (void)
{
struct temp_slot *p, *q, *next, *next_q;
enum machine_mode mode;
rtx addr;
+ if (x == 0)
+ return;
+
+ /* If this is a CONCAT, recurse for the pieces. */
+ if (GET_CODE (x) == CONCAT)
+ {
+ instantiate_decl (XEXP (x, 0), size / 2, valid_only);
+ instantiate_decl (XEXP (x, 1), size / 2, valid_only);
+ return;
+ }
+
/* If this is not a MEM, no need to do anything. Similarly if the
address is a constant or a register that is not a virtual register. */
-
- if (x == 0 || !MEM_P (x))
+ if (!MEM_P (x))
return;
addr = XEXP (x, 0);
present and valid in DATA->STACK_RTL. */
static void
-assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
+assign_parm_setup_block (struct assign_parm_data_all *all,
+ tree parm, struct assign_parm_data_one *data)
{
rtx entry_parm = data->entry_parm;
rtx stack_parm = data->stack_parm;
+ if (GET_CODE (entry_parm) == PARALLEL)
+ entry_parm = emit_group_move_into_temps (entry_parm);
+
/* If we've a non-block object that's nevertheless passed in parts,
reconstitute it in register operations rather than on the stack. */
if (GET_CODE (entry_parm) == PARALLEL
{
rtx parmreg = gen_reg_rtx (data->nominal_mode);
- emit_group_store (parmreg, entry_parm, data->nominal_type,
- int_size_in_bytes (data->nominal_type));
+ push_to_sequence (all->conversion_insns);
+
+ /* For values returned in multiple registers, handle possible
+ incompatible calls to emit_group_store.
+
+ For example, the following would be invalid, and would have to
+ be fixed by the conditional below:
+
+ emit_group_store ((reg:SF), (parallel:DF))
+ emit_group_store ((reg:SI), (parallel:DI))
+
+ An example of this are doubles in e500 v2:
+ (parallel:DF (expr_list (reg:SI) (const_int 0))
+ (expr_list (reg:SI) (const_int 4))). */
+ if (data->nominal_mode != data->passed_mode)
+ {
+ rtx t = gen_reg_rtx (GET_MODE (entry_parm));
+ emit_group_store (t, entry_parm, NULL_TREE,
+ GET_MODE_SIZE (GET_MODE (entry_parm)));
+ convert_move (parmreg, t, 0);
+ }
+ else
+ emit_group_store (parmreg, entry_parm, data->nominal_type,
+ int_size_in_bytes (data->nominal_type));
+
+ all->conversion_insns = get_insns ();
+ end_sequence ();
+
SET_DECL_RTL (parm, parmreg);
return;
}
/* Handle values in multiple non-contiguous locations. */
if (GET_CODE (entry_parm) == PARALLEL)
- emit_group_store (mem, entry_parm, data->passed_type, size);
+ {
+ push_to_sequence (all->conversion_insns);
+ emit_group_store (mem, entry_parm, data->passed_type, size);
+ all->conversion_insns = get_insns ();
+ end_sequence ();
+ }
else if (size == 0)
;
{
rtx tem, x;
int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
- rtx reg = gen_rtx_REG (word_mode, REGNO (data->entry_parm));
+ rtx reg = gen_lowpart (word_mode, entry_parm);
x = expand_shift (LSHIFT_EXPR, word_mode, reg,
build_int_cst (NULL_TREE, by),
emit_move_insn (tem, x);
}
else
- move_block_from_reg (REGNO (data->entry_parm), mem,
+ move_block_from_reg (REGNO (entry_parm), mem,
size_stored / UNITS_PER_WORD);
}
else
- move_block_from_reg (REGNO (data->entry_parm), mem,
+ move_block_from_reg (REGNO (entry_parm), mem,
size_stored / UNITS_PER_WORD);
}
/* TREE_USED gets set erroneously during expand_assignment. */
save_tree_used = TREE_USED (parm);
- expand_assignment (parm, make_tree (data->nominal_type, tempreg), 0);
+ expand_assignment (parm, make_tree (data->nominal_type, tempreg));
TREE_USED (parm) = save_tree_used;
all->conversion_insns = get_insns ();
end_sequence ();
emit_move_insn (tempreg, DECL_RTL (parm));
tempreg = convert_to_mode (GET_MODE (parmreg), tempreg, unsigned_p);
emit_move_insn (parmreg, tempreg);
- all->conversion_insns = get_insns();
+ all->conversion_insns = get_insns ();
end_sequence ();
did_conversion = true;
/* Assign RTL expressions to the function's parameters. This may involve
copying them into registers and using those registers as the DECL_RTL. */
-void
+static void
assign_parms (tree fndecl)
{
struct assign_parm_data_all all;
assign_parm_adjust_stack_rtl (&data);
if (assign_parm_setup_block_p (&data))
- assign_parm_setup_block (parm, &data);
+ assign_parm_setup_block (&all, parm, &data);
else if (data.passed_pointer || use_register_for_decl (parm))
assign_parm_setup_reg (&all, parm, &data);
else
for the current function. The PENDING_SIZES are a TREE_LIST. The
TREE_VALUE of each node is a SAVE_EXPR. */
-void
+static void
expand_pending_sizes (tree pending_sizes)
{
tree tem;
is computed. */
clobber_after = get_last_insn ();
- /* Output the label for the actual return from the function,
- if one is expected. This happens either because a function epilogue
- is used instead of a return instruction, or because a return was done
- with a goto in order to run local cleanups, or because of pcc-style
- structure returning. */
- if (return_label)
- emit_label (return_label);
+ /* Output the label for the actual return from the function. */
+ emit_label (return_label);
/* Let except.c know where it should emit the call to unregister
the function context for sjlj exceptions. */