From patchwork Fri Mar 3 18:00:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 65986 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 81E6D3858004 for ; Fri, 3 Mar 2023 18:00:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 81E6D3858004 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1677866445; bh=hole1elLWJfHwIJvZESyrx2Yd9iWGeomhQ+EJlpjdMw=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=gLA3v1MA1ET/Hg6kzSl4cE1GyQC1Db+3QRdNfQD7gVSMj/Z0GGDnRtktXf3TYoN1G 9MxO3Vhd357BLayb8kfI9phcnoGHY0km9faQY4tBvPU5T2Z3XVpbMAwxqlbjjuZhFi NL9qnxjMLmCis99qL/Ac3SwsogYdV3fuxP7OdTuk= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from rock.gnat.com (rock.gnat.com [205.232.38.15]) by sourceware.org (Postfix) with ESMTPS id F34173858CDB; Fri, 3 Mar 2023 18:00:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F34173858CDB Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id D0B8E11656A; Fri, 3 Mar 2023 13:00:13 -0500 (EST) X-Virus-Scanned: Debian amavisd-new at gnat.com Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id t+AizWX7vOCP; Fri, 3 Mar 2023 13:00:13 -0500 (EST) Received: from free.home (tron.gnat.com [IPv6:2620:20:4000:0:46a8:42ff:fe0e:e294]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by rock.gnat.com (Postfix) with ESMTPS id D3BDF1165A3; Fri, 3 Mar 2023 13:00:10 -0500 (EST) Received: from livre (livre.home [172.31.160.2]) by free.home (8.15.2/8.15.2) with ESMTPS id 323I020L606608 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 3 Mar 2023 15:00:02 -0300 To: gcc-patches@gcc.gnu.org Cc: Tom Tromey , David Edelsohn , Segher Boessenkool , Kewen Lin , Jason Merrill , Cary Coutant , Jakub Jelinek Subject: [PATCH] [rs6000] adjust return_pc debug attrs Organization: Free thinker, does not speak for AdaCore Date: Fri, 03 Mar 2023 15:00:02 -0300 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Alexandre Oliva via Gcc-patches From: Alexandre Oliva Reply-To: Alexandre Oliva Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Some of the rs6000 call patterns, on some ABIs, issue multiple opcodes out of a single call insn, but the call (bl) or jump (b) is not always the last opcode in the sequence. This does not seem to be a problem for exception handling tables, but the return_pc attribute in the call graph output in dwarf2+ debug information, that takes the address of a label output right after the call, does not match the value of the link register even for non-tail calls. E.g., with ABI_AIX or ABI_ELFv2, such code as: foo (); outputs: bl foo nop LVL#: [...] .8byte .LVL# # DW_AT_call_return_pc but debug info consumers may rely on the return_pc address, and draw incorrect conclusions from its off-by-4 value. This patch introduces infrastructure for targets to add an offset to the label issued after the call_insn to set the call_return_pc attribute, and uses that on rs6000 to account for nop and l opcodes issued after actual call opcode as part of call insns output patterns. for gcc/ChangeLog * target.def (call_offset_return_label): New hook. * gcc/doc/tm.texi.in (TARGET_CALL_OFFSET_RETURN_LABEL): Add placeholder. * gcc/doc/tm.texi: Rebuild. * dwarf2out.cc (struct call_arg_loc_node): Record call_insn instad of call_arg_loc_note. (add_AT_lbl_id): Add optional offset argument. (gen_call_site_die): Compute and pass on a return pc offset. (gen_subprogram_die): Move call_arg_loc_note computation... (dwarf2out_var_location): ... from here. Set call_insn. * config/rs6000/rs6000.cc (TARGET_CALL_OFFSET_RETURN_LABEL): Override. (rs6000_call_offset_return_label): New. * config/rs6000/rs6000.md (call_needs_return_offset): New attribute. Set it on call patterns that may require offsetting. --- gcc/config/rs6000/rs6000.cc | 37 +++++++++++++++++++++++++++++++++++++ gcc/config/rs6000/rs6000.md | 24 ++++++++++++++++++++++++ gcc/doc/tm.texi | 7 +++++++ gcc/doc/tm.texi.in | 2 ++ gcc/dwarf2out.cc | 26 +++++++++++++++++--------- gcc/target.def | 9 +++++++++ 6 files changed, 96 insertions(+), 9 deletions(-) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 8e0b0d022db2f..edbc7a011886c 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -1760,6 +1760,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_UPDATE_IPA_FN_TARGET_INFO #define TARGET_UPDATE_IPA_FN_TARGET_INFO rs6000_update_ipa_fn_target_info + +#undef TARGET_CALL_OFFSET_RETURN_LABEL +#define TARGET_CALL_OFFSET_RETURN_LABEL rs6000_call_offset_return_label /* Processor table. */ @@ -14593,6 +14596,40 @@ rs6000_assemble_integer (rtx x, unsigned int size, int aligned_p) return default_assemble_integer (x, size, aligned_p); } +/* Return the offset to be added to the label output after CALL_INSN + to compute the address to be placed in DW_AT_call_return_pc. Some + call insns output nop or l after bl, so the return address would be + wrong without this offset. */ + +static int +rs6000_call_offset_return_label (rtx_insn *call_insn) +{ + /* We don't expect SEQUENCEs in this port. */ + gcc_checking_assert (GET_CODE (call_insn) == CALL_INSN); + + enum attr_call_needs_return_offset cnro + = get_attr_call_needs_return_offset (call_insn); + + if (cnro == CALL_NEEDS_RETURN_OFFSET_NONE) + return 0; + + if (rs6000_pcrel_p ()) + return 0; + else if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) + /* rs6000_call_template_1 outputs a nop after non-sibcall insns; + we mark sibcall insns with NONE rather than DIRECT, so we + should have returned zero above. + rs6000_indirect_call_template_1 outputs an l insn after + indirect calls in these ABIs. */ + return -4; + else if (DEFAULT_ABI == ABI_V4) + return 0; + else if (DEFAULT_ABI == ABI_DARWIN) + return 0; + else + return 0; +} + /* Return a template string for assembly to emit when making an external call. FUNOP is the call mem argument operand number. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 81bffb04ceb0c..7dc73b21af731 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -342,6 +342,12 @@ (define_attr "max_prefixed_insns" "" (const_int 1)) ;; num_insns and recurse). (define_attr "length" "" (const_int 4)) +;; Calls that output insns after bl need DW_AT_call_return_pc to be +;; adjusted. rs6000_call_offset_return_label uses this attribute to +;; conservatively recognize the relevant patterns. +(define_attr "call_needs_return_offset" "none,direct,indirect" + (const_string "none")) + ;; Processor type -- this attribute must exactly match the processor_type ;; enumeration in rs6000-opts.h. (define_attr "cpu" @@ -11355,6 +11361,7 @@ (define_insn "*call_indirect_nonlocal_sysv" return rs6000_indirect_call_template (operands, 0); } [(set_attr "type" "jmpreg") + (set_attr "call_needs_return_offset" "indirect") (set (attr "length") (cond [(and (and (match_test "!rs6000_speculate_indirect_jumps") (match_test "which_alternative != 1")) @@ -11384,6 +11391,7 @@ (define_insn "*call_nonlocal_sysv" return rs6000_call_template (operands, 0); } [(set_attr "type" "branch,branch") + (set_attr "call_needs_return_offset" "direct") (set_attr "length" "4,8")]) (define_insn "*call_nonlocal_sysv_secure" @@ -11405,6 +11413,7 @@ (define_insn "*call_nonlocal_sysv_secure" return rs6000_call_template (operands, 0); } [(set_attr "type" "branch,branch") + (set_attr "call_needs_return_offset" "direct") (set_attr "length" "4,8")]) (define_insn "*call_value_indirect_nonlocal_sysv" @@ -11425,6 +11434,7 @@ (define_insn "*call_value_indirect_nonlocal_sysv" return rs6000_indirect_call_template (operands, 1); } [(set_attr "type" "jmpreg") + (set_attr "call_needs_return_offset" "indirect") (set (attr "length") (plus (if_then_else (match_test "IS_V4_FP_ARGS (operands[3])") @@ -11454,6 +11464,7 @@ (define_insn "*call_value_nonlocal_sysv" return rs6000_call_template (operands, 1); } [(set_attr "type" "branch") + (set_attr "call_needs_return_offset" "direct") (set (attr "length") (if_then_else (match_test "IS_V4_FP_ARGS (operands[3])") (const_int 8) @@ -11479,6 +11490,7 @@ (define_insn "*call_value_nonlocal_sysv_secure" return rs6000_call_template (operands, 1); } [(set_attr "type" "branch") + (set_attr "call_needs_return_offset" "direct") (set (attr "length") (if_then_else (match_test "IS_V4_FP_ARGS (operands[3])") (const_int 8) @@ -11498,6 +11510,7 @@ (define_insn "*call_nonlocal_aix" return rs6000_call_template (operands, 0); } [(set_attr "type" "branch") + (set_attr "call_needs_return_offset" "direct") (set (attr "length") (if_then_else (match_test "rs6000_pcrel_p ()") (const_int 4) @@ -11515,6 +11528,7 @@ (define_insn "*call_value_nonlocal_aix" return rs6000_call_template (operands, 1); } [(set_attr "type" "branch") + (set_attr "call_needs_return_offset" "direct") (set (attr "length") (if_then_else (match_test "rs6000_pcrel_p ()") (const_int 4) @@ -11537,6 +11551,7 @@ (define_insn "*call_indirect_aix" return rs6000_indirect_call_template (operands, 0); } [(set_attr "type" "jmpreg") + (set_attr "call_needs_return_offset" "indirect") (set (attr "length") (if_then_else (and (match_test "!rs6000_speculate_indirect_jumps") (match_test "which_alternative != 1")) @@ -11558,6 +11573,7 @@ (define_insn "*call_value_indirect_aix" return rs6000_indirect_call_template (operands, 1); } [(set_attr "type" "jmpreg") + (set_attr "call_needs_return_offset" "indirect") (set (attr "length") (if_then_else (and (match_test "!rs6000_speculate_indirect_jumps") (match_test "which_alternative != 1")) @@ -11579,6 +11595,7 @@ (define_insn "*call_indirect_elfv2" return rs6000_indirect_call_template (operands, 0); } [(set_attr "type" "jmpreg") + (set_attr "call_needs_return_offset" "indirect") (set (attr "length") (if_then_else (and (match_test "!rs6000_speculate_indirect_jumps") (match_test "which_alternative != 1")) @@ -11595,6 +11612,7 @@ (define_insn "*call_indirect_pcrel" return rs6000_indirect_call_template (operands, 0); } [(set_attr "type" "jmpreg") + (set_attr "call_needs_return_offset" "indirect") (set (attr "length") (if_then_else (and (match_test "!rs6000_speculate_indirect_jumps") (match_test "which_alternative != 1")) @@ -11615,6 +11633,7 @@ (define_insn "*call_value_indirect_elfv2" return rs6000_indirect_call_template (operands, 1); } [(set_attr "type" "jmpreg") + (set_attr "call_needs_return_offset" "indirect") (set (attr "length") (if_then_else (and (match_test "!rs6000_speculate_indirect_jumps") (match_test "which_alternative != 1")) @@ -11632,6 +11651,7 @@ (define_insn "*call_value_indirect_pcrel" return rs6000_indirect_call_template (operands, 1); } [(set_attr "type" "jmpreg") + (set_attr "call_needs_return_offset" "indirect") (set (attr "length") (if_then_else (and (match_test "!rs6000_speculate_indirect_jumps") (match_test "which_alternative != 1")) @@ -11783,6 +11803,7 @@ (define_insn "*sibcall_indirect_nonlocal_sysv" return rs6000_indirect_sibcall_template (operands, 0); } [(set_attr "type" "jmpreg") + (set_attr "call_needs_return_offset" "indirect") (set (attr "length") (cond [(and (and (match_test "!rs6000_speculate_indirect_jumps") (match_test "which_alternative != 1")) @@ -11812,6 +11833,7 @@ (define_insn "*sibcall_nonlocal_sysv" return rs6000_sibcall_template (operands, 0); } [(set_attr "type" "branch") + (set_attr "call_needs_return_offset" "none") (set_attr "length" "4,8")]) (define_insn "*sibcall_value_indirect_nonlocal_sysv" @@ -11832,6 +11854,7 @@ (define_insn "*sibcall_value_indirect_nonlocal_sysv" return rs6000_indirect_sibcall_template (operands, 1); } [(set_attr "type" "jmpreg") + (set_attr "call_needs_return_offset" "indirect") (set (attr "length") (cond [(and (and (match_test "!rs6000_speculate_indirect_jumps") (match_test "which_alternative != 1")) @@ -11862,6 +11885,7 @@ (define_insn "*sibcall_value_nonlocal_sysv" return rs6000_sibcall_template (operands, 1); } [(set_attr "type" "branch") + (set_attr "call_needs_return_offset" "none") (set_attr "length" "4,8")]) ;; AIX ABI sibling call patterns. diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index ec90c46ea2ffd..16bb089a9a657 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -5426,6 +5426,13 @@ except the last are treated as named. You need not define this hook if it always returns @code{false}. @end deftypefn +@deftypefn {Target Hook} int TARGET_CALL_OFFSET_RETURN_LABEL (rtx_insn *@var{call_insn}) +While generating call-site debug info for a CALL insn, or a SEQUENCE +insn starting with a CALL, this target hook is invoked to compute the +offset to be added to the debug label emitted after the call to obtain +the return address that should be recorded as the return PC. +@end deftypefn + @deftypefn {Target Hook} void TARGET_CALL_ARGS (rtx, @var{tree}) While generating RTL for a function call, this target hook is invoked once for each argument passed to the function, either a register returned by diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 930b109863f23..1706965e9a0cd 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3785,6 +3785,8 @@ These machine description macros help implement varargs: @hook TARGET_STRICT_ARGUMENT_NAMING +@hook TARGET_CALL_OFFSET_RETURN_LABEL + @hook TARGET_CALL_ARGS @hook TARGET_END_CALL_ARGS diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index 1f39df3b1e250..b706c36b87af6 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -3584,7 +3584,7 @@ typedef struct var_loc_list_def var_loc_list; /* Call argument location list. */ struct GTY ((chain_next ("%h.next"))) call_arg_loc_node { - rtx GTY (()) call_arg_loc_note; + rtx_insn * GTY (()) call_insn; const char * GTY (()) label; tree GTY (()) block; bool tail_call_p; @@ -3768,7 +3768,8 @@ static void remove_addr_table_entry (addr_table_entry *); static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx, bool); static inline rtx AT_addr (dw_attr_node *); static void add_AT_symview (dw_die_ref, enum dwarf_attribute, const char *); -static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *); +static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *, + int = 0); static void add_AT_lineptr (dw_die_ref, enum dwarf_attribute, const char *); static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *); static void add_AT_range_list (dw_die_ref, enum dwarf_attribute, @@ -5327,14 +5328,17 @@ add_AT_symview (dw_die_ref die, enum dwarf_attribute attr_kind, static inline void add_AT_lbl_id (dw_die_ref die, enum dwarf_attribute attr_kind, - const char *lbl_id) + const char *lbl_id, int offset) { dw_attr_node attr; attr.dw_attr = attr_kind; attr.dw_attr_val.val_class = dw_val_class_lbl_id; attr.dw_attr_val.val_entry = NULL; - attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_id); + if (!offset) + attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_id); + else + attr.dw_attr_val.v.val_lbl_id = xasprintf ("%s%+i", lbl_id, offset); if (dwarf_split_debug_info) attr.dw_attr_val.val_entry = add_addr_table_entry (attr.dw_attr_val.v.val_lbl_id, @@ -23405,7 +23409,9 @@ gen_call_site_die (tree decl, dw_die_ref subr_die, if (stmt_die == NULL) stmt_die = subr_die; die = new_die (dwarf_TAG (DW_TAG_call_site), stmt_die, NULL_TREE); - add_AT_lbl_id (die, dwarf_AT (DW_AT_call_return_pc), ca_loc->label); + add_AT_lbl_id (die, dwarf_AT (DW_AT_call_return_pc), + ca_loc->label, + targetm.calls.call_offset_return_label (ca_loc->call_insn)); if (ca_loc->tail_call_p) add_AT_flag (die, dwarf_AT (DW_AT_call_tail_call), 1); if (ca_loc->symbol_ref) @@ -24092,11 +24098,14 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) { dw_die_ref die = NULL; rtx tloc = NULL_RTX, tlocc = NULL_RTX; + rtx call_arg_loc_note + = find_reg_note (ca_loc->call_insn, + REG_CALL_ARG_LOCATION, NULL_RTX); rtx arg, next_arg; tree arg_decl = NULL_TREE; - for (arg = (ca_loc->call_arg_loc_note != NULL_RTX - ? XEXP (ca_loc->call_arg_loc_note, 0) + for (arg = (call_arg_loc_note != NULL_RTX + ? XEXP (call_arg_loc_note, 0) : NULL_RTX); arg; arg = next_arg) { @@ -28122,8 +28131,7 @@ create_label: = ggc_cleared_alloc (); rtx_insn *prev = call_insn; - ca_loc->call_arg_loc_note - = find_reg_note (call_insn, REG_CALL_ARG_LOCATION, NULL_RTX); + ca_loc->call_insn = call_insn; ca_loc->next = NULL; ca_loc->label = last_label; gcc_assert (prev diff --git a/gcc/target.def b/gcc/target.def index 4b2c53aba14e6..a5c2046e98250 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4738,6 +4738,15 @@ not generate any instructions in this case.", int *pretend_args_size, int second_time), default_setup_incoming_varargs) +DEFHOOK +(call_offset_return_label, + "While generating call-site debug info for a CALL insn, or a SEQUENCE\n\ +insn starting with a CALL, this target hook is invoked to compute the\n\ +offset to be added to the debug label emitted after the call to obtain\n\ +the return address that should be recorded as the return PC.", + int, (rtx_insn *call_insn), + hook_int_rtx_insn_0) + DEFHOOK (call_args, "While generating RTL for a function call, this target hook is invoked once\n\