This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][fortran] Use a TRANSLATION_UNIT_DECL for DECL_CONTEXT
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: fortran at gcc dot gnu dot org
- Date: Fri, 17 Sep 2010 13:55:51 +0200 (CEST)
- Subject: [PATCH][fortran] Use a TRANSLATION_UNIT_DECL for DECL_CONTEXT
This transitions the Fortran frontend to use a TRANSLATION_UNIT_DECL
for DECL_CONTEXT of global entities. This will allow LTO to produce
proper language specific debug information.
The patch leaves some DECL_CONTEXT tests for NULL untouched, as the
FE seems to have both test-for-globalness and test-for-not-yet-initialized
tests - I'd appreciate if somebody could go over those in the Frontend
and use DECL_FILE_SCOPE_P for those that really mean it.
I'm also somewhat confused about binding-level use - for modules
its state seems to be strange. Maybe somebody can shed a light
on this. (Possibly module decls want to use a different T_U_D
in the future as well)
As of the ???s in the patch:
/* Create the variable. */
pushdecl (decl);
/* Why is current_binding_level == global_binding_level here?
gcc_assert (DECL_CONTEXT (decl) == NULL_TREE); */
gcc_assert (sym->ns->proc_name->attr.flavor == FL_MODULE);
DECL_CONTEXT (decl) = sym->ns->proc_name->backend_decl;
this (and the other two similar cases) seems to assert that
pushdecl doesn't set DECL_CONTEXT (well, before my patch
it set it to current_function_decl which is NULL). So, does
this check that the decl is at file-scope or does it want to
test that current_function_decl is NULL?
Bootstrap and regtest re-running after some minor changes on
x86_64-unknown-linux-gnu. Any idea about the above?
Thanks,
Richard.
2010-09-17 Richard Guenther <rguenther@suse.de>
* f95-lang.c (current_translation_unit): New global variable.
(gfc_create_decls): Build a translation-unit decl.
(pushdecl): In the global binding-level use the
translation-unit decl as DECL_CONTEXT.
* trans-decl.c (gfc_get_symbol_decl): Use DECL_FILE_SCOPE_P.
(build_function_decl): Likewise. Delay setting the assembler
name, leave setting of DECL_CONTEXT to pushdecl.
(trans_function_start): Use DECL_FILE_SCOPE_P.
(gfc_create_module_variable): Likewise. Add some ???s
* trans.c (gfc_generate_module_code): Likewise.
Index: gcc/fortran/f95-lang.c
===================================================================
*** gcc/fortran/f95-lang.c.orig 2010-09-17 12:40:00.000000000 +0200
--- gcc/fortran/f95-lang.c 2010-09-17 13:42:18.000000000 +0200
*************** tree *ridpointers = NULL;
*** 172,177 ****
--- 172,180 ----
/* True means we've initialized exception handling. */
bool gfc_eh_initialized_p;
+ /* The current translation unit. */
+ static GTY(()) tree current_translation_unit;
+
/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
or validate its data type for an `if' or `while' statement or ?..: exp.
*************** gfc_create_decls (void)
*** 229,234 ****
--- 232,240 ----
gfc_build_builtin_function_decls ();
gfc_init_constants ();
+
+ /* Build our translation-unit decl. */
+ current_translation_unit = build_translation_unit_decl (NULL_TREE);
}
*************** tree
*** 491,498 ****
pushdecl (tree decl)
{
/* External objects aren't nested, other objects may be. */
! if ((DECL_EXTERNAL (decl)) || (decl == current_function_decl))
! DECL_CONTEXT (decl) = 0;
else
DECL_CONTEXT (decl) = current_function_decl;
--- 497,506 ----
pushdecl (tree decl)
{
/* External objects aren't nested, other objects may be. */
! if (DECL_EXTERNAL (decl))
! DECL_CONTEXT (decl) = NULL_TREE;
! else if (global_bindings_p ())
! DECL_CONTEXT (decl) = current_translation_unit;
else
DECL_CONTEXT (decl) = current_function_decl;
Index: gcc/fortran/trans-decl.c
===================================================================
*** gcc/fortran/trans-decl.c.orig 2010-09-17 12:40:00.000000000 +0200
--- gcc/fortran/trans-decl.c 2010-09-17 13:40:49.000000000 +0200
*************** gfc_get_symbol_decl (gfc_symbol * sym)
*** 1089,1095 ****
else
length = sym->ts.u.cl->backend_decl;
if (TREE_CODE (length) == VAR_DECL
! && DECL_CONTEXT (length) == NULL_TREE)
{
/* Add the string length to the same context as the symbol. */
if (DECL_CONTEXT (sym->backend_decl) == current_function_decl)
--- 1089,1095 ----
else
length = sym->ts.u.cl->backend_decl;
if (TREE_CODE (length) == VAR_DECL
! && DECL_FILE_SCOPE_P (length))
{
/* Add the string length to the same context as the symbol. */
if (DECL_CONTEXT (sym->backend_decl) == current_function_decl)
*************** build_function_decl (gfc_symbol * sym, b
*** 1631,1639 ****
/* Allow only one nesting level. Allow public declarations. */
gcc_assert (current_function_decl == NULL_TREE
! || DECL_CONTEXT (current_function_decl) == NULL_TREE
! || TREE_CODE (DECL_CONTEXT (current_function_decl))
! == NAMESPACE_DECL);
type = gfc_get_function_type (sym);
fndecl = build_decl (input_location,
--- 1631,1639 ----
/* Allow only one nesting level. Allow public declarations. */
gcc_assert (current_function_decl == NULL_TREE
! || DECL_FILE_SCOPE_P (current_function_decl)
! || (TREE_CODE (DECL_CONTEXT (current_function_decl))
! == NAMESPACE_DECL));
type = gfc_get_function_type (sym);
fndecl = build_decl (input_location,
*************** build_function_decl (gfc_symbol * sym, b
*** 1644,1653 ****
attributes = add_attributes_to_decl (attr, NULL_TREE);
decl_attributes (&fndecl, attributes, 0);
- /* Perform name mangling if this is a top level or module procedure. */
- if (current_function_decl == NULL_TREE)
- gfc_set_decl_assembler_name (fndecl, gfc_sym_mangled_function_id (sym));
-
/* Figure out the return type of the declared function, and build a
RESULT_DECL for it. If this is a subroutine with alternate
returns, build a RESULT_DECL for it. */
--- 1644,1649 ----
*************** build_function_decl (gfc_symbol * sym, b
*** 1695,1706 ****
layout_decl (result_decl, 0); */
/* Set up all attributes for the function. */
- DECL_CONTEXT (fndecl) = current_function_decl;
DECL_EXTERNAL (fndecl) = 0;
/* This specifies if a function is globally visible, i.e. it is
the opposite of declaring static in C. */
! if (DECL_CONTEXT (fndecl) == NULL_TREE
&& !sym->attr.entry_master && !sym->attr.is_main_program)
TREE_PUBLIC (fndecl) = 1;
--- 1691,1701 ----
layout_decl (result_decl, 0); */
/* Set up all attributes for the function. */
DECL_EXTERNAL (fndecl) = 0;
/* This specifies if a function is globally visible, i.e. it is
the opposite of declaring static in C. */
! if (!current_function_decl
&& !sym->attr.entry_master && !sym->attr.is_main_program)
TREE_PUBLIC (fndecl) = 1;
*************** build_function_decl (gfc_symbol * sym, b
*** 1729,1734 ****
--- 1724,1733 ----
else
pushdecl (fndecl);
+ /* Perform name mangling if this is a top level or module procedure. */
+ if (current_function_decl == NULL_TREE)
+ gfc_set_decl_assembler_name (fndecl, gfc_sym_mangled_function_id (sym));
+
sym->backend_decl = fndecl;
}
*************** trans_function_start (gfc_symbol * sym)
*** 1976,1982 ****
/* Let the world know what we're about to do. */
announce_function (fndecl);
! if (DECL_CONTEXT (fndecl) == NULL_TREE)
{
/* Create RTL for function declaration. */
rest_of_decl_compilation (fndecl, 1, 0);
--- 1975,1981 ----
/* Let the world know what we're about to do. */
announce_function (fndecl);
! if (DECL_FILE_SCOPE_P (fndecl))
{
/* Create RTL for function declaration. */
rest_of_decl_compilation (fndecl, 1, 0);
*************** gfc_create_module_variable (gfc_symbol *
*** 3583,3589 ****
if ((sym->attr.in_common || sym->attr.in_equivalence) && sym->backend_decl)
{
decl = sym->backend_decl;
! gcc_assert (DECL_CONTEXT (decl) == NULL_TREE);
gcc_assert (sym->ns->proc_name->attr.flavor == FL_MODULE);
DECL_CONTEXT (decl) = sym->ns->proc_name->backend_decl;
gfc_module_add_decl (cur_module, decl);
--- 3582,3588 ----
if ((sym->attr.in_common || sym->attr.in_equivalence) && sym->backend_decl)
{
decl = sym->backend_decl;
! gcc_assert (DECL_FILE_SCOPE_P (decl));
gcc_assert (sym->ns->proc_name->attr.flavor == FL_MODULE);
DECL_CONTEXT (decl) = sym->ns->proc_name->backend_decl;
gfc_module_add_decl (cur_module, decl);
*************** gfc_create_module_variable (gfc_symbol *
*** 3610,3616 ****
/* Create the variable. */
pushdecl (decl);
! gcc_assert (DECL_CONTEXT (decl) == NULL_TREE);
gcc_assert (sym->ns->proc_name->attr.flavor == FL_MODULE);
DECL_CONTEXT (decl) = sym->ns->proc_name->backend_decl;
rest_of_decl_compilation (decl, 1, 0);
--- 3609,3616 ----
/* Create the variable. */
pushdecl (decl);
! /* Why is current_binding_level == global_binding_level here?
! gcc_assert (DECL_CONTEXT (decl) == NULL_TREE); */
gcc_assert (sym->ns->proc_name->attr.flavor == FL_MODULE);
DECL_CONTEXT (decl) = sym->ns->proc_name->backend_decl;
rest_of_decl_compilation (decl, 1, 0);
Index: gcc/fortran/trans.c
===================================================================
*** gcc/fortran/trans.c.orig 2010-09-17 12:40:00.000000000 +0200
--- gcc/fortran/trans.c 2010-09-17 13:34:29.000000000 +0200
*************** gfc_generate_module_code (gfc_namespace
*** 1413,1425 ****
if (!n->proc_name)
continue;
gfc_create_function_decl (n, false);
! gcc_assert (DECL_CONTEXT (n->proc_name->backend_decl) == NULL_TREE);
DECL_CONTEXT (n->proc_name->backend_decl) = ns->proc_name->backend_decl;
gfc_module_add_decl (entry, n->proc_name->backend_decl);
for (el = ns->entries; el; el = el->next)
{
! gcc_assert (DECL_CONTEXT (el->sym->backend_decl) == NULL_TREE);
DECL_CONTEXT (el->sym->backend_decl) = ns->proc_name->backend_decl;
gfc_module_add_decl (entry, el->sym->backend_decl);
}
--- 1413,1426 ----
if (!n->proc_name)
continue;
+ /* ??? Why's the binding level not that of the module here? */
gfc_create_function_decl (n, false);
! /* gcc_assert (DECL_CONTEXT (n->proc_name->backend_decl) == NULL_TREE); */
DECL_CONTEXT (n->proc_name->backend_decl) = ns->proc_name->backend_decl;
gfc_module_add_decl (entry, n->proc_name->backend_decl);
for (el = ns->entries; el; el = el->next)
{
! /* gcc_assert (DECL_CONTEXT (el->sym->backend_decl) == NULL_TREE); */
DECL_CONTEXT (el->sym->backend_decl) = ns->proc_name->backend_decl;
gfc_module_add_decl (entry, el->sym->backend_decl);
}