The RTL backend code is full of singleton state, so we have to handle
functions as soon as we parse them. This requires various special-casing
in the callgraph code.
gcc/ChangeLog:
* cgraph.h (symtab_node::native_rtl_p): New decl.
* cgraphunit.c (symtab_node::native_rtl_p): New function.
(symtab_node::needed_p): Don't assert for early assembly output
for __RTL functions.
(cgraph_node::finalize_function): Set "force_output" for __RTL
functions.
(cgraph_node::analyze): Bail out early for __RTL functions.
(analyze_functions): Update assertion to support __RTL functions.
(cgraph_node::expand): Bail out early for __RTL functions.
* gimple-expr.c: Include "tree-pass.h".
(gimple_has_body_p): Return false for __RTL functions.
---
gcc/cgraph.h | 4 ++++
gcc/cgraphunit.c | 41 ++++++++++++++++++++++++++++++++++++++---
gcc/gimple-expr.c | 3 ++-
3 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index db2915c..edaae51 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -328,6 +328,10 @@ public:
configury. This function is used just during symbol creation. */
bool needed_p (void);
+ /* Return true if this symbol is a function from the C frontend specified
+ directly in RTL form (with "__RTL"). */
+ bool native_rtl_p () const;
+
/* Return true when there are references to the node. */
bool referred_to_p (bool include_self = true);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 81a3ae9..ed699e1 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -217,6 +217,19 @@ static void handle_alias_pairs (void);
/* Used for vtable lookup in thunk adjusting. */
static GTY (()) tree vtable_entry_type;
+/* Return true if this symbol is a function from the C frontend specified
+ directly in RTL form (with "__RTL"). */
+
+bool
+symtab_node::native_rtl_p () const
+{
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ return false;
+ if (!DECL_STRUCT_FUNCTION (decl))
+ return false;
+ return DECL_STRUCT_FUNCTION (decl)->curr_properties & PROP_rtl;
+}
+
/* Determine if symbol declaration is needed. That is, visible to something
either outside this translation unit, something magic in the system
configury */
@@ -225,8 +238,10 @@ symtab_node::needed_p (void)
{
/* Double check that no one output the function into assembly file
early. */
- gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
- || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
+ if (!native_rtl_p ())
+ gcc_checking_assert
+ (!DECL_ASSEMBLER_NAME_SET_P (decl)
+ || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
if (!definition)
return false;
@@ -435,6 +450,14 @@ cgraph_node::finalize_function (tree decl, bool no_collect)
&& !DECL_DISREGARD_INLINE_LIMITS (decl))
node->force_output = 1;
+ /* __RTL functions were already output as soon as they were parsed (due
+ to the large amount of global state in the backend).
+ Mark such functions as "force_output" to reflect the fact that they
+ will be in the asm file when considering the symbols they reference.
+ The attempt to output them later on will bail out immediately. */
+ if (node->native_rtl_p ())
+ node->force_output = 1;
+
/* When not optimizing, also output the static functions. (see
PR24561), but don't do so for always_inline functions, functions
declared inline and nested functions. These were optimized out
@@ -568,6 +591,12 @@ cgraph_node::add_new_function (tree fndecl, bool lowered)
void
cgraph_node::analyze (void)
{
+ if (native_rtl_p ())
+ {
+ analyzed = true;
+ return;
+ }
+
tree decl = this->decl;
location_t saved_loc = input_location;
input_location = DECL_SOURCE_LOCATION (decl);
@@ -1226,7 +1255,8 @@ analyze_functions (bool first_time)
gcc_assert (!cnode->definition || cnode->thunk.thunk_p
|| cnode->alias
- || gimple_has_body_p (decl));
+ || gimple_has_body_p (decl)
+ || cnode->native_rtl_p ());
gcc_assert (cnode->analyzed == cnode->definition);
}
node->aux = NULL;
@@ -1965,6 +1995,11 @@ cgraph_node::expand (void)
/* We ought to not compile any inline clones. */
gcc_assert (!global.inlined_to);
+ /* __RTL functions are compiled as soon as they are parsed, so don't
+ do it again. */
+ if (native_rtl_p ())
+ return;
+
announce_function (decl);
process = 0;
gcc_assert (lowered);
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index b435b99..2ee87c2 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "demangle.h"
#include "hash-set.h"
#include "rtl.h"
+#include "tree-pass.h"
/* ----- Type related ----- */
@@ -323,7 +324,7 @@ bool
gimple_has_body_p (tree fndecl)
{
struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
- return (gimple_body (fndecl) || (fn && fn->cfg));
+ return (gimple_body (fndecl) || (fn && fn->cfg && !(fn->curr_properties &
PROP_rtl)));
}
/* Return a printable name for symbol DECL. */
--
1.8.5.3