X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ffunction.c;h=3721a60c713fa8d4c3e343fdaf9eba76d5be6cfc;hb=341714a96243da1bf4a6852d572d8fe4007ce3ac;hp=8e7eeae372b512c53795392e6b2099a25b719c7d;hpb=13d534046885e06335cbfec13655427f8fa013f5;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/function.c b/gcc/function.c index 8e7eeae372b..3721a60c713 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -45,9 +45,7 @@ Boston, MA 02111-1307, USA. */ #include "flags.h" #include "except.h" #include "function.h" -#include "insn-flags.h" #include "expr.h" -#include "insn-codes.h" #include "regs.h" #include "hard-reg-set.h" #include "insn-config.h" @@ -60,10 +58,6 @@ Boston, MA 02111-1307, USA. */ #include "ggc.h" #include "tm_p.h" -#ifndef ACCUMULATE_OUTGOING_ARGS -#define ACCUMULATE_OUTGOING_ARGS 0 -#endif - #ifndef TRAMPOLINE_ALIGNMENT #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY #endif @@ -126,8 +120,10 @@ int current_function_sp_is_unchanging; int current_function_uses_only_leaf_regs; /* Nonzero once virtual register instantiation has been done. - assign_stack_local uses frame_pointer_rtx when this is nonzero. */ -static int virtuals_instantiated; + assign_stack_local uses frame_pointer_rtx when this is nonzero. + calls.c:emit_library_call_value_1 uses it to set up + post-instantiation libcalls. */ +int virtuals_instantiated; /* These variables hold pointers to functions to create and destroy target specific, per-function data structures. */ @@ -269,6 +265,7 @@ static void optimize_bit_field PARAMS ((rtx, rtx, rtx *)); static void instantiate_decls PARAMS ((tree, int)); static void instantiate_decls_1 PARAMS ((tree, int)); static void instantiate_decl PARAMS ((rtx, HOST_WIDE_INT, int)); +static rtx instantiate_new_reg PARAMS ((rtx, HOST_WIDE_INT *)); static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int)); static void delete_handlers PARAMS ((void)); static void pad_to_arg_alignment PARAMS ((struct args_size *, int, @@ -293,7 +290,7 @@ static int contains PARAMS ((rtx, varray_type)); static void emit_return_into_block PARAMS ((basic_block, rtx)); #endif static void put_addressof_into_stack PARAMS ((rtx, struct hash_table *)); -static boolean purge_addressof_1 PARAMS ((rtx *, rtx, int, int, +static bool purge_addressof_1 PARAMS ((rtx *, rtx, int, int, struct hash_table *)); static void purge_single_hard_subreg_set PARAMS ((rtx)); #ifdef HAVE_epilogue @@ -304,7 +301,7 @@ static struct hash_entry *insns_for_mem_newfunc PARAMS ((struct hash_entry *, struct hash_table *, hash_table_key)); static unsigned long insns_for_mem_hash PARAMS ((hash_table_key)); -static boolean insns_for_mem_comp PARAMS ((hash_table_key, hash_table_key)); +static bool insns_for_mem_comp PARAMS ((hash_table_key, hash_table_key)); static int insns_for_mem_walk PARAMS ((rtx *, void *)); static void compute_insns_for_mem PARAMS ((rtx, rtx, struct hash_table *)); static void mark_temp_slot PARAMS ((struct temp_slot *)); @@ -1337,7 +1334,9 @@ put_var_into_stack (decl) context = decl_function_context (decl); /* Get the current rtl used for this object and its original mode. */ - reg = TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl) : DECL_RTL (decl); + reg = (TREE_CODE (decl) == SAVE_EXPR + ? SAVE_EXPR_RTL (decl) + : DECL_RTL_IF_SET (decl)); /* No need to do anything if decl has no rtx yet since in that case caller is setting TREE_ADDRESSABLE @@ -1583,11 +1582,6 @@ fixup_var_refs (var, promoted_mode, unsignedp, ht) end_sequence (); } } - - /* Scan the catch clauses for exception handling too. */ - push_to_full_sequence (catch_clauses, catch_clauses_last); - fixup_var_refs_insns (catch_clauses, var, promoted_mode, unsignedp, 0); - end_full_sequence (&catch_clauses, &catch_clauses_last); } /* REPLACEMENTS is a pointer to a list of the struct fixup_replacement and X is @@ -1688,7 +1682,7 @@ fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp) rtx insn = XEXP (insn_list, 0); if (INSN_P (insn)) - fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, 0); + fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, 1); insn_list = XEXP (insn_list, 1); } @@ -2150,7 +2144,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements) { replacement = find_fixup_replacement (replacements, var); if (replacement->new == 0) - replacement->new = gen_reg_rtx (GET_MODE (var)); + replacement->new = gen_reg_rtx (promoted_mode); SUBREG_REG (x) = replacement->new; return; } @@ -2184,7 +2178,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements) optimize_bit_field (x, insn, 0); if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT) - optimize_bit_field (x, insn, NULL_PTR); + optimize_bit_field (x, insn, 0); /* For a paradoxical SUBREG inside a ZERO_EXTRACT, load the object into a register and then store it back out. */ @@ -2229,7 +2223,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements) dest = XEXP (dest, 0); if (GET_CODE (src) == SUBREG) - src = XEXP (src, 0); + src = SUBREG_REG (src); /* If VAR does not appear at the top level of the SET just scan the lower levels of the tree. */ @@ -2513,7 +2507,7 @@ fixup_memory_subreg (x, insn, uncritical) rtx insn; int uncritical; { - int offset = SUBREG_WORD (x) * UNITS_PER_WORD; + int offset = SUBREG_BYTE (x); rtx addr = XEXP (SUBREG_REG (x), 0); enum machine_mode mode = GET_MODE (x); rtx result; @@ -2523,9 +2517,6 @@ fixup_memory_subreg (x, insn, uncritical) && ! uncritical) abort (); - if (BYTES_BIG_ENDIAN) - offset += (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) - - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))); addr = plus_constant (addr, offset); if (!flag_force_addr && memory_address_p (mode, addr)) /* Shortcut if no insns need be emitted. */ @@ -2719,7 +2710,8 @@ optimize_bit_field (body, insn, equiv_mem) offset /= BITS_PER_UNIT; if (GET_CODE (XEXP (bitfield, 0)) == SUBREG) { - offset += SUBREG_WORD (XEXP (bitfield, 0)) * UNITS_PER_WORD; + offset += (SUBREG_BYTE (XEXP (bitfield, 0)) + / UNITS_PER_WORD) * UNITS_PER_WORD; if (BYTES_BIG_ENDIAN) offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0)))) @@ -2744,7 +2736,7 @@ optimize_bit_field (body, insn, equiv_mem) { rtx src = SET_SRC (body); while (GET_CODE (src) == SUBREG - && SUBREG_WORD (src) == 0) + && SUBREG_BYTE (src) == 0) src = SUBREG_REG (src); if (GET_MODE (src) != GET_MODE (memref)) src = gen_lowpart (GET_MODE (memref), SET_SRC (body)); @@ -2765,7 +2757,7 @@ optimize_bit_field (body, insn, equiv_mem) rtx dest = SET_DEST (body); while (GET_CODE (dest) == SUBREG - && SUBREG_WORD (dest) == 0 + && SUBREG_BYTE (dest) == 0 && (GET_MODE_CLASS (GET_MODE (dest)) == GET_MODE_CLASS (GET_MODE (SUBREG_REG (dest)))) && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) @@ -2968,7 +2960,7 @@ static rtx purge_addressof_replacements; the stack. If the function returns FALSE then the replacement could not be made. */ -static boolean +static bool purge_addressof_1 (loc, insn, force, store, ht) rtx *loc; rtx insn; @@ -2979,7 +2971,7 @@ purge_addressof_1 (loc, insn, force, store, ht) RTX_CODE code; int i, j; const char *fmt; - boolean result = true; + bool result = true; /* Re-start here to avoid recursion in common cases. */ restart: @@ -2999,14 +2991,19 @@ purge_addressof_1 (loc, insn, force, store, ht) result &= purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht); return result; } - - else if (code == ADDRESSOF && GET_CODE (XEXP (x, 0)) == MEM) + else if (code == ADDRESSOF) { + rtx sub, insns; + + if (GET_CODE (XEXP (x, 0)) != MEM) + { + put_addressof_into_stack (x, ht); + return true; + } + /* We must create a copy of the rtx because it was created by overwriting a REG rtx which is always shared. */ - rtx sub = copy_rtx (XEXP (XEXP (x, 0), 0)); - rtx insns; - + sub = copy_rtx (XEXP (XEXP (x, 0), 0)); if (validate_change (insn, loc, sub, 0) || validate_replace_rtx (x, sub, insn)) return true; @@ -3075,7 +3072,7 @@ purge_addressof_1 (loc, insn, force, store, ht) code did. This is especially true of REG_RETVAL. */ - if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0) + if (GET_CODE (z) == SUBREG && SUBREG_BYTE (z) == 0) z = SUBREG_REG (z); if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD @@ -3218,22 +3215,9 @@ purge_addressof_1 (loc, insn, force, store, ht) } goto restart; } - give_up:; - /* else give up and put it into the stack */ - } - - else if (code == ADDRESSOF) - { - put_addressof_into_stack (x, ht); - return true; - } - else if (code == SET) - { - result = purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht); - result &= purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht); - return result; } + give_up: /* Scan all subexpressions. */ fmt = GET_RTX_FORMAT (code); for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++) @@ -3279,7 +3263,7 @@ insns_for_mem_hash (k) /* Return non-zero if K1 and K2 (two REGs) are the same. */ -static boolean +static bool insns_for_mem_comp (k1, k2) hash_table_key k1; hash_table_key k2; @@ -3451,17 +3435,22 @@ purge_single_hard_subreg_set (pattern) { rtx reg = SET_DEST (pattern); enum machine_mode mode = GET_MODE (SET_DEST (pattern)); - int word = 0; - - while (GET_CODE (reg) == SUBREG) + int offset = 0; + + if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG + && REGNO (SUBREG_REG (reg)) < FIRST_PSEUDO_REGISTER) { - word += SUBREG_WORD (reg); + offset = subreg_regno_offset (REGNO (SUBREG_REG (reg)), + GET_MODE (SUBREG_REG (reg)), + SUBREG_BYTE (reg), + GET_MODE (reg)); reg = SUBREG_REG (reg); } - - if (REGNO (reg) < FIRST_PSEUDO_REGISTER) + + + if (GET_CODE (reg) == REG && REGNO (reg) < FIRST_PSEUDO_REGISTER) { - reg = gen_rtx_REG (mode, REGNO (reg) + word); + reg = gen_rtx_REG (mode, REGNO (reg) + offset); SET_DEST (pattern) = reg; } } @@ -3605,8 +3594,10 @@ instantiate_decls_1 (let, valid_only) tree t; for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t)) - instantiate_decl (DECL_RTL (t), int_size_in_bytes (TREE_TYPE (t)), - valid_only); + if (DECL_RTL_SET_P (t)) + instantiate_decl (DECL_RTL (t), + int_size_in_bytes (TREE_TYPE (t)), + valid_only); /* Process all subblocks. */ for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t)) @@ -3680,6 +3671,35 @@ instantiate_decl (x, size, valid_only) XEXP (x, 0) = addr; } +/* Given a piece of RTX and a pointer to a HOST_WIDE_INT, if the RTX + is a virtual register, return the requivalent hard register and set the + offset indirectly through the pointer. Otherwise, return 0. */ + +static rtx +instantiate_new_reg (x, poffset) + rtx x; + HOST_WIDE_INT *poffset; +{ + rtx new; + HOST_WIDE_INT offset; + + if (x == virtual_incoming_args_rtx) + new = arg_pointer_rtx, offset = in_arg_offset; + else if (x == virtual_stack_vars_rtx) + new = frame_pointer_rtx, offset = var_offset; + else if (x == virtual_stack_dynamic_rtx) + new = stack_pointer_rtx, offset = dynamic_offset; + else if (x == virtual_outgoing_args_rtx) + new = stack_pointer_rtx, offset = out_arg_offset; + else if (x == virtual_cfa_rtx) + new = arg_pointer_rtx, offset = cfa_offset; + else + return 0; + + *poffset = offset; + return new; +} + /* Given a pointer to a piece of rtx and an optional pointer to the containing object, instantiate any virtual registers present in it. @@ -3739,21 +3759,14 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) the actual register should receive the source minus the appropriate offset. This is used, for example, in the handling of non-local gotos. */ - if (SET_DEST (x) == virtual_incoming_args_rtx) - new = arg_pointer_rtx, offset = -in_arg_offset; - else if (SET_DEST (x) == virtual_stack_vars_rtx) - new = frame_pointer_rtx, offset = -var_offset; - else if (SET_DEST (x) == virtual_stack_dynamic_rtx) - new = stack_pointer_rtx, offset = -dynamic_offset; - else if (SET_DEST (x) == virtual_outgoing_args_rtx) - new = stack_pointer_rtx, offset = -out_arg_offset; - else if (SET_DEST (x) == virtual_cfa_rtx) - new = arg_pointer_rtx, offset = -cfa_offset; - - if (new) + if ((new = instantiate_new_reg (SET_DEST (x), &offset)) != 0) { rtx src = SET_SRC (x); + /* We are setting the register, not using it, so the relevant + offset is the negative of the offset to use were we using + the register. */ + offset = - offset; instantiate_virtual_regs_1 (&src, NULL_RTX, 0); /* The only valid sources here are PLUS or REG. Just do @@ -3793,40 +3806,37 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) /* Check for (plus (plus VIRT foo) (const_int)) first. */ if (GET_CODE (XEXP (x, 0)) == PLUS) { - rtx inner = XEXP (XEXP (x, 0), 0); - - if (inner == virtual_incoming_args_rtx) - new = arg_pointer_rtx, offset = in_arg_offset; - else if (inner == virtual_stack_vars_rtx) - new = frame_pointer_rtx, offset = var_offset; - else if (inner == virtual_stack_dynamic_rtx) - new = stack_pointer_rtx, offset = dynamic_offset; - else if (inner == virtual_outgoing_args_rtx) - new = stack_pointer_rtx, offset = out_arg_offset; - else if (inner == virtual_cfa_rtx) - new = arg_pointer_rtx, offset = cfa_offset; + if ((new = instantiate_new_reg (XEXP (XEXP (x, 0), 0), &offset))) + { + instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object, + extra_insns); + new = gen_rtx_PLUS (Pmode, new, XEXP (XEXP (x, 0), 1)); + } else { loc = &XEXP (x, 0); goto restart; } - - instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object, - extra_insns); - new = gen_rtx_PLUS (Pmode, new, XEXP (XEXP (x, 0), 1)); } - else if (XEXP (x, 0) == virtual_incoming_args_rtx) - new = arg_pointer_rtx, offset = in_arg_offset; - else if (XEXP (x, 0) == virtual_stack_vars_rtx) - new = frame_pointer_rtx, offset = var_offset; - else if (XEXP (x, 0) == virtual_stack_dynamic_rtx) - new = stack_pointer_rtx, offset = dynamic_offset; - else if (XEXP (x, 0) == virtual_outgoing_args_rtx) - new = stack_pointer_rtx, offset = out_arg_offset; - else if (XEXP (x, 0) == virtual_cfa_rtx) - new = arg_pointer_rtx, offset = cfa_offset; - else +#ifdef POINTERS_EXTEND_UNSIGNED + /* If we have (plus (subreg (virtual-reg)) (const_int)), we know + we can commute the PLUS and SUBREG because pointers into the + frame are well-behaved. */ + else if (GET_CODE (XEXP (x, 0)) == SUBREG && GET_MODE (x) == ptr_mode + && GET_CODE (XEXP (x, 1)) == CONST_INT + && 0 != (new + = instantiate_new_reg (SUBREG_REG (XEXP (x, 0)), + &offset)) + && validate_change (object, loc, + plus_constant (gen_lowpart (ptr_mode, + new), + offset + + INTVAL (XEXP (x, 1))), + 0)) + return 1; +#endif + else if ((new = instantiate_new_reg (XEXP (x, 0), &offset)) == 0) { /* We know the second operand is a constant. Unless the first operand is a REG (which has been already checked), @@ -4025,18 +4035,7 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) case REG: /* Try to replace with a PLUS. If that doesn't work, compute the sum in front of this insn and substitute the temporary. */ - if (x == virtual_incoming_args_rtx) - new = arg_pointer_rtx, offset = in_arg_offset; - else if (x == virtual_stack_vars_rtx) - new = frame_pointer_rtx, offset = var_offset; - else if (x == virtual_stack_dynamic_rtx) - new = stack_pointer_rtx, offset = dynamic_offset; - else if (x == virtual_outgoing_args_rtx) - new = stack_pointer_rtx, offset = out_arg_offset; - else if (x == virtual_cfa_rtx) - new = arg_pointer_rtx, offset = cfa_offset; - - if (new) + if ((new = instantiate_new_reg (x, &offset)) != 0) { temp = plus_constant (new, offset); if (!validate_change (object, loc, temp, 0)) @@ -4344,8 +4343,8 @@ assign_parms (fndecl) || TREE_CODE (parm) != PARM_DECL || passed_type == NULL) { - DECL_INCOMING_RTL (parm) = DECL_RTL (parm) - = gen_rtx_MEM (BLKmode, const0_rtx); + SET_DECL_RTL (parm, gen_rtx_MEM (BLKmode, const0_rtx)); + DECL_INCOMING_RTL (parm) = DECL_RTL (parm); TREE_USED (parm) = 1; continue; } @@ -4364,7 +4363,8 @@ assign_parms (fndecl) and avoid the usual things like emit_move_insn that could crash. */ if (nominal_mode == VOIDmode) { - DECL_INCOMING_RTL (parm) = DECL_RTL (parm) = const0_rtx; + SET_DECL_RTL (parm, const0_rtx); + DECL_INCOMING_RTL (parm) = DECL_RTL (parm); continue; } @@ -4595,7 +4595,7 @@ assign_parms (fndecl) && GET_CODE (XEXP (XVECEXP (entry_parm, 0, i), 0)) == REG && (GET_MODE (XEXP (XVECEXP (entry_parm, 0, i), 0)) == passed_mode) - && XINT (XEXP (XVECEXP (entry_parm, 0, i), 1), 0) == 0) + && INTVAL (XEXP (XVECEXP (entry_parm, 0, i), 1)) == 0) { entry_parm = XEXP (XVECEXP (entry_parm, 0, i), 0); DECL_INCOMING_RTL (parm) = entry_parm; @@ -4660,7 +4660,7 @@ assign_parms (fndecl) size_stored / UNITS_PER_WORD, int_size_in_bytes (TREE_TYPE (parm))); } - DECL_RTL (parm) = stack_parm; + SET_DECL_RTL (parm, stack_parm); } else if (! ((! optimize && ! DECL_REGISTER (parm) @@ -4692,13 +4692,17 @@ assign_parms (fndecl) appropriately. */ if (passed_pointer) { - DECL_RTL (parm) - = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (passed_type)), parmreg); + SET_DECL_RTL (parm, + gen_rtx_MEM (TYPE_MODE (TREE_TYPE (passed_type)), + parmreg)); set_mem_attributes (DECL_RTL (parm), parm, 1); } else - DECL_RTL (parm) = parmreg; - + { + SET_DECL_RTL (parm, parmreg); + maybe_set_unchanging (DECL_RTL (parm), parm); + } + /* Copy the value into the register. */ if (nominal_mode != passed_mode || promoted_nominal_mode != promoted_mode) @@ -4730,6 +4734,20 @@ assign_parms (fndecl) push_to_sequence (conversion_insns); tempreg = convert_to_mode (nominal_mode, tempreg, unsignedp); + if (GET_CODE (tempreg) == SUBREG + && GET_MODE (tempreg) == nominal_mode + && GET_CODE (SUBREG_REG (tempreg)) == REG + && nominal_mode == passed_mode + && GET_MODE (SUBREG_REG (tempreg)) == GET_MODE (entry_parm) + && GET_MODE_SIZE (GET_MODE (tempreg)) + < GET_MODE_SIZE (GET_MODE (entry_parm))) + { + /* The argument is already sign/zero extended, so note it + into the subreg. */ + SUBREG_PROMOTED_VAR_P (tempreg) = 1; + SUBREG_PROMOTED_UNSIGNED_P (tempreg) = unsignedp; + } + /* TREE_USED gets set erroneously during expand_assignment. */ save_tree_used = TREE_USED (parm); expand_assignment (parm, @@ -4761,12 +4779,13 @@ assign_parms (fndecl) if (GET_MODE (parmreg) != GET_MODE (DECL_RTL (parm))) { rtx tempreg = gen_reg_rtx (GET_MODE (DECL_RTL (parm))); - + int unsigned_p = TREE_UNSIGNED (TREE_TYPE (parm)); push_to_sequence (conversion_insns); emit_move_insn (tempreg, DECL_RTL (parm)); - DECL_RTL (parm) - = convert_to_mode (GET_MODE (parmreg), tempreg, - TREE_UNSIGNED (TREE_TYPE (parm))); + SET_DECL_RTL (parm, + convert_to_mode (GET_MODE (parmreg), + tempreg, + unsigned_p)); emit_move_insn (parmreg, DECL_RTL (parm)); conversion_insns = get_insns(); did_conversion = 1; @@ -4774,7 +4793,7 @@ assign_parms (fndecl) } else emit_move_insn (parmreg, DECL_RTL (parm)); - DECL_RTL (parm) = parmreg; + SET_DECL_RTL (parm, parmreg); /* STACK_PARM is the pointer, not the parm, and PARMREG is now the parm. */ stack_parm = 0; @@ -5009,7 +5028,7 @@ assign_parms (fndecl) conversion_insns = get_insns (); end_sequence (); } - DECL_RTL (parm) = stack_parm; + SET_DECL_RTL (parm, stack_parm); } /* If this "parameter" was the place where we are receiving the @@ -5018,8 +5037,8 @@ assign_parms (fndecl) { tree result = DECL_RESULT (fndecl); - DECL_RTL (result) - = gen_rtx_MEM (DECL_MODE (result), DECL_RTL (parm)); + SET_DECL_RTL (result, + gen_rtx_MEM (DECL_MODE (result), DECL_RTL (parm))); set_mem_attributes (DECL_RTL (result), result, 1); } @@ -5078,7 +5097,9 @@ assign_parms (fndecl) to include tree.h. Do this here so it gets done when an inlined function gets output. */ - current_function_return_rtx = DECL_RTL (DECL_RESULT (fndecl)); + current_function_return_rtx + = (DECL_RTL_SET_P (DECL_RESULT (fndecl)) + ? DECL_RTL (DECL_RESULT (fndecl)) : NULL_RTX); } /* Indicate whether REGNO is an incoming argument to the current function @@ -6188,7 +6209,7 @@ init_function_start (subr, filename, line) /* Make sure first insn is a note even if we don't want linenums. This makes sure the first insn will never be deleted. Also, final expects a note to appear there. */ - emit_note (NULL_PTR, NOTE_INSN_DELETED); + emit_note (NULL, NOTE_INSN_DELETED); /* Set flags used by final.c. */ if (aggregate_value_p (DECL_RESULT (subr))) @@ -6300,20 +6321,10 @@ expand_function_start (subr, parms_have_cleanups) else cleanup_label = 0; - /* Make the label for return statements to jump to, if this machine - does not have a one-instruction return and uses an epilogue, - or if it returns a structure, or if it has parm cleanups. */ -#ifdef HAVE_return - if (cleanup_label == 0 && HAVE_return - && ! current_function_instrument_entry_exit - && ! current_function_returns_pcc_struct - && ! (current_function_returns_struct && ! optimize)) - return_label = 0; - else - return_label = gen_label_rtx (); -#else + /* Make the label for return statements to jump to. Do not special + case machines with special return instructions -- they will be + handled later during jump, ifcvt, or epilogue creation. */ return_label = gen_label_rtx (); -#endif /* Initialize rtx used to return the value. */ /* Do this before assign_parms so that we copy the struct value address @@ -6345,16 +6356,19 @@ expand_function_start (subr, parms_have_cleanups) } if (value_address) { - DECL_RTL (DECL_RESULT (subr)) - = gen_rtx_MEM (DECL_MODE (DECL_RESULT (subr)), value_address); + SET_DECL_RTL (DECL_RESULT (subr), + gen_rtx_MEM (DECL_MODE (DECL_RESULT (subr)), + value_address)); set_mem_attributes (DECL_RTL (DECL_RESULT (subr)), DECL_RESULT (subr), 1); } } else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode) /* If return mode is void, this decl rtl should not be used. */ - DECL_RTL (DECL_RESULT (subr)) = 0; - else if (parms_have_cleanups || current_function_instrument_entry_exit) + SET_DECL_RTL (DECL_RESULT (subr), NULL_RTX); + else if (parms_have_cleanups + || current_function_instrument_entry_exit + || (flag_exceptions && USING_SJLJ_EXCEPTIONS)) { /* If function will end with cleanup code for parms, compute the return values into a pseudo reg, @@ -6370,13 +6384,17 @@ expand_function_start (subr, parms_have_cleanups) mode = promote_mode (type, mode, &unsignedp, 1); #endif - DECL_RTL (DECL_RESULT (subr)) = gen_reg_rtx (mode); + SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (mode)); + /* Needed because we may need to move this to memory + in case it's a named return value whose address is taken. */ + DECL_REGISTER (DECL_RESULT (subr)) = 1; } else - /* Scalar, returned in a register. */ { - DECL_RTL (DECL_RESULT (subr)) - = hard_function_value (TREE_TYPE (DECL_RESULT (subr)), subr, 1); + /* Scalar, returned in a register. */ + SET_DECL_RTL (DECL_RESULT (subr), + hard_function_value (TREE_TYPE (DECL_RESULT (subr)), + subr, 1)); /* Mark this reg as the function's return value. */ if (GET_CODE (DECL_RTL (DECL_RESULT (subr))) == REG) @@ -6404,10 +6422,10 @@ expand_function_start (subr, parms_have_cleanups) The move is supposed to make sdb output more accurate. */ /* Indicate the beginning of the function body, as opposed to parm setup. */ - emit_note (NULL_PTR, NOTE_INSN_FUNCTION_BEG); + emit_note (NULL, NOTE_INSN_FUNCTION_BEG); if (GET_CODE (get_last_insn ()) != NOTE) - emit_note (NULL_PTR, NOTE_INSN_DELETED); + emit_note (NULL, NOTE_INSN_DELETED); parm_birth_insn = get_last_insn (); context_display = 0; @@ -6471,10 +6489,15 @@ expand_function_start (subr, parms_have_cleanups) Pmode); } +#ifdef PROFILE_HOOK + if (profile_flag) + PROFILE_HOOK (profile_label_no); +#endif + /* After the display initializations is where the tail-recursion label should go, if we end up needing one. Ensure we have a NOTE here since some things (like trampolines) get placed before this. */ - tail_recursion_reentry = emit_note (NULL_PTR, NOTE_INSN_DELETED); + tail_recursion_reentry = emit_note (NULL, NOTE_INSN_DELETED); /* Evaluate now the sizes of any types declared among the arguments. */ for (tem = nreverse (get_pending_sizes ()); tem; tem = TREE_CHAIN (tem)) @@ -6732,7 +6755,7 @@ expand_function_end (filename, line, end_bindings) /* Mark the end of the function body. If control reaches this insn, the function can drop through without returning a value. */ - emit_note (NULL_PTR, NOTE_INSN_FUNCTION_END); + emit_note (NULL, NOTE_INSN_FUNCTION_END); /* Must mark the last line number note in the function, so that the test coverage code can avoid counting the last line twice. This just tells @@ -6740,63 +6763,40 @@ expand_function_end (filename, line, end_bindings) already exists a copy of this note somewhere above. This line number note is still needed for debugging though, so we can't delete it. */ if (flag_test_coverage) - emit_note (NULL_PTR, NOTE_INSN_REPEATED_LINE_NUMBER); + emit_note (NULL, NOTE_INSN_REPEATED_LINE_NUMBER); /* Output a linenumber for the end of the function. SDB depends on this. */ emit_line_note_force (filename, line); + /* Before the return label (if any), clobber the return + registers so that they are not propogated live to the rest of + the function. This can only happen with functions that drop + through; if there had been a return statement, there would + have either been a return rtx, or a jump to the return label. */ + { + rtx before, after; + + before = get_last_insn (); + clobber_return_register (); + after = get_last_insn (); + + if (before != after) + cfun->x_clobber_return_insn = after; + } + /* Output the label for the actual return from the function, if one is expected. This happens either because a function epilogue is used instead of a return instruction, or because a return was done with a goto in order to run local cleanups, or because of pcc-style structure returning. */ - if (return_label) - { - rtx before, after; - - /* Before the return label, clobber the return registers so that - they are not propogated live to the rest of the function. This - can only happen with functions that drop through; if there had - been a return statement, there would have either been a return - rtx, or a jump to the return label. */ - - before = get_last_insn (); - clobber_return_register (); - after = get_last_insn (); - - if (before != after) - cfun->x_clobber_return_insn = after; - - emit_label (return_label); - } + emit_label (return_label); /* C++ uses this. */ 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 there are any catch_clauses remaining, output them now. */ - emit_insns (catch_clauses); - catch_clauses = catch_clauses_last = NULL_RTX; - /* 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 (current_function_instrument_entry_exit) { rtx fun = DECL_RTL (current_function_decl); @@ -6812,6 +6812,11 @@ expand_function_end (filename, line, end_bindings) Pmode); } + /* Let except.c know where it should emit the call to unregister + the function context for sjlj exceptions. */ + 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. */ @@ -6829,7 +6834,7 @@ expand_function_end (filename, line, end_bindings) /* 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. */ - if (DECL_RTL (DECL_RESULT (current_function_decl)) != 0) + if (DECL_RTL_SET_P (DECL_RESULT (current_function_decl))) { tree decl_result = DECL_RESULT (current_function_decl); rtx decl_rtl = DECL_RTL (decl_result); @@ -6870,6 +6875,10 @@ expand_function_end (filename, line, end_bindings) convert_move (real_decl_rtl, decl_rtl, unsignedp); } + else if (GET_CODE (real_decl_rtl) == PARALLEL) + emit_group_load (real_decl_rtl, decl_rtl, + int_size_in_bytes (TREE_TYPE (decl_result)), + TYPE_ALIGN (TREE_TYPE (decl_result))); else emit_move_insn (real_decl_rtl, decl_rtl); @@ -6919,16 +6928,16 @@ expand_function_end (filename, line, end_bindings) current_function_return_rtx = outgoing; } + /* If this is an implementation of throw, do what's necessary to + communicate between __builtin_eh_return and the epilogue. */ + expand_eh_return (); + /* ??? 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 instead of using the general framework. */ use_return_register (); - /* If this is an implementation of __throw, do what's necessary to - communicate between __builtin_eh_return and the epilogue. */ - expand_eh_return (); - /* Output a return insn if we are using one. Otherwise, let the rtl chain end here, to drop through into the epilogue. */ @@ -7367,7 +7376,13 @@ epilogue_done: there are line number notes before where we inserted the prologue we should move them, and (2) we should generate a note before the end of the first basic block, if there isn't - one already there. */ + one already there. + + ??? This behaviour is completely broken when dealing with + multiple entry functions. We simply place the note always + into first basic block and let alternate entry points + to be missed. + */ for (insn = prologue_end; insn; insn = prev) { @@ -7385,7 +7400,7 @@ epilogue_done: /* Find the last line number note in the first block. */ for (insn = BASIC_BLOCK (0)->end; - insn != prologue_end; + insn != prologue_end && insn; insn = PREV_INSN (insn)) if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) break; @@ -7470,6 +7485,9 @@ reposition_prologue_and_epilogue_notes (f) BLOCK_HEAD (0) = next; remove_insn (note); + /* Avoid placing note between CODE_LABEL and BASIC_BLOCK note. */ + if (GET_CODE (insn) == CODE_LABEL) + insn = NEXT_INSN (insn); add_insn_after (note, insn); } }