aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.cc
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2024-11-11 12:32:13 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2024-11-11 12:32:13 +0000
commit9d14f677a0da80bc6355955469c69709b1d3c67e (patch)
tree32915e2302ca5aa12385dc1576e6d06a72c687b7 /gcc/function.cc
parente22d80d4f0f8d33f538c1a4bad07b2c819a6d55c (diff)
downloadgcc-9d14f677a0da80bc6355955469c69709b1d3c67e.zip
gcc-9d14f677a0da80bc6355955469c69709b1d3c67e.tar.gz
gcc-9d14f677a0da80bc6355955469c69709b1d3c67e.tar.bz2
Add push/pop_function_decl
For the aarch64 simd clones patches, it would be useful to be able to push a function declaration onto the cfun stack, even though it has no function body associated with it. That is, we want cfun to be null, current_function_decl to be the decl itself, and the target and optimisation flags to reflect the declaration. This patch adds a push/pop_function_decl pair to do that. I think the more direct way of doing what I want to do under the existing interface would have been: push_cfun (nullptr); invoke_set_current_function_hook (fndecl); pop_cfun (); where invoke_set_current_function_hook would need to become public. But it seemed safer to use the higher-level routines, since it makes sure that the target/optimisation changes are synchronised with the function changes. In particular, if cfun was null before the sequence above, the pop_cfun would leave the flags unchanged, rather than restore them to the state before the push_cfun. gcc/ * function.h (push_function_decl, pop_function_decl): Declare. * function.cc (set_function_decl): New function, extracted from... (set_cfun): ...here. (push_function_decl): New function, extracted from... (push_cfun): ...here. (pop_cfun_1): New function, extracted from... (pop_cfun): ...here. (pop_function_decl): New function.
Diffstat (limited to 'gcc/function.cc')
-rw-r--r--gcc/function.cc80
1 files changed, 67 insertions, 13 deletions
diff --git a/gcc/function.cc b/gcc/function.cc
index 73490f0..bf74e1e 100644
--- a/gcc/function.cc
+++ b/gcc/function.cc
@@ -4707,40 +4707,74 @@ invoke_set_current_function_hook (tree fndecl)
}
}
-/* cfun should never be set directly; use this function. */
+/* Set cfun to NEW_CFUN and switch to the optimization and target options
+ associated with NEW_FNDECL.
-void
-set_cfun (struct function *new_cfun, bool force)
+ FORCE says whether we should do the switch even if NEW_CFUN is the current
+ function, e.g. because there has been a change in optimization or target
+ options. */
+
+static void
+set_function_decl (function *new_cfun, tree new_fndecl, bool force)
{
if (cfun != new_cfun || force)
{
cfun = new_cfun;
- invoke_set_current_function_hook (new_cfun ? new_cfun->decl : NULL_TREE);
+ invoke_set_current_function_hook (new_fndecl);
redirect_edge_var_map_empty ();
}
}
+/* cfun should never be set directly; use this function. */
+
+void
+set_cfun (struct function *new_cfun, bool force)
+{
+ set_function_decl (new_cfun, new_cfun ? new_cfun->decl : NULL_TREE, force);
+}
+
/* Initialized with NOGC, making this poisonous to the garbage collector. */
static vec<function *> cfun_stack;
-/* Push the current cfun onto the stack, and set cfun to new_cfun. Also set
- current_function_decl accordingly. */
+/* Push the current cfun onto the stack, then switch to function NEW_CFUN
+ and FUNCTION_DECL NEW_FNDECL. FORCE is as for set_function_decl. */
-void
-push_cfun (struct function *new_cfun)
+static void
+push_function_decl (function *new_cfun, tree new_fndecl, bool force)
{
gcc_assert ((!cfun && !current_function_decl)
|| (cfun && current_function_decl == cfun->decl));
cfun_stack.safe_push (cfun);
- current_function_decl = new_cfun ? new_cfun->decl : NULL_TREE;
- set_cfun (new_cfun);
+ current_function_decl = new_fndecl;
+ set_function_decl (new_cfun, new_fndecl, force);
}
-/* Pop cfun from the stack. Also set current_function_decl accordingly. */
+/* Push the current cfun onto the stack and switch to function declaration
+ NEW_FNDECL, which might or might not have a function body. FORCE is as for
+ set_function_decl. */
void
-pop_cfun (void)
+push_function_decl (tree new_fndecl, bool force)
+{
+ force |= current_function_decl != new_fndecl;
+ push_function_decl (DECL_STRUCT_FUNCTION (new_fndecl), new_fndecl, force);
+}
+
+/* Push the current cfun onto the stack, and set cfun to new_cfun. Also set
+ current_function_decl accordingly. */
+
+void
+push_cfun (struct function *new_cfun)
+{
+ push_function_decl (new_cfun, new_cfun ? new_cfun->decl : NULL_TREE, false);
+}
+
+/* A common subroutine for pop_cfun and pop_function_decl. FORCE is as
+ for set_function_decl. */
+
+static void
+pop_cfun_1 (bool force)
{
struct function *new_cfun = cfun_stack.pop ();
/* When in_dummy_function, we do have a cfun but current_function_decl is
@@ -4750,10 +4784,30 @@ pop_cfun (void)
gcc_checking_assert (in_dummy_function
|| !cfun
|| current_function_decl == cfun->decl);
- set_cfun (new_cfun);
+ set_cfun (new_cfun, force);
current_function_decl = new_cfun ? new_cfun->decl : NULL_TREE;
}
+/* Pop cfun from the stack. Also set current_function_decl accordingly. */
+
+void
+pop_cfun (void)
+{
+ pop_cfun_1 (false);
+}
+
+/* Undo push_function_decl. */
+
+void
+pop_function_decl (void)
+{
+ /* If the previous cfun was null, the options should be reset to the
+ global set. Checking the current cfun against the new (popped) cfun
+ wouldn't catch this if the current function decl has no function
+ struct. */
+ pop_cfun_1 (!cfun_stack.last ());
+}
+
/* Return value of funcdef and increase it. */
int
get_next_funcdef_no (void)