4.2 BSD f77 compiler bug (1)
donn at sdchema.UUCP
donn at sdchema.UUCP
Thu Nov 24 06:06:06 AEST 1983
Subject: Bug in f77 loop optimizer generates incorrect code (serious!)
Index: /usr/src/usr.bin/f77/src/f77pass1/exec.c 4.2BSD
Description:
This problem occurs in the f77 compiler supplied on a tape
made on 8/23/83.
In f77 DO loops, a variable loop limit is squirreled away in a
local variable so that it cannot be altered during the course
of the loop. (This is because the standard says that DO loop
initializations, limits and increments are only evaluated once,
when the loop is first entered.) Unfortunately the loop limit
is saved in a temporary variable which may be reallocated when
subroutine arguments are evaluated in the loop. (Since f77
requires that arguments be passed to subroutines by reference
rather than by value, these temporaries are used to give an
address to the output of an expression.) This leads to loops
which are executed an unpredictable number of times, clearly a
major error. The problem is mitigated slightly by the fact
that unless the loop is complicated, the loop limit quantity
will migrate into register from its place on the stack, and
after this it is safe from being clobbered.
Repeat-By:
Copy the following f77 program into the file bug1.f:
--------------------------------------------------------------
program bug1
integer i, j, k, l, m, n, o
j = 2
k = 3
l = 4
m = 5
n = 6
o = 7
do 20 i=1,k
j = j + l
l = i + j
j = l * j
l = j - l
m = l * i
n = l * m
o = m - l
m = o + 3
n = o / m
o = j + n
call dummy( i+1, j+2, l+3 )
write(unit=6,fmt=10) i
10 format('Loop pass ', i3)
20 continue
stop
end
subroutine dummy( a, b, c )
integer a, b, c
return
end
--------------------------------------------------------------
Notice that the expected output is:
Loop pass 1
Loop pass 2
Loop pass 3
In fact this program goes into an infinite loop, counting up to
infinity. To see why, compile again using the command:
f77 -d14 -S -O bug1.f
F77pass1 will print the debugging comment that offset -4 is being
reused. If you look at the assembler output file bug1.s, you
should see that the loop limit is stored at -4(fp), and that the
call to dummy() clobbers -4(fp) with the value of i+1... hence
the infinite loop.
Fix:
The best fix I can find is to cause the loop limit to be put in a
TADDR-type temporary rather than a TTEMP temporary. TTEMP stack
temporaries can be re-used quickly, while TADDR temporaries are
not recycled until the end of a routine. The loop increment is
also a TTEMP temporary, so for safety I have also made that a
TADDR temporary. The changes to src/f77pass1/exec.c are:
***************
*** 444,450
if( CONSTLIMIT )
ctlstack->domax = DOLIMIT;
else
! ctlstack->domax = (expptr) mktemp(dotype, PNULL);
if( CONSTINCR )
{
--- 461,467 -----
if( CONSTLIMIT )
ctlstack->domax = DOLIMIT;
else
! ctlstack->domax = (expptr) mkaltemp(dotype, PNULL);
if( CONSTINCR )
{
***************
*** 455,461
}
else
{
! ctlstack->dostep = (expptr) mktemp(dotype, PNULL);
ctlstack->dostepsign = VARSTEP;
}
--- 472,478 -----
}
else
{
! ctlstack->dostep = (expptr) mkaltemp(dotype, PNULL);
ctlstack->dostepsign = VARSTEP;
}
Donn Seeley UCSD Chemistry Dept. RRCF ucbvax!sdcsvax!sdchema!donn
32 52' 30"N 117 14' 25"W (619) 452-4016 sdcsvax!sdchema!donn at noscvax
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list