public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/aoliva/heads/testme)] WIP fix -fstrub={all,at-calls}
@ 2021-11-16 3:48 Alexandre Oliva
0 siblings, 0 replies; only message in thread
From: Alexandre Oliva @ 2021-11-16 3:48 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:4252b60901c7323900eb3e1cbfb441c6efb09d5a
commit 4252b60901c7323900eb3e1cbfb441c6efb09d5a
Author: Alexandre Oliva <oliva@adacore.com>
Date: Wed Nov 10 00:24:30 2021 -0300
WIP fix -fstrub={all,at-calls}
Diff:
---
gcc/ipa-strub.cc | 134 +++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 110 insertions(+), 24 deletions(-)
diff --git a/gcc/ipa-strub.cc b/gcc/ipa-strub.cc
index 43b2dd80d5d..c8122a8b9e2 100644
--- a/gcc/ipa-strub.cc
+++ b/gcc/ipa-strub.cc
@@ -1317,6 +1317,104 @@ strub_comptypes (tree t1, tree t2)
return 2;
}
+/* Return true if CALL uses a function type different from that of the
+ callee. ??? This cannot tell when a function has a non-explicit
+ strub mode, and it's converted to a type that does not have a strub
+ mode. This should never happen, since such conversions necessarily
+ involve address-taking, which makes transformations that would add
+ type-changing modes non-viable. */
+
+static bool
+call_typecast_p (gcall *call)
+{
+ tree fntype = gimple_call_fntype (call);
+ tree fndecl = gimple_call_fndecl (call);
+ tree fn_type = TREE_TYPE (fndecl
+ ? fndecl
+ : TREE_TYPE (gimple_call_fn (call)));
+
+ return fntype && TYPE_MAIN_VARIANT (fntype) != TYPE_MAIN_VARIANT (fn_type);
+}
+
+/* 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 (call_typecast_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 (!new_ptr_type)
+ new_ptr_type = build_pointer_type (new_type);
+ TREE_TYPE (fnaddr) = new_ptr_type;
+ if (call_typecast_p (e->call_stmt))
+ continue;
+ 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)
+{
+ 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 +1439,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 +1452,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 +1468,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 (!call_typecast_p (e->call_stmt))
error_at (gimple_location (e->call_stmt),
"calling non-%<strub%> %qD in %<strub%> context %qD",
e->callee->decl, node->decl);
@@ -2056,6 +2145,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 +2403,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 +2425,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 +2488,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));
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-11-16 3:48 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-16 3:48 [gcc(refs/users/aoliva/heads/testme)] WIP fix -fstrub={all,at-calls} Alexandre Oliva
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).