From: Jakub Jelinek Date: Wed, 16 Mar 2011 08:36:42 +0000 (+0100) Subject: calls.c (emit_call_1): Set MEM_EXPR on call's MEM. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=325f5379f113d8ee0a709dc51394ba959245b2a6;p=gcc.git calls.c (emit_call_1): Set MEM_EXPR on call's MEM. * calls.c (emit_call_1): Set MEM_EXPR on call's MEM. * var-tracking.c (prepare_call_arguments): Use MEM_EXPR on call's MEM. Handle functions returning aggregate through a hidden first pointer. For virtual calls add clobbered pc to call arguments chain. * dwarf2out.c (gen_subprogram_die): Emit DW_AT_GNU_call_site_target_clobbered if DW_AT_GNU_call_site_target can't be emitted. From-SVN: r171036 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ea855fe905c..e3934df4e22 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,14 @@ 2011-03-16 Jakub Jelinek + * calls.c (emit_call_1): Set MEM_EXPR on call's MEM. + * var-tracking.c (prepare_call_arguments): Use MEM_EXPR on + call's MEM. Handle functions returning aggregate through a hidden + first pointer. For virtual calls add clobbered pc to call arguments + chain. + * dwarf2out.c (gen_subprogram_die): Emit + DW_AT_GNU_call_site_target_clobbered if DW_AT_GNU_call_site_target + can't be emitted. + PR debug/45882 * rtl.def (ENTRY_VALUE): Change format from "e" to "0". * rtl.h (ENTRY_VALUE_EXP): Define. diff --git a/gcc/calls.c b/gcc/calls.c index b15bfefa3c1..fe99bc065e3 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -256,7 +256,7 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU CUMULATIVE_ARGS *args_so_far ATTRIBUTE_UNUSED) { rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size); - rtx call_insn; + rtx call_insn, call, funmem; int already_popped = 0; HOST_WIDE_INT n_popped = targetm.calls.return_pops_args (fndecl, funtype, stack_size); @@ -271,6 +271,12 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU if (GET_CODE (funexp) != SYMBOL_REF) funexp = memory_address (FUNCTION_MODE, funexp); + funmem = gen_rtx_MEM (FUNCTION_MODE, funexp); + if (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL) + set_mem_expr (funmem, fndecl); + else if (fntree) + set_mem_expr (funmem, build_fold_indirect_ref (CALL_EXPR_FN (fntree))); + #if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop) if ((ecf_flags & ECF_SIBCALL) && HAVE_sibcall_pop && HAVE_sibcall_value_pop @@ -283,13 +289,11 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU if possible, for the sake of frame pointer elimination. */ if (valreg) - pat = GEN_SIBCALL_VALUE_POP (valreg, - gen_rtx_MEM (FUNCTION_MODE, funexp), - rounded_stack_size_rtx, next_arg_reg, - n_pop); + pat = GEN_SIBCALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx, + next_arg_reg, n_pop); else - pat = GEN_SIBCALL_POP (gen_rtx_MEM (FUNCTION_MODE, funexp), - rounded_stack_size_rtx, next_arg_reg, n_pop); + pat = GEN_SIBCALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg, + n_pop); emit_call_insn (pat); already_popped = 1; @@ -316,12 +320,11 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU if possible, for the sake of frame pointer elimination. */ if (valreg) - pat = GEN_CALL_VALUE_POP (valreg, - gen_rtx_MEM (FUNCTION_MODE, funexp), - rounded_stack_size_rtx, next_arg_reg, n_pop); + pat = GEN_CALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx, + next_arg_reg, n_pop); else - pat = GEN_CALL_POP (gen_rtx_MEM (FUNCTION_MODE, funexp), - rounded_stack_size_rtx, next_arg_reg, n_pop); + pat = GEN_CALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg, + n_pop); emit_call_insn (pat); already_popped = 1; @@ -334,13 +337,12 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU && HAVE_sibcall && HAVE_sibcall_value) { if (valreg) - emit_call_insn (GEN_SIBCALL_VALUE (valreg, - gen_rtx_MEM (FUNCTION_MODE, funexp), + emit_call_insn (GEN_SIBCALL_VALUE (valreg, funmem, rounded_stack_size_rtx, next_arg_reg, NULL_RTX)); else - emit_call_insn (GEN_SIBCALL (gen_rtx_MEM (FUNCTION_MODE, funexp), - rounded_stack_size_rtx, next_arg_reg, + emit_call_insn (GEN_SIBCALL (funmem, rounded_stack_size_rtx, + next_arg_reg, GEN_INT (struct_value_size))); } else @@ -350,13 +352,10 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU if (HAVE_call && HAVE_call_value) { if (valreg) - emit_call_insn (GEN_CALL_VALUE (valreg, - gen_rtx_MEM (FUNCTION_MODE, funexp), - rounded_stack_size_rtx, next_arg_reg, - NULL_RTX)); + emit_call_insn (GEN_CALL_VALUE (valreg, funmem, rounded_stack_size_rtx, + next_arg_reg, NULL_RTX)); else - emit_call_insn (GEN_CALL (gen_rtx_MEM (FUNCTION_MODE, funexp), - rounded_stack_size_rtx, next_arg_reg, + emit_call_insn (GEN_CALL (funmem, rounded_stack_size_rtx, next_arg_reg, GEN_INT (struct_value_size))); } else @@ -366,6 +365,19 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU /* Find the call we just emitted. */ call_insn = last_call_insn (); + /* Some target create a fresh MEM instead of reusing the one provided + above. Set its MEM_EXPR. */ + call = PATTERN (call_insn); + if (GET_CODE (call) == PARALLEL) + call = XVECEXP (call, 0, 0); + if (GET_CODE (call) == SET) + call = SET_SRC (call); + if (GET_CODE (call) == CALL + && MEM_P (XEXP (call, 0)) + && MEM_EXPR (XEXP (call, 0)) == NULL_TREE + && MEM_EXPR (funmem) != NULL_TREE) + set_mem_expr (XEXP (call, 0), MEM_EXPR (funmem)); + /* Put the register usage information there. */ add_function_usage_to (call_insn, call_fusage); diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index b4bca785832..38b1422d40f 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -19615,7 +19615,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) for (ca_loc = call_arg_locations; ca_loc; ca_loc = ca_loc->next) { dw_die_ref die = NULL; - rtx tloc = NULL_RTX; + rtx tloc = NULL_RTX, tlocc = NULL_RTX; rtx arg, next_arg; for (arg = NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note); @@ -19644,6 +19644,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) tloc = XEXP (XEXP (arg, 0), 1); continue; } + else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER + && XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx) + { + gcc_assert (ca_loc->symbol_ref == NULL_RTX); + tlocc = XEXP (XEXP (arg, 0), 1); + continue; + } if (REG_P (XEXP (XEXP (arg, 0), 0))) reg = reg_loc_descriptor (XEXP (XEXP (arg, 0), 0), VAR_INIT_STATUS_INITIALIZED); @@ -19677,13 +19684,23 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) if (die == NULL && (ca_loc->symbol_ref || tloc)) die = gen_call_site_die (decl, subr_die, ca_loc); - if (die != NULL && tloc != NULL_RTX) + if (die != NULL && (tloc != NULL_RTX || tlocc != NULL_RTX)) { - dw_loc_descr_ref tval - = mem_loc_descriptor (tloc, VOIDmode, - VAR_INIT_STATUS_INITIALIZED); + dw_loc_descr_ref tval = NULL; + + if (tloc != NULL_RTX) + tval = mem_loc_descriptor (tloc, VOIDmode, + VAR_INIT_STATUS_INITIALIZED); if (tval) add_AT_loc (die, DW_AT_GNU_call_site_target, tval); + else if (tlocc != NULL_RTX) + { + tval = mem_loc_descriptor (tlocc, VOIDmode, + VAR_INIT_STATUS_INITIALIZED); + if (tval) + add_AT_loc (die, DW_AT_GNU_call_site_target_clobbered, + tval); + } } if (die != NULL) { diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 50890d8c0cc..ee180f13f62 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -5576,7 +5576,9 @@ prepare_call_arguments (basic_block bb, rtx insn) rtx link, x; rtx prev, cur, next; rtx call = PATTERN (insn); - tree type = NULL_TREE, t; + rtx this_arg = NULL_RTX; + tree type = NULL_TREE, t, fndecl = NULL_TREE; + tree obj_type_ref = NULL_TREE; CUMULATIVE_ARGS args_so_far; memset (&args_so_far, 0, sizeof (args_so_far)); @@ -5584,27 +5586,91 @@ prepare_call_arguments (basic_block bb, rtx insn) call = XVECEXP (call, 0, 0); if (GET_CODE (call) == SET) call = SET_SRC (call); - if (GET_CODE (call) == CALL - && MEM_P (XEXP (call, 0)) - && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF) - { - rtx symbol = XEXP (XEXP (call, 0), 0); - if (SYMBOL_REF_DECL (symbol) - && TREE_CODE (SYMBOL_REF_DECL (symbol)) == FUNCTION_DECL - && TYPE_ARG_TYPES (TREE_TYPE (SYMBOL_REF_DECL (symbol)))) + if (GET_CODE (call) == CALL && MEM_P (XEXP (call, 0))) + { + if (GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF) + { + rtx symbol = XEXP (XEXP (call, 0), 0); + if (SYMBOL_REF_DECL (symbol)) + fndecl = SYMBOL_REF_DECL (symbol); + } + if (fndecl == NULL_TREE) + fndecl = MEM_EXPR (XEXP (call, 0)); + if (fndecl + && TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE + && TREE_CODE (TREE_TYPE (fndecl)) != METHOD_TYPE) + fndecl = NULL_TREE; + if (fndecl && TYPE_ARG_TYPES (TREE_TYPE (fndecl))) + type = TREE_TYPE (fndecl); + if (fndecl && TREE_CODE (fndecl) != FUNCTION_DECL) + { + if (TREE_CODE (fndecl) == INDIRECT_REF + && TREE_CODE (TREE_OPERAND (fndecl, 0)) == OBJ_TYPE_REF) + obj_type_ref = TREE_OPERAND (fndecl, 0); + fndecl = NULL_TREE; + } + if (type) { - type = TREE_TYPE (SYMBOL_REF_DECL (symbol)); for (t = TYPE_ARG_TYPES (type); t && t != void_list_node; t = TREE_CHAIN (t)) if (TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE && INTEGRAL_TYPE_P (TREE_TYPE (TREE_VALUE (t)))) break; - if (t == NULL || t == void_list_node) + if ((t == NULL || t == void_list_node) && obj_type_ref == NULL_TREE) type = NULL; else - INIT_CUMULATIVE_ARGS (args_so_far, type, NULL_RTX, - SYMBOL_REF_DECL (symbol), - list_length (TYPE_ARG_TYPES (type))); + { + int nargs = list_length (TYPE_ARG_TYPES (type)); + link = CALL_INSN_FUNCTION_USAGE (insn); +#ifndef PCC_STATIC_STRUCT_RETURN + if (aggregate_value_p (TREE_TYPE (type), type) + && targetm.calls.struct_value_rtx (type, 0) == 0) + { + tree struct_addr = build_pointer_type (TREE_TYPE (type)); + enum machine_mode mode = TYPE_MODE (struct_addr); + rtx reg; + INIT_CUMULATIVE_ARGS (args_so_far, type, NULL_RTX, fndecl, + nargs + 1); + reg = targetm.calls.function_arg (&args_so_far, mode, + struct_addr, true); + targetm.calls.function_arg_advance (&args_so_far, mode, + struct_addr, true); + if (reg == NULL_RTX) + { + for (; link; link = XEXP (link, 1)) + if (GET_CODE (XEXP (link, 0)) == USE + && MEM_P (XEXP (XEXP (link, 0), 0))) + { + link = XEXP (link, 1); + break; + } + } + } +#endif + else + INIT_CUMULATIVE_ARGS (args_so_far, type, NULL_RTX, fndecl, + nargs); + if (obj_type_ref && TYPE_ARG_TYPES (type) != void_list_node) + { + enum machine_mode mode; + t = TYPE_ARG_TYPES (type); + mode = TYPE_MODE (TREE_VALUE (t)); + this_arg = targetm.calls.function_arg (&args_so_far, mode, + TREE_VALUE (t), true); + if (this_arg && !REG_P (this_arg)) + this_arg = NULL_RTX; + else if (this_arg == NULL_RTX) + { + for (; link; link = XEXP (link, 1)) + if (GET_CODE (XEXP (link, 0)) == USE + && MEM_P (XEXP (XEXP (link, 0), 0))) + { + this_arg = XEXP (XEXP (link, 0), 0); + break; + } + } + } + } } } t = type ? TYPE_ARG_TYPES (type) : NULL_TREE; @@ -5752,6 +5818,20 @@ prepare_call_arguments (basic_block bb, rtx insn) } } } + if (this_arg) + { + enum machine_mode mode + = TYPE_MODE (TREE_TYPE (OBJ_TYPE_REF_EXPR (obj_type_ref))); + rtx clobbered = gen_rtx_MEM (mode, this_arg); + HOST_WIDE_INT token + = tree_low_cst (OBJ_TYPE_REF_TOKEN (obj_type_ref), 0); + if (token) + clobbered = plus_constant (clobbered, token * GET_MODE_SIZE (mode)); + clobbered = gen_rtx_MEM (mode, clobbered); + x = gen_rtx_CONCAT (mode, gen_rtx_CLOBBER (VOIDmode, pc_rtx), clobbered); + call_arguments + = gen_rtx_EXPR_LIST (VOIDmode, x, call_arguments); + } } /* Callback for cselib_record_sets_hook, that records as micro