mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-12 20:33:13 +02:00
* last commit fixing calculation of do_loopvar_at_end was not complete,
hopefully finally fixed git-svn-id: trunk@44041 -
This commit is contained in:
parent
965d94109d
commit
22197641b8
@ -1744,6 +1744,15 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function checkcontinue(var n:tnode; arg: pointer): foreachnoderesult;
|
||||
begin
|
||||
if n.nodetype=continuen then
|
||||
result:=fen_norecurse_true
|
||||
else
|
||||
result:=fen_false;
|
||||
end;
|
||||
|
||||
|
||||
function tfornode.makewhileloop : tnode;
|
||||
var
|
||||
ifblock,loopblock : tblocknode;
|
||||
@ -1760,6 +1769,7 @@ implementation
|
||||
{ if the lower bound is not constant, it must be store in a temp before calculating the upper bound }
|
||||
usefromtemp : boolean;
|
||||
storefilepos: tfileposinfo;
|
||||
countermin, countermax: Tconstexprint;
|
||||
|
||||
procedure iterate_counter(var s : tstatementnode;fw : boolean);
|
||||
begin
|
||||
@ -1785,18 +1795,48 @@ implementation
|
||||
fromtemp:=nil;
|
||||
storefilepos:=current_filepos;
|
||||
current_filepos:=fileinfo;
|
||||
|
||||
case left.resultdef.typ of
|
||||
enumdef:
|
||||
begin
|
||||
countermin:=tenumdef(left.resultdef).min;
|
||||
countermax:=tenumdef(left.resultdef).max;
|
||||
end;
|
||||
orddef:
|
||||
begin
|
||||
countermin:=torddef(left.resultdef).low;
|
||||
countermax:=torddef(left.resultdef).high;
|
||||
end;
|
||||
else
|
||||
Internalerror(2020012601);
|
||||
end;
|
||||
|
||||
{ check if we can pred/succ the loop var at the end }
|
||||
do_loopvar_at_end:=(lnf_dont_mind_loopvar_on_exit in loopflags) and
|
||||
(right.nodetype=ordconstn) and (t1.nodetype=ordconstn) and
|
||||
{ we cannot test at the end after the inc/dec if the to value is equal to the max. value of the counter variable }
|
||||
not(not(is_signed(left.resultdef)) and (tordconstnode(t1).value<>((1 shl (left.resultdef.size*8))-1))) and
|
||||
not(is_signed(left.resultdef) and (tordconstnode(t1).value<>((1 shl (left.resultdef.size*8-1))-1))) and
|
||||
is_constnode(right) and is_constnode(t1) and
|
||||
{ we cannot test at the end after the pred/succ if the to value is equal to the max./min. value of the counter variable
|
||||
because we either get an overflow/underflow or the compiler removes the check as it never can be true }
|
||||
|
||||
{ checking just the min./max. value depending on the pure size of the counter does not work as the check might
|
||||
get optimized away
|
||||
not(not(lnf_backward in loopflags) and not(is_signed(left.resultdef)) and (get_ordinal_value(t1)=((1 shl (left.resultdef.size*8))-1))) and
|
||||
not(not(lnf_backward in loopflags) and is_signed(left.resultdef) and (get_ordinal_value(t1)=((1 shl (left.resultdef.size*8-1))-1))) and
|
||||
not((lnf_backward in loopflags) and not(is_signed(left.resultdef)) and (get_ordinal_value(t1)=0)) and
|
||||
not((lnf_backward in loopflags) and is_signed(left.resultdef) and (get_ordinal_value(t1)=(-Tconstexprint(1 shl (left.resultdef.size*8-1))))) and
|
||||
}
|
||||
|
||||
not(not(lnf_backward in loopflags) and (get_ordinal_value(t1)=countermax)) and
|
||||
not((lnf_backward in loopflags) and (get_ordinal_value(t1)=countermin)) and
|
||||
{ neither might the for loop contain a continue statement as continue in a while loop would skip the increment at the end
|
||||
of the loop, this could be overcome by replacing the continue statement with an pred/succ; continue sequence }
|
||||
not(foreachnodestatic(t2,@checkcontinue,nil)) and
|
||||
{ if the loop is unrolled and there is a jump into the loop,
|
||||
then we can't do the trick with incrementing the loop var only at the
|
||||
end
|
||||
}
|
||||
not(assigned(entrylabel));
|
||||
|
||||
needsifblock:=(right.nodetype<>ordconstn) or (t1.nodetype<>ordconstn);
|
||||
needsifblock:=not(is_constnode(right)) or not(is_constnode(t1));
|
||||
|
||||
{ convert the for loop into a while loop }
|
||||
result:=internalstatements(statements);
|
||||
|
Loading…
Reference in New Issue
Block a user