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

Behaviour of ifort compiler for cray pointer test case

kumar__anil
Beginner
1,243 Views

Dear Team, 

                  I have the confusion about the behaviour of fortran compilers for below mentioned test case.

PROGRAM MAIN
  IMPLICIT NONE
  external RCPTEE
  INTEGER::I
  INTEGER(KIND=8)::RCPTR
  INTEGER::RCPTEE
  POINTER(RCPTR,RCPTEE)
  RCPTR=10*100+10
  I=RCPTR+10/10+1
  RCPTR=10+10+LOC(FUNC)+10*10
  RCPTR=10*1.5+10
  I=RCPTEE()
  WRITE(*,'(5I5)')I
  contains
   INTEGER FUNCTION FUNC()
   FUNC=123
  END FUNCTION FUNC
END PROGRAM MAIN

Above mentioned test case is getting compile successfully with intel fortran compiler, however it's giving compile time error with gfortran and f90  compiler. 

I think that the behaviour of intel fortran compiler is correct as compared to gfortran and f90.

Can anyone help me to explain it's behaviour or it's internal implementation for the above mentioned test case in ifort compiler? 

Is there any command line option to generate IL for the same in ifort compiler ?

 

 

Regards,

Anil Kumar 

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
1,243 Views

Neither LOC nor "Cray pointers" are in the standard, so anything goes. But your program doesn't use LOC on a Cray pointer - rather, it uses LOC on an internal procedure. 

You are really venturing FAR outside the standard here. Cray pointers to procedures were not part of the original implementations of this by Cray and others. In fact I may have been one of the earliest implementors of this "extension to an extension" in VAX FORTRAN. Then you compound this by asking for LOC of an internal procedure, which would require passing the caller's context for uplevel referencing of variables. That is not supported, and if you try it (when the internal procedure has uplevel references) the Intel compiler will now complain:

t.f90(9): warning #5440: Address taken of internal procedure (FUNC) with up-level references; calls through this address may fail.
  RCPTR=10+10+LOC(FUNC)+10*10

My old blog post Doctor Fortran in "Think, Thank, Thunk" discusses some aspects of this.

That said, I haven't the faintest idea what your program is attempting to do. You assign to the Cray pointer the sum of two function addresses? Or is this just a syntax test?

View solution in original post

0 Kudos
14 Replies
FortranFan
Honored Contributor II
1,243 Views

@Anil Kumar,

You are using a non-standard feature with a Cray pointer in your code.  You can read more about this at these links:

https://gcc.gnu.org/onlinedocs/gfortran/Cray-pointers.html

https://software.intel.com/en-us/fortran-compiler-18.0-developer-guide-and-reference-pointer-integer

Note with gfortran, you will need to specific the compiler flag -fcray-pointer:

https://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html#Fortran-Dialect-Options

By the way, note the Fortran standard provides a facility to achieve the same end in a cleaner, more portable manner with procedure pointers: you may want to look into it, especially if you plan on working further with Fortran:

https://software.intel.com/en-us/fortran-compiler-18.0-developer-guide-and-reference-procedure-pointers

0 Kudos
mecej4
Honored Contributor III
1,243 Views

This deplorable program deserves whatever bad things happen when it is run, and you should be grateful to any compiler that refuses to compile it.

Here is why: After the statement "RCPTR=10*1.5+10" is executed, RCPTR has the value 25  (= 19H) which, even on the long-dead 8086, was not a proper address for users' code (this address is at the low end of memory, i.e., the interrupt vector table area, where ISR addresses were stored). If you look at the assembly code that the compiler produces, you will see something such as the following (with IFort)

        mov       eax, 25                                       ;12.5

        call      eax
 
With Gfortran, the corresponding code fragment is
 
        movl    $25, -16(%ebp)
        movl    $0, -12(%ebp)
        movl    -16(%ebp), %eax
        call    *%eax
 
In other words, you have re-invented a way to execute data as if it were code. This abuse of Cray pointers causes an arbitrary integer value to be used as the address of a subroutine. Fortunately for you, this will cause an access violation abort.
0 Kudos
kumar__anil
Beginner
1,243 Views

Thanks for your kind reply. 

As I checked with different version of fortran compiler, "gcc version 6.2.0 (GCC)" is compiling above test case, however "gcc version 4.4.7" is not compiling this test case. I used complier option "-fdump-tree-original" to see the intermediate code which mentioned as below. 

<================================ start of Intermediate code ==========================>

func ()
{
  integer(kind=4) __result_func;

  __result_func = 123;
  return __result_func;
}


MAIN__ ()
{
  static integer(kind=4) func (void);
  integer(kind=4) i;
  integer(kind=8) rcptr;

  rcptr = 1010;
  i = (integer(kind=4)) ((unsigned int) rcptr + 2);
  {
    integer(kind=8) D.3434;

    D.3434 = (integer(kind=8)) func;
    rcptr = D.3434 + 120;
  }
  rcptr = 25;
  {
    integer(kind=4) (*<T8dc>) () D.3436;

    D.3436 = (integer(kind=4) (*<T8dc>) ()) rcptr;
    i = D.3436 ();
  }
  {
    struct __st_parameter_dt dt_parm.0;

    dt_parm.0.common.filename = &"IF03I0002_520.f90"[1]{lb: 1 sz: 1};
    dt_parm.0.common.line = 16;
    dt_parm.0.format = &"(5I5)"[1]{lb: 1 sz: 1};
    dt_parm.0.format_len = 5;
    dt_parm.0.common.flags = 4096;
    dt_parm.0.common.unit = 6;
    _gfortran_st_write (&dt_parm.0);
    _gfortran_transfer_integer_write (&dt_parm.0, &i, 4);
    _gfortran_st_write_done (&dt_parm.0);
  }
}


__attribute__((externally_visible))
main (integer(kind=4) argc, character(kind=1) * * argv)
{
  static integer(kind=4) options.1[9] = {68, 1023, 0, 0, 1, 1, 0, 0, 31};

  _gfortran_set_args (argc, argv);
  _gfortran_set_options (9, &options.1[0]);
  MAIN__ ();
  return 0;
}

<================================ End of Intermediate code ==========================>

Is there any compilation option is present in ifort like gfortran to see the intermediate code ? 

I need to know the behaviour of ifort that how it's handling the case of function pointer.

 

Thanks 

0 Kudos
Lorri_M_Intel
Employee
1,243 Views

No, there is no option in ifort to see the intermediate code, although you can use -S to get the assembly code.

                   --Lorri

0 Kudos
FortranFan
Honored Contributor II
1,243 Views

kumar, anil wrote:

Thanks for your kind reply.  ..

I need to know the behaviour of ifort that how it's handling the case of function pointer. ..

@Anil Kumar,

Why do you need to see how Intel Fortran is handling this when you're able to compile your code with a later version of gfortran and see what it is doing?

Also, did you read Quote #3?  The code in your original post makes little sense, will it be possible for you to explain what you're trying to do?

0 Kudos
kumar__anil
Beginner
1,243 Views

Thanks for your valuable information. 

Actually, I am implementing the feature of procedure pointers using cray pointer in our compiler, similar to gfortran and ifort.

 

 

0 Kudos
FortranFan
Honored Contributor II
1,243 Views

kumar, anil wrote:

.. I am implementing the feature of procedure pointers using cray pointer in our compiler, similar to gfortran and ifort.

@Anil Kumar,

Re: "I am implementing the feature .. in our compiler," can you please share which compiler is that?

Thanks,

0 Kudos
JVanB
Valued Contributor II
1,243 Views

@mecej4, Calling arbitrary data addresses is a good thing. See https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/747920#comment-1914450 where it makes it possible for Fortran programs to use the RDTSC instruction.

 

0 Kudos
mecej4
Honored Contributor III
1,243 Views

Repeat Offender wrote:
@mecej4, Calling arbitrary data addresses is a good thing. 
In your hands, yes! I remember one of your posts where you showed how to write the Fortran source of an expression evaluator from another Fortran program, call the compiler and receive the results in the large Fortran program.

But calling a non-existing routine at address Z'19' ? Wait, I want to put on a hard hat first!

 

0 Kudos
kumar__anil
Beginner
1,243 Views

Dear Intel Team,

                          What is the standard specification of LOC function with cray pointer. i.e. below mentioned test case is showing different behaviour with different compiler. 

TEST CASE:

PROGRAM MAIN
  IMPLICIT NONE
  EXTERNAL RCPTEE
  INTEGER::I
  INTEGER:: VAR = 10
  INTEGER(KIND=8)::RCPTR
  INTEGER::RCPTEE
  POINTER(RCPTR,RCPTEE)
  RCPTR=10+10+LOC(FUNC)+10*10
  RCPTR=10*1.5+10
  RCPTR=LOC(FUNC)+LOC(FUNC)
  I=RCPTEE()
  WRITE(*,'(5I5)')I
  CONTAINS
   INTEGER FUNCTION FUNC()
   FUNC=123
  END FUNCTION FUNC
END PROGRAM MAIN

In above test case, for below statement.

RCPTR=LOC(FUNC)+LOC(FUNC)

gfortran compiler of version "gcc version 4.1.2" , showing compilation error. However with "gcc version 6.2.0" version , it's compiling successfully. 

I tried with ifort compiler "ifort version 15.0.3" , it's also compiling it successfully. I don't have older version of ifort .

Can you please confirm, whether it's working fine with older version of ifort or not , and also standard behaviour of LOC function with cray pointer , i.e. above statement is valid or not in fortran.

 

 

0 Kudos
FortranFan
Honored Contributor II
1,243 Views

@Anil Kumar,

You may want to review the Fortran standard:

https://www.iso.org/standard/50459.html

https://wg5-fortran.org/

Note LOC is NOT part of the Fortran standard.

By the way, you'd previously mentioned this is all toward work on your compiler - can you please provide some details on it?

0 Kudos
mecej4
Honored Contributor III
1,243 Views

It is quite likely that RCPTR=LOC(FUNC)+LOC(FUNC), if you can delude a compiler into compiling it, gives an address that is twice the integer value of the address of a function. That is very likely to be an address that is beyond the addresses that your program is allowed to call. That address, even if valid, may contain the code or data of some other process.

Such code is illogical and it is unreasonable of you to ask what the standard result is, and expect an answer other than "the program is not legal, the behavior is undefined".

0 Kudos
Steve_Lionel
Honored Contributor III
1,244 Views

Neither LOC nor "Cray pointers" are in the standard, so anything goes. But your program doesn't use LOC on a Cray pointer - rather, it uses LOC on an internal procedure. 

You are really venturing FAR outside the standard here. Cray pointers to procedures were not part of the original implementations of this by Cray and others. In fact I may have been one of the earliest implementors of this "extension to an extension" in VAX FORTRAN. Then you compound this by asking for LOC of an internal procedure, which would require passing the caller's context for uplevel referencing of variables. That is not supported, and if you try it (when the internal procedure has uplevel references) the Intel compiler will now complain:

t.f90(9): warning #5440: Address taken of internal procedure (FUNC) with up-level references; calls through this address may fail.
  RCPTR=10+10+LOC(FUNC)+10*10

My old blog post Doctor Fortran in "Think, Thank, Thunk" discusses some aspects of this.

That said, I haven't the faintest idea what your program is attempting to do. You assign to the Cray pointer the sum of two function addresses? Or is this just a syntax test?

0 Kudos
kumar__anil
Beginner
1,243 Views

Steve Lionel (Ret.) wrote:

Neither LOC nor "Cray pointers" are in the standard, so anything goes. But your program doesn't use LOC on a Cray pointer - rather, it uses LOC on an internal procedure. 

You are really venturing FAR outside the standard here. Cray pointers to procedures were not part of the original implementations of this by Cray and others. In fact I may have been one of the earliest implementors of this "extension to an extension" in VAX FORTRAN. Then you compound this by asking for LOC of an internal procedure, which would require passing the caller's context for uplevel referencing of variables. That is not supported, and if you try it (when the internal procedure has uplevel references) the Intel compiler will now complain:

t.f90(9): warning #5440: Address taken of internal procedure (FUNC) with up-level references; calls through this address may fail.
  RCPTR=10+10+LOC(FUNC)+10*10

My old blog post Doctor Fortran in "Think, Thank, Thunk" discusses some aspects of this.

That said, I haven't the faintest idea what your program is attempting to do. You assign to the Cray pointer the sum of two function addresses? Or is this just a syntax test?

 

 

Dear Steave Sir,

                Thanks for your valuable comments, I used above mentioned test case as a negative test case to check the behaviour of different compiler.

0 Kudos
Reply