* 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:
florian 2020-01-26 20:13:17 +00:00
parent 965d94109d
commit 22197641b8

View File

@ -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);