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

IFX apparently generating incorrect code for function call

publiusrgj
Novice
2,150 Views

 

    I discovered some odd behavior with IFX vs IFORT on a program of mine. To try to minimize details to keep this as short, the program display a live screen on the console, and makes use of the Console API in Kernel32 to reposition the cursor. I decided to compile the program with the newer IFX, and the output screen was corrupted. I thought at first it might be some differences between how IFX handles PRINT and FORMAT statements, but that wasn't. 

 

    Running both the IFORT and IFX debug versions of the program and looking at the disassembly output, I discovered this.  A 32-bit "COORD" structure should be loaded into the EDX register before the call to the "SetConsoleCursorPosition" function. IFORT does this. However, IFX appears to incorrectly use a 16 bit instruction to just load 16-bits of the structure into the 16-bit DX portion of the register. I've copied and pasted the assembly here:

------------------------------------------------------------------------

Intel IFORT:
 
retval = SetConsoleCursorPosition(ConHandle, buffinfo%dwCursorPosition)
00007FF67F0559A3  mov         rax,qword ptr [CONHANDLE]  
00007FF67F0559AA  mov         edx,dword ptr [BUFFINFO+4h (07FF67F077C3Ch)]  
00007FF67F0559B0  mov         rcx,rax  
00007FF67F0559B3  call        SetConsoleCursorPosition (07FF67F0619A0h)  
00007FF67F0559B8  mov         dword ptr [rbp+17Ch],eax  
00007FF67F0559BE  mov         eax,dword ptr [rbp+17Ch]  
00007FF67F0559C4  mov         dword ptr [RETVAL (07FF67F077C60h)],eax  
 
Registers before call:
 
RAX=0000000000000048 RBX=00007FF67F067980 RCX=0000000000000048 
RDX=0000000000020000 RSI=00007FF67F077760 RDI=00007FF67F07761A 
R8 =000000DA876FF098 R9 =000000DA876FF1A0 
 
Intel IFX:
 
retval = SetConsoleCursorPosition(ConHandle, buffinfo%dwCursorPosition)
00007FF6F05C4D86  mov         rcx,qword ptr [CONHANDLE]  
00007FF6F05C4D8D  mov         r8w,word ptr [BUFFINFO+6h (07FF6F05E4C2Eh)]  
00007FF6F05C4D95  mov         dx,word ptr [BUFFINFO+4h (07FF6F05E4C2Ch)]  
00007FF6F05C4D9C  call        SetConsoleCursorPosition (07FF6F05D0250h)  
00007FF6F05C4DA1  mov         dword ptr [RETVAL (07FF6F05E4AD8h)],eax  
 
Registers before call:
 
RAX=000000000000000 RBX=00007FF6F05E4AB8 RCX=000000000000005C 
RDX=0000000000000000 RSI=00007FF6F05E4AC0 RDI=00007FF6F05E45D8 
R8 =0000007007AF0002 R9 =0000007007AFF890 
-------------------------------------------------------------------------
 
buffinfo%dwCursorPosition is a 32-bit structure of the form (Y, X) and the value here should be (0, 2). IFORT loads the full 32 bit value into the EDX register, but as you can see IFX loads only the first half into the DX register. 
 
   I haven't yet had time to try to reduce that to just some simple code and see if IFX always does this, or if this something about this particular source file that triggers this bug. 
 
   Thanks. 
0 Kudos
12 Replies
mecej4
Honored Contributor III
2,094 Views

An old (2009) post in this Forum provides the source code of a subroutine that can be used as the test code for this issue. The IFX disassembly actually shows that three arguments are being passed to SetConsoleCursorPosition rather than the expected two: one 64-bit argument in RCX, and two 16-bit arguments in DX and R8W.

0 Kudos
publiusrgj
Novice
2,081 Views

Thanks. I didn't even catch that, but IFX is passing the lower 16 bits of the COORD structure in DX, and the upper 16 bits in R8W, as if they are two separate 16 bit parameters. 

 

   And thanks for that test code, that will do very nicely. I'll see if IFX does the same thing with that.

0 Kudos
andrew_4619
Honored Contributor III
2,075 Views

You are probably aware but take care with "Console API in Kernel32" the latest Windows 11 updates  by default use "Windows Terminal" rather than the classic "Windows Console Host". If The terminal type is used many Console API calls don't work (or appear to work but corrupt things that get you later) and some cause the console to close unexpectedly.  I have been forced to have a fork in my software to support both options. The "new" terminal  is escape sequence driven, this "new way forward" reminds me of MSDOS days in the 80s with ANSI.SYS escape sequences....

0 Kudos
publiusrgj
Novice
2,023 Views

Thanks.  I had read a little bit about the new terminal. I'm still running Windows 10,  and the old console host is still the default, although I do have Windows Terminal installed, but haven't played around with it too much, or tried to run any of my console programs in it. 

  

   There was also the "new console" vs the "legacy console", and I remember I had some problem with that.  To get a program to run correctly I had to switch it back to legacy mode.  

 

   I have played around a bit with the escape sequences for terminal control in Linux. It's a bit cumbersome to me, although the Windows API isn't exactly non-cumbersome itself. 

0 Kudos
publiusrgj
Novice
2,032 Views

 

   Okay, I created a short test program calling SetConsoleCursorPosition, and the problem occurs exactly as in the original. I'll attach the source file separately below as well as paste it right here:

----------------------------------------------------------------------------------------------

Program TestConsoleCall

Use ifcore
Use kernel32

TYPE (T_CONSOLE_SCREEN_BUFFER_INFO) :: buffinfo
TYPE (T_COORD) :: scoord
integer(HANDLE) ConHandle
Integer*4 retval


ConHandle = GetStdHandle(STD_OUTPUT_HANDLE) ! Get handle to console
retval = GetConsoleScreenBufferInfo(ConHandle, buffinfo) ! Get bufferinfo

scoord = buffinfo%dwCursorPosition ! Copy cursor coordinates to separate structure.

!Now try call in both both forms:

retval = SetConsoleCursorPosition(ConHandle, buffinfo%dwCursorPosition)

retval = SetConsoleCursorPosition(ConHandle, scoord)



End Program TestConsoleCall

------------------------------------------------------------------------------------------------------

 

     While the SetConsoleCursorPosition is simple enough, there is no corresponding GetConsoleCursortPosition function, and you have to use GetConsoleScreenBufferInfo which returns a larger structure with the current coordinates in a substructure, %dwCursorPosition. I wondered if maybe IFX got confused by passing a member of the larger structure, so I created a separate  T_COORD structure, and did two calls with each. The problem occurred in both forms, so that didn't have anything to do with it. 

   

   Disassembly of the above is as follows:

---------------------------------------------------------------------------------------------------------

scoord = buffinfo%dwCursorPosition ! Copy cursor coordinates to seperate structure.
00007FF6AAF01037 mov eax,dword ptr [BUFFINFO+4h (07FF6AAF080ACh)]
00007FF6AAF0103D mov dword ptr [SCOORD (07FF6AAF080A0h)],eax

!Now try call in both both forms:

retval = SetConsoleCursorPosition(ConHandle, buffinfo%dwCursorPosition)
00007FF6AAF01043 mov rcx,qword ptr [CONHANDLE]
00007FF6AAF01047 mov r8w,word ptr [BUFFINFO+6h (07FF6AAF080AEh)]
00007FF6AAF0104F mov dx,word ptr [BUFFINFO+4h (07FF6AAF080ACh)]
00007FF6AAF01056 call SetConsoleCursorPosition (07FF6AAF0129Ch)
00007FF6AAF0105B mov dword ptr [RETVAL],eax

retval = SetConsoleCursorPosition(ConHandle, scoord)
00007FF6AAF0105E mov rcx,qword ptr [CONHANDLE]
00007FF6AAF01062 mov r8w,word ptr [SCOORD+2h (07FF6AAF080A2h)]
00007FF6AAF0106A mov dx,word ptr [SCOORD (07FF6AAF080A0h)]
00007FF6AAF01071 call SetConsoleCursorPosition (07FF6AAF0129Ch)
00007FF6AAF01076 mov dword ptr [RETVAL],eax

 

-------------------------------------------------------------------

 

  Note the copy of the Coord structure goes as expected, IFX sees that as a 32-bit structure.  But in the calls to SetConsoleCursorPosition, it tries to pass it as though it is two separate 16-bit arguments. 

Barbara_P_Intel
Employee
1,884 Views

With this nice reproducer, I'm filing a bug report for this issue. I kinda fog over when looking at assembly code. The Fortran compiler team doesn't.

What do you mean "the output screen was corrupted"? Is that true with this reproducer?

I compiled and ran the reproducer from the oneAPI Windows command window. What should I see or not see?



0 Kudos
publiusrgj
Novice
1,872 Views

 

    You  won't see anything with that test program above, it doesn't produce any output at all. It was just to see what the assembly output of IFX was and verify it was producing incorrect function call code to the "SetConsoleCursorPosition" API call.  All the program does is get the current cursor position, then just set the cursor position to the original via the suspect function call. 

    The original program where I first noticed this with IFX basically printed some text to the console window, with some numeric fields. Then it would update some output numbers by returning the cursor to the starting position and then print out the new output. The result was a "live" looking screen with output values changing. 

 

  When I compiled and ran it with IFX, that didn't work right with the output all misaligned,  and it turned out it wasn't returning the cursor to proper initial position because of this bug with the function call. 

0 Kudos
publiusrgj
Novice
1,866 Views

 

   The assembly output above was just copied and pasted from the Disassembly window of the Visual Studio Debugger of the executable. I remembered that IFort can do assembler listings, and IFX will as well. But with IFX, I see it will only do one or the other. Produce an .asm or an .obj file, but not both, and the output is very barebones, no /FAs assembler with source, and uses the GAS(AT&T) syntax rather than MASM(Intel) syntax. 

   Anyway, I've attached the asm output of both IFort and IFX on the test program here, if anyone is interested. These were compiled with default Debug build settings of each compiler. 

   Well, the forum doesn't seem to like .asm files, so I changed the extension to .txt

0 Kudos
Barbara_P_Intel
Employee
1,863 Views

Thanks! The bug ID is CMPLRLLVM-54058. I'll let you know when there's a fix!


0 Kudos
publiusrgj
Novice
1,804 Views

 

     Thank you. I'll be interested when they fix this, and to see what was going wrong there. 

0 Kudos
Barbara_P_Intel
Employee
1,108 Views

Please check the ifx compiler 2024.1. It was released last week. The issue you reported is fixed.



0 Kudos
publiusrgj
Novice
1,084 Views

    Thank you so much for the update! Glad this bug happened to show up with me, so they could fix it. 

0 Kudos
Reply