diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2024-11-11 12:32:13 +0000 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2024-11-11 12:32:13 +0000 |
commit | 9d14f677a0da80bc6355955469c69709b1d3c67e (patch) | |
tree | 32915e2302ca5aa12385dc1576e6d06a72c687b7 /gcc/function.cc | |
parent | e22d80d4f0f8d33f538c1a4bad07b2c819a6d55c (diff) | |
download | gcc-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.cc | 80 |
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) |