From patchwork Fri Nov 8 14:48:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yury Khrustalev X-Patchwork-Id: 2008529 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XlMT82j5yz1xxq for ; Sat, 9 Nov 2024 01:56:12 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 54A17385840C for ; Fri, 8 Nov 2024 14:56:10 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id DB0F63857710; Fri, 8 Nov 2024 14:51:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DB0F63857710 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DB0F63857710 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1731077489; cv=none; b=BtJR7aDeCL1DqOfN+tHM+ORY/N0kw/EYTZsKMMAqehdJawwKoCBopfDIAFnY5ws7zjfVhYz4oAwIEEJs6ecjnv2z+Qxw7RTyyS1N4RNQs2903xiX0aGZgWW01O9hKGMxBzOJjpCkEG+Zl4MlouERjCcyM4iu9mo0Yd0eJw5rXMY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1731077489; c=relaxed/simple; bh=TehQ7TvpWhbSs5nd8gqtL+Y+xK2gf3NFZ826neG9SFc=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=jAihNEjCYT8b786iGn2Oas1VZYkV6G1YGJrGAHUT4R4ZXNA3l9K7u3pftomO298uXM5y8GVwfrBGMsgV9XtGjP95SynhoC78PR1dqNnArbDWXsOCunrn3jsqjPXUCa6texC/CR7nwPlyWQs3aUDrSDjp4UP0HDQZ5vMl7t2FnDU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 82D6D497; Fri, 8 Nov 2024 06:51:52 -0800 (PST) Received: from udebian.localdomain (unknown [10.57.26.225]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2714E3F528; Fri, 8 Nov 2024 06:51:21 -0800 (PST) From: Yury Khrustalev To: gcc-patches@gcc.gnu.org Cc: nsz@gcc.gnu.org, richard.earnshaw@arm.com, matthieu.longo@arm.com, richard.ball@arm.com, richard.sandiford@arm.com, ktkachov@nvidia.com, john.brawn@arm.com, Yury Khrustalev Subject: [PATCH v3 20/23] aarch64: Introduce indirect_return attribute Date: Fri, 8 Nov 2024 14:48:13 +0000 Message-Id: <20241108144816.2681175-21-yury.khrustalev@arm.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241108144816.2681175-1-yury.khrustalev@arm.com> References: <20241108144816.2681175-1-yury.khrustalev@arm.com> MIME-Version: 1.0 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org From: Szabolcs Nagy Tail calls of indirect_return functions from non-indirect_return functions are disallowed even if BTI is disabled, since the call site may have BTI enabled. Following x86, mismatching attribute on function pointers is not a type error even though this can lead to bugs. Needed for swapcontext within the same function when GCS is enabled. gcc/ChangeLog: * config/aarch64/aarch64.cc (aarch64_gnu_attributes): Add indirect_return. (aarch64_gen_callee_cookie): Use indirect_return attribute. (aarch64_callee_indirect_return): New. (aarch_fun_is_indirect_return): New. (aarch64_function_ok_for_sibcall): Disallow tail calls if caller is non-indirect_return but callee is indirect_return. (aarch64_function_arg): Add indirect_return to cookie. (aarch64_init_cumulative_args): Record indirect_return in CUMULATIVE_ARGS. (aarch64_comp_type_attributes): Check indirect_return attribute. (aarch64_output_mi_thunk): Add indirect_return to cookie. * config/aarch64/aarch64.h (CUMULATIVE_ARGS): Add new field indirect_return. * config/aarch64/aarch64.md (tlsdesc_small_): Update. * config/aarch64/aarch64-opts.h (AARCH64_NUM_ABI_ATTRIBUTES): New. * config/aarch64/aarch64-protos.h (aarch64_gen_callee_cookie): Update. * config/arm/aarch-bti-insert.cc (call_needs_bti_j): New. (rest_of_insert_bti): Use call_needs_bti_j. * config/arm/aarch-common-protos.h (aarch_fun_is_indirect_return): New. * config/arm/arm.cc (aarch_fun_is_indirect_return): New. Co-authored-by: Yury Khrustalev --- gcc/config/aarch64/aarch64-opts.h | 2 ++ gcc/config/aarch64/aarch64-protos.h | 2 +- gcc/config/aarch64/aarch64.cc | 53 ++++++++++++++++++++++++---- gcc/config/aarch64/aarch64.h | 1 + gcc/config/aarch64/aarch64.md | 3 +- gcc/config/arm/aarch-bti-insert.cc | 23 +++++++++--- gcc/config/arm/aarch-common-protos.h | 1 + gcc/config/arm/arm.cc | 9 +++++ 8 files changed, 81 insertions(+), 13 deletions(-) diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h index 9fb62e58398..2b5d9e55f97 100644 --- a/gcc/config/aarch64/aarch64-opts.h +++ b/gcc/config/aarch64/aarch64-opts.h @@ -25,6 +25,8 @@ #ifndef USED_FOR_TARGET #include "bbitmap.h" +constexpr unsigned int AARCH64_NUM_ABI_ATTRIBUTES = 1; + typedef uint64_t aarch64_isa_mode; constexpr unsigned int AARCH64_NUM_ISA_MODES = (0 diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 632be022ce9..04add400264 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -853,7 +853,7 @@ bool aarch64_emit_approx_div (rtx, rtx, rtx); bool aarch64_emit_approx_sqrt (rtx, rtx, bool); bool aarch64_emit_opt_vec_rotate (rtx, rtx, rtx); tree aarch64_vector_load_decl (tree); -rtx aarch64_gen_callee_cookie (aarch64_isa_mode, arm_pcs); +rtx aarch64_gen_callee_cookie (aarch64_isa_mode, arm_pcs, bool); void aarch64_expand_call (rtx, rtx, rtx, bool); bool aarch64_expand_cpymem_mops (rtx *, bool); bool aarch64_expand_cpymem (rtx *, bool); diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index d6b7b5c8ae9..99de52f526c 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -863,6 +863,7 @@ static const attribute_spec aarch64_gnu_attributes[] = affects_type_identity, handler, exclude } */ { "aarch64_vector_pcs", 0, 0, false, true, true, true, handle_aarch64_vector_pcs_attribute, NULL }, + { "indirect_return", 0, 0, false, true, true, true, NULL, NULL }, { "arm_sve_vector_bits", 1, 1, false, true, false, true, aarch64_sve::handle_arm_sve_vector_bits_attribute, NULL }, @@ -2483,11 +2484,14 @@ aarch64_reg_save_mode (unsigned int regno) return the CONST_INT that should be placed in an UNSPEC_CALLEE_ABI rtx. */ rtx -aarch64_gen_callee_cookie (aarch64_isa_mode isa_mode, arm_pcs pcs_variant) +aarch64_gen_callee_cookie (aarch64_isa_mode isa_mode, arm_pcs pcs_variant, + bool indirect_return) { - return gen_int_mode ((unsigned int) isa_mode - | (unsigned int) pcs_variant << AARCH64_NUM_ISA_MODES, - DImode); + unsigned int im = (unsigned int) isa_mode; + unsigned int ir = (indirect_return ? 1 : 0) << AARCH64_NUM_ISA_MODES; + unsigned int pv = (unsigned int) pcs_variant + << (AARCH64_NUM_ABI_ATTRIBUTES + AARCH64_NUM_ISA_MODES); + return gen_int_mode (im | ir | pv, DImode); } /* COOKIE is a CONST_INT from an UNSPEC_CALLEE_ABI rtx. Return the @@ -2496,7 +2500,8 @@ aarch64_gen_callee_cookie (aarch64_isa_mode isa_mode, arm_pcs pcs_variant) static const predefined_function_abi & aarch64_callee_abi (rtx cookie) { - return function_abis[UINTVAL (cookie) >> AARCH64_NUM_ISA_MODES]; + return function_abis[UINTVAL (cookie) + >> (AARCH64_NUM_ABI_ATTRIBUTES + AARCH64_NUM_ISA_MODES)]; } /* COOKIE is a CONST_INT from an UNSPEC_CALLEE_ABI rtx. Return the @@ -2509,6 +2514,15 @@ aarch64_callee_isa_mode (rtx cookie) return UINTVAL (cookie) & ((1 << AARCH64_NUM_ISA_MODES) - 1); } +/* COOKIE is a CONST_INT from an UNSPEC_CALLEE_ABI rtx. Return + whether function was marked with indirect_return attribute. */ + +static bool +aarch64_callee_indirect_return (rtx cookie) +{ + return (UINTVAL (cookie) >> AARCH64_NUM_ISA_MODES) & 1 == 1; +} + /* INSN is a call instruction. Return the CONST_INT stored in its UNSPEC_CALLEE_ABI rtx. */ @@ -2523,6 +2537,16 @@ aarch64_insn_callee_cookie (const rtx_insn *insn) return XVECEXP (unspec, 0, 0); } +/* INSN is a call instruction. Check if function associated with + INSN has indirect return attribute declared in its cookie. */ + +bool +aarch_fun_is_indirect_return (rtx_insn *insn) +{ + rtx cookie = aarch64_insn_callee_cookie (insn); + return aarch64_callee_indirect_return (cookie); +} + /* Implement TARGET_INSN_CALLEE_ABI. */ const predefined_function_abi & @@ -6459,6 +6483,14 @@ aarch64_function_ok_for_sibcall (tree, tree exp) if (bool (aarch64_cfun_shared_flags (state)) != bool (aarch64_fntype_shared_flags (fntype, state))) return false; + + /* BTI J is needed where indirect_return functions may return + if bti is enabled there. */ + if (lookup_attribute ("indirect_return", TYPE_ATTRIBUTES (fntype)) + && !lookup_attribute ("indirect_return", + TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))) + return false; + return true; } @@ -7288,7 +7320,8 @@ aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg) if (arg.end_marker_p ()) { rtx abi_cookie = aarch64_gen_callee_cookie (pcum->isa_mode, - pcum->pcs_variant); + pcum->pcs_variant, + pcum->indirect_return); rtx sme_mode_switch_args = aarch64_finish_sme_mode_switch_args (pcum); rtx shared_za_flags = gen_int_mode (pcum->shared_za_flags, SImode); rtx shared_zt0_flags = gen_int_mode (pcum->shared_zt0_flags, SImode); @@ -7320,11 +7353,13 @@ aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum, { pcum->pcs_variant = (arm_pcs) fntype_abi (fntype).id (); pcum->isa_mode = aarch64_fntype_isa_mode (fntype); + pcum->indirect_return = lookup_attribute ("indirect_return", TYPE_ATTRIBUTES (fntype)); } else { pcum->pcs_variant = ARM_PCS_AAPCS64; pcum->isa_mode = AARCH64_DEFAULT_ISA_MODE; + pcum->indirect_return = false; } pcum->aapcs_reg = NULL_RTX; pcum->aapcs_arg_processed = false; @@ -10227,7 +10262,9 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, funexp = gen_rtx_MEM (FUNCTION_MODE, funexp); auto isa_mode = aarch64_fntype_isa_mode (TREE_TYPE (function)); auto pcs_variant = arm_pcs (fndecl_abi (function).id ()); - rtx callee_abi = aarch64_gen_callee_cookie (isa_mode, pcs_variant); + bool ir = lookup_attribute ("indirect_return", + TYPE_ATTRIBUTES (TREE_TYPE (function))); + rtx callee_abi = aarch64_gen_callee_cookie (isa_mode, pcs_variant, ir); insn = emit_call_insn (gen_sibcall (funexp, const0_rtx, callee_abi)); SIBLING_CALL_P (insn) = 1; @@ -29286,6 +29323,8 @@ aarch64_comp_type_attributes (const_tree type1, const_tree type2) if (!check_attr ("gnu", "aarch64_vector_pcs")) return 0; + if (!check_attr ("gnu", "indirect_return")) + return 0; if (!check_attr ("gnu", "Advanced SIMD type")) return 0; if (!check_attr ("gnu", "SVE type")) diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index c3fbe9b464c..45ca9e282ff 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -1131,6 +1131,7 @@ typedef struct { enum arm_pcs pcs_variant; aarch64_isa_mode isa_mode; + bool indirect_return; /* Whether function is marked with indirect_return attribute. */ int aapcs_arg_processed; /* No need to lay out this argument again. */ int aapcs_ncrn; /* Next Core register number. */ int aapcs_nextncrn; /* Next next core register number. */ diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 861527fce36..dd579692317 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -7692,7 +7692,8 @@ (define_expand "tlsdesc_small_" if (TARGET_SVE) { rtx abi = aarch64_gen_callee_cookie (AARCH64_ISA_MODE, - aarch64_tlsdesc_abi_id ()); + aarch64_tlsdesc_abi_id (), + false); rtx_insn *call = emit_call_insn (gen_tlsdesc_small_sve_ (operands[0], abi)); RTL_CONST_CALL_P (call) = 1; diff --git a/gcc/config/arm/aarch-bti-insert.cc b/gcc/config/arm/aarch-bti-insert.cc index 14d36971cd4..4eb2034a2de 100644 --- a/gcc/config/arm/aarch-bti-insert.cc +++ b/gcc/config/arm/aarch-bti-insert.cc @@ -92,6 +92,22 @@ const pass_data pass_data_insert_bti = 0, /* todo_flags_finish. */ }; +/* Decide if BTI J is needed after a call instruction. */ +static bool +call_needs_bti_j (rtx_insn *insn) +{ + /* Call returns twice, one of which may be indirect. */ + if (find_reg_note (insn, REG_SETJMP, NULL)) + return true; + + /* Tail call does not return. */ + if (SIBLING_CALL_P (insn)) + return false; + + /* Check if the function is marked to return indirectly. */ + return aarch_fun_is_indirect_return(insn); +} + /* Insert the BTI instruction. */ /* This is implemented as a late RTL pass that runs before branch shortening and does the following. */ @@ -147,10 +163,9 @@ rest_of_insert_bti (void) } } - /* Also look for calls to setjmp () which would be marked with - REG_SETJMP note and put a BTI J after. This is where longjump () - will return. */ - if (CALL_P (insn) && (find_reg_note (insn, REG_SETJMP, NULL))) + /* Also look for calls that may return indirectly, such as setjmp, + and put a BTI J after them. */ + if (CALL_P (insn) && call_needs_bti_j (insn)) { bti_insn = aarch_gen_bti_j (); emit_insn_after (bti_insn, insn); diff --git a/gcc/config/arm/aarch-common-protos.h b/gcc/config/arm/aarch-common-protos.h index 9849fcbc098..04d73c7fad5 100644 --- a/gcc/config/arm/aarch-common-protos.h +++ b/gcc/config/arm/aarch-common-protos.h @@ -48,6 +48,7 @@ extern bool aarch_bti_j_insn_p (rtx_insn *); extern bool aarch_pac_insn_p (rtx); extern rtx aarch_gen_bti_c (void); extern rtx aarch_gen_bti_j (void); +extern bool aarch_fun_is_indirect_return (rtx_insn *); /* RTX cost table definitions. These are used when tuning for speed rather than for size and should reflect the _additional_ cost over the cost diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index 6f11b6c816d..5075140c2a1 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -33492,6 +33492,15 @@ aarch_gen_bti_j (void) return gen_bti_nop (); } +/* For Arm, we always return false because indirect_return attribute + is only supported on AArch64 targets. */ + +bool +aarch_fun_is_indirect_return (rtx_insn *) +{ + return false; +} + /* Implement TARGET_SCHED_CAN_SPECULATE_INSN. Return true if INSN can be scheduled for speculative execution. Reject the long-running division and square-root instructions. */