mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-02 19:43:15 +01:00
* genlinear(cmp)list can now be overridden by descendents
This commit is contained in:
parent
6e499880f3
commit
3446f05f12
@ -27,7 +27,7 @@ unit ncgset;
|
||||
interface
|
||||
|
||||
uses
|
||||
node,nset,cpubase,cginfo,cgbase,cgobj,aasmbase,aasmtai;
|
||||
node,nset,cpubase,cginfo,cgbase,cgobj,aasmbase,aasmtai,globals;
|
||||
|
||||
type
|
||||
tcgsetelementnode = class(tsetelementnode)
|
||||
@ -56,6 +56,23 @@ interface
|
||||
because of portability problems.
|
||||
}
|
||||
procedure pass_2;override;
|
||||
|
||||
protected
|
||||
|
||||
procedure genlinearlist(hp : pcaserecord); virtual;
|
||||
procedure genlinearcmplist(hp : pcaserecord); virtual;
|
||||
|
||||
with_sign : boolean;
|
||||
opsize : tcgsize;
|
||||
jmp_gt,jmp_lt,jmp_le : topcmp;
|
||||
{ register with case expression }
|
||||
hregister,hregister2 : tregister;
|
||||
endlabel,elselabel : tasmlabel;
|
||||
|
||||
{ true, if we can omit the range check of the jump table }
|
||||
jumptable_no_range : boolean;
|
||||
min_label : tconstexprint;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
@ -63,7 +80,7 @@ implementation
|
||||
|
||||
uses
|
||||
globtype,systems,
|
||||
verbose,globals,
|
||||
verbose,
|
||||
symconst,symdef,defbase,
|
||||
paramgr,
|
||||
pass_2,
|
||||
@ -572,19 +589,175 @@ implementation
|
||||
TCGCASENODE
|
||||
*****************************************************************************}
|
||||
|
||||
procedure tcgcasenode.pass_2;
|
||||
var
|
||||
with_sign : boolean;
|
||||
opsize : tcgsize;
|
||||
jmp_gt,jmp_lt,jmp_le : topcmp;
|
||||
hp : tnode;
|
||||
{ register with case expression }
|
||||
hregister,hregister2 : tregister;
|
||||
endlabel,elselabel : tasmlabel;
|
||||
procedure tcgcasenode.genlinearlist(hp : pcaserecord);
|
||||
|
||||
{ true, if we can omit the range check of the jump table }
|
||||
jumptable_no_range : boolean;
|
||||
min_label : tconstexprint;
|
||||
var
|
||||
first : boolean;
|
||||
last : TConstExprInt;
|
||||
scratch_reg: tregister;
|
||||
|
||||
procedure genitem(t : pcaserecord);
|
||||
|
||||
procedure gensub(value:longint);
|
||||
begin
|
||||
{ here, since the sub and cmp are separate we need
|
||||
to move the result before subtract to a help
|
||||
register.
|
||||
}
|
||||
cg.a_load_reg_reg(exprasmlist, opsize, hregister, scratch_reg);
|
||||
cg.a_op_const_reg(exprasmlist, OP_SUB, value, hregister);
|
||||
end;
|
||||
|
||||
begin
|
||||
if assigned(t^.less) then
|
||||
genitem(t^.less);
|
||||
{ need we to test the first value }
|
||||
if first and (t^._low>get_min_value(left.resulttype.def)) then
|
||||
begin
|
||||
cg.a_cmp_const_reg_label(exprasmlist,OS_INT,jmp_lt,longint(t^._low),hregister,elselabel);
|
||||
end;
|
||||
if t^._low=t^._high then
|
||||
begin
|
||||
if t^._low-last=0 then
|
||||
begin
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ,0,hregister,t^.statement);
|
||||
end
|
||||
else
|
||||
begin
|
||||
gensub(longint(t^._low-last));
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ,longint(t^._low-last),scratch_reg,t^.statement);
|
||||
end;
|
||||
last:=t^._low;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ it begins with the smallest label, if the value }
|
||||
{ is even smaller then jump immediately to the }
|
||||
{ ELSE-label }
|
||||
if first then
|
||||
begin
|
||||
{ have we to ajust the first value ? }
|
||||
if (t^._low>get_min_value(left.resulttype.def)) then
|
||||
gensub(longint(t^._low));
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ if there is no unused label between the last and the }
|
||||
{ present label then the lower limit can be checked }
|
||||
{ immediately. else check the range in between: }
|
||||
gensub(longint(t^._low-last));
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT,jmp_lt,longint(t^._low-last),scratch_reg,elselabel);
|
||||
end;
|
||||
gensub(longint(t^._high-t^._low));
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT,jmp_le,longint(t^._high-t^._low),scratch_reg,t^.statement);
|
||||
last:=t^._high;
|
||||
end;
|
||||
first:=false;
|
||||
if assigned(t^.greater) then
|
||||
genitem(t^.greater);
|
||||
end;
|
||||
|
||||
begin
|
||||
{ do we need to generate cmps? }
|
||||
if (with_sign and (min_label<0)) then
|
||||
genlinearcmplist(hp)
|
||||
else
|
||||
begin
|
||||
last:=0;
|
||||
first:=true;
|
||||
scratch_reg := cg.get_scratch_reg_int(exprasmlist);
|
||||
genitem(hp);
|
||||
cg.free_scratch_reg(exprasmlist,scratch_reg);
|
||||
cg.a_jmp_always(exprasmlist,elselabel);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgcasenode.genlinearcmplist(hp : pcaserecord);
|
||||
|
||||
var
|
||||
first : boolean;
|
||||
last : TConstExprInt;
|
||||
|
||||
procedure genitem(t : pcaserecord);
|
||||
|
||||
var
|
||||
l1 : tasmlabel;
|
||||
|
||||
begin
|
||||
if assigned(t^.less) then
|
||||
genitem(t^.less);
|
||||
if t^._low=t^._high then
|
||||
begin
|
||||
if opsize in [OS_S64,OS_64] then
|
||||
begin
|
||||
getlabel(l1);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_NE, longint(hi(int64(t^._low))),hregister2,l1);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ, longint(lo(int64(t^._low))),hregister, t^.statement);
|
||||
cg.a_label(exprasmlist,l1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ, longint(t^._low),hregister, t^.statement);
|
||||
last:=t^._low;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ it begins with the smallest label, if the value }
|
||||
{ is even smaller then jump immediately to the }
|
||||
{ ELSE-label }
|
||||
if first or (t^._low-last>1) then
|
||||
begin
|
||||
if opsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
getlabel(l1);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(hi(int64(t^._low))),
|
||||
hregister2, elselabel);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_gt, longint(hi(int64(t^._low))),
|
||||
hregister2, l1);
|
||||
{ the comparisation of the low dword must be always unsigned! }
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_B, longint(lo(int64(t^._low))), hregister, elselabel);
|
||||
cg.a_label(exprasmlist,l1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(t^._low), hregister,
|
||||
elselabel);
|
||||
end;
|
||||
end;
|
||||
|
||||
if opsize in [OS_S64,OS_64] then
|
||||
begin
|
||||
getlabel(l1);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(hi(int64(t^._high))), hregister2,
|
||||
t^.statement);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_gt, longint(hi(int64(t^._high))), hregister2,
|
||||
l1);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_BE, longint(lo(int64(t^._high))), hregister, t^.statement);
|
||||
cg.a_label(exprasmlist,l1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_le, longint(t^._high), hregister, t^.statement);
|
||||
end;
|
||||
|
||||
last:=t^._high;
|
||||
end;
|
||||
first:=false;
|
||||
if assigned(t^.greater) then
|
||||
genitem(t^.greater);
|
||||
end;
|
||||
|
||||
begin
|
||||
last:=0;
|
||||
first:=true;
|
||||
genitem(hp);
|
||||
cg.a_jmp_always(exprasmlist,elselabel);
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgcasenode.pass_2;
|
||||
|
||||
procedure gentreejmp(p : pcaserecord);
|
||||
|
||||
@ -629,172 +802,6 @@ implementation
|
||||
gentreejmp(p^.greater);
|
||||
end;
|
||||
|
||||
procedure genlinearcmplist(hp : pcaserecord);
|
||||
|
||||
var
|
||||
first : boolean;
|
||||
last : TConstExprInt;
|
||||
|
||||
procedure genitem(t : pcaserecord);
|
||||
|
||||
var
|
||||
l1 : tasmlabel;
|
||||
|
||||
begin
|
||||
if assigned(t^.less) then
|
||||
genitem(t^.less);
|
||||
if t^._low=t^._high then
|
||||
begin
|
||||
if opsize in [OS_S64,OS_64] then
|
||||
begin
|
||||
getlabel(l1);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_NE, longint(hi(int64(t^._low))),hregister2,l1);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ, longint(lo(int64(t^._low))),hregister, t^.statement);
|
||||
cg.a_label(exprasmlist,l1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ, longint(t^._low),hregister, t^.statement);
|
||||
last:=t^._low;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ it begins with the smallest label, if the value }
|
||||
{ is even smaller then jump immediately to the }
|
||||
{ ELSE-label }
|
||||
if first or (t^._low-last>1) then
|
||||
begin
|
||||
if opsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
getlabel(l1);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(hi(int64(t^._low))),
|
||||
hregister2, elselabel);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_gt, longint(hi(int64(t^._low))),
|
||||
hregister2, l1);
|
||||
{ the comparisation of the low dword must be always unsigned! }
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_B, longint(lo(int64(t^._low))), hregister, elselabel);
|
||||
cg.a_label(exprasmlist,l1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(t^._low), hregister,
|
||||
elselabel);
|
||||
end;
|
||||
end;
|
||||
|
||||
if opsize in [OS_S64,OS_64] then
|
||||
begin
|
||||
getlabel(l1);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(hi(int64(t^._high))), hregister2,
|
||||
t^.statement);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_gt, longint(hi(int64(t^._high))), hregister2,
|
||||
l1);
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_BE, longint(lo(int64(t^._high))), hregister, t^.statement);
|
||||
cg.a_label(exprasmlist,l1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_le, longint(t^._high), hregister, t^.statement);
|
||||
end;
|
||||
|
||||
last:=t^._high;
|
||||
end;
|
||||
first:=false;
|
||||
if assigned(t^.greater) then
|
||||
genitem(t^.greater);
|
||||
end;
|
||||
|
||||
begin
|
||||
last:=0;
|
||||
first:=true;
|
||||
genitem(hp);
|
||||
cg.a_jmp_always(exprasmlist,elselabel);
|
||||
end;
|
||||
|
||||
procedure genlinearlist(hp : pcaserecord);
|
||||
|
||||
var
|
||||
first : boolean;
|
||||
last : TConstExprInt;
|
||||
scratch_reg: tregister;
|
||||
|
||||
procedure genitem(t : pcaserecord);
|
||||
|
||||
procedure gensub(value:longint);
|
||||
begin
|
||||
{ here, since the sub and cmp are separate we need
|
||||
to move the result before subtract to a help
|
||||
register.
|
||||
}
|
||||
cg.a_load_reg_reg(exprasmlist, opsize, hregister, scratch_reg);
|
||||
cg.a_op_const_reg(exprasmlist, OP_SUB, value, hregister);
|
||||
end;
|
||||
|
||||
begin
|
||||
if assigned(t^.less) then
|
||||
genitem(t^.less);
|
||||
{ need we to test the first value }
|
||||
if first and (t^._low>get_min_value(left.resulttype.def)) then
|
||||
begin
|
||||
cg.a_cmp_const_reg_label(exprasmlist,OS_INT,jmp_lt,longint(t^._low),hregister,elselabel);
|
||||
end;
|
||||
if t^._low=t^._high then
|
||||
begin
|
||||
if t^._low-last=0 then
|
||||
begin
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ,0,hregister,t^.statement);
|
||||
end
|
||||
else
|
||||
begin
|
||||
gensub(longint(t^._low-last));
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ,longint(t^._low-last),hregister,t^.statement);
|
||||
end;
|
||||
last:=t^._low;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ it begins with the smallest label, if the value }
|
||||
{ is even smaller then jump immediately to the }
|
||||
{ ELSE-label }
|
||||
if first then
|
||||
begin
|
||||
{ have we to ajust the first value ? }
|
||||
if (t^._low>get_min_value(left.resulttype.def)) then
|
||||
gensub(longint(t^._low));
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ if there is no unused label between the last and the }
|
||||
{ present label then the lower limit can be checked }
|
||||
{ immediately. else check the range in between: }
|
||||
gensub(longint(t^._low-last));
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT,jmp_lt,longint(t^._low-last),hregister,elselabel);
|
||||
end;
|
||||
gensub(longint(t^._high-t^._low));
|
||||
cg.a_cmp_const_reg_label(exprasmlist, OS_INT,jmp_le,longint(t^._high-t^._low),hregister,t^.statement);
|
||||
last:=t^._high;
|
||||
end;
|
||||
first:=false;
|
||||
if assigned(t^.greater) then
|
||||
genitem(t^.greater);
|
||||
end;
|
||||
|
||||
begin
|
||||
{ do we need to generate cmps? }
|
||||
if (with_sign and (min_label<0)) then
|
||||
genlinearcmplist(hp)
|
||||
else
|
||||
begin
|
||||
last:=0;
|
||||
first:=true;
|
||||
scratch_reg := cg.get_scratch_reg_int(exprasmlist);
|
||||
genitem(hp);
|
||||
cg.free_scratch_reg(exprasmlist,scratch_reg);
|
||||
cg.a_jmp_always(exprasmlist,elselabel);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
var
|
||||
lv,hv,
|
||||
@ -804,6 +811,7 @@ implementation
|
||||
otl, ofl: tasmlabel;
|
||||
isjump : boolean;
|
||||
dist : cardinal;
|
||||
hp : tnode;
|
||||
begin
|
||||
getlabel(endlabel);
|
||||
getlabel(elselabel);
|
||||
@ -949,7 +957,10 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.13 2002-08-11 06:14:40 florian
|
||||
Revision 1.14 2002-08-11 11:37:42 jonas
|
||||
* genlinear(cmp)list can now be overridden by descendents
|
||||
|
||||
Revision 1.13 2002/08/11 06:14:40 florian
|
||||
* fixed powerpc compilation problems
|
||||
|
||||
Revision 1.12 2002/08/10 17:15:12 jonas
|
||||
|
||||
Loading…
Reference in New Issue
Block a user