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

%VAL sign extends and passes incorrect address C275A0CC becomes FFFFFFFFC275A0CC

JP_SECTOR7_COM
New Contributor I
400 Views

FYI: Porting VMS FORTRAN (32 bit) to 64 bit IFORT
LIB$MOVC3/LIB$MOVC5 explodes (VMS equivalent of memcpy)

 

program meme
integer *4 source
!fix is to make 'source' INTEGER *8
!making source LOGICAL *4 does NOT fix the problem
!integer *8 source 
write (*,*) source
source = Z'c275a0cc'
write (*,'(Z16)') source
! iret = lib$movec5(,%val(source),,,)
call ccc(%val(source))
end program

subroutine ccc(addr)
integer *8 addr
write (*,'(Z16)') LOC(addr)
end subroutine

INCORRECT RUN (with integer *4 source)

-1032478516
C275A0CC
FFFFFFFFC275A0CC

 

CORRECT ADDRESS VALUE (with integer *8 source)

3262488780
C275A0CC
C275A0CC

VMS sign extends %VAL
gfortran does NOT sign extend %VAL

0 Kudos
3 Replies
Steve_Lionel
Honored Contributor III
381 Views

This looks like correct behavior to me. Fortran doesn't have unsigned integer types, so once you assign a value to a 32-bit integer that has the sign bit set, it's a negative number. The program is already incorrect in that an INTEGER(4) is passed to an INTEGER(8), so the results are implementation-dependent. Intel Fortran has an extension where it permits such a mismatch when the actual argument is an expression, and it sign-extends the value.

Your post title is not correct - it is not passing an address; it's passing a 32-bit integer value. That the called procedure interprets it as an address is another violation of language rules.

The proper way to do what I think you're doing here is to use C_F_POINTER to convert the integer value (you can use TRANSFER to "cast" the value to a C_PTR) to a Fortran POINTER and pass the POINTER.

I am well aware that this sort of hack was very common on VMS, but I never saw it done with mismatched address sizes.

 
 
mecej4
Honored Contributor III
375 Views

The program that you posted has several faults, so a compiler can do what it wants with it, including refusing to compile it into an executable.

  • The first WRITE statement outputs the value of an uninitialized variable.
  • The argument to subroutine CCC is 4 bytes long in the caller and 8 bytes in the subroutine.
  • Using BOZ in an assignment statement 

Steve Lionel has already addressed the second item. Regarding the third, the standard says:

C7109 (R764) A boz-literal-constant shall appear only as a data-stmt-constant in a DATA statement, or where 27 explicitly allowed in 16.9 as an actual argument of an intrinsic procedure.

A comment that I wish to make is that most of us do not know what VAX Fortran would have done with your code, and it is mostly up to you to decide what you wish the code to do now. 

Steve_Lionel
Honored Contributor III
363 Views

I know what VAX FORTRAN would have done... I was the project lead for a number of years. It would have said it had no idea what "INTEGER*8" was, nor did it understand 64-bit addressing. DEC Fortran for OpenVMS Alpha was 64-bit, and as noted, it sign-extended the value. gfortran can do whatever it wants here, since the call is nonconforming in multiple ways.

Fundamentally, it is a halfway job of porting to 64-bit, making some assumptions that are just wishful thinking.

 
0 Kudos
Reply