mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
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.
This commit is contained in:
parent
e22d80d4f0
commit
9d14f677a0
@ -4707,40 +4707,74 @@ invoke_set_current_function_hook (tree fndecl)
|
||||
}
|
||||
}
|
||||
|
||||
/* Set cfun to NEW_CFUN and switch to the optimization and target options
|
||||
associated with NEW_FNDECL.
|
||||
|
||||
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_fndecl);
|
||||
redirect_edge_var_map_empty ();
|
||||
}
|
||||
}
|
||||
|
||||
/* cfun should never be set directly; use this function. */
|
||||
|
||||
void
|
||||
set_cfun (struct function *new_cfun, bool force)
|
||||
{
|
||||
if (cfun != new_cfun || force)
|
||||
{
|
||||
cfun = new_cfun;
|
||||
invoke_set_current_function_hook (new_cfun ? new_cfun->decl : NULL_TREE);
|
||||
redirect_edge_var_map_empty ();
|
||||
}
|
||||
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, then switch to function NEW_CFUN
|
||||
and FUNCTION_DECL NEW_FNDECL. FORCE is as for set_function_decl. */
|
||||
|
||||
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_fndecl;
|
||||
set_function_decl (new_cfun, new_fndecl, force);
|
||||
}
|
||||
|
||||
/* 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
|
||||
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)
|
||||
{
|
||||
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);
|
||||
push_function_decl (new_cfun, new_cfun ? new_cfun->decl : NULL_TREE, false);
|
||||
}
|
||||
|
||||
/* Pop cfun from the stack. Also set current_function_decl accordingly. */
|
||||
/* A common subroutine for pop_cfun and pop_function_decl. FORCE is as
|
||||
for set_function_decl. */
|
||||
|
||||
void
|
||||
pop_cfun (void)
|
||||
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)
|
||||
|
@ -701,6 +701,8 @@ extern void number_blocks (tree);
|
||||
extern void set_cfun (struct function *new_cfun, bool force = false);
|
||||
extern void push_cfun (struct function *new_cfun);
|
||||
extern void pop_cfun (void);
|
||||
extern void push_function_decl (tree, bool = false);
|
||||
extern void pop_function_decl (void);
|
||||
|
||||
extern int get_next_funcdef_no (void);
|
||||
extern int get_last_funcdef_no (void);
|
||||
|
Loading…
Reference in New Issue
Block a user