Variable argument call does not work on 64-bit gfortran
Bob Deen
Bob.Deen@jpl.nasa.gov
Mon May 31 17:59:00 GMT 2010
Hello to all...
I have a very large legacy Fortran system that is riddled with calls to
variadic (stdarg) C routines. I know this is not a good idea, is not
supported, is platform/compiler specific, etc., and if I were to design
the interface now I would change it. However, this system consists of
200,000+ lines of Fortran code, with over 15,000 calls to these kinds of
routines, so changing it would be problematic, to say the least! I'm
stuck with having to deal with it.
I am also very well aware of all the pitfalls involved in calling C from
Fortran, including finding character string lengths, name mangling, pass
by reference, array ordering, and all that. Those are all solvable.
The system is already set up to handle this, with 10 different methods
currently implemented going all the way back to VAX/VMS (it's all
centralized; I can expound on it if you want but I don't think it's
relevant here).
Bottom line is, I'm perfectly happy with a compiler/OS specific solution
here.
With the prologue out of the way...
The problem boils down to a Fortran routine calling a C stdarg one. If
I can just get to the C, I can handle all the argument passing issues.
The following is the test case:
% cat yyy.f
program main
call xxx(5)
stop
end
% cat xxx.c
#include <stdio.h>
#include <stdarg.h>
void xxx_(int *v1, ...)
//void xxx_(int *v1)
{
printf("v1=%d\n",*v1);
}
% gfortran yyy.f xxx.c
% ./a.out
Segmentation fault
%
This fails on my current target platform (gfortran 4.1.3, Red Hat
Enterprise 5.5, 64-bit architecture). It works on all other platforms
I've tried, including the exact same system in 32-bit mode:
% gfortran -m32 yyy.f xxx.c
% ./a.out
v1=5
%
and on other identically-configured 32-bit machines. It also works if
you swap out the xxx_() declarations (to simply eliminate the "...").
It fails immediately, in the C function prologue; it appears to
calculate a jump point incorrectly which then fails (sometimes with
illegal instruction, sometimes with seg fault). It does not make it as
far as the actual C code, which limits my ability to work around the
problem.
After some research (including looking at the assembler code), it
appears that the x86_64 ABI is different for stdargs and non-stdargs
cases. And it seems like the gfortran compiler is using the non-stdargs
ABI.
This is right and proper, for the standard use of Fortran. But I'm
hoping there's some switch I can flip that will tell the compiler to
generate stdarg-compatible ABI calls (or alternatively, some way to
convince C to accept the non-stdarg ABI in the stdarg macros). Note
that we use no Fortran libraries other than intrinsics that we do not
build ourselves, so a global change of ABI would be fine (assuming
intrinsics still worked).
I'm also okay with moving to gfortran 4.4 if that would help.
Platform particulars (host name deleted for security reasons):
% uname -a
Linux xxx 2.6.18-194.3.1.el5 #1 SMP Sun May 2 04:17:42 EDT 2010 x86_64
x86_64 x86_64 GNU/Linux
% gfortran --version
GNU Fortran (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
Copyright (C) 2007 Free Software Foundation, Inc.
GNU Fortran comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of GNU Fortran
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING
% gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Thanks...
-Bob
Bob Deen @ NASA-JPL Multimission Image Processing Lab
Bob.Deen@jpl.nasa.gov
More information about the Fortran
mailing list