From af38291233efd6aca943d82675fc011f20d03f3f Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sat, 3 Mar 2001 12:41:22 +0000 Subject: [PATCH] * simplified and optimized range checking code, FPC_BOUNDCHECK is no longer necessary --- compiler/i386/n386util.pas | 167 +++++++++---------------------------- compiler/options.pas | 6 +- rtl/i386/i386.inc | 10 ++- rtl/inc/generic.inc | 15 ++-- 4 files changed, 62 insertions(+), 136 deletions(-) diff --git a/compiler/i386/n386util.pas b/compiler/i386/n386util.pas index faf3b0c7dc..f1adaaf4bf 100644 --- a/compiler/i386/n386util.pas +++ b/compiler/i386/n386util.pas @@ -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 diff --git a/compiler/options.pas b/compiler/options.pas index 9d22de2ffc..a8e3c77e81 100644 --- a/compiler/options.pas +++ b/compiler/options.pas @@ -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 diff --git a/rtl/i386/i386.inc b/rtl/i386/i386.inc index ba5a488fe1..4f64bad7be 100644 --- a/rtl/i386/i386.inc +++ b/rtl/i386/i386.inc @@ -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 diff --git a/rtl/inc/generic.inc b/rtl/inc/generic.inc index 9ce3dcb307..4c6f19a885 100644 --- a/rtl/inc/generic.inc +++ b/rtl/inc/generic.inc @@ -293,11 +293,11 @@ begin if (Len<>0) and (@Buf1<>@Buf2) then begin while (I0) 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 - + }