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 ?
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. */