From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2140) id 76EBB3857823; Tue, 16 Nov 2021 05:13:17 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 76EBB3857823 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Alexandre Oliva To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/aoliva/heads/strub)] fix strub function type sharing X-Act-Checkin: gcc X-Git-Author: Alexandre Oliva X-Git-Refname: refs/users/aoliva/heads/strub X-Git-Oldrev: cd941b8fcb1052ecd54fa83b65f66efef4612794 X-Git-Newrev: 859656002a7d255ed6697d06afe654fceb8302e7 Message-Id: <20211116051317.76EBB3857823@sourceware.org> Date: Tue, 16 Nov 2021 05:13:17 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Nov 2021 05:13:17 -0000 https://gcc.gnu.org/g:859656002a7d255ed6697d06afe654fceb8302e7 commit 859656002a7d255ed6697d06afe654fceb8302e7 Author: Alexandre Oliva Date: Wed Nov 10 00:24:30 2021 -0300 fix strub function type sharing When a function type is copied and modified to add an at-calls strub mode, propagate the function type to fntype and address type in any calls involving the function, so that we don't modify unrelated types equivalent to the unmodified function type. for gcc/ChangeLog * ipa-strub.cc (effective_strub_mode_for_call): New. (distinctify_node_type): New. (same_strub_mode_in_variants_p): New. (verify_strub): Use factored-out effective mode logic. (pass_ipa_strub::adjust_at_calls_type): Likewise. Check mode in all variant and canonical types. (pass_ipa_strub::execute): Use dinstinctify_node_type. Diff: --- gcc/ipa-strub.cc | 120 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 96 insertions(+), 24 deletions(-) diff --git a/gcc/ipa-strub.cc b/gcc/ipa-strub.cc index 43b2dd80d5d..4c1efe73f7f 100644 --- a/gcc/ipa-strub.cc +++ b/gcc/ipa-strub.cc @@ -1317,6 +1317,90 @@ strub_comptypes (tree t1, tree t2) return 2; } +/* Return the effective strub mode used for CALL, and set *TYPEP to + the effective type used for the call. The effective type and mode + are those of the callee, unless the call involves a typecast. */ + +static enum strub_mode +effective_strub_mode_for_call (gcall *call, tree *typep) +{ + tree type; + enum strub_mode mode; + + if (gimple_call_fntype_override_p (call)) + { + type = gimple_call_fntype (call); + mode = get_strub_mode_from_type (type); + } + else + { + type = TREE_TYPE (TREE_TYPE (gimple_call_fn (call))); + tree decl = gimple_call_fndecl (call); + if (decl) + mode = get_strub_mode_from_fndecl (decl); + else + mode = get_strub_mode_from_type (type); + } + + if (typep) + *typep = type; + + return mode; +} + +/* Create a distinct copy of the type of NODE's function, and change + the fntype of all calls to it with the same main type to the new + type. */ + +static void +distinctify_node_type (cgraph_node *node) +{ + tree old_type = TREE_TYPE (node->decl); + tree new_type = build_distinct_type_copy (old_type); + tree new_ptr_type = NULL_TREE; + + /* Remap any calls to node->decl that use old_type, or a variant + thereof, to new_type as well. We don't look for aliases, their + declarations will have their types changed independently, and + we'll adjust their fntypes then. */ + for (cgraph_edge *e = node->callers; e; e = e->next_caller) + { + tree fnaddr = gimple_call_fn (e->call_stmt); + gcc_checking_assert (TREE_CODE (fnaddr) == ADDR_EXPR + && TREE_OPERAND (fnaddr, 0) == node->decl); + if (gimple_call_fntype_override_p (e->call_stmt)) + continue; + if (!new_ptr_type) + new_ptr_type = build_pointer_type (new_type); + TREE_TYPE (fnaddr) = new_ptr_type; + gimple_call_set_fntype (e->call_stmt, new_type); + } + + TREE_TYPE (node->decl) = new_type; +} + +/* Return TRUE if TYPE and any variants have the same strub mode, + and false otherwise. */ + +static bool +same_strub_mode_in_variants_p (tree type) +{ + if (TYPE_CANONICAL (type) + && (get_strub_mode_from_type (type) + != get_strub_mode_from_type (TYPE_CANONICAL (type)))) + return false; + + for (tree other = TYPE_MAIN_VARIANT (type); + other != NULL_TREE; other = TYPE_NEXT_VARIANT (type)) + if (other == type) + continue; + else if (get_strub_mode_from_type (type) + != get_strub_mode_from_type (TYPE_MAIN_VARIANT (type))) + return false; + + return true; +} + /* Check that strub functions don't call non-strub functions, and that always_inline strub functions are only called by strub functions. */ @@ -1341,9 +1425,8 @@ verify_strub () { gcc_checking_assert (e->indirect_unknown_callee); - tree callee_fntype = gimple_call_fntype (e->call_stmt); enum strub_mode callee_mode - = get_strub_mode_from_type (callee_fntype); + = effective_strub_mode_for_call (e->call_stmt, NULL); if (!strub_callable_from_p (caller_mode, callee_mode)) error_at (gimple_location (e->call_stmt), @@ -1355,17 +1438,9 @@ verify_strub () { gcc_checking_assert (!e->indirect_unknown_callee); - tree callee_fntype = gimple_call_fntype (e->call_stmt); - /* fntype is NULL for internal calls, and builtins may carry a - variant type. */ - bool use_callee_mode_p - = (!callee_fntype - || (TYPE_MAIN_VARIANT (TREE_TYPE (e->callee->decl)) - == TYPE_MAIN_VARIANT (callee_fntype))); - strub_mode callee_mode - = (use_callee_mode_p - ? get_strub_mode (e->callee) - : get_strub_mode_from_type (callee_fntype)); + tree callee_fntype; + enum strub_mode callee_mode + = effective_strub_mode_for_call (e->call_stmt, &callee_fntype); if (!strub_callable_from_p (caller_mode, callee_mode)) { @@ -1379,7 +1454,7 @@ verify_strub () /* This is ok, it will be kept in the STRUB_WRAPPER, and removed from the STRUB_WRAPPED's strub context. */ continue; - else if (use_callee_mode_p) + else if (!gimple_call_fntype_override_p (e->call_stmt)) error_at (gimple_location (e->call_stmt), "calling non-% %qD in % context %qD", e->callee->decl, node->decl); @@ -2056,6 +2131,8 @@ pass_ipa_strub::adjust_at_calls_type (tree type) { int named_args = 0; + gcc_checking_assert (same_strub_mode_in_variants_p (type)); + if (!TYPE_ARG_TYPES (type)) return named_args; @@ -2312,9 +2389,9 @@ pass_ipa_strub::adjust_at_calls_calls (cgraph_node *node) { gcc_checking_assert (e->indirect_unknown_callee); - tree callee_fntype = gimple_call_fntype (e->call_stmt); + tree callee_fntype; enum strub_mode callee_mode - = get_strub_mode_from_type (callee_fntype); + = effective_strub_mode_for_call (e->call_stmt, &callee_fntype); if (callee_mode != STRUB_AT_CALLS && callee_mode != STRUB_AT_CALLS_OPT) @@ -2334,13 +2411,9 @@ pass_ipa_strub::adjust_at_calls_calls (cgraph_node *node) { gcc_checking_assert (!e->indirect_unknown_callee); - tree callee_fntype = gimple_call_fntype (e->call_stmt); + tree callee_fntype; enum strub_mode callee_mode - = (!callee_fntype - || (TYPE_MAIN_VARIANT (callee_fntype) - != TYPE_MAIN_VARIANT (TREE_TYPE (e->callee->decl))) - ? get_strub_mode (e->callee) - : get_strub_mode_from_type (callee_fntype)); + = effective_strub_mode_for_call (e->call_stmt, &callee_fntype); if (callee_mode != STRUB_AT_CALLS && callee_mode != STRUB_AT_CALLS_OPT) @@ -2401,8 +2474,7 @@ pass_ipa_strub::execute (function *) /* Create a type variant if strubbing was not explicitly requested in the function type. */ if (get_strub_mode_from_type (TREE_TYPE (onode->decl)) != mode) - TREE_TYPE (onode->decl) = build_distinct_type_copy (TREE_TYPE - (onode->decl)); + distinctify_node_type (onode); int named_args = adjust_at_calls_type (TREE_TYPE (onode->decl));