char *current_function_name;
-/* If non-zero, an RTL expression for that location at which the current
- function returns its result. Always equal to
- DECL_RTL (DECL_RESULT (current_function_decl)), but provided
- independently of the tree structures. */
+/* If non-zero, an RTL expression for the location at which the current
+ function returns its result. If the current function returns its
+ result in a register, current_function_return_rtx will always be
+ the hard register containing the result. */
rtx current_function_return_rtx;
/* If this variable comes from an outer function,
find that function's saved context. */
- if (context != current_function_decl)
+ if (context != current_function_decl && context != inline_function_decl)
for (function = outer_function_chain; function; function = function->next)
if (function->decl == context)
break;
if (GET_CODE (XEXP (reg, 0)) == PLUS)
XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));
}
+ else
+ return;
+
+ if (flag_check_memory_usage)
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ XEXP (reg, 0), ptr_mode,
+ GEN_INT (GET_MODE_SIZE (GET_MODE (reg))),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW), QImode);
}
/* Subroutine of put_var_into_stack. This puts a single pseudo reg REG
else
stack_parm = gen_rtx (MEM, nominal_mode,
gen_rtx (PLUS, Pmode,
+ 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,
+ GEN_INT (int_size_in_bytes
+ (TREE_TYPE (parm))),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW), QImode);
+ conversion_insns = get_insns ();
+ end_sequence ();
+ }
internal_arg_pointer, offset_rtx));
/* If this is a memory ref that contains aggregate components,
store_expr (parm, copy, 0);
emit_move_insn (parmreg, XEXP (copy, 0));
+ if (flag_check_memory_usage)
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ XEXP (copy, 0), ptr_mode,
+ GEN_INT (int_size_in_bytes (type)),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW), QImode);
conversion_insns = get_insns ();
did_conversion = 1;
end_sequence ();
emit_move_insn (validize_mem (stack_parm),
validize_mem (entry_parm));
}
+ 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,
+ GEN_INT (GET_MODE_SIZE (GET_MODE
+ (entry_parm))),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW), QImode);
+ conversion_insns = get_insns ();
+ end_sequence ();
+ }
DECL_RTL (parm) = stack_parm;
}
= (stack_args_size.var == 0 ? GEN_INT (-stack_args_size.constant)
: expand_expr (size_binop (MINUS_EXPR, stack_args_size.var,
size_int (-stack_args_size.constant)),
- NULL_RTX, VOIDmode, 0));
+ NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD));
#else
current_function_arg_offset_rtx = ARGS_SIZE_RTX (stack_args_size);
#endif
/* Find the `struct function' for the function containing FUNCTION. */
fp = 0;
fn_context = decl_function_context (function);
- if (fn_context != current_function_decl)
+ if (fn_context != current_function_decl
+ && fn_context != inline_function_decl)
for (fp = outer_function_chain; fp; fp = fp->next)
if (fp->decl == fn_context)
break;
/* Evaluate now the sizes of any types declared among the arguments. */
for (tem = nreverse (get_pending_sizes ()); tem; tem = TREE_CHAIN (tem))
{
- expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode, 0);
+ expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode,
+ EXPAND_MEMORY_USE_BAD);
/* Flush the queue in case this parameter declaration has
side-effects. */
emit_queue ();
emit_insns_before (seq, tail_recursion_reentry);
}
+ /* If we are doing stack checking and this function makes calls,
+ do a stack probe at the start of the function to ensure we have enough
+ space for another stack frame. */
+ if (flag_stack_check && ! STACK_CHECK_BUILTIN)
+ {
+ rtx insn, seq;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ start_sequence ();
+ probe_stack_range (STACK_CHECK_PROTECT,
+ GEN_INT (STACK_CHECK_MAX_FRAME_SIZE));
+ seq = get_insns ();
+ end_sequence ();
+ emit_insns_before (seq, tail_recursion_reentry);
+ break;
+ }
+ }
+
/* Warn about unused parms if extra warnings were specified. */
if (warn_unused && extra_warnings)
{
if (end_bindings)
expand_end_bindings (0, 0, 0);
+ /* Now handle any leftover exception regions that may have been
+ created for the parameters. */
+ {
+ rtx last = get_last_insn ();
+ rtx label;
+
+ expand_leftover_cleanups ();
+
+ /* If the above emitted any code, may sure we jump around it. */
+ if (last != get_last_insn ())
+ {
+ label = gen_label_rtx ();
+ last = emit_jump_insn_after (gen_jump (label), last);
+ last = emit_barrier_after (last);
+ emit_label (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. */
emit_move_insn (real_decl_result,
DECL_RTL (DECL_RESULT (current_function_decl)));
emit_insn (gen_rtx (USE, VOIDmode, real_decl_result));
+
+ /* The delay slot scheduler assumes that current_function_return_rtx
+ holds the hard register containing the return value, not a temporary
+ pseudo. */
+ current_function_return_rtx = real_decl_result;
}
/* If returning a structure, arrange to return the address of the value