diff options
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r-- | gcc/cgraphunit.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 13079a2b803..7a043d0edea 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -168,6 +168,75 @@ static void cgraph_output_pending_asms (void); static FILE *cgraph_dump_file; +static GTY (()) tree static_ctors; +static GTY (()) tree static_dtors; + +/* When target does not have ctors and dtors, we call all constructor + and destructor by special initialization/destruction functio + recognized by collect2. + + When we are going to build this function, collect all constructors and + destructors and turn them into normal functions. */ + +static void +record_cdtor_fn (tree fndecl) +{ + if (targetm.have_ctors_dtors) + return; + + if (DECL_STATIC_CONSTRUCTOR (fndecl)) + { + static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors); + DECL_STATIC_CONSTRUCTOR (fndecl) = 0; + cgraph_mark_reachable_node (cgraph_node (fndecl)); + } + if (DECL_STATIC_DESTRUCTOR (fndecl)) + { + static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors); + DECL_STATIC_DESTRUCTOR (fndecl) = 0; + cgraph_mark_reachable_node (cgraph_node (fndecl)); + } +} + +/* Synthesize a function which calls all the global ctors or global + dtors in this file. This is only used for targets which do not + support .ctors/.dtors sections. */ +static void +build_cdtor (int method_type, tree cdtors) +{ + tree body = 0; + + if (!cdtors) + return; + + for (; cdtors; cdtors = TREE_CHAIN (cdtors)) + append_to_statement_list (build_function_call_expr (TREE_VALUE (cdtors), 0), + &body); + + cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY); +} + +/* Generate functions to call static constructors and destructors + for targets that do not support .ctors/.dtors sections. These + functions have magic names which are detected by collect2. */ + +static void +cgraph_build_cdtor_fns (void) +{ + if (!targetm.have_ctors_dtors) + { + build_cdtor ('I', static_ctors); + static_ctors = NULL_TREE; + build_cdtor ('D', static_dtors); + static_dtors = NULL_TREE; + } + else + { + gcc_assert (!static_ctors); + gcc_assert (!static_dtors); + } +} + /* Determine if function DECL is needed. That is, visible to something either outside this translation unit, something magic in the system configury, or (if not doing unit-at-a-time) to something we havn't @@ -458,6 +527,7 @@ cgraph_finalize_function (tree decl, bool nested) node->decl = decl; node->local.finalized = true; node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL; + record_cdtor_fn (node->decl); if (node->nested) lower_nested_functions (decl); gcc_assert (!node->nested); @@ -1222,6 +1292,10 @@ cgraph_optimize (void) #ifdef ENABLE_CHECKING verify_cgraph (); #endif + + /* Call functions declared with the "constructor" or "destructor" + attribute. */ + cgraph_build_cdtor_fns (); if (!flag_unit_at_a_time) { cgraph_assemble_pending_functions (); @@ -1572,3 +1646,5 @@ save_inline_function_body (struct cgraph_node *node) #endif return first_clone; } + +#include "gt-cgraphunit.h" |