* simplified and optimized range checking code, FPC_BOUNDCHECK is no longer necessary

This commit is contained in:
Jonas Maebe 2001-03-03 12:41:22 +00:00
parent bf5d803a93
commit af38291233
4 changed files with 62 additions and 136 deletions

View File

@ -994,7 +994,7 @@ implementation
if from_signed and to_signed then
begin
getlabel(endlabel);
emitjmp(C_NO,endlabel);
emitjmp(C_None,endlabel);
{ if the high dword = $ffffffff, then the low dword (when }
{ considered as a longint) must be < 0 }
emitlab(neglabel);
@ -1135,29 +1135,6 @@ implementation
end;
{ generate the rangecheck code for the def where we are going to
store the result }
doublebound:=false;
case todef^.deftype of
orddef :
begin
porddef(todef)^.genrangecheck;
rstr:=porddef(todef)^.getrangecheckstring;
doublebound:=
((porddef(todef)^.typ=u32bit) and (lto>hto)) or
(is_signed(todef) and (porddef(fromdef)^.typ=u32bit)) or
(is_signed(fromdef) and (porddef(todef)^.typ=u32bit));
end;
enumdef :
begin
penumdef(todef)^.genrangecheck;
rstr:=penumdef(todef)^.getrangecheckstring;
end;
arraydef :
begin
parraydef(todef)^.genrangecheck;
rstr:=parraydef(todef)^.getrangecheckstring;
doublebound:=(lto>hto);
end;
end;
{ get op and opsize }
opsize:=def2def_opsize(fromdef,u32bitdef);
if opsize in [S_B,S_W,S_L] then
@ -1168,112 +1145,41 @@ implementation
else
op:=A_MOVZX;
is_reg:=(p.location.loc in [LOC_REGISTER,LOC_CREGISTER]);
if is_reg then
hreg:=p.location.register;
if not target_os.use_bound_instruction then
begin
{ FPC_BOUNDCHECK needs to be called with
%ecx - value
%edi - pointer to the ranges }
popecx:=false;
if not(is_reg) or
(p.location.register<>R_ECX) then
begin
if not(R_ECX in unused) then
begin
exprasmList.concat(Taicpu.Op_reg(A_PUSH,S_L,R_ECX));
popecx:=true;
end
else exprasmList.concat(Tairegalloc.Alloc(R_ECX));
if is_reg then
emit_reg_reg(op,opsize,p.location.register,R_ECX)
else
emit_ref_reg(op,opsize,newreference(p.location.reference),R_ECX);
end;
if doublebound then
begin
getlabel(neglabel);
getlabel(poslabel);
emit_reg_reg(A_OR,S_L,R_ECX,R_ECX);
emitjmp(C_L,neglabel);
end;
{ insert bound instruction only }
getexplicitregister32(R_EDI);
exprasmList.concat(Taicpu.Op_sym_ofs_reg(A_MOV,S_L,newasmsymbol(rstr),0,R_EDI));
emitcall('FPC_BOUNDCHECK');
ungetregister32(R_EDI);
{ u32bit needs 2 checks }
if doublebound then
begin
emitjmp(C_None,poslabel);
emitlab(neglabel);
{ if a cardinal is > $7fffffff, this is an illegal longint }
{ value (and vice versa)! (JM) }
if ((todef^.deftype = orddef) and
((is_signed(todef) and (porddef(fromdef)^.typ=u32bit)) or
(is_signed(fromdef) and (porddef(todef)^.typ=u32bit)))) or
{ similar for array indexes (JM) }
((todef^.deftype = arraydef) and
(((lto < 0) and (porddef(fromdef)^.typ=u32bit)) or
((lto >= 0) and is_signed(fromdef)))) then
emitcall('FPC_RANGEERROR')
else
begin
getexplicitregister32(R_EDI);
exprasmList.concat(Taicpu.Op_sym_ofs_reg(A_MOV,S_L,newasmsymbol(rstr),8,R_EDI));
emitcall('FPC_BOUNDCHECK');
ungetregister32(R_EDI);
end;
emitlab(poslabel);
end;
if popecx then
exprasmList.concat(Taicpu.Op_reg(A_POP,S_L,R_ECX))
else exprasmList.concat(Tairegalloc.DeAlloc(R_ECX));
end
getexplicitregister32(R_EDI);
{ use the trick that }
{ a <= x <= b <=> 0 <= x-a <= b-a <=> cardinal(x-a) <= cardinal(b-a) }
{ To be able to do that, we have to make sure however that either }
{ fromdef and todef are both signed or unsigned, or that we leave }
{ the parts < 0 and > maxlongint out }
{ is_signed now also works for arrays (it checks the rangetype) (JM) }
if is_signed(fromdef) xor is_signed(todef) then
begin
lto := max(lto,0);
hto := hto and $7fffffff;
end;
if is_reg and
(opsize = S_L) then
emit_ref_reg(A_LEA,opsize,new_reference(p.location.register,-lto),
R_EDI)
else
begin
reset_reference(href);
href.symbol:=newasmsymbol(rstr);
{ load the value in a register }
if is_reg then
begin
{ be sure that hreg is a 32 bit reg, if not load it in %edi }
if p.location.register in [R_EAX..R_EDI] then
hreg:=p.location.register
else
begin
getexplicitregister32(R_EDI);
emit_reg_reg(op,opsize,p.location.register,R_EDI);
hreg:=R_EDI;
end;
end
else
begin
getexplicitregister32(R_EDI);
begin
if is_reg then
emit_reg_reg(op,opsize,p.location.register,R_EDI)
else
emit_ref_reg(op,opsize,newreference(p.location.reference),R_EDI);
hreg:=R_EDI;
end;
if doublebound then
begin
getlabel(neglabel);
getlabel(poslabel);
emit_reg_reg(A_TEST,S_L,hreg,hreg);
emitjmp(C_L,neglabel);
end;
{ insert bound instruction only }
exprasmList.concat(Taicpu.Op_reg_ref(A_BOUND,S_L,hreg,newreference(href)));
{ u32bit needs 2 checks }
if doublebound then
begin
href.offset:=8;
emitjmp(C_None,poslabel);
emitlab(neglabel);
exprasmList.concat(Taicpu.Op_reg_ref(A_BOUND,S_L,hreg,newreference(href)));
emitlab(poslabel);
end;
if hreg = R_EDI then
ungetregister32(R_EDI);
end;
if lto <> 0 then
emit_const_reg(A_SUB,S_L,lto,R_EDI);
end;
emit_const_reg(A_CMP,S_L,hto-lto,R_EDI);
ungetregister32(R_EDI);
getlabel(neglabel);
emitjmp(C_BE,neglabel);
emitcall('FPC_RANGEERROR');
emitlab(neglabel);
end;
@ -1548,7 +1454,10 @@ implementation
end.
{
$Log$
Revision 1.10 2000-12-31 11:02:12 jonas
Revision 1.11 2001-03-03 12:41:22 jonas
* simplified and optimized range checking code, FPC_BOUNDCHECK is no longer necessary
Revision 1.10 2000/12/31 11:02:12 jonas
* optimized loadshortstring a bit
Revision 1.9 2000/12/25 00:07:33 peter

View File

@ -1294,6 +1294,7 @@ begin
def_symbol('INT64FUNCRESOK');
def_symbol('PACKENUMFIXED');
def_symbol('HAS_ADDR_STACK_ON_STACK');
def_symbol('NOBOPUNDCHECK');
{ some stuff for TP compatibility }
{$ifdef i386}
@ -1571,7 +1572,10 @@ finalization
end.
{
$Log$
Revision 1.32 2001-02-26 19:44:53 peter
Revision 1.33 2001-03-03 12:41:22 jonas
* simplified and optimized range checking code, FPC_BOUNDCHECK is no longer necessary
Revision 1.32 2001/02/26 19:44:53 peter
* merged generic m68k updates from fixes branch
Revision 1.31 2001/02/26 12:47:46 jonas

View File

@ -1088,6 +1088,8 @@ end;
Bounds Check
****************************************************************************}
{$ifndef NOBOUNDCHECK}
{$define FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
{$ifdef SYSTEMDEBUG}
@ -1117,6 +1119,9 @@ end;
{$ifdef SYSTEMDEBUG}
end;
{$endif def SYSTEMDEBUG}
{$endif NOBOUNDCHECK}
{ do a thread save inc/dec }
procedure declocked(var l : longint);assembler;
@ -1159,7 +1164,10 @@ procedure inclocked(var l : longint);assembler;
{
$Log$
Revision 1.5 2000-11-12 23:23:34 florian
Revision 1.6 2001-03-03 12:41:22 jonas
* simplified and optimized range checking code, FPC_BOUNDCHECK is no longer necessary
Revision 1.5 2000/11/12 23:23:34 florian
* interfaces basically running
Revision 1.4 2000/11/07 23:42:21 florian

View File

@ -293,11 +293,11 @@ begin
if (Len<>0) and (@Buf1<>@Buf2) then
begin
while (I<Len) And
((Pbyte(@Buf1)[i]<>0) and (PByte(@buf2)[i]<>0)) and
((Pbyte(@Buf1)[i]<>0) and (PByte(@buf2)[i]<>0)) and
(pbyte(@Buf1)[I]=pbyte(@Buf2)[I]) do
inc(I);
if (I=Len) or
(PByte(@Buf1)[i]=0) or
if (I=Len) or
(PByte(@Buf1)[i]=0) or
(PByte(@buf2)[I]=0) then {No difference or 0 reached }
I:=0
else
@ -756,6 +756,7 @@ end;
Bounds Check
****************************************************************************}
{$ifndef NOBOUNDCHECK}
{$ifndef FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
procedure int_boundcheck(l : longint; range : pointer);[public,alias: 'FPC_BOUNDCHECK'];
@ -771,11 +772,15 @@ begin
end;
{$endif ndef FPC_SYSTEM_HAS_FPC_BOUNDCHECK}
{$endif NOBOUNDCHECK}
{
$Log$
Revision 1.5 2000-10-01 13:17:35 michael
Revision 1.6 2001-03-03 12:41:22 jonas
* simplified and optimized range checking code, FPC_BOUNDCHECK is no longer necessary
Revision 1.5 2000/10/01 13:17:35 michael
+ Merged from fixbranch
Revision 1.4 2000/08/09 11:29:01 jonas
@ -792,5 +797,5 @@ end;
Revision 1.2 2000/07/13 11:33:43 michael
+ removed logs
}