Boston, MA 02111-1307, USA. */
#include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
#include "system.h"
#include "rtl.h"
#include "tree.h"
HOST_WIDE_INT, rtx, rtx,
int, rtx, int));
static void store_one_arg PROTO ((struct arg_data *, rtx, int, int,
- tree, int));
+ int));
\f
/* If WHICH is 1, return 1 if EXP contains a call to the built-in function
`alloca'.
next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
is_const)
rtx funexp;
- tree fndecl;
- tree funtype;
+ tree fndecl ATTRIBUTE_UNUSED;
+ tree funtype ATTRIBUTE_UNUSED;
HOST_WIDE_INT stack_size;
HOST_WIDE_INT struct_value_size;
rtx next_arg_reg;
if -fcheck-memory-usage, code which invokes functions (and thus
damages some hard registers) can be inserted before using the value.
So, target is always a pseudo-register in that case. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
target = 0;
/* See if we can find a DECL-node for the actual function.
pop_temp_slots (); /* FUNEXP can't be BLKmode */
/* Check the function is executable. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_check_exec_libfunc, 1,
VOIDmode, 1,
funexp, ptr_mode);
for (i = 0; i < num_actuals; i++)
if (args[i].reg == 0 || args[i].pass_on_stack)
store_one_arg (&args[i], argblock, may_be_alloca,
- args_size.var != 0, fndecl, reg_parm_stack_space);
+ args_size.var != 0, reg_parm_stack_space);
/* If we have a parm that is passed in registers but not in memory
and whose alignment does not permit a direct copy into registers,
if (args[i].reg != 0 && ! args[i].pass_on_stack
&& args[i].mode == BLKmode
&& (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
- < MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
+ < (unsigned int) MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
{
int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
int big_endian_correction = 0;
{
rtx reg = gen_reg_rtx (word_mode);
rtx word = operand_subword_force (args[i].value, j, BLKmode);
- int bitsize = TYPE_ALIGN (TREE_TYPE (args[i].tree_value));
- int bitpos;
+ int bitsize = MIN (bytes * BITS_PER_UNIT, BITS_PER_WORD);
+ int bitalign = TYPE_ALIGN (TREE_TYPE (args[i].tree_value));
args[i].aligned_regs[j] = reg;
- /* Clobber REG and move each partword into it. Ensure we don't
- go past the end of the structure. Note that the loop below
- works because we've already verified that padding
- and endianness are compatible.
+ /* There is no need to restrict this code to loading items
+ in TYPE_ALIGN sized hunks. The bitfield instructions can
+ load up entire word sized registers efficiently.
+ ??? This may not be needed anymore.
We use to emit a clobber here but that doesn't let later
passes optimize the instructions we emit. By storing 0 into
the register later passes know the first AND to zero out the
emit_move_insn (reg, const0_rtx);
- for (bitpos = 0;
- bitpos < BITS_PER_WORD && bytes > 0;
- bitpos += bitsize, bytes -= bitsize / BITS_PER_UNIT)
- {
- int xbitpos = bitpos + big_endian_correction;
-
- store_bit_field (reg, bitsize, xbitpos, word_mode,
- extract_bit_field (word, bitsize, bitpos, 1,
- NULL_RTX, word_mode,
- word_mode,
- bitsize / BITS_PER_UNIT,
- BITS_PER_WORD),
- bitsize / BITS_PER_UNIT, BITS_PER_WORD);
- }
+ bytes -= bitsize / BITS_PER_UNIT;
+ store_bit_field (reg, bitsize, big_endian_correction, word_mode,
+ extract_bit_field (word, bitsize, 0, 1,
+ NULL_RTX, word_mode,
+ word_mode,
+ bitalign / BITS_PER_UNIT,
+ BITS_PER_WORD),
+ bitalign / BITS_PER_UNIT, BITS_PER_WORD);
}
}
for (i = 0; i < num_actuals; i++)
if (args[i].partial != 0 && ! args[i].pass_on_stack)
store_one_arg (&args[i], argblock, may_be_alloca,
- args_size.var != 0, fndecl, reg_parm_stack_space);
+ args_size.var != 0, reg_parm_stack_space);
#ifndef PUSH_ARGS_REVERSED
#ifdef STACK_BOUNDARY
NULL_RTX)));
/* Mark the memory for the aggregate as write-only. */
- if (flag_check_memory_usage)
+ if (current_function_check_memory_usage)
emit_library_call (chkr_set_right_libfunc, 1,
VOIDmode, 3,
structure_value_addr, ptr_mode,
when function inlining is being done. */
emit_move_insn (target, valreg);
else if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
- {
- /* Some machines (the PA for example) want to return all small
- structures in registers regardless of the structure's alignment.
-
- Deal with them explicitly by copying from the return registers
- into the target MEM locations. */
- int bytes = int_size_in_bytes (TREE_TYPE (exp));
- rtx src = NULL, dst = NULL;
- int bitsize = MIN (TYPE_ALIGN (TREE_TYPE (exp)), BITS_PER_WORD);
- int bitpos, xbitpos, big_endian_correction = 0;
-
- if (target == 0)
- {
- target = assign_stack_temp (BLKmode, bytes, 0);
- MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
- preserve_temp_slots (target);
- }
-
- /* This code assumes valreg is at least a full word. If it isn't,
- copy it into a new pseudo which is a full word. */
- if (GET_MODE (valreg) != BLKmode
- && GET_MODE_SIZE (GET_MODE (valreg)) < UNITS_PER_WORD)
- valreg = convert_to_mode (word_mode, valreg,
- TREE_UNSIGNED (TREE_TYPE (exp)));
-
- /* Structures whose size is not a multiple of a word are aligned
- to the least significant byte (to the right). On a BYTES_BIG_ENDIAN
- machine, this means we must skip the empty high order bytes when
- calculating the bit offset. */
- if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
- big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
- * BITS_PER_UNIT));
-
- /* Copy the structure BITSIZE bites at a time.
-
- We could probably emit more efficient code for machines
- which do not use strict alignment, but it doesn't seem
- worth the effort at the current time. */
- for (bitpos = 0, xbitpos = big_endian_correction;
- bitpos < bytes * BITS_PER_UNIT;
- bitpos += bitsize, xbitpos += bitsize)
- {
-
- /* We need a new source operand each time xbitpos is on a
- word boundary and when xbitpos == big_endian_correction
- (the first time through). */
- if (xbitpos % BITS_PER_WORD == 0
- || xbitpos == big_endian_correction)
- src = operand_subword_force (valreg,
- xbitpos / BITS_PER_WORD,
- BLKmode);
-
- /* We need a new destination operand each time bitpos is on
- a word boundary. */
- if (bitpos % BITS_PER_WORD == 0)
- dst = operand_subword (target, bitpos / BITS_PER_WORD, 1, BLKmode);
-
- /* Use xbitpos for the source extraction (right justified) and
- xbitpos for the destination store (left justified). */
- store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode,
- extract_bit_field (src, bitsize,
- xbitpos % BITS_PER_WORD, 1,
- NULL_RTX, word_mode,
- word_mode,
- bitsize / BITS_PER_UNIT,
- BITS_PER_WORD),
- bitsize / BITS_PER_UNIT, BITS_PER_WORD);
- }
- }
+ target = copy_blkmode_from_reg (target, valreg, TREE_TYPE (exp));
else
target = copy_to_reg (valreg);
FNDECL is the declaration of the function we are calling. */
static void
-store_one_arg (arg, argblock, may_be_alloca, variable_size, fndecl,
+store_one_arg (arg, argblock, may_be_alloca, variable_size,
reg_parm_stack_space)
struct arg_data *arg;
rtx argblock;
int may_be_alloca;
int variable_size;
- tree fndecl;
int reg_parm_stack_space;
{
register tree pval = arg->tree_value;
if (arg->value == arg->stack)
{
- /* If the value is already in the stack slot, we are done. */
- if (flag_check_memory_usage && GET_CODE (arg->stack) == MEM)
+ /* If the value is already in the stack slot, we are done moving
+ data. */
+ if (current_function_check_memory_usage && GET_CODE (arg->stack) == MEM)
{
- if (arg->mode == BLKmode)
- abort ();
-
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
XEXP (arg->stack, 0), ptr_mode,
- GEN_INT (GET_MODE_SIZE (arg->mode)),
+ ARGS_SIZE_RTX (arg->size),
TYPE_MODE (sizetype),
GEN_INT (MEMORY_USE_RW),
TYPE_MODE (integer_type_node));