Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

getarg does not work?

vincenzo_s_
Beginner
1,093 Views

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

 

0 Kudos
9 Replies
TimP
Honored Contributor III
1,093 Views

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.

0 Kudos
Steven_L_Intel1
Employee
1,093 Views

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.

0 Kudos
Martyn_C_Intel
Employee
1,093 Views

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.

0 Kudos
vincenzo_s_
Beginner
1,093 Views

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

 

0 Kudos
Steven_L_Intel1
Employee
1,093 Views

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.

0 Kudos
vincenzo_s_
Beginner
1,093 Views

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

 

0 Kudos
Martyn_C_Intel
Employee
1,093 Views

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.

0 Kudos
Steven_L_Intel1
Employee
1,093 Views

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.)

0 Kudos
Martyn_C_Intel
Employee
1,093 Views

A fix for this is in progress, though it likely won't appear before the next major compiler version.

0 Kudos
Reply