diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 630eab1268e..fed571d55e7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2010-12-22 Alexandre Oliva + + PR debug/46724 + * function.c (assign_parms_augmented_arg_list): Name and mark + DECL of result address as NAMELESS rather than IGNORED. + (assign_parms): Set DECL_VALUE_EXPR for indirect result. + * tree.h (tree_decl_common::decl_flag_2): Document RESULT_DECL. + (DECL_HAS_VALUE_EXPR_P): Accept RESULT_DECL. + * dwarf2out.c (loc_list_from_tree) : Use + DECL_VALUE_EXPR. + * dbxout.c (dbxout_expand_expr) : Likewise. + * var-tracking.c (vt_add_function_parameter): New, split out of... + (vt_add_function_parameters): ... this. Handle incoming + pointer to hold result. + 2010-12-22 Jie Zhang * config/arm/arm.c (output_move_double): Update the comment diff --git a/gcc/dbxout.c b/gcc/dbxout.c index 89ea0f36090..3b0cf342f5e 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -2396,12 +2396,12 @@ dbxout_expand_expr (tree expr) /* FALLTHRU */ case PARM_DECL: + case RESULT_DECL: if (DECL_HAS_VALUE_EXPR_P (expr)) return dbxout_expand_expr (DECL_VALUE_EXPR (expr)); /* FALLTHRU */ case CONST_DECL: - case RESULT_DECL: return DECL_RTL_IF_SET (expr); case INTEGER_CST: diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 1fa33001a77..bc218752ddf 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -15446,12 +15446,12 @@ loc_list_from_tree (tree loc, int want_address) /* FALLTHRU */ case PARM_DECL: + case RESULT_DECL: if (DECL_HAS_VALUE_EXPR_P (loc)) return loc_list_from_tree (DECL_VALUE_EXPR (loc), want_address); /* FALLTHRU */ - case RESULT_DECL: case FUNCTION_DECL: { rtx rtl; diff --git a/gcc/function.c b/gcc/function.c index 7fa3b0c0aac..0c4d5f82464 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -2253,10 +2253,11 @@ assign_parms_augmented_arg_list (struct assign_parm_data_all *all) tree decl; decl = build_decl (DECL_SOURCE_LOCATION (fndecl), - PARM_DECL, NULL_TREE, type); + PARM_DECL, get_identifier (".result_ptr"), type); DECL_ARG_TYPE (decl) = type; DECL_ARTIFICIAL (decl) = 1; - DECL_IGNORED_P (decl) = 1; + DECL_NAMELESS (decl) = 1; + TREE_CONSTANT (decl) = 1; DECL_CHAIN (decl) = all->orig_fnargs; all->orig_fnargs = decl; @@ -3418,13 +3419,22 @@ assign_parms (tree fndecl) rtx x; if (DECL_BY_REFERENCE (result)) - x = addr; + { + SET_DECL_VALUE_EXPR (result, all.function_result_decl); + x = addr; + } else { + SET_DECL_VALUE_EXPR (result, + build1 (INDIRECT_REF, TREE_TYPE (result), + all.function_result_decl)); addr = convert_memory_address (Pmode, addr); x = gen_rtx_MEM (DECL_MODE (result), addr); set_mem_attributes (x, result, 1); } + + DECL_HAS_VALUE_EXPR_P (result) = 1; + SET_DECL_RTL (result, x); } diff --git a/gcc/tree.h b/gcc/tree.h index 8ba20449720..216f3d27ff0 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2773,7 +2773,8 @@ struct GTY(()) tree_decl_common { In TYPE_DECL, this is TYPE_DECL_SUPPRESS_DEBUG. */ unsigned decl_flag_1 : 1; /* In FIELD_DECL, this is DECL_NONADDRESSABLE_P - In VAR_DECL and PARM_DECL, this is DECL_HAS_VALUE_EXPR_P. */ + In VAR_DECL, PARM_DECL and RESULT_DECL, this is + DECL_HAS_VALUE_EXPR_P. */ unsigned decl_flag_2 : 1; /* Logically, these two would go in a theoretical base shared by var and parm decl. */ @@ -2818,7 +2819,8 @@ extern void decl_value_expr_insert (tree, tree); decl itself. This should only be used for debugging; once this field has been set, the decl itself may not legitimately appear in the function. */ #define DECL_HAS_VALUE_EXPR_P(NODE) \ - (TREE_CHECK2 (NODE, VAR_DECL, PARM_DECL)->decl_common.decl_flag_2) + (TREE_CHECK3 (NODE, VAR_DECL, PARM_DECL, RESULT_DECL) \ + ->decl_common.decl_flag_2) #define DECL_VALUE_EXPR(NODE) \ (decl_value_expr_lookup (DECL_WRTL_CHECK (NODE))) #define SET_DECL_VALUE_EXPR(NODE, VAL) \ diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 44701be12e8..58dce1b654e 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -7999,6 +7999,113 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp) return false; } +/* Insert function parameter PARM in IN and OUT sets of ENTRY_BLOCK. */ + +static void +vt_add_function_parameter (tree parm) +{ + rtx decl_rtl = DECL_RTL_IF_SET (parm); + rtx incoming = DECL_INCOMING_RTL (parm); + tree decl; + enum machine_mode mode; + HOST_WIDE_INT offset; + dataflow_set *out; + decl_or_value dv; + + if (TREE_CODE (parm) != PARM_DECL) + return; + + if (!decl_rtl || !incoming) + return; + + if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode) + return; + + if (!vt_get_decl_and_offset (incoming, &decl, &offset)) + { + if (REG_P (incoming) || MEM_P (incoming)) + { + /* This means argument is passed by invisible reference. */ + offset = 0; + decl = parm; + incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming); + } + else + { + if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset)) + return; + offset += byte_lowpart_offset (GET_MODE (incoming), + GET_MODE (decl_rtl)); + } + } + + if (!decl) + return; + + if (parm != decl) + { + /* Assume that DECL_RTL was a pseudo that got spilled to + memory. The spill slot sharing code will force the + memory to reference spill_slot_decl (%sfp), so we don't + match above. That's ok, the pseudo must have referenced + the entire parameter, so just reset OFFSET. */ + gcc_assert (decl == get_spill_slot_decl (false)); + offset = 0; + } + + if (!track_loc_p (incoming, parm, offset, false, &mode, &offset)) + return; + + out = &VTI (ENTRY_BLOCK_PTR)->out; + + dv = dv_from_decl (parm); + + if (target_for_debug_bind (parm) + /* We can't deal with these right now, because this kind of + variable is single-part. ??? We could handle parallels + that describe multiple locations for the same single + value, but ATM we don't. */ + && GET_CODE (incoming) != PARALLEL) + { + cselib_val *val; + + /* ??? We shouldn't ever hit this, but it may happen because + arguments passed by invisible reference aren't dealt with + above: incoming-rtl will have Pmode rather than the + expected mode for the type. */ + if (offset) + return; + + val = cselib_lookup (var_lowpart (mode, incoming), mode, true); + + /* ??? Float-typed values in memory are not handled by + cselib. */ + if (val) + { + preserve_value (val); + set_variable_part (out, val->val_rtx, dv, offset, + VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); + dv = dv_from_value (val->val_rtx); + } + } + + if (REG_P (incoming)) + { + incoming = var_lowpart (mode, incoming); + gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER); + attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset, + incoming); + set_variable_part (out, incoming, dv, offset, + VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); + } + else if (MEM_P (incoming)) + { + incoming = var_lowpart (mode, incoming); + set_variable_part (out, incoming, dv, offset, + VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); + } +} + /* Insert function parameters to IN and OUT sets of ENTRY_BLOCK. */ static void @@ -8008,110 +8115,20 @@ vt_add_function_parameters (void) for (parm = DECL_ARGUMENTS (current_function_decl); parm; parm = DECL_CHAIN (parm)) + vt_add_function_parameter (parm); + + if (DECL_HAS_VALUE_EXPR_P (DECL_RESULT (current_function_decl))) { - rtx decl_rtl = DECL_RTL_IF_SET (parm); - rtx incoming = DECL_INCOMING_RTL (parm); - tree decl; - enum machine_mode mode; - HOST_WIDE_INT offset; - dataflow_set *out; - decl_or_value dv; + tree vexpr = DECL_VALUE_EXPR (DECL_RESULT (current_function_decl)); - if (TREE_CODE (parm) != PARM_DECL) - continue; + if (TREE_CODE (vexpr) == INDIRECT_REF) + vexpr = TREE_OPERAND (vexpr, 0); - if (!DECL_NAME (parm)) - continue; - - if (!decl_rtl || !incoming) - continue; - - if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode) - continue; - - if (!vt_get_decl_and_offset (incoming, &decl, &offset)) - { - if (REG_P (incoming) || MEM_P (incoming)) - { - /* This means argument is passed by invisible reference. */ - offset = 0; - decl = parm; - incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming); - } - else - { - if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset)) - continue; - offset += byte_lowpart_offset (GET_MODE (incoming), - GET_MODE (decl_rtl)); - } - } - - if (!decl) - continue; - - if (parm != decl) - { - /* Assume that DECL_RTL was a pseudo that got spilled to - memory. The spill slot sharing code will force the - memory to reference spill_slot_decl (%sfp), so we don't - match above. That's ok, the pseudo must have referenced - the entire parameter, so just reset OFFSET. */ - gcc_assert (decl == get_spill_slot_decl (false)); - offset = 0; - } - - if (!track_loc_p (incoming, parm, offset, false, &mode, &offset)) - continue; - - out = &VTI (ENTRY_BLOCK_PTR)->out; - - dv = dv_from_decl (parm); - - if (target_for_debug_bind (parm) - /* We can't deal with these right now, because this kind of - variable is single-part. ??? We could handle parallels - that describe multiple locations for the same single - value, but ATM we don't. */ - && GET_CODE (incoming) != PARALLEL) - { - cselib_val *val; - - /* ??? We shouldn't ever hit this, but it may happen because - arguments passed by invisible reference aren't dealt with - above: incoming-rtl will have Pmode rather than the - expected mode for the type. */ - if (offset) - continue; - - val = cselib_lookup (var_lowpart (mode, incoming), mode, true); - - /* ??? Float-typed values in memory are not handled by - cselib. */ - if (val) - { - preserve_value (val); - set_variable_part (out, val->val_rtx, dv, offset, - VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); - dv = dv_from_value (val->val_rtx); - } - } - - if (REG_P (incoming)) - { - incoming = var_lowpart (mode, incoming); - gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER); - attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset, - incoming); - set_variable_part (out, incoming, dv, offset, - VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); - } - else if (MEM_P (incoming)) - { - incoming = var_lowpart (mode, incoming); - set_variable_part (out, incoming, dv, offset, - VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); - } + if (TREE_CODE (vexpr) == PARM_DECL + && DECL_ARTIFICIAL (vexpr) + && !DECL_IGNORED_P (vexpr) + && DECL_NAMELESS (vexpr)) + vt_add_function_parameter (vexpr); } if (MAY_HAVE_DEBUG_INSNS)