- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
i'm porting some programs from 32 bit linux suse to 64 bit linux suse.
in 32 bit version i use fortran compiler XE 12.0 update 2 for linux
in 64 bit version i use XE 13.1 for linux
function getarg seems not work in 64 bit version.
test.f90:
program test
implicit none
integer*4 ::iarg
character(len=64)::string,string1,string2
iarg = iargc()
write(*,*) iarg
call getarg(1,string )
write(*,*) 'test --- ',string
pause
read(string,*)string1
write(*,*)'string1= ',string1
!
call getarg(2,string)
read(string,*)string2
write(*,*)'string2= ',string2
!
stop ' ok'
end program test
-------------------------------------------------------------
ifort -g -c -traceback -noalign -integer-size 16 -double-size 64 -132 -O0 -assume dummy_aliases -assume byterecl -warn noalignments test.f90
ifort -o test.out test.o
------------------------------------------------------------------------
EXEC in 64 bit:
./test.out str1 str2
2
test ---
FORTRAN PAUSE
PAUSE prompt>
forrtl: severe (24): end-of-file during read, unit -5, file Internal List-Directed Read
Image PC Routine Line Source
test.out 00000000004749AE Unknown Unknown Unknown
test.out 0000000000473446 Unknown Unknown Unknown
test.out 0000000000449942 Unknown Unknown Unknown
test.out 000000000042D13B Unknown Unknown Unknown
test.out 000000000042C6A2 Unknown Unknown Unknown
test.out 0000000000408EAB Unknown Unknown Unknown
test.out 00000000004076DC Unknown Unknown Unknown
test.out 0000000000403013 MAIN__ 13 test.f90
test.out 0000000000402E2C Unknown Unknown Unknown
libc.so.6 00007FBEA99F4A15 Unknown Unknown Unknown
test.out 0000000000402D29 Unknown Unknown Unknown
------------------------------------------
EXEC in 32 bit:
./test.out str1 str2
2
test --- str1
FORTRAN PAUSE
PAUSE prompt>
string1= str1
string2= str2
ok
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I suppose your integer-size option may break your iargc() call, which anyway is broken as Fortran requires explicit interface for the case of null and optional arguments. Unfortunately, the ifort documentation doesn't say whether supplied 'USE ifposix' or INCLUDE file would take care of this. This might be the time to update your code to Fortran 2003 or later in this respect (command_argument_count, get_command_argument intrinsic procedures). integer(int32) is available in current ifort and gfortran (not sure about your compiler which has aged out of support).
I'd hate to see the source code which needs integer-size 16; this makes even less sense to use in 64-bit mode.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'll note that Intel Fortran treats iargc and getarg as intrinsics, so no declaration is needed. I see that Martyn is investigating this, so wait for his reply.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I believe the problem results from compiling with -integer-size 16
This has the effect of converting the first argument of getarg from integer(4) to integer(2), whereas GETARG only accepts integer(4) or integer(8) arguments. The simplest way to work around this, assuming you really want to use -integer-size 16, is to make the argument explicitly kind=4 i.e., integer(4):
call getarg(1_4,string )
call getarg(2_4,string )
As to why this works on IA-32, I can't say; it might depend on what gets overwritten by the extra 2 bytes that GETARG returns but the main program is not expecting. Or maybe an integer(2) version was implemented for IA-32, but somehow got omitted for Intel64. The documentation of GETARG does not explicitly exclude integer(2) arguments.
It's not immediately clear to me whether the compiler ought to be able to detect the argument mismatch at compile time, assuming that integer(2) is not supported. I could not find a header for an interface block for GETARG, and adding USE IFLPORT to your code did not detect the mismatch; on the other hand, getarg is considered an intrinsic subroutine. I'll find out what is the intended behavior, and file a ticket to get the appropriate things fixed. In the meantime, please use the workaround above.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Martyn
The problem, i think, is exactly as you say due to -integer-size 16.
if i use this code:
integer*4 ::iarg,ind
character(len=64)::string,string1,string2
iarg = iargc()
write(*,*) iarg
ind=1
call getarg(ind,string )
write(*,*) 'test --- ',string
defining ind as i*4 and using it in getarg the program work fine
Unfortunately i need -integer-size 16 for my code ( not for this test code; i intensively use EQUIVALENCE ed COMMON).
Some of my oldest routines came from PDP11 fortran, VAX fortran, SCO fortran(LIANT), Digital Visual Fortran, Compaq Visual fortran and so on....
But,... however..... i think this fact is in great discordance whith fortran-rules itself, isn't it so?
One of the great pecularity of fortran is (was?) that, by default, parameters are passed by reference in a "blind" mode.
For the number "1" or "2" or "16535", I*2 and I*4 have the same bit representation ( for the first 2 bytes) and the reference of i*2 parameter fall whithin i*4 ( byte 0 aligned).
How can "1", passed as i*2 instead of I*4, create problem to compiler (fortran)?
Does it means that passing mechanism is not so "fortran compliant"?
:) :)
Thank to all.
Vincenzo
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is nothing in the Fortran language about this - it's a consequence of whether the system uses little-endian or big-endian byte ordering. But if you pass a 16-bit integer to a routine that is expecting a 32-bit, the called routine will try to read 32 bits and pick up "garbage" in the high order 16 bits.
As I wrote above, getarg is now a compiler intrinsic. The library has a variant of getarg, for_getarg_i2 for 16-bit arguments, but it isn't being used in this case. That's a compiler bug - Martyn, please include this in your bug report.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve,
thanks for your answer.
The problem is clearly defined and i'll update ( correct?) my old routines to avoid this occurrence.
However....i think i'm too old for this stuff..(Danny Glover as Roger).
:) :) :)
Thanks again
Vincenzo
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've updated the bug report. Strange that there's a separate entry point for i2, but not for i8 (which works).
I see the same issue on IA-32, contrary to Vincenzo's original report.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
One might argue that an i8 entry point isn't needed as the argument count can't ever get that big, but it could lead to returning an argument where it should instead return none if the user passes a value greater than 2**32-1. I can't get terribly excited about this, but as an intrinsic, it either should be defined for all integer kinds or the compiler should give an error if an unsupported kind is passed. I also noticed that the compiler accepts an INTEGER(1) argument but passes it to the I4 routine, which is another aspect of the same problem. (There is no I1 library routine.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A fix for this is in progress, though it likely won't appear before the next major compiler version.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page