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