diff options
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/gcc/function.c b/gcc/function.c index 301d59d..c3f4dc6 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4507,6 +4507,8 @@ assign_parms (tree fndecl) offset_rtx)); set_mem_attributes (stack_parm, parm, 1); + if (entry_parm && MEM_ATTRS (stack_parm)->align < PARM_BOUNDARY) + set_mem_align (stack_parm, PARM_BOUNDARY); /* Set also REG_ATTRS if parameter was passed in a register. */ if (entry_parm) @@ -4538,6 +4540,7 @@ assign_parms (tree fndecl) locations. The Irix 6 ABI has examples of this. */ if (GET_CODE (entry_parm) == PARALLEL) emit_group_store (validize_mem (stack_parm), entry_parm, + TREE_TYPE (parm), int_size_in_bytes (TREE_TYPE (parm))); else @@ -4644,7 +4647,12 @@ assign_parms (tree fndecl) Set DECL_RTL to that place. */ - if (nominal_mode == BLKmode || GET_CODE (entry_parm) == PARALLEL) + if (nominal_mode == BLKmode +#ifdef BLOCK_REG_PADDING + || (locate.where_pad == (BYTES_BIG_ENDIAN ? upward : downward) + && GET_MODE_SIZE (promoted_mode) < UNITS_PER_WORD) +#endif + || GET_CODE (entry_parm) == PARALLEL) { /* If a BLKmode arrives in registers, copy it to a stack slot. Handle calls that pass values in multiple non-contiguous @@ -4680,7 +4688,7 @@ assign_parms (tree fndecl) /* 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 (mem, entry_parm, size); + emit_group_store (mem, entry_parm, TREE_TYPE (parm), size); else if (size == 0) ; @@ -4692,7 +4700,13 @@ assign_parms (tree fndecl) enum machine_mode mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0); - if (mode != BLKmode) + if (mode != BLKmode +#ifdef BLOCK_REG_PADDING + && (size == UNITS_PER_WORD + || (BLOCK_REG_PADDING (mode, TREE_TYPE (parm), 1) + != (BYTES_BIG_ENDIAN ? upward : downward))) +#endif + ) { rtx reg = gen_rtx_REG (mode, REGNO (entry_parm)); emit_move_insn (change_address (mem, mode, 0), reg); @@ -4703,7 +4717,13 @@ assign_parms (tree fndecl) to memory. Note that the previous test doesn't handle all cases (e.g. SIZE == 3). */ else if (size != UNITS_PER_WORD - && BYTES_BIG_ENDIAN) +#ifdef BLOCK_REG_PADDING + && (BLOCK_REG_PADDING (mode, TREE_TYPE (parm), 1) + == downward) +#else + && BYTES_BIG_ENDIAN +#endif + ) { rtx tem, x; int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT; @@ -5367,6 +5387,7 @@ locate_and_pad_parm (enum machine_mode passed_mode, tree type, int in_regs, = 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); + locate->where_pad = where_pad; #ifdef ARGS_GROW_DOWNWARD locate->slot_offset.constant = -initial_offset_ptr->constant; @@ -7036,6 +7057,7 @@ expand_function_end (void) emit_group_move (real_decl_rtl, decl_rtl); else emit_group_load (real_decl_rtl, decl_rtl, + TREE_TYPE (decl_result), int_size_in_bytes (TREE_TYPE (decl_result))); } else |