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. */
|
/* cfun should never be set directly; use this function. */
|
||||||
|
|
||||||
void
|
void
|
||||||
set_cfun (struct function *new_cfun, bool force)
|
set_cfun (struct function *new_cfun, bool force)
|
||||||
{
|
{
|
||||||
if (cfun != new_cfun || force)
|
set_function_decl (new_cfun, new_cfun ? new_cfun->decl : NULL_TREE, force);
|
||||||
{
|
|
||||||
cfun = new_cfun;
|
|
||||||
invoke_set_current_function_hook (new_cfun ? new_cfun->decl : NULL_TREE);
|
|
||||||
redirect_edge_var_map_empty ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialized with NOGC, making this poisonous to the garbage collector. */
|
/* Initialized with NOGC, making this poisonous to the garbage collector. */
|
||||||
|
|
||||||
static vec<function *> cfun_stack;
|
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
|
/* Push the current cfun onto the stack, and set cfun to new_cfun. Also set
|
||||||
current_function_decl accordingly. */
|
current_function_decl accordingly. */
|
||||||
|
|
||||||
void
|
void
|
||||||
push_cfun (struct function *new_cfun)
|
push_cfun (struct function *new_cfun)
|
||||||
{
|
{
|
||||||
gcc_assert ((!cfun && !current_function_decl)
|
push_function_decl (new_cfun, new_cfun ? new_cfun->decl : NULL_TREE, false);
|
||||||
|| (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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
static void
|
||||||
pop_cfun (void)
|
pop_cfun_1 (bool force)
|
||||||
{
|
{
|
||||||
struct function *new_cfun = cfun_stack.pop ();
|
struct function *new_cfun = cfun_stack.pop ();
|
||||||
/* When in_dummy_function, we do have a cfun but current_function_decl is
|
/* 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
|
gcc_checking_assert (in_dummy_function
|
||||||
|| !cfun
|
|| !cfun
|
||||||
|| current_function_decl == cfun->decl);
|
|| current_function_decl == cfun->decl);
|
||||||
set_cfun (new_cfun);
|
set_cfun (new_cfun, force);
|
||||||
current_function_decl = new_cfun ? new_cfun->decl : NULL_TREE;
|
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. */
|
/* Return value of funcdef and increase it. */
|
||||||
int
|
int
|
||||||
get_next_funcdef_no (void)
|
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 set_cfun (struct function *new_cfun, bool force = false);
|
||||||
extern void push_cfun (struct function *new_cfun);
|
extern void push_cfun (struct function *new_cfun);
|
||||||
extern void pop_cfun (void);
|
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_next_funcdef_no (void);
|
||||||
extern int get_last_funcdef_no (void);
|
extern int get_last_funcdef_no (void);
|
||||||
|
Loading…
Reference in New Issue
Block a user