Message ID | D999EBA8-A0F5-49E6-9BC3-90A44A8BE9DD@adacore.com |
---|---|
State | New |
Headers | show |
On Tue, 20 Mar 2012, Tristan Gingold wrote: > > On Mar 20, 2012, at 3:19 PM, Richard Guenther wrote: > > […] > > > > I'd rather get away from using a global main_identifier_node, instead > > make that frontend specific, and introduce targetm.main_assembler_name > > which the assembler-name creating langhook would make sure to use > > when mangling what the FE thinks main is. main_identifier_node should > > not serve any purpose outside of Frontends. > > > > But I see both as a possible cleanup opportunity, not a necessary change. > > Something along these lines ? Yes, but I'd simply call the hook at the places you now use main_assembler_name and not create a global tree node for it. Richard. > Tristan. > > diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c > index 89f5438..c575e97 100644 > --- a/gcc/ada/gcc-interface/trans.c > +++ b/gcc/ada/gcc-interface/trans.c > @@ -622,8 +622,6 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED, > integer_type_node, NULL_TREE, true, false, true, false, > NULL, Empty); > > - main_identifier_node = get_identifier ("main"); > - > /* Install the builtins we might need, either internally or as > user available facilities for Intrinsic imports. */ > gnat_install_builtins (); > diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c > index 7383358..b0fa085d 100644 > --- a/gcc/ada/gcc-interface/utils.c > +++ b/gcc/ada/gcc-interface/utils.c > @@ -1902,14 +1902,12 @@ create_subprog_decl (tree subprog_name, tree asm_name, tree subprog_type, > { > SET_DECL_ASSEMBLER_NAME (subprog_decl, asm_name); > > - /* The expand_main_function circuitry expects "main_identifier_node" to > - designate the DECL_NAME of the 'main' entry point, in turn expected > - to be declared as the "main" function literally by default. Ada > - program entry points are typically declared with a different name > + /* Ada program entry points are typically declared with a different name > within the binder generated file, exported as 'main' to satisfy the > - system expectations. Force main_identifier_node in this case. */ > - if (asm_name == main_identifier_node) > - DECL_NAME (subprog_decl) = main_identifier_node; > + system expectations. Force main_assembler_node in this case. */ > + if (IDENTIFIER_LENGTH (asm_name) == 4 > + && memcmp (IDENTIFIER_POINTER (asm_name), "main", 4) == 0) > + DECL_NAME (subprog_decl) = main_assembler_name; > } > > /* Add this decl to the current binding level. */ > diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h > index 835b13b..fea5181 100644 > --- a/gcc/c-family/c-common.h > +++ b/gcc/c-family/c-common.h > @@ -291,6 +291,8 @@ enum c_tree_index > > CTI_DEFAULT_FUNCTION_TYPE, > > + CTI_MAIN_IDENTIFIER, > + > /* These are not types, but we have to look them up all the time. */ > CTI_FUNCTION_NAME_DECL, > CTI_PRETTY_FUNCTION_NAME_DECL, > @@ -426,6 +428,10 @@ extern const unsigned int num_c_common_reswords; > > #define default_function_type c_global_trees[CTI_DEFAULT_FUNCTION_TYPE] > > +#define main_identifier_node c_global_trees[CTI_MAIN_IDENTIFIER] > +#define MAIN_NAME_P(NODE) \ > + (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node) > + > #define function_name_decl_node c_global_trees[CTI_FUNCTION_NAME_DECL] > #define pretty_function_name_decl_node c_global_trees[CTI_PRETTY_FUNCTION_NAME_DECL] > #define c99_function_name_decl_node c_global_trees[CTI_C99_FUNCTION_NAME_DECL] > diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c > index bd21169..db53309 100644 > --- a/gcc/cfgexpand.c > +++ b/gcc/cfgexpand.c > @@ -4513,9 +4513,7 @@ gimple_expand_cfg (void) > > /* If this function is `main', emit a call to `__main' > to run global initializers, etc. */ > - if (DECL_NAME (current_function_decl) > - && MAIN_NAME_P (DECL_NAME (current_function_decl)) > - && DECL_FILE_SCOPE_P (current_function_decl)) > + if (cgraph_main_function_p (cgraph_get_node (current_function_decl))) > expand_main_function (); > > /* Initialize the stack_protect_guard field. This must happen after the > diff --git a/gcc/cgraph.c b/gcc/cgraph.c > index 9cc3690..528fd19 100644 > --- a/gcc/cgraph.c > +++ b/gcc/cgraph.c > @@ -2766,7 +2766,7 @@ cgraph_propagate_frequency_1 (struct cgraph_node *node, void *data) > /* It makes sense to put main() together with the static constructors. > It will be executed for sure, but rest of functions called from > main are definitely not at startup only. */ > - if (MAIN_NAME_P (DECL_NAME (edge->caller->decl))) > + if (cgraph_main_function_p (edge->caller)) > d->only_called_at_startup = 0; > d->only_called_at_exit &= edge->caller->only_called_at_exit; > } > diff --git a/gcc/cgraph.h b/gcc/cgraph.h > index 191364c..089d851 100644 > --- a/gcc/cgraph.h > +++ b/gcc/cgraph.h > @@ -101,6 +101,9 @@ struct GTY(()) cgraph_local_info { > > /* True if the function may enter serial irrevocable mode. */ > unsigned tm_may_enter_irr : 1; > + > + /* True if the function is the program entry point (main in C). */ > + unsigned main_function : 1; > }; > > /* Information about the function that needs to be computed globally > @@ -790,6 +793,13 @@ cgraph_next_function_with_gimple_body (struct cgraph_node *node) > return NULL; > } > > +/* Return true iff NODE is the main function (main in C). */ > +static inline bool > +cgraph_main_function_p (struct cgraph_node *node) > +{ > + return node && node->local.main_function; > +} > + > /* Walk all functions with body defined. */ > #define FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node) \ > for ((node) = cgraph_first_function_with_gimple_body (); (node); \ > diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c > index 516f187..556f21c 100644 > --- a/gcc/cgraphunit.c > +++ b/gcc/cgraphunit.c > @@ -346,6 +346,9 @@ cgraph_finalize_function (tree decl, bool nested) > notice_global_symbol (decl); > node->local.finalized = true; > node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL; > + node->local.main_function = > + DECL_FILE_SCOPE_P (decl) > + && decl_assembler_name_equal (decl, main_assembler_name); > > if (cgraph_decide_is_function_needed (node, decl)) > cgraph_mark_needed_node (node); > diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h > index 2eccda9..e0f6234 100644 > --- a/gcc/config/i386/cygming.h > +++ b/gcc/config/i386/cygming.h > @@ -360,7 +360,7 @@ do { \ > > #undef PROFILE_HOOK > #define PROFILE_HOOK(LABEL) \ > - if (MAIN_NAME_P (DECL_NAME (current_function_decl))) \ > + if (cgraph_main_function_p (cgraph_get_node (current_function_decl))) \ > { \ > emit_call_insn (gen_rtx_CALL (VOIDmode, \ > gen_rtx_MEM (FUNCTION_MODE, \ > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c > index 78a366e..c4a78b1 100644 > --- a/gcc/config/i386/i386.c > +++ b/gcc/config/i386/i386.c > @@ -9509,9 +9509,7 @@ ix86_minimum_incoming_stack_boundary (bool sibcall) > /* Stack at entrance of main is aligned by runtime. We use the > smallest incoming stack boundary. */ > if (incoming_stack_boundary > MAIN_STACK_BOUNDARY > - && DECL_NAME (current_function_decl) > - && MAIN_NAME_P (DECL_NAME (current_function_decl)) > - && DECL_FILE_SCOPE_P (current_function_decl)) > + && cgraph_main_function_p (cgraph_get_node (current_function_decl))) > incoming_stack_boundary = MAIN_STACK_BOUNDARY; > > return incoming_stack_boundary; > diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c > index 42e3af0..d1df127 100644 > --- a/gcc/config/pdp11/pdp11.c > +++ b/gcc/config/pdp11/pdp11.c > @@ -240,7 +240,8 @@ pdp11_expand_prologue (void) > > /* If we are outputting code for main, the switch FPU to the > right mode if TARGET_FPU. */ > - if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU) > + if (TARGET_FPU > + && cgraph_main_function_p (cgraph_get_node (current_function_decl))) > { > emit_insn (gen_setd ()); > emit_insn (gen_seti ()); > diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi > index 2891bb6..654f8ec 100644 > --- a/gcc/doc/tm.texi > +++ b/gcc/doc/tm.texi > @@ -8102,6 +8102,11 @@ systems. This macro is used in @code{assemble_name}. > Given a symbol @var{name}, perform same mangling as @code{varasm.c}'s @code{assemble_name}, but in memory rather than to a file stream, returning result as an @code{IDENTIFIER_NODE}. Required for correct LTO symtabs. The default implementation calls the @code{TARGET_STRIP_NAME_ENCODING} hook and then prepends the @code{USER_LABEL_PREFIX}, if any. > @end deftypefn > > +@deftypefn {Target Hook} tree TARGET_MAIN_ASSEMBLER_NAME (void) > +It returns the assembler name for the 'main' function. > +The default is to return 'main', which will be prefixed by USER_LABEL_PREFIX. > +@end deftypefn > + > @defmac ASM_OUTPUT_SYMBOL_REF (@var{stream}, @var{sym}) > A C statement (sans semicolon) to output a reference to > @code{SYMBOL_REF} @var{sym}. If not defined, @code{assemble_name} > diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in > index a222654..6765344 100644 > --- a/gcc/doc/tm.texi.in > +++ b/gcc/doc/tm.texi.in > @@ -8007,6 +8007,8 @@ systems. This macro is used in @code{assemble_name}. > > @hook TARGET_MANGLE_ASSEMBLER_NAME > > +@hook TARGET_MAIN_ASSEMBLER_NAME > + > @defmac ASM_OUTPUT_SYMBOL_REF (@var{stream}, @var{sym}) > A C statement (sans semicolon) to output a reference to > @code{SYMBOL_REF} @var{sym}. If not defined, @code{assemble_name} > diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c > index 8a1dd2e..a51b0ac 100644 > --- a/gcc/fortran/trans-decl.c > +++ b/gcc/fortran/trans-decl.c > @@ -4922,9 +4922,8 @@ create_main_function (tree fndecl) > tmp = build_function_type_list (integer_type_node, integer_type_node, > build_pointer_type (pchar_type_node), > NULL_TREE); > - main_identifier_node = get_identifier ("main"); > ftn_main = build_decl (input_location, FUNCTION_DECL, > - main_identifier_node, tmp); > + get_identifier ("main"), tmp); > DECL_EXTERNAL (ftn_main) = 0; > TREE_PUBLIC (ftn_main) = 1; > TREE_STATIC (ftn_main) = 1; > diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c > index 9dddf39..595330e 100644 > --- a/gcc/ipa-split.c > +++ b/gcc/ipa-split.c > @@ -1409,7 +1409,7 @@ execute_split_functions (void) > fprintf (dump_file, "Not splitting: noreturn/malloc function.\n"); > return 0; > } > - if (MAIN_NAME_P (DECL_NAME (current_function_decl))) > + if (cgraph_main_function_p (node)) > { > if (dump_file) > fprintf (dump_file, "Not splitting: main function.\n"); > diff --git a/gcc/ipa.c b/gcc/ipa.c > index 388291a..f9dc42d 100644 > --- a/gcc/ipa.c > +++ b/gcc/ipa.c > @@ -639,7 +639,7 @@ cgraph_externally_visible_p (struct cgraph_node *node, > else if (!whole_program) > return true; > > - if (MAIN_NAME_P (DECL_NAME (node->decl))) > + if (cgraph_main_function_p (node)) > return true; > > return false; > diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c > index 5e899bc..34bcc55 100644 > --- a/gcc/lto-cgraph.c > +++ b/gcc/lto-cgraph.c > @@ -502,6 +502,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, > bp_pack_value (&bp, node->local.versionable, 1); > bp_pack_value (&bp, node->local.can_change_signature, 1); > bp_pack_value (&bp, node->local.redefined_extern_inline, 1); > + bp_pack_value (&bp, node->local.main_function, 1); > bp_pack_value (&bp, node->needed, 1); > bp_pack_value (&bp, node->address_taken, 1); > bp_pack_value (&bp, node->abstract_and_needed, 1); > @@ -904,6 +905,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data, > node->local.versionable = bp_unpack_value (bp, 1); > node->local.can_change_signature = bp_unpack_value (bp, 1); > node->local.redefined_extern_inline = bp_unpack_value (bp, 1); > + node->local.main_function = bp_unpack_value (bp, 1); > node->needed = bp_unpack_value (bp, 1); > node->address_taken = bp_unpack_value (bp, 1); > node->abstract_and_needed = bp_unpack_value (bp, 1); > diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c > index 999db8b..a44a35f 100644 > --- a/gcc/lto/lto-lang.c > +++ b/gcc/lto/lto-lang.c > @@ -1137,13 +1137,6 @@ lto_init (void) > /* Create the basic integer types. */ > build_common_tree_nodes (flag_signed_char, /*short_double=*/false); > > - /* The global tree for the main identifier is filled in by > - language-specific front-end initialization that is not run in the > - LTO back-end. It appears that all languages that perform such > - initialization currently do so in the same way, so we do it here. */ > - if (main_identifier_node == NULL_TREE) > - main_identifier_node = get_identifier ("main"); > - > /* In the C++ front-end, fileptr_type_node is defined as a variant > copy of of ptr_type_node, rather than ptr_node itself. The > distinction should only be relevant to the front-end, so we > diff --git a/gcc/predict.c b/gcc/predict.c > index c12b45f..819e64c 100644 > --- a/gcc/predict.c > +++ b/gcc/predict.c > @@ -2275,7 +2275,7 @@ compute_function_frequency (void) > basic_block bb; > struct cgraph_node *node = cgraph_get_node (current_function_decl); > if (DECL_STATIC_CONSTRUCTOR (current_function_decl) > - || MAIN_NAME_P (DECL_NAME (current_function_decl))) > + || cgraph_main_function_p (node)) > node->only_called_at_startup = true; > if (DECL_STATIC_DESTRUCTOR (current_function_decl)) > node->only_called_at_exit = true; > @@ -2291,7 +2291,7 @@ compute_function_frequency (void) > node->frequency = NODE_FREQUENCY_HOT; > else if (flags & ECF_NORETURN) > node->frequency = NODE_FREQUENCY_EXECUTED_ONCE; > - else if (MAIN_NAME_P (DECL_NAME (current_function_decl))) > + else if (cgraph_main_function_p (node)) > node->frequency = NODE_FREQUENCY_EXECUTED_ONCE; > else if (DECL_STATIC_CONSTRUCTOR (current_function_decl) > || DECL_STATIC_DESTRUCTOR (current_function_decl)) > diff --git a/gcc/target.def b/gcc/target.def > index d658b11..2c91620 100644 > --- a/gcc/target.def > +++ b/gcc/target.def > @@ -1473,6 +1473,17 @@ DEFHOOK > tree, (tree decl, tree id), > default_mangle_decl_assembler_name) > > +/* Return the assembler name for the 'main' function. It should return the > + same identifier as mandle_decl_assembler_name will for the C 'main' > + function. > + The default is to return 'main'. */ > +DEFHOOK > +(main_assembler_name, > + "It returns the assembler name for the 'main' function.\n\ > +The default is to return 'main', which will be prefixed by USER_LABEL_PREFIX.", > + tree, (void), > + default_main_assembler_name) > + > /* Do something target-specific to record properties of the DECL into > the associated SYMBOL_REF. */ > DEFHOOK > diff --git a/gcc/targhooks.c b/gcc/targhooks.c > index 8e3d74e..08535b4 100644 > --- a/gcc/targhooks.c > +++ b/gcc/targhooks.c > @@ -371,6 +371,13 @@ default_mangle_assembler_name (const char *name ATTRIBUTE_UNUSED) > return get_identifier (stripped); > } > > +/* The default implementation of TARGET_MAIN_ASSEMBLER_NAME. */ > +tree > +default_main_assembler_name (void) > +{ > + return get_identifier ("main"); > +} > + > /* True if MODE is valid for the target. By "valid", we mean able to > be manipulated in non-trivial ways. In particular, this means all > the arithmetic is supported. > diff --git a/gcc/targhooks.h b/gcc/targhooks.h > index 8618115..3016f04 100644 > --- a/gcc/targhooks.h > +++ b/gcc/targhooks.h > @@ -66,6 +66,7 @@ extern void default_print_operand (FILE *, rtx, int); > extern void default_print_operand_address (FILE *, rtx); > extern bool default_print_operand_punct_valid_p (unsigned char); > extern tree default_mangle_assembler_name (const char *); > +extern tree default_main_assembler_name (void); > > extern bool default_scalar_mode_supported_p (enum machine_mode); > extern bool targhook_words_big_endian (void); > diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c > index b65f5aa..9cb7a16 100644 > --- a/gcc/tree-ssa-structalias.c > +++ b/gcc/tree-ssa-structalias.c > @@ -6933,7 +6933,7 @@ ipa_pta_execute (void) > > /* We also need to make function return values escape. Nothing > escapes by returning from main though. */ > - if (!MAIN_NAME_P (DECL_NAME (node->decl))) > + if (!cgraph_main_function_p (node->decl)) > { > varinfo_t fi, rvi; > fi = lookup_vi_for_tree (node->decl); > diff --git a/gcc/tree.c b/gcc/tree.c > index cfea9f7..6a0d380 100644 > --- a/gcc/tree.c > +++ b/gcc/tree.c > @@ -9477,6 +9477,8 @@ build_common_tree_nodes (bool signed_char, bool short_double) > > va_list_type_node = t; > } > + > + main_assembler_name = targetm.main_assembler_name (); > } > > /* A subroutine of build_common_builtin_nodes. Define a builtin function. */ > diff --git a/gcc/tree.h b/gcc/tree.h > index 62ee454..45c750f 100644 > --- a/gcc/tree.h > +++ b/gcc/tree.h > @@ -3805,7 +3805,7 @@ enum tree_index > > TI_VOID_LIST_NODE, > > - TI_MAIN_IDENTIFIER, > + TI_MAIN_ASSEMBLER_NAME, > > TI_SAT_SFRACT_TYPE, > TI_SAT_FRACT_TYPE, > @@ -4048,9 +4048,7 @@ extern GTY(()) tree global_trees[TI_MAX]; > anything else about this node. */ > #define void_list_node global_trees[TI_VOID_LIST_NODE] > > -#define main_identifier_node global_trees[TI_MAIN_IDENTIFIER] > -#define MAIN_NAME_P(NODE) \ > - (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node) > +#define main_assembler_name global_trees[TI_MAIN_ASSEMBLER_NAME] > > /* Optimization options (OPTIMIZATION_NODE) to use for default and current > functions. */ > >
On Mar 20, 2012, at 5:01 PM, Richard Guenther wrote: > On Tue, 20 Mar 2012, Tristan Gingold wrote: > >> >> On Mar 20, 2012, at 3:19 PM, Richard Guenther wrote: >> >> […] >>> >>> I'd rather get away from using a global main_identifier_node, instead >>> make that frontend specific, and introduce targetm.main_assembler_name >>> which the assembler-name creating langhook would make sure to use >>> when mangling what the FE thinks main is. main_identifier_node should >>> not serve any purpose outside of Frontends. >>> >>> But I see both as a possible cleanup opportunity, not a necessary change. >> >> Something along these lines ? > > Yes, but I'd simply call the hook at the places you now use > main_assembler_name and not create a global tree node for it. But we use it at the beginning of graph_finalize_function, so caching it makes sense, doesn't it ? Tristan.
On Tue, 20 Mar 2012, Tristan Gingold wrote: > > On Mar 20, 2012, at 5:01 PM, Richard Guenther wrote: > > > On Tue, 20 Mar 2012, Tristan Gingold wrote: > > > >> > >> On Mar 20, 2012, at 3:19 PM, Richard Guenther wrote: > >> > >> [...] > >>> > >>> I'd rather get away from using a global main_identifier_node, instead > >>> make that frontend specific, and introduce targetm.main_assembler_name > >>> which the assembler-name creating langhook would make sure to use > >>> when mangling what the FE thinks main is. main_identifier_node should > >>> not serve any purpose outside of Frontends. > >>> > >>> But I see both as a possible cleanup opportunity, not a necessary change. > >> > >> Something along these lines ? > > > > Yes, but I'd simply call the hook at the places you now use > > main_assembler_name and not create a global tree node for it. > > But we use it at the beginning of graph_finalize_function, so caching it > makes sense, doesn't it ? Well, maybe ;) I have no strong opinion here. Richard.
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 89f5438..c575e97 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -622,8 +622,6 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED, integer_type_node, NULL_TREE, true, false, true, false, NULL, Empty); - main_identifier_node = get_identifier ("main"); - /* Install the builtins we might need, either internally or as user available facilities for Intrinsic imports. */ gnat_install_builtins (); diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 7383358..b0fa085d 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -1902,14 +1902,12 @@ create_subprog_decl (tree subprog_name, tree asm_name, tree subprog_type, { SET_DECL_ASSEMBLER_NAME (subprog_decl, asm_name); - /* The expand_main_function circuitry expects "main_identifier_node" to - designate the DECL_NAME of the 'main' entry point, in turn expected - to be declared as the "main" function literally by default. Ada - program entry points are typically declared with a different name + /* Ada program entry points are typically declared with a different name within the binder generated file, exported as 'main' to satisfy the - system expectations. Force main_identifier_node in this case. */ - if (asm_name == main_identifier_node) - DECL_NAME (subprog_decl) = main_identifier_node; + system expectations. Force main_assembler_node in this case. */ + if (IDENTIFIER_LENGTH (asm_name) == 4 + && memcmp (IDENTIFIER_POINTER (asm_name), "main", 4) == 0) + DECL_NAME (subprog_decl) = main_assembler_name; } /* Add this decl to the current binding level. */ diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 835b13b..fea5181 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -291,6 +291,8 @@ enum c_tree_index CTI_DEFAULT_FUNCTION_TYPE, + CTI_MAIN_IDENTIFIER, + /* These are not types, but we have to look them up all the time. */ CTI_FUNCTION_NAME_DECL, CTI_PRETTY_FUNCTION_NAME_DECL, @@ -426,6 +428,10 @@ extern const unsigned int num_c_common_reswords; #define default_function_type c_global_trees[CTI_DEFAULT_FUNCTION_TYPE] +#define main_identifier_node c_global_trees[CTI_MAIN_IDENTIFIER] +#define MAIN_NAME_P(NODE) \ + (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node) + #define function_name_decl_node c_global_trees[CTI_FUNCTION_NAME_DECL] #define pretty_function_name_decl_node c_global_trees[CTI_PRETTY_FUNCTION_NAME_DECL] #define c99_function_name_decl_node c_global_trees[CTI_C99_FUNCTION_NAME_DECL] diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index bd21169..db53309 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -4513,9 +4513,7 @@ gimple_expand_cfg (void) /* If this function is `main', emit a call to `__main' to run global initializers, etc. */ - if (DECL_NAME (current_function_decl) - && MAIN_NAME_P (DECL_NAME (current_function_decl)) - && DECL_FILE_SCOPE_P (current_function_decl)) + if (cgraph_main_function_p (cgraph_get_node (current_function_decl))) expand_main_function (); /* Initialize the stack_protect_guard field. This must happen after the diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 9cc3690..528fd19 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2766,7 +2766,7 @@ cgraph_propagate_frequency_1 (struct cgraph_node *node, void *data) /* It makes sense to put main() together with the static constructors. It will be executed for sure, but rest of functions called from main are definitely not at startup only. */ - if (MAIN_NAME_P (DECL_NAME (edge->caller->decl))) + if (cgraph_main_function_p (edge->caller)) d->only_called_at_startup = 0; d->only_called_at_exit &= edge->caller->only_called_at_exit; } diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 191364c..089d851 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -101,6 +101,9 @@ struct GTY(()) cgraph_local_info { /* True if the function may enter serial irrevocable mode. */ unsigned tm_may_enter_irr : 1; + + /* True if the function is the program entry point (main in C). */ + unsigned main_function : 1; }; /* Information about the function that needs to be computed globally @@ -790,6 +793,13 @@ cgraph_next_function_with_gimple_body (struct cgraph_node *node) return NULL; } +/* Return true iff NODE is the main function (main in C). */ +static inline bool +cgraph_main_function_p (struct cgraph_node *node) +{ + return node && node->local.main_function; +} + /* Walk all functions with body defined. */ #define FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node) \ for ((node) = cgraph_first_function_with_gimple_body (); (node); \ diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 516f187..556f21c 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -346,6 +346,9 @@ cgraph_finalize_function (tree decl, bool nested) notice_global_symbol (decl); node->local.finalized = true; node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL; + node->local.main_function = + DECL_FILE_SCOPE_P (decl) + && decl_assembler_name_equal (decl, main_assembler_name); if (cgraph_decide_is_function_needed (node, decl)) cgraph_mark_needed_node (node); diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h index 2eccda9..e0f6234 100644 --- a/gcc/config/i386/cygming.h +++ b/gcc/config/i386/cygming.h @@ -360,7 +360,7 @@ do { \ #undef PROFILE_HOOK #define PROFILE_HOOK(LABEL) \ - if (MAIN_NAME_P (DECL_NAME (current_function_decl))) \ + if (cgraph_main_function_p (cgraph_get_node (current_function_decl))) \ { \ emit_call_insn (gen_rtx_CALL (VOIDmode, \ gen_rtx_MEM (FUNCTION_MODE, \ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 78a366e..c4a78b1 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -9509,9 +9509,7 @@ ix86_minimum_incoming_stack_boundary (bool sibcall) /* Stack at entrance of main is aligned by runtime. We use the smallest incoming stack boundary. */ if (incoming_stack_boundary > MAIN_STACK_BOUNDARY - && DECL_NAME (current_function_decl) - && MAIN_NAME_P (DECL_NAME (current_function_decl)) - && DECL_FILE_SCOPE_P (current_function_decl)) + && cgraph_main_function_p (cgraph_get_node (current_function_decl))) incoming_stack_boundary = MAIN_STACK_BOUNDARY; return incoming_stack_boundary; diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c index 42e3af0..d1df127 100644 --- a/gcc/config/pdp11/pdp11.c +++ b/gcc/config/pdp11/pdp11.c @@ -240,7 +240,8 @@ pdp11_expand_prologue (void) /* If we are outputting code for main, the switch FPU to the right mode if TARGET_FPU. */ - if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU) + if (TARGET_FPU + && cgraph_main_function_p (cgraph_get_node (current_function_decl))) { emit_insn (gen_setd ()); emit_insn (gen_seti ()); diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 2891bb6..654f8ec 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -8102,6 +8102,11 @@ systems. This macro is used in @code{assemble_name}. Given a symbol @var{name}, perform same mangling as @code{varasm.c}'s @code{assemble_name}, but in memory rather than to a file stream, returning result as an @code{IDENTIFIER_NODE}. Required for correct LTO symtabs. The default implementation calls the @code{TARGET_STRIP_NAME_ENCODING} hook and then prepends the @code{USER_LABEL_PREFIX}, if any. @end deftypefn +@deftypefn {Target Hook} tree TARGET_MAIN_ASSEMBLER_NAME (void) +It returns the assembler name for the 'main' function. +The default is to return 'main', which will be prefixed by USER_LABEL_PREFIX. +@end deftypefn + @defmac ASM_OUTPUT_SYMBOL_REF (@var{stream}, @var{sym}) A C statement (sans semicolon) to output a reference to @code{SYMBOL_REF} @var{sym}. If not defined, @code{assemble_name} diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index a222654..6765344 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -8007,6 +8007,8 @@ systems. This macro is used in @code{assemble_name}. @hook TARGET_MANGLE_ASSEMBLER_NAME +@hook TARGET_MAIN_ASSEMBLER_NAME + @defmac ASM_OUTPUT_SYMBOL_REF (@var{stream}, @var{sym}) A C statement (sans semicolon) to output a reference to @code{SYMBOL_REF} @var{sym}. If not defined, @code{assemble_name} diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 8a1dd2e..a51b0ac 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -4922,9 +4922,8 @@ create_main_function (tree fndecl) tmp = build_function_type_list (integer_type_node, integer_type_node, build_pointer_type (pchar_type_node), NULL_TREE); - main_identifier_node = get_identifier ("main"); ftn_main = build_decl (input_location, FUNCTION_DECL, - main_identifier_node, tmp); + get_identifier ("main"), tmp); DECL_EXTERNAL (ftn_main) = 0; TREE_PUBLIC (ftn_main) = 1; TREE_STATIC (ftn_main) = 1; diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index 9dddf39..595330e 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -1409,7 +1409,7 @@ execute_split_functions (void) fprintf (dump_file, "Not splitting: noreturn/malloc function.\n"); return 0; } - if (MAIN_NAME_P (DECL_NAME (current_function_decl))) + if (cgraph_main_function_p (node)) { if (dump_file) fprintf (dump_file, "Not splitting: main function.\n"); diff --git a/gcc/ipa.c b/gcc/ipa.c index 388291a..f9dc42d 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -639,7 +639,7 @@ cgraph_externally_visible_p (struct cgraph_node *node, else if (!whole_program) return true; - if (MAIN_NAME_P (DECL_NAME (node->decl))) + if (cgraph_main_function_p (node)) return true; return false; diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 5e899bc..34bcc55 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -502,6 +502,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, bp_pack_value (&bp, node->local.versionable, 1); bp_pack_value (&bp, node->local.can_change_signature, 1); bp_pack_value (&bp, node->local.redefined_extern_inline, 1); + bp_pack_value (&bp, node->local.main_function, 1); bp_pack_value (&bp, node->needed, 1); bp_pack_value (&bp, node->address_taken, 1); bp_pack_value (&bp, node->abstract_and_needed, 1); @@ -904,6 +905,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data, node->local.versionable = bp_unpack_value (bp, 1); node->local.can_change_signature = bp_unpack_value (bp, 1); node->local.redefined_extern_inline = bp_unpack_value (bp, 1); + node->local.main_function = bp_unpack_value (bp, 1); node->needed = bp_unpack_value (bp, 1); node->address_taken = bp_unpack_value (bp, 1); node->abstract_and_needed = bp_unpack_value (bp, 1); diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index 999db8b..a44a35f 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -1137,13 +1137,6 @@ lto_init (void) /* Create the basic integer types. */ build_common_tree_nodes (flag_signed_char, /*short_double=*/false); - /* The global tree for the main identifier is filled in by - language-specific front-end initialization that is not run in the - LTO back-end. It appears that all languages that perform such - initialization currently do so in the same way, so we do it here. */ - if (main_identifier_node == NULL_TREE) - main_identifier_node = get_identifier ("main"); - /* In the C++ front-end, fileptr_type_node is defined as a variant copy of of ptr_type_node, rather than ptr_node itself. The distinction should only be relevant to the front-end, so we diff --git a/gcc/predict.c b/gcc/predict.c index c12b45f..819e64c 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -2275,7 +2275,7 @@ compute_function_frequency (void) basic_block bb; struct cgraph_node *node = cgraph_get_node (current_function_decl); if (DECL_STATIC_CONSTRUCTOR (current_function_decl) - || MAIN_NAME_P (DECL_NAME (current_function_decl))) + || cgraph_main_function_p (node)) node->only_called_at_startup = true; if (DECL_STATIC_DESTRUCTOR (current_function_decl)) node->only_called_at_exit = true; @@ -2291,7 +2291,7 @@ compute_function_frequency (void) node->frequency = NODE_FREQUENCY_HOT; else if (flags & ECF_NORETURN) node->frequency = NODE_FREQUENCY_EXECUTED_ONCE; - else if (MAIN_NAME_P (DECL_NAME (current_function_decl))) + else if (cgraph_main_function_p (node)) node->frequency = NODE_FREQUENCY_EXECUTED_ONCE; else if (DECL_STATIC_CONSTRUCTOR (current_function_decl) || DECL_STATIC_DESTRUCTOR (current_function_decl)) diff --git a/gcc/target.def b/gcc/target.def index d658b11..2c91620 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1473,6 +1473,17 @@ DEFHOOK tree, (tree decl, tree id), default_mangle_decl_assembler_name) +/* Return the assembler name for the 'main' function. It should return the + same identifier as mandle_decl_assembler_name will for the C 'main' + function. + The default is to return 'main'. */ +DEFHOOK +(main_assembler_name, + "It returns the assembler name for the 'main' function.\n\ +The default is to return 'main', which will be prefixed by USER_LABEL_PREFIX.", + tree, (void), + default_main_assembler_name) + /* Do something target-specific to record properties of the DECL into the associated SYMBOL_REF. */ DEFHOOK diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 8e3d74e..08535b4 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -371,6 +371,13 @@ default_mangle_assembler_name (const char *name ATTRIBUTE_UNUSED) return get_identifier (stripped); } +/* The default implementation of TARGET_MAIN_ASSEMBLER_NAME. */ +tree +default_main_assembler_name (void) +{ + return get_identifier ("main"); +} + /* True if MODE is valid for the target. By "valid", we mean able to be manipulated in non-trivial ways. In particular, this means all the arithmetic is supported. diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 8618115..3016f04 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -66,6 +66,7 @@ extern void default_print_operand (FILE *, rtx, int); extern void default_print_operand_address (FILE *, rtx); extern bool default_print_operand_punct_valid_p (unsigned char); extern tree default_mangle_assembler_name (const char *); +extern tree default_main_assembler_name (void); extern bool default_scalar_mode_supported_p (enum machine_mode); extern bool targhook_words_big_endian (void); diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index b65f5aa..9cb7a16 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -6933,7 +6933,7 @@ ipa_pta_execute (void) /* We also need to make function return values escape. Nothing escapes by returning from main though. */ - if (!MAIN_NAME_P (DECL_NAME (node->decl))) + if (!cgraph_main_function_p (node->decl)) { varinfo_t fi, rvi; fi = lookup_vi_for_tree (node->decl); diff --git a/gcc/tree.c b/gcc/tree.c index cfea9f7..6a0d380 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -9477,6 +9477,8 @@ build_common_tree_nodes (bool signed_char, bool short_double) va_list_type_node = t; } + + main_assembler_name = targetm.main_assembler_name (); } /* A subroutine of build_common_builtin_nodes. Define a builtin function. */ diff --git a/gcc/tree.h b/gcc/tree.h index 62ee454..45c750f 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3805,7 +3805,7 @@ enum tree_index TI_VOID_LIST_NODE, - TI_MAIN_IDENTIFIER, + TI_MAIN_ASSEMBLER_NAME, TI_SAT_SFRACT_TYPE, TI_SAT_FRACT_TYPE, @@ -4048,9 +4048,7 @@ extern GTY(()) tree global_trees[TI_MAX]; anything else about this node. */ #define void_list_node global_trees[TI_VOID_LIST_NODE] -#define main_identifier_node global_trees[TI_MAIN_IDENTIFIER] -#define MAIN_NAME_P(NODE) \ - (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node) +#define main_assembler_name global_trees[TI_MAIN_ASSEMBLER_NAME] /* Optimization options (OPTIMIZATION_NODE) to use for default and current functions. */