This size counts from zero. It is not rounded to PREFERRED_STACK_BOUNDARY;
the caller may have to do that. */
-HOST_WIDE_INT
+static HOST_WIDE_INT
get_func_frame_size (struct function *f)
{
#ifdef FRAME_GROWS_DOWNWARD
struct locate_and_pad_arg_data locate;
int partial;
BOOL_BITFIELD named_arg : 1;
- BOOL_BITFIELD last_named : 1;
BOOL_BITFIELD passed_pointer : 1;
BOOL_BITFIELD on_stack : 1;
BOOL_BITFIELD loaded_in_reg : 1;
memset (data, 0, sizeof (*data));
- /* Set LAST_NAMED if this is last named arg before last anonymous args. */
- if (current_function_stdarg)
- {
- tree tem;
- for (tem = TREE_CHAIN (parm); tem; tem = TREE_CHAIN (tem))
- if (DECL_NAME (tem))
- break;
- if (tem == 0)
- data->last_named = true;
- }
-
- /* Set NAMED_ARG if this arg should be treated as a named arg. For
- most machines, if this is a varargs/stdarg function, then we treat
- the last named arg as if it were anonymous too. */
- if (targetm.calls.strict_argument_naming (&all->args_so_far))
- data->named_arg = 1;
+ /* NAMED_ARG is a mis-nomer. We really mean 'non-varadic'. */
+ if (!current_function_stdarg)
+ data->named_arg = 1; /* No varadic parms. */
+ else if (TREE_CHAIN (parm))
+ data->named_arg = 1; /* Not the last non-varadic parm. */
+ else if (targetm.calls.strict_argument_naming (&all->args_so_far))
+ data->named_arg = 1; /* Only varadic ones are unnamed. */
else
- data->named_arg = !data->last_named;
+ data->named_arg = 0; /* Treat as varadic. */
nominal_type = TREE_TYPE (parm);
passed_type = DECL_ARG_TYPE (parm);
rtx stack_parm = data->stack_parm;
HOST_WIDE_INT size;
HOST_WIDE_INT size_stored;
+ rtx orig_entry_parm = entry_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
- && data->nominal_mode != BLKmode
- && XVECLEN (entry_parm, 0) > 1
- && use_register_for_decl (parm))
+ && data->nominal_mode != BLKmode)
{
- rtx parmreg = gen_reg_rtx (data->nominal_mode);
+ rtx elt0 = XEXP (XVECEXP (orig_entry_parm, 0, 0), 0);
- push_to_sequence (all->conversion_insns);
+ if ((XVECLEN (entry_parm, 0) > 1
+ || hard_regno_nregs[REGNO (elt0)][GET_MODE (elt0)] > 1)
+ && use_register_for_decl (parm))
+ {
+ rtx parmreg = gen_reg_rtx (data->nominal_mode);
- /* For values returned in multiple registers, handle possible
- incompatible calls to emit_group_store.
+ push_to_sequence (all->conversion_insns);
- For example, the following would be invalid, and would have to
- be fixed by the conditional below:
+ /* For values returned in multiple registers, handle possible
+ incompatible calls to emit_group_store.
- emit_group_store ((reg:SF), (parallel:DF))
- emit_group_store ((reg:SI), (parallel:DI))
+ For example, the following would be invalid, and would have to
+ be fixed by the conditional below:
- 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));
+ emit_group_store ((reg:SF), (parallel:DF))
+ emit_group_store ((reg:SI), (parallel:DI))
- all->conversion_insns = get_insns ();
- end_sequence ();
+ 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));
- SET_DECL_RTL (parm, parmreg);
- return;
+ all->conversion_insns = get_insns ();
+ end_sequence ();
+
+ SET_DECL_RTL (parm, parmreg);
+ return;
+ }
}
size = int_size_in_bytes (data->passed_type);
size_stored = CEIL_ROUND (size, UNITS_PER_WORD);
if (stack_parm == 0)
{
+ DECL_ALIGN (parm) = MAX (DECL_ALIGN (parm), BITS_PER_WORD);
stack_parm = assign_stack_local (BLKmode, size_stored,
- TYPE_ALIGN (data->passed_type));
+ DECL_ALIGN (parm));
if (GET_MODE_SIZE (GET_MODE (entry_parm)) == size)
PUT_MODE (stack_parm, GET_MODE (entry_parm));
set_mem_attributes (stack_parm, parm, 1);
struct assign_parm_data_all all;
tree fnargs, parm;
rtx internal_arg_pointer;
- int varargs_setup = 0;
/* If the reg that the virtual arg pointer will be translated into is
not a fixed reg or is the stack pointer, make a copy of the virtual
continue;
}
- /* Handle stdargs. LAST_NAMED is a slight mis-nomer; it's also true
- for the unnamed dummy argument following the last named argument.
- See ABI silliness wrt strict_argument_naming and NAMED_ARG. So
- we only want to do this when we get to the actual last named
- argument, which will be the first time LAST_NAMED gets set. */
- if (data.last_named && !varargs_setup)
- {
- varargs_setup = true;
- assign_parms_setup_varargs (&all, &data, false);
- }
+ if (current_function_stdarg && !TREE_CHAIN (parm))
+ assign_parms_setup_varargs (&all, &data, false);
/* Find out where the parameter arrives in this function. */
assign_parm_find_entry_rtl (&all, &data);
if (flag_exceptions && USING_SJLJ_EXCEPTIONS)
sjlj_emit_function_exit_after (get_last_insn ());
- /* If we had calls to alloca, and this machine needs
- an accurate stack pointer to exit the function,
- insert some code to save and restore the stack pointer. */
- if (! EXIT_IGNORE_STACK
- && current_function_calls_alloca)
- {
- rtx tem = 0;
-
- emit_stack_save (SAVE_FUNCTION, &tem, parm_birth_insn);
- emit_stack_restore (SAVE_FUNCTION, tem, NULL_RTX);
- }
-
/* If scalar return value was computed in a pseudo-reg, or was a named
return value that got dumped to the stack, copy that to the hard
return register. */
/* Output the label for the naked return from the function. */
emit_label (naked_return_label);
+ /* If we had calls to alloca, and this machine needs
+ an accurate stack pointer to exit the function,
+ insert some code to save and restore the stack pointer. */
+ if (! EXIT_IGNORE_STACK
+ && current_function_calls_alloca)
+ {
+ rtx tem = 0;
+
+ emit_stack_save (SAVE_FUNCTION, &tem, parm_birth_insn);
+ emit_stack_restore (SAVE_FUNCTION, tem, NULL_RTX);
+ }
+
/* ??? This should no longer be necessary since stupid is no longer with
us, but there are some parts of the compiler (eg reload_combine, and
sh mach_dep_reorg) that still try and compute their own lifetime info
/* Can't deal with multiple successors of the entry block
at the moment. Function should always have at least one
entry point. */
- gcc_assert (EDGE_COUNT (ENTRY_BLOCK_PTR->succs) == 1);
+ gcc_assert (single_succ_p (ENTRY_BLOCK_PTR));
- insert_insn_on_edge (seq, EDGE_SUCC (ENTRY_BLOCK_PTR, 0));
+ insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR));
inserted = 1;
}
#endif
/* If this block has only one successor, it both jumps
and falls through to the fallthru block, so we can't
delete the edge. */
- if (EDGE_COUNT (bb->succs) == 1)
+ if (single_succ_p (bb))
{
ei_next (&ei2);
continue;
emit_barrier_after (BB_END (last));
emit_return_into_block (last, epilogue_line_note);
epilogue_end = BB_END (last);
- EDGE_SUCC (last, 0)->flags &= ~EDGE_FALLTHRU;
+ single_succ_edge (last)->flags &= ~EDGE_FALLTHRU;
goto epilogue_done;
}
}
{
basic_block bb = e->src;
rtx insn = BB_END (bb);
- rtx i;
- rtx newinsn;
if (!CALL_P (insn)
|| ! SIBLING_CALL_P (insn))
record_insns (seq, &sibcall_epilogue);
set_insn_locators (seq, epilogue_locator);
- i = PREV_INSN (insn);
- newinsn = emit_insn_before (seq, insn);
+ emit_insn_before (seq, insn);
ei_next (&ei);
}
#endif