Silverfrost Forums

Welcome to our forums

Code generation bug, FTN95 32-bit version 7.20

12 Apr 2016 1:46 (Edited: 12 Apr 2016 10:30) #17403

A recent thread exposes, among other problems, a code generation bug. The code given in https://forums.silverfrost.com/Forum/Topic/2859&postdays=0&postorder=asc&start=0 is rather long. The arrays needed for the calculation are allocated in one subroutine and used in many other subroutines. The following stripped down example may look silly, but it captures the code generation bug.

program tst
implicit none
integer, allocatable :: lnxt(:)
integer :: i, tot
!
tot = 10
allocate(lnxt(tot))
do i=1,tot
   lnxt(i) = i+1
end do
lnxt(ubound(lnxt,1)) = 0    ! I don't write code like this, but it is still legit !
write(*,'(20I4)')lnxt
end program

Compiling and linking with the default options causes an access violation in one of the 60+ instructions generated by the line with the comment.

The bug may not be seen if the /debug or /opt compiler options are used.

12 Apr 2016 6:11 #17408

Thanks for this. I have logged it for investigation. The good news is that it runs OK with FTN95 /64.

12 Apr 2016 8:32 #17410

That is really good that it is taken up for further investigation.

But I like to include some more observations. Sometimes during run time, the array values show some unknown character values, in spite of its initialisation after its is allocated. This can be seen during step-in (F11) in debug mode. However, it shows the right values while printing.

I face this issue randomly, but can not be seen consistently. This may not be directly linked with UBOUND bug, but want to know the reasons for this.

12 Apr 2016 3:02 (Edited: 12 Apr 2016 5:25) #17412

Paul,

It is good to note that this bug does not occur with the 64-bit beta-3 compiler.

Here is some additional information that may help fix the bug.

I used the following modification of the test code:

program tst
implicit none
integer, allocatable :: lnxt(:)
integer :: i, tot
!
tot = 10
allocate(lnxt(tot))
do i=1,tot
   lnxt(i) = i+1
end do
call sub(lnxt)
write(*,'(20I4)')lnxt

contains
subroutine sub(ia)
   integer :: ia(:)
   ia(ubound(ia)) = 0
   return
end subroutine
end program

This modification places the instruction causing the access violation to occur close to the subroutine entry, making it easier to locate and examine. With this code, the buggy code is emitted when /opt is used. I suspect that what happens is that, depending on the compiler options used, one assembly instruction gets lost. Here is the Exp-List portion near the entry to the contained subroutine (with some annotation added by me):

              ; Start of SUBROUTINE TST~SUB
      00000000(96/2/275)         push      ebp
      00000001(97/2/275)         mov       ebp,esp
      00000003(98/2/275)         push      ebx
      00000004(99/2/275)         push      esi
      00000005(100/2/275)        push      edi
      00000006(101/2/275)        push      eax
      00000007(102/2/275)        sub       esp,=24           ; Adjusted later if temporaries allocated
      0000000d(103/2/275)        mov       ecx,address of IA
                            ; Register ecx contains IA 
                            ; Register edx contains (IA:extent:1) ; ***NOT TRUE, here lies the bug *** 
   0013                                                                                          AT 10
   0014   contains                                                                               AT 10
   0015   subroutine sub(ia)                                                                     AT 10
   0016      integer :: ia(:)                                                                    AT 10
      00000010(106/6/270)        lea       eax,[edx-1]            ; ***GARBAGE in EDX***
      00000013(108/5/98)         and       eax,eax
      00000015(109/5/98)         jge       __N9
      0000001b(110/5/98)         mov       eax,=-1
      00000020(111/5/98)      Label     __N9
      00000020(112/5/98)         mov       (IA:size:1),eax
   0017      ia(ubound(ia)) = 0                                                                  AT 23
      00000023(113/6/126)        mov       esi,(IA:size:1)
      00000026(114/6/126)        inc       esi
      00000027(115/6/126)        mov       ArrayTemp@3,esi
      0000002a(116/5/141)        mov       edi,ArrayTemp@3
      0000002d(117/5/141)        mov       ArrayTemp@4,edi
      00000030(118/6/274)        mov       eax,ArrayTemp@4
      00000033(119/5/167)        mov       [ecx+eax*4-4],=0  ; *** ACCESS VIOLATION ***

The instruction that got left out, and should have been inserted after the instruction at offset 0000000D:

                                 mov       edx,(IA:extent:1)
12 Apr 2016 4:37 #17413

Thanks for the extra information.

17 May 2016 3:00 #17488

This bug has now been fixed for the next full release.

10 Jun 2016 10:11 #17620

Paul, Is this issue ubound() fixed in 8.00?

10 Jun 2016 10:24 #17621

No. The issue at the beginning of this thread has been fixed for the next release after 8.0.

Please login to reply.