diff options
author | amodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-05-02 14:22:09 +0000 |
---|---|---|
committer | amodra <amodra@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-05-02 14:22:09 +0000 |
commit | 241399f6793dac1fdefa6b6c7c33cabe1c4f1cc9 (patch) | |
tree | 3499480542d5aee3c1e4cc0cd83f51a439861617 | |
parent | 30e87df7d5b99e14e55e7f93055e8481ffff587a (diff) | |
download | gcc-241399f6793dac1fdefa6b6c7c33cabe1c4f1cc9.tar.gz |
* calls.c (struct arg_data): Move offset, slot_offset, size and
alignment_pad to struct locate_and_pad_arg_data. Update all refs.
(initialize_argument_information): Adjust call to locate_and_pad_parm.
Delete alignment_pad var. Don't calculate slot_offset here.
(emit_library_call_value_1): Delete alignment_pad, offset and size
vars. Use struct locate_and_pad_arg_data instead. Adjust refs.
Adjust call to locate_and_pad_parm. Don't tweak arg size for
partial in-regs here. Formatting fixes.
* expr.h (struct locate_and_pad_arg_data): New struct.
(locate_and_pad_parm): Adjust declaration.
* function.c (assign_parms): Localize vars. Use "locate" instead of
other arg location vars. Don't invoke FUNCTION_ARG or
FUNCTION_INCOMING_ARG unless pretend_named is different from
named_arg. Heed MUST_PASS_IN_STACK and set up "partial" before
calling locate_and_pad_parm. Adjust locate_and_pad_parm call.
Use slot_offset for stack home of reg parms. Correct test for
parm passed in memory. Formatting fixes.
(locate_and_pad_parm): Add "partial" to params. Replace offset_ptr
arg_size_ptr and alignment pad with "locate". Set slot_offset here.
Correct initial_offset_ptr handling. Localize vars. Always pad
locate->offset even when in_regs.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@66383 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/calls.c | 170 | ||||
-rw-r--r-- | gcc/expr.h | 30 | ||||
-rw-r--r-- | gcc/function.c | 291 |
4 files changed, 264 insertions, 251 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1509141d34f..c2b1e8da47f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2003-05-02 Alan Modra <amodra@bigpond.net.au> + + * calls.c (struct arg_data): Move offset, slot_offset, size and + alignment_pad to struct locate_and_pad_arg_data. Update all refs. + (initialize_argument_information): Adjust call to locate_and_pad_parm. + Delete alignment_pad var. Don't calculate slot_offset here. + (emit_library_call_value_1): Delete alignment_pad, offset and size + vars. Use struct locate_and_pad_arg_data instead. Adjust refs. + Adjust call to locate_and_pad_parm. Don't tweak arg size for + partial in-regs here. Formatting fixes. + * expr.h (struct locate_and_pad_arg_data): New struct. + (locate_and_pad_parm): Adjust declaration. + * function.c (assign_parms): Localize vars. Use "locate" instead of + other arg location vars. Don't invoke FUNCTION_ARG or + FUNCTION_INCOMING_ARG unless pretend_named is different from + named_arg. Heed MUST_PASS_IN_STACK and set up "partial" before + calling locate_and_pad_parm. Adjust locate_and_pad_parm call. + Use slot_offset for stack home of reg parms. Correct test for + parm passed in memory. Formatting fixes. + (locate_and_pad_parm): Add "partial" to params. Replace offset_ptr + arg_size_ptr and alignment pad with "locate". Set slot_offset here. + Correct initial_offset_ptr handling. Localize vars. Always pad + locate->offset even when in_regs. + 2003-05-02 Nathan Sidwell <nathan@codesourcery.com> * Makefile.in (TREE_H): Replace location.h with input.h. diff --git a/gcc/calls.c b/gcc/calls.c index 135f949028c..8fb84e9b906 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -98,16 +98,8 @@ struct arg_data even though pass_on_stack is zero, just because FUNCTION_ARG says so. pass_on_stack identifies arguments that *cannot* go in registers. */ int pass_on_stack; - /* Offset of this argument from beginning of stack-args. */ - struct args_size offset; - /* Similar, but offset to the start of the stack slot. Different from - OFFSET if this arg pads downward. */ - struct args_size slot_offset; - /* Size of this argument on the stack, rounded up for any padding it gets, - parts of the argument passed in registers do not count. - If REG_PARM_STACK_SPACE is defined, then register parms - are counted here as well. */ - struct args_size size; + /* Some fields packaged up for locate_and_pad_parm. */ + struct locate_and_pad_arg_data locate; /* Location on the stack at which parameter should be stored. The store has already been done if STACK == VALUE. */ rtx stack; @@ -123,9 +115,6 @@ struct arg_data word-sized pseudos we made. */ rtx *aligned_regs; int n_aligned_regs; - /* The amount that the stack pointer needs to be adjusted to - force alignment for the next argument. */ - struct args_size alignment_pad; }; /* A vector of one char per byte of stack space. A byte if nonzero if @@ -1120,7 +1109,6 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args, /* Count arg position in order args appear. */ int argpos; - struct args_size alignment_pad; int i; tree p; @@ -1331,39 +1319,14 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args, #else args[i].reg != 0, #endif - fndecl, args_size, &args[i].offset, - &args[i].size, &alignment_pad); - -#ifndef ARGS_GROW_DOWNWARD - args[i].slot_offset = *args_size; -#endif - - args[i].alignment_pad = alignment_pad; - - /* If a part of the arg was put into registers, - don't include that part in the amount pushed. */ - if (reg_parm_stack_space == 0 && ! args[i].pass_on_stack) - args[i].size.constant -= ((args[i].partial * UNITS_PER_WORD) - / (PARM_BOUNDARY / BITS_PER_UNIT) - * (PARM_BOUNDARY / BITS_PER_UNIT)); + args[i].pass_on_stack ? 0 : args[i].partial, + fndecl, args_size, &args[i].locate); /* Update ARGS_SIZE, the total stack space for args so far. */ - args_size->constant += args[i].size.constant; - if (args[i].size.var) - { - ADD_PARM_SIZE (*args_size, args[i].size.var); - } - - /* Since the slot offset points to the bottom of the slot, - we must record it after incrementing if the args grow down. */ -#ifdef ARGS_GROW_DOWNWARD - args[i].slot_offset = *args_size; - - args[i].slot_offset.constant = -args_size->constant; - if (args_size->var) - SUB_PARM_SIZE (args[i].slot_offset, args_size->var); -#endif + args_size->constant += args[i].locate.size.constant; + if (args[i].locate.size.var) + ADD_PARM_SIZE (*args_size, args[i].locate.size.var); /* Increment ARGS_SO_FAR, which has info about which arg-registers have been used, etc. */ @@ -1616,8 +1579,8 @@ compute_argument_addresses (args, argblock, num_actuals) for (i = 0; i < num_actuals; i++) { - rtx offset = ARGS_SIZE_RTX (args[i].offset); - rtx slot_offset = ARGS_SIZE_RTX (args[i].slot_offset); + rtx offset = ARGS_SIZE_RTX (args[i].locate.offset); + rtx slot_offset = ARGS_SIZE_RTX (args[i].locate.slot_offset); rtx addr; /* Skip this parm if it will not be passed on the stack. */ @@ -2060,12 +2023,12 @@ check_sibcall_argument_overlap (insn, arg, mark_stored_args_map) if (mark_stored_args_map) { #ifdef ARGS_GROW_DOWNWARD - low = -arg->slot_offset.constant - arg->size.constant; + low = -arg->locate.slot_offset.constant - arg->locate.size.constant; #else - low = arg->slot_offset.constant; + low = arg->locate.slot_offset.constant; #endif - for (high = low + arg->size.constant; low < high; low++) + for (high = low + arg->locate.size.constant; low < high; low++) SET_BIT (stored_args_map, low); } return insn != NULL_RTX; @@ -3364,7 +3327,7 @@ expand_call (exp, target, ignore) emit_move_insn (stack_area, args[i].save_area); else emit_block_move (stack_area, args[i].save_area, - GEN_INT (args[i].size.constant), + GEN_INT (args[i].locate.size.constant), BLOCK_OP_CALL_PARM); } @@ -3513,7 +3476,6 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) rtx fun; int inc; int count; - struct args_size alignment_pad; rtx argblock = 0; CUMULATIVE_ARGS args_so_far; struct arg @@ -3522,8 +3484,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) enum machine_mode mode; rtx reg; int partial; - struct args_size offset; - struct args_size size; + struct locate_and_pad_arg_data locate; rtx save_area; }; struct arg *argvec; @@ -3683,12 +3644,11 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) #else argvec[count].reg != 0, #endif - NULL_TREE, &args_size, &argvec[count].offset, - &argvec[count].size, &alignment_pad); + 0, NULL_TREE, &args_size, &argvec[count].locate); if (argvec[count].reg == 0 || argvec[count].partial != 0 || reg_parm_stack_space > 0) - args_size.constant += argvec[count].size.constant; + args_size.constant += argvec[count].locate.size.constant; FUNCTION_ARG_ADVANCE (args_so_far, Pmode, (tree) 0, 1); @@ -3802,18 +3762,15 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) #else argvec[count].reg != 0, #endif - NULL_TREE, &args_size, &argvec[count].offset, - &argvec[count].size, &alignment_pad); + argvec[count].partial, + NULL_TREE, &args_size, &argvec[count].locate); - if (argvec[count].size.var) + if (argvec[count].locate.size.var) abort (); - if (reg_parm_stack_space == 0 && argvec[count].partial) - argvec[count].size.constant -= argvec[count].partial * UNITS_PER_WORD; - if (argvec[count].reg == 0 || argvec[count].partial != 0 || reg_parm_stack_space > 0) - args_size.constant += argvec[count].size.constant; + args_size.constant += argvec[count].locate.size.constant; FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1); } @@ -3951,11 +3908,11 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) #ifdef ARGS_GROW_DOWNWARD /* stack_slot is negative, but we want to index stack_usage_map with positive values. */ - upper_bound = -argvec[argnum].offset.constant + 1; - lower_bound = upper_bound - argvec[argnum].size.constant; + upper_bound = -argvec[argnum].locate.offset.constant + 1; + lower_bound = upper_bound - argvec[argnum].locate.size.constant; #else - lower_bound = argvec[argnum].offset.constant; - upper_bound = lower_bound + argvec[argnum].size.constant; + lower_bound = argvec[argnum].locate.offset.constant; + upper_bound = lower_bound + argvec[argnum].locate.size.constant; #endif i = lower_bound; @@ -3968,19 +3925,16 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) if (i < upper_bound) { - /* We need to make a save area. See what mode we can make - it. */ + /* We need to make a save area. */ + unsigned int size + = argvec[argnum].locate.size.constant * BITS_PER_UNIT; enum machine_mode save_mode - = mode_for_size (argvec[argnum].size.constant - * BITS_PER_UNIT, - MODE_INT, 1); + = mode_for_size (size, MODE_INT, 1); + rtx adr + = plus_constant (argblock, + argvec[argnum].locate.offset.constant); rtx stack_area - = gen_rtx_MEM - (save_mode, - memory_address - (save_mode, - plus_constant (argblock, - argvec[argnum].offset.constant))); + = gen_rtx_MEM (save_mode, memory_address (save_mode, adr)); argvec[argnum].save_area = gen_reg_rtx (save_mode); emit_move_insn (argvec[argnum].save_area, stack_area); @@ -3989,8 +3943,9 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) emit_push_insn (val, mode, NULL_TREE, NULL_RTX, PARM_BOUNDARY, partial, reg, 0, argblock, - GEN_INT (argvec[argnum].offset.constant), - reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad)); + GEN_INT (argvec[argnum].locate.offset.constant), + reg_parm_stack_space, + ARGS_SIZE_RTX (argvec[argnum].locate.alignment_pad)); /* Now mark the segment we just used. */ if (ACCUMULATE_OUTGOING_ARGS) @@ -4195,12 +4150,10 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) if (argvec[count].save_area) { enum machine_mode save_mode = GET_MODE (argvec[count].save_area); - rtx stack_area - = gen_rtx_MEM (save_mode, - memory_address - (save_mode, - plus_constant (argblock, - argvec[count].offset.constant))); + rtx adr = plus_constant (argblock, + argvec[count].locate.offset.constant); + rtx stack_area = gen_rtx_MEM (save_mode, + memory_address (save_mode, adr)); emit_move_insn (stack_area, argvec[count].save_area); } @@ -4327,14 +4280,14 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) else upper_bound = 0; - lower_bound = upper_bound - arg->size.constant; + lower_bound = upper_bound - arg->locate.size.constant; #else if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS) lower_bound = INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1)); else lower_bound = 0; - upper_bound = lower_bound + arg->size.constant; + upper_bound = lower_bound + arg->locate.size.constant; #endif i = lower_bound; @@ -4347,13 +4300,11 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) if (i < upper_bound) { - /* We need to make a save area. See what mode we can make it. */ - enum machine_mode save_mode - = mode_for_size (arg->size.constant * BITS_PER_UNIT, MODE_INT, 1); - rtx stack_area - = gen_rtx_MEM (save_mode, - memory_address (save_mode, - XEXP (arg->stack_slot, 0))); + /* We need to make a save area. */ + unsigned int size = arg->locate.size.constant * BITS_PER_UNIT; + enum machine_mode save_mode = mode_for_size (size, MODE_INT, 1); + rtx adr = memory_address (save_mode, XEXP (arg->stack_slot, 0)); + rtx stack_area = gen_rtx_MEM (save_mode, adr); if (save_mode == BLKmode) { @@ -4481,8 +4432,8 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) This can either be done with push or copy insns. */ emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, PARM_BOUNDARY, partial, reg, used - size, argblock, - ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space, - ARGS_SIZE_RTX (arg->alignment_pad)); + ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space, + ARGS_SIZE_RTX (arg->locate.alignment_pad)); /* Unless this is a partially-in-register argument, the argument is now in the stack. */ @@ -4504,16 +4455,17 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) /* Round its size up to a multiple of the allocation unit for arguments. */ - if (arg->size.var != 0) + if (arg->locate.size.var != 0) { excess = 0; - size_rtx = ARGS_SIZE_RTX (arg->size); + size_rtx = ARGS_SIZE_RTX (arg->locate.size); } else { /* PUSH_ROUNDING has no effect on us, because emit_push_insn for BLKmode is careful to avoid it. */ - excess = (arg->size.constant - int_size_in_bytes (TREE_TYPE (pval)) + excess = (arg->locate.size.constant + - int_size_in_bytes (TREE_TYPE (pval)) + partial * UNITS_PER_WORD); size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)), NULL_RTX, TYPE_MODE (sizetype), 0); @@ -4527,7 +4479,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) PARM_BOUNDARY, but the actual argument isn't. */ if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward) { - if (arg->size.var) + if (arg->locate.size.var) parm_align = BITS_PER_UNIT; else if (excess) { @@ -4539,7 +4491,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) if ((flags & ECF_SIBCALL) && GET_CODE (arg->value) == MEM) { /* emit_push_insn might not work properly if arg->value and - argblock + arg->offset areas overlap. */ + argblock + arg->locate.offset areas overlap. */ rtx x = arg->value; int i = 0; @@ -4553,17 +4505,17 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) i = INTVAL (XEXP (XEXP (x, 0), 1)); /* expand_call should ensure this */ - if (arg->offset.var || GET_CODE (size_rtx) != CONST_INT) + if (arg->locate.offset.var || GET_CODE (size_rtx) != CONST_INT) abort (); - if (arg->offset.constant > i) + if (arg->locate.offset.constant > i) { - if (arg->offset.constant < i + INTVAL (size_rtx)) + if (arg->locate.offset.constant < i + INTVAL (size_rtx)) sibcall_failure = 1; } - else if (arg->offset.constant < i) + else if (arg->locate.offset.constant < i) { - if (i < arg->offset.constant + INTVAL (size_rtx)) + if (i < arg->locate.offset.constant + INTVAL (size_rtx)) sibcall_failure = 1; } } @@ -4571,8 +4523,8 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx, parm_align, partial, reg, excess, argblock, - ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space, - ARGS_SIZE_RTX (arg->alignment_pad)); + ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space, + ARGS_SIZE_RTX (arg->locate.alignment_pad)); /* Unless this is a partially-in-register argument, the argument is now in the stack. diff --git a/gcc/expr.h b/gcc/expr.h index 7e157cdf302..dfd83d43c23 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -63,6 +63,8 @@ enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM = 2, EXPAND_SUM, more information. */ #define OK_DEFER_POP (inhibit_defer_pop -= 1) +enum direction {none, upward, downward}; + #ifdef TREE_CODE /* Don't lose if tree.h not included. */ /* Structure to record the size of a sequence of arguments as the sum of a tree-expression and a constant. This structure is @@ -74,6 +76,24 @@ struct args_size HOST_WIDE_INT constant; tree var; }; + +/* Package up various arg related fields of struct args for + locate_and_pad_parm. */ +struct locate_and_pad_arg_data +{ + /* Size of this argument on the stack, rounded up for any padding it + gets. If REG_PARM_STACK_SPACE is defined, then register parms are + counted here, otherwise they aren't. */ + struct args_size size; + /* Offset of this argument from beginning of stack-args. */ + struct args_size offset; + /* Offset to the start of the stack slot. Different from OFFSET + if this arg pads downward. */ + struct args_size slot_offset; + /* The amount that the stack pointer needs to be adjusted to + force alignment for the next argument. */ + struct args_size alignment_pad; +}; #endif /* Add the value of the tree INC to the `struct args_size' TO. */ @@ -119,8 +139,6 @@ do { \ usually pad upward, but pad short args downward on big-endian machines. */ -enum direction {none, upward, downward}; /* Value has this type. */ - #ifndef FUNCTION_ARG_PADDING #define FUNCTION_ARG_PADDING(MODE, TYPE) \ (! BYTES_BIG_ENDIAN \ @@ -570,11 +588,9 @@ extern rtx expand_shift PARAMS ((enum tree_code, enum machine_mode, rtx, tree, rtx, int)); extern rtx expand_divmod PARAMS ((int, enum tree_code, enum machine_mode, rtx, rtx, rtx, int)); -extern void locate_and_pad_parm PARAMS ((enum machine_mode, tree, int, tree, - struct args_size *, - struct args_size *, - struct args_size *, - struct args_size *)); +extern void locate_and_pad_parm PARAMS ((enum machine_mode, tree, int, int, + tree, struct args_size *, + struct locate_and_pad_arg_data *)); extern rtx expand_inline_function PARAMS ((tree, tree, rtx, int, tree, rtx)); /* Return the CODE_LABEL rtx for a LABEL_DECL, creating it if necessary. */ diff --git a/gcc/function.c b/gcc/function.c index 6e52d7e1ddb..5684392b5e9 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4340,12 +4340,7 @@ assign_parms (fndecl) tree fndecl; { tree parm; - rtx entry_parm = 0; - rtx stack_parm = 0; CUMULATIVE_ARGS args_so_far; - enum machine_mode promoted_mode, passed_mode; - enum machine_mode nominal_mode, promoted_nominal_mode; - int unsignedp; /* Total space needed so far for args on the stack, given as a constant and a tree-expression. */ struct args_size stack_args_size; @@ -4359,8 +4354,8 @@ assign_parms (fndecl) #ifdef SETUP_INCOMING_VARARGS int varargs_setup = 0; #endif + int reg_parm_stack_space = 0; rtx conversion_insns = 0; - struct args_size alignment_pad; /* Nonzero if function takes extra anonymous args. This means the last named arg must be on the stack @@ -4407,6 +4402,14 @@ assign_parms (fndecl) max_parm_reg = LAST_VIRTUAL_REGISTER + 1; parm_reg_stack_loc = (rtx *) ggc_alloc_cleared (max_parm_reg * sizeof (rtx)); +#ifdef REG_PARM_STACK_SPACE +#ifdef MAYBE_REG_PARM_STACK_SPACE + reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE; +#else + reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl); +#endif +#endif + #ifdef INIT_CUMULATIVE_INCOMING_ARGS INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX); #else @@ -4419,14 +4422,19 @@ assign_parms (fndecl) for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) { - struct args_size stack_offset; - struct args_size arg_size; + rtx entry_parm; + rtx stack_parm; + enum machine_mode promoted_mode, passed_mode; + enum machine_mode nominal_mode, promoted_nominal_mode; + int unsignedp; + struct locate_and_pad_arg_data locate; int passed_pointer = 0; int did_conversion = 0; tree passed_type = DECL_ARG_TYPE (parm); tree nominal_type = TREE_TYPE (parm); - int pretend_named; int last_named = 0, named_arg; + int in_regs; + int partial = 0; /* Set LAST_NAMED if this is last named arg before last anonymous args. */ @@ -4490,7 +4498,7 @@ assign_parms (fndecl) || TREE_ADDRESSABLE (passed_type) #ifdef FUNCTION_ARG_PASS_BY_REFERENCE || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, passed_mode, - passed_type, named_arg) + passed_type, named_arg) #endif ) { @@ -4560,27 +4568,52 @@ assign_parms (fndecl) it came in a register so that REG_PARM_STACK_SPACE isn't skipped. In this case, we call FUNCTION_ARG with NAMED set to 1 instead of 0 as it was the previous time. */ - - pretend_named = named_arg || PRETEND_OUTGOING_VARARGS_NAMED; - locate_and_pad_parm (promoted_mode, passed_type, + in_regs = entry_parm != 0; #ifdef STACK_PARMS_IN_REG_PARM_AREA - 1, -#else + in_regs = 1; +#endif + if (!in_regs && !named_arg) + { + int pretend_named = PRETEND_OUTGOING_VARARGS_NAMED; + if (pretend_named) + { #ifdef FUNCTION_INCOMING_ARG - FUNCTION_INCOMING_ARG (args_so_far, promoted_mode, - passed_type, - pretend_named) != 0, + in_regs = FUNCTION_INCOMING_ARG (args_so_far, promoted_mode, + passed_type, + pretend_named) != 0; #else - FUNCTION_ARG (args_so_far, promoted_mode, - passed_type, - pretend_named) != 0, + in_regs = FUNCTION_ARG (args_so_far, promoted_mode, + passed_type, + pretend_named) != 0; #endif + } + } + + /* If this parameter was passed both in registers and in the stack, + use the copy on the stack. */ + if (MUST_PASS_IN_STACK (promoted_mode, passed_type)) + entry_parm = 0; + +#ifdef FUNCTION_ARG_PARTIAL_NREGS + if (entry_parm) + partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode, + passed_type, named_arg); #endif - fndecl, &stack_args_size, &stack_offset, &arg_size, - &alignment_pad); + + memset (&locate, 0, sizeof (locate)); + locate_and_pad_parm (promoted_mode, passed_type, in_regs, + entry_parm ? partial : 0, fndecl, + &stack_args_size, &locate); { - rtx offset_rtx = ARGS_SIZE_RTX (stack_offset); + rtx offset_rtx; + + /* If we're passing this arg using a reg, make its stack home + the aligned stack slot. */ + if (entry_parm) + offset_rtx = ARGS_SIZE_RTX (locate.slot_offset); + else + offset_rtx = ARGS_SIZE_RTX (locate.offset); if (offset_rtx == const0_rtx) stack_parm = gen_rtx_MEM (promoted_mode, internal_arg_pointer); @@ -4597,12 +4630,6 @@ assign_parms (fndecl) set_reg_attrs_for_parm (entry_parm, stack_parm); } - /* If this parameter was passed both in registers and in the stack, - use the copy on the stack. */ - if (MUST_PASS_IN_STACK (promoted_mode, passed_type)) - entry_parm = 0; - -#ifdef FUNCTION_ARG_PARTIAL_NREGS /* If this parm was passed part in regs and part in memory, pretend it arrived entirely in memory by pushing the register-part onto the stack. @@ -4611,39 +4638,31 @@ assign_parms (fndecl) we could put it together in a pseudoreg directly, but for now that's not worth bothering with. */ - if (entry_parm) + if (partial) { - int nregs = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode, - passed_type, named_arg); - - if (nregs > 0) - { -#if defined (REG_PARM_STACK_SPACE) && !defined (MAYBE_REG_PARM_STACK_SPACE) - /* When REG_PARM_STACK_SPACE is nonzero, stack space for - split parameters was allocated by our caller, so we - won't be pushing it in the prolog. */ - if (REG_PARM_STACK_SPACE (fndecl) == 0) +#ifndef MAYBE_REG_PARM_STACK_SPACE + /* When REG_PARM_STACK_SPACE is nonzero, stack space for + split parameters was allocated by our caller, so we + won't be pushing it in the prolog. */ + if (reg_parm_stack_space) #endif - current_function_pretend_args_size - = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1) - / (PARM_BOUNDARY / BITS_PER_UNIT) - * (PARM_BOUNDARY / BITS_PER_UNIT)); + current_function_pretend_args_size + = (((partial * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1) + / (PARM_BOUNDARY / BITS_PER_UNIT) + * (PARM_BOUNDARY / BITS_PER_UNIT)); - /* Handle calls that pass values in multiple non-contiguous - locations. The Irix 6 ABI has examples of this. */ - if (GET_CODE (entry_parm) == PARALLEL) - emit_group_store (validize_mem (stack_parm), entry_parm, - int_size_in_bytes (TREE_TYPE (parm))); + /* Handle calls that pass values in multiple non-contiguous + locations. The Irix 6 ABI has examples of this. */ + if (GET_CODE (entry_parm) == PARALLEL) + emit_group_store (validize_mem (stack_parm), entry_parm, + int_size_in_bytes (TREE_TYPE (parm))); - else - move_block_from_reg (REGNO (entry_parm), - validize_mem (stack_parm), nregs, - int_size_in_bytes (TREE_TYPE (parm))); + else + move_block_from_reg (REGNO (entry_parm), validize_mem (stack_parm), + partial, int_size_in_bytes (TREE_TYPE (parm))); - entry_parm = stack_parm; - } + entry_parm = stack_parm; } -#endif /* If we didn't decide this parm came in a register, by default it came on the stack. */ @@ -4674,9 +4693,9 @@ assign_parms (fndecl) #endif ) { - stack_args_size.constant += arg_size.constant; - if (arg_size.var) - ADD_PARM_SIZE (stack_args_size, arg_size.var); + stack_args_size.constant += locate.size.constant; + if (locate.size.var) + ADD_PARM_SIZE (stack_args_size, locate.size.var); } else /* No stack slot was pushed for this parm. */ @@ -4700,7 +4719,7 @@ assign_parms (fndecl) /* If parm was passed in memory, and we need to convert it on entry, don't store it back in that same slot. */ - if (entry_parm != 0 + if (entry_parm == stack_parm && nominal_mode != BLKmode && nominal_mode != passed_mode) stack_parm = 0; @@ -5023,7 +5042,7 @@ assign_parms (fndecl) && ! did_conversion && stack_parm != 0 && GET_CODE (stack_parm) == MEM - && stack_offset.var == 0 + && locate.offset.var == 0 && reg_mentioned_p (virtual_incoming_args_rtx, XEXP (stack_parm, 0))) { @@ -5109,7 +5128,8 @@ assign_parms (fndecl) { stack_parm = assign_stack_local (GET_MODE (entry_parm), - GET_MODE_SIZE (GET_MODE (entry_parm)), 0); + GET_MODE_SIZE (GET_MODE (entry_parm)), + 0); set_mem_attributes (stack_parm, parm, 1); } @@ -5280,8 +5300,11 @@ promoted_input_arg (regno, pmode, punsignedp) INITIAL_OFFSET_PTR points to the current offset into the stacked arguments. - The starting offset and size for this parm are returned in *OFFSET_PTR - and *ARG_SIZE_PTR, respectively. + The starting offset and size for this parm are returned in + LOCATE->OFFSET and LOCATE->SIZE, respectively. When IN_REGS is + nonzero, the offset is that of stack slot, which is returned in + LOCATE->SLOT_OFFSET. LOCATE->ALIGNMENT_PAD is the amount of + padding required from the initial offset ptr to the stack slot. IN_REGS is nonzero if the argument will be passed in registers. It will never be set if REG_PARM_STACK_SPACE is not defined. @@ -5298,45 +5321,39 @@ promoted_input_arg (regno, pmode, punsignedp) initial offset is not affected by this rounding, while the size always is and the starting offset may be. */ -/* offset_ptr will be negative for ARGS_GROW_DOWNWARD case; - initial_offset_ptr is positive because locate_and_pad_parm's +/* LOCATE->OFFSET will be negative for ARGS_GROW_DOWNWARD case; + INITIAL_OFFSET_PTR is positive because locate_and_pad_parm's callers pass in the total size of args so far as - initial_offset_ptr. arg_size_ptr is always positive. */ + INITIAL_OFFSET_PTR. LOCATE->SIZE is always positive. */ void -locate_and_pad_parm (passed_mode, type, in_regs, fndecl, - initial_offset_ptr, offset_ptr, arg_size_ptr, - alignment_pad) +locate_and_pad_parm (passed_mode, type, in_regs, partial, fndecl, + initial_offset_ptr, locate) enum machine_mode passed_mode; tree type; - int in_regs ATTRIBUTE_UNUSED; + int in_regs; + int partial; tree fndecl ATTRIBUTE_UNUSED; struct args_size *initial_offset_ptr; - struct args_size *offset_ptr; - struct args_size *arg_size_ptr; - struct args_size *alignment_pad; - + struct locate_and_pad_arg_data *locate; { - 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); -#ifdef ARGS_GROW_DOWNWARD - tree s2 = sizetree; -#endif + tree sizetree; + enum direction where_pad; + int boundary; + int reg_parm_stack_space = 0; + int part_size_in_regs; #ifdef REG_PARM_STACK_SPACE +#ifdef MAYBE_REG_PARM_STACK_SPACE + reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE; +#else + reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl); +#endif + /* If we have found a stack parm before we reach the end of the area reserved for registers, skip that area. */ if (! in_regs) { - int reg_parm_stack_space = 0; - -#ifdef MAYBE_REG_PARM_STACK_SPACE - reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE; -#else - reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl); -#endif if (reg_parm_stack_space > 0) { if (initial_offset_ptr->var) @@ -5352,54 +5369,56 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl, } #endif /* REG_PARM_STACK_SPACE */ - arg_size_ptr->var = 0; - arg_size_ptr->constant = 0; - alignment_pad->var = 0; - alignment_pad->constant = 0; + part_size_in_regs = 0; + if (reg_parm_stack_space == 0) + part_size_in_regs = ((partial * UNITS_PER_WORD) + / (PARM_BOUNDARY / BITS_PER_UNIT) + * (PARM_BOUNDARY / BITS_PER_UNIT)); + + 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); #ifdef ARGS_GROW_DOWNWARD + locate->slot_offset.constant = -initial_offset_ptr->constant; if (initial_offset_ptr->var) - { - offset_ptr->constant = 0; - offset_ptr->var = size_binop (MINUS_EXPR, ssize_int (0), - initial_offset_ptr->var); - } - else - { - offset_ptr->constant = -initial_offset_ptr->constant; - offset_ptr->var = 0; - } + locate->slot_offset.var = size_binop (MINUS_EXPR, ssize_int (0), + initial_offset_ptr->var); - if (where_pad != none - && (!host_integerp (sizetree, 1) - || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY)) - s2 = round_up (s2, PARM_BOUNDARY / BITS_PER_UNIT); - SUB_PARM_SIZE (*offset_ptr, s2); + { + tree s2 = sizetree; + if (where_pad != none + && (!host_integerp (sizetree, 1) + || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY)) + s2 = round_up (s2, PARM_BOUNDARY / BITS_PER_UNIT); + SUB_PARM_SIZE (locate->slot_offset, s2); + } + + locate->slot_offset.constant += part_size_in_regs; if (!in_regs #ifdef REG_PARM_STACK_SPACE || REG_PARM_STACK_SPACE (fndecl) > 0 #endif ) - pad_to_arg_alignment (offset_ptr, boundary, alignment_pad); + pad_to_arg_alignment (&locate->slot_offset, boundary, + &locate->alignment_pad); + locate->size.constant = (-initial_offset_ptr->constant + - locate->slot_offset.constant); if (initial_offset_ptr->var) - arg_size_ptr->var = size_binop (MINUS_EXPR, - size_binop (MINUS_EXPR, - ssize_int (0), - initial_offset_ptr->var), - offset_ptr->var); - - else - arg_size_ptr->constant = (-initial_offset_ptr->constant - - offset_ptr->constant); - - /* Pad_below needs the pre-rounded size to know how much to pad below. - We only pad parameters which are not in registers as they have their - padding done elsewhere. */ - if (where_pad == downward - && !in_regs) - pad_below (offset_ptr, passed_mode, sizetree); + locate->size.var = size_binop (MINUS_EXPR, + size_binop (MINUS_EXPR, + ssize_int (0), + initial_offset_ptr->var), + locate->slot_offset.var); + + /* Pad_below needs the pre-rounded size to know how much to pad + below. */ + locate->offset = locate->slot_offset; + if (where_pad == downward) + pad_below (&locate->offset, passed_mode, sizetree); #else /* !ARGS_GROW_DOWNWARD */ if (!in_regs @@ -5407,8 +5426,9 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl, || REG_PARM_STACK_SPACE (fndecl) > 0 #endif ) - pad_to_arg_alignment (initial_offset_ptr, boundary, alignment_pad); - *offset_ptr = *initial_offset_ptr; + pad_to_arg_alignment (initial_offset_ptr, boundary, + &locate->alignment_pad); + locate->slot_offset = *initial_offset_ptr; #ifdef PUSH_ROUNDING if (passed_mode != BLKmode) @@ -5417,18 +5437,18 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl, /* Pad_below needs the pre-rounded size to know how much to pad below so this must be done before rounding up. */ - if (where_pad == downward - /* 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); + locate->offset = locate->slot_offset; + if (where_pad == downward) + pad_below (&locate->offset, passed_mode, sizetree); if (where_pad != none && (!host_integerp (sizetree, 1) || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY)) sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT); - ADD_PARM_SIZE (*arg_size_ptr, sizetree); + ADD_PARM_SIZE (locate->size, sizetree); + + locate->size.constant -= part_size_in_regs; #endif /* ARGS_GROW_DOWNWARD */ } @@ -5467,7 +5487,8 @@ pad_to_arg_alignment (offset_ptr, boundary, alignment_pad) #endif (ARGS_SIZE_TREE (*offset_ptr), boundary / BITS_PER_UNIT); - offset_ptr->constant = 0; /*?*/ + /* ARGS_SIZE_TREE includes constant term. */ + offset_ptr->constant = 0; if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY) alignment_pad->var = size_binop (MINUS_EXPR, offset_ptr->var, save_var); |