rfc: multiple decls for functions
Daniel Franke
franke.daniel@gmail.com
Fri Dec 19 20:33:00 GMT 2008
Hi all,
I spent some time with the multiple-decl-per function problem gfortran has. As
trans-* is nothing for the lighthearted, I'd like to get some comments before
proceeding.
First, what's the actual problem? Consider:
SUBROUTINE F()
CALL G()
END SUBROUTINE
SUBROUTINE G()
END SUBROUTINE
When translating, the following backend_decls are created:
building decl for subroutine: F (build_function_decl)
building decl for called subroutine: G (gfc_get_extern_function_decl)
building decl for subroutine: G (build_function_decl)
Now, whatever the optimizer might figure out about (global) G, e.g. G not
changing its arguments, it does not affect optimization of F as F has another,
second, decl for G (see also [1]). The same holds if G is declared before F!
FX worked on this problem earlier this year. When he finally got stuck, he
noted:
"The best way to fix this is to use the other approach:
file-scope resolution" [2].
Thus, I'd propose the following: create a list/table of known functions where
new decls are added to, using the mangled name as a key. Before adding a decl,
check the list if the mangled name already exists, if so, use that decl
instead of creating a new one. Above would then become:
looking up decl for subroutine F: not found
building decl for subroutine: F
adding decl for subroutine F to list
looking up decl for subroutine G: not found
building decl for subroutine: G
adding decl for subroutine G to list
looking up decl for subroutine G: found
The list could be implemented as hashtable (provided by libiberty).
Noteworthy side-effect: if multiple source-files are compiled simultaniously,
decls could be shared between the files if the list is not cleared in between.
Question is: do we want this, or should the list be cleared for each
compilation unit?
Generally, this seems to be straight forward. However, does this work for any
combination of functions/subroutines, if external, if contained, if in
modules, if ... any corner-cases that spring to mind? Maybe [3]?
Also, is there any other approach possible? PaulT pointed out on IRC that one
might get a working solution if a backend_decl would be added to struct
gsymbol. I haven't looked into this yet (because I haven't knowingly used
gsymbol before), but maybe someone could comment on this as well?
Thanks :)
Daniel
[1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23169
[2] http://gcc.gnu.org/ml/fortran/2008-08/msg00173.html
[3]
Would this be legal?
SUBROUTINE g()
END SUBROUTINE
SUBROUTINE f()
CALL g()
CONTAINS
SUBROUTINE g()
END SUBROUTINE
END SUBROUTINE
It is accepted by gfortran and the contained g() is called; nm shows
000000da T f_
0000006d t g.1501
00000000 T g_
Where does '.1501' come from? Is it possible to distinguish between global g()
and contained g() in the approach outlined above?
If F and G as shown above are grouped into a module (MODULE m), nm shows:
0000006d T __m_MOD_f
00000000 t g.1501
0000007a T g_
Should G/contained G not be mangled here (as it is if the contained G is
removed)?
$> cat callg.f90
USE m
CALL G()
END
$> gfortran-svn -g -Wall call2.f90 call.o
/tmp/ccsU0BKE.o: In function `MAIN__':
/home/daniel/pr/call2.f90:2: undefined reference to `__m_MOD_g'
collect2: ld returned 1 exit status
More information about the Fortran
mailing list