|
@@ -99,6 +99,7 @@ implementation
|
|
opsize : topsize;
|
|
opsize : topsize;
|
|
setparts : array[1..8] of Tsetpart;
|
|
setparts : array[1..8] of Tsetpart;
|
|
i,numparts : byte;
|
|
i,numparts : byte;
|
|
|
|
+ adjustment : longint;
|
|
{href,href2 : Treference;}
|
|
{href,href2 : Treference;}
|
|
l,l2 : pasmlabel;
|
|
l,l2 : pasmlabel;
|
|
{$ifdef CORRECT_SET_IN_FPC}
|
|
{$ifdef CORRECT_SET_IN_FPC}
|
|
@@ -148,20 +149,19 @@ implementation
|
|
setparts[numparts].range:=true;
|
|
setparts[numparts].range:=true;
|
|
setparts[numparts].start:=setparts[numparts].stop;
|
|
setparts[numparts].start:=setparts[numparts].stop;
|
|
setparts[numparts].stop:=i;
|
|
setparts[numparts].stop:=i;
|
|
- inc(compares);
|
|
|
|
|
|
+ ranges := true;
|
|
|
|
+ { there's only one compare per range anymore. Only a }
|
|
|
|
+ { sub is added, but that's much faster than a }
|
|
|
|
+ { cmp/jcc combo so neglect its effect }
|
|
|
|
+{ inc(compares);
|
|
if compares>maxcompares then
|
|
if compares>maxcompares then
|
|
- exit;
|
|
|
|
|
|
+ exit; }
|
|
end
|
|
end
|
|
- else
|
|
|
|
- begin
|
|
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
{Extend a range.}
|
|
{Extend a range.}
|
|
setparts[numparts].stop:=i;
|
|
setparts[numparts].stop:=i;
|
|
- {A range of two elements can better
|
|
|
|
- be checked as two separate ones.
|
|
|
|
- When extending a range, our range
|
|
|
|
- becomes larger than two elements.}
|
|
|
|
- ranges:=true;
|
|
|
|
- end;
|
|
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
analizeset:=true;
|
|
analizeset:=true;
|
|
end;
|
|
end;
|
|
@@ -208,19 +208,34 @@ implementation
|
|
if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
|
|
if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
|
|
begin
|
|
begin
|
|
pleftreg:=left.location.register;
|
|
pleftreg:=left.location.register;
|
|
- if pleftreg in [R_AX..R_DX] then
|
|
|
|
|
|
+ if pleftreg in [R_AX..R_DI] then
|
|
begin
|
|
begin
|
|
- emit_const_reg(A_AND,S_W,255,pleftreg);
|
|
|
|
- opsize:=S_W;
|
|
|
|
|
|
+ emit_const_reg(A_AND,S_L,255,reg16toreg32(pleftreg));
|
|
end
|
|
end
|
|
else
|
|
else
|
|
if pleftreg in [R_EAX..R_EDI] then
|
|
if pleftreg in [R_EAX..R_EDI] then
|
|
begin
|
|
begin
|
|
emit_const_reg(A_AND,S_L,255,pleftreg);
|
|
emit_const_reg(A_AND,S_L,255,pleftreg);
|
|
- opsize:=S_L;
|
|
|
|
end
|
|
end
|
|
else
|
|
else
|
|
- opsize:=S_B;
|
|
|
|
|
|
+ begin
|
|
|
|
+ if ranges then
|
|
|
|
+ emit_const_reg(A_AND,S_L,255,reg8toreg32(pleftreg));
|
|
|
|
+ end;
|
|
|
|
+ opsize := S_L;
|
|
|
|
+ if ranges then
|
|
|
|
+ begin
|
|
|
|
+ pleftreg := makereg32(pleftreg);
|
|
|
|
+ opsize := S_L;
|
|
|
|
+ end
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ { load the value in a register }
|
|
|
|
+ pleftreg := getexplicitregister32(R_EDI);
|
|
|
|
+ opsize := S_L;
|
|
|
|
+ emit_ref_reg(A_MOVZX,S_BL,newreference(left.location.reference),
|
|
|
|
+ pleftreg);
|
|
end;
|
|
end;
|
|
|
|
|
|
{ Get a label to jump to the end }
|
|
{ Get a label to jump to the end }
|
|
@@ -235,102 +250,82 @@ implementation
|
|
|
|
|
|
getlabel(l);
|
|
getlabel(l);
|
|
|
|
|
|
|
|
+ { how much have we already substracted from the x in the }
|
|
|
|
+ { "x in [y..z]" expression }
|
|
|
|
+ adjustment := 0;
|
|
|
|
+
|
|
for i:=1 to numparts do
|
|
for i:=1 to numparts do
|
|
if setparts[i].range then
|
|
if setparts[i].range then
|
|
|
|
+ { use fact that a <= x <= b <=> cardinal(x-a) <= cardinal(b-a) }
|
|
begin
|
|
begin
|
|
- { Check if left is in a range }
|
|
|
|
- { Get a label to jump over the check }
|
|
|
|
- getlabel(l2);
|
|
|
|
- if setparts[i].start=setparts[i].stop-1 then
|
|
|
|
- begin
|
|
|
|
- case left.location.loc of
|
|
|
|
- LOC_REGISTER,
|
|
|
|
- LOC_CREGISTER : emit_const_reg(A_CMP,opsize,
|
|
|
|
- setparts[i].start,pleftreg);
|
|
|
|
- else
|
|
|
|
- emit_const_ref(A_CMP,S_B,
|
|
|
|
- setparts[i].start,newreference(left.location.reference));
|
|
|
|
- end;
|
|
|
|
- { Result should be in carry flag when ranges are used }
|
|
|
|
- if ranges then
|
|
|
|
- emit_none(A_STC,S_NO);
|
|
|
|
- { If found, jump to end }
|
|
|
|
- emitjmp(C_E,l);
|
|
|
|
- case left.location.loc of
|
|
|
|
- LOC_REGISTER,
|
|
|
|
- LOC_CREGISTER : emit_const_reg(A_CMP,opsize,
|
|
|
|
- setparts[i].stop,pleftreg);
|
|
|
|
- else
|
|
|
|
- emit_const_ref(A_CMP,S_B,
|
|
|
|
- setparts[i].stop,newreference(left.location.reference));
|
|
|
|
- end;
|
|
|
|
- { Result should be in carry flag when ranges are used }
|
|
|
|
- if ranges then
|
|
|
|
- emit_none(A_STC,S_NO);
|
|
|
|
- { If found, jump to end }
|
|
|
|
- emitjmp(C_E,l);
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- if setparts[i].start<>0 then
|
|
|
|
- begin
|
|
|
|
- { We only check for the lower bound if it is > 0, because
|
|
|
|
- set elements lower than 0 dont exist }
|
|
|
|
- case left.location.loc of
|
|
|
|
- LOC_REGISTER,
|
|
|
|
- LOC_CREGISTER :
|
|
|
|
- emit_const_reg(A_CMP,opsize,
|
|
|
|
- setparts[i].start,pleftreg);
|
|
|
|
- else
|
|
|
|
- emit_const_ref(A_CMP,S_B,
|
|
|
|
- setparts[i].start,newreference(left.location.reference));
|
|
|
|
- end;
|
|
|
|
- { If lower, jump to next check }
|
|
|
|
- emitjmp(C_B,l2);
|
|
|
|
- end;
|
|
|
|
- { We only check for the high bound if it is < 255, because
|
|
|
|
- set elements higher than 255 do nt exist, the its always true,
|
|
|
|
- so only a JMP is generated }
|
|
|
|
- if setparts[i].stop<>255 then
|
|
|
|
- begin
|
|
|
|
- case left.location.loc of
|
|
|
|
- LOC_REGISTER,
|
|
|
|
- LOC_CREGISTER : emit_const_reg(A_CMP,opsize,
|
|
|
|
- setparts[i].stop+1,pleftreg);
|
|
|
|
|
|
+ { is the range different from all legal values? }
|
|
|
|
+ if (setparts[i].stop-setparts[i].start <> 255) then
|
|
|
|
+ begin
|
|
|
|
+ { yes, is the lower bound <> 0? }
|
|
|
|
+ if (setparts[i].start <> 0) then
|
|
|
|
+ { we're going to substract from the left register, }
|
|
|
|
+ { so in case of a LOC_CREGISTER first move the value }
|
|
|
|
+ { to edi (not done before because now we can do the }
|
|
|
|
+ { move and substract in one instruction with LEA) }
|
|
|
|
+ if (pleftreg <> R_EDI) and
|
|
|
|
+ (left.location.loc = LOC_CREGISTER) then
|
|
|
|
+ begin
|
|
|
|
+ getexplicitregister32(R_EDI);
|
|
|
|
+ emit_ref_reg(A_LEA,S_L,
|
|
|
|
+ new_reference(pleftreg,-setparts[i].start),R_EDI);
|
|
|
|
+ { only now change pleftreg since previous value is }
|
|
|
|
+ { still used in previous instruction }
|
|
|
|
+ pleftreg := R_EDI;
|
|
|
|
+ opsize := S_L;
|
|
|
|
+ end
|
|
else
|
|
else
|
|
- emit_const_ref(A_CMP,S_B,
|
|
|
|
- setparts[i].stop+1,newreference(left.location.reference));
|
|
|
|
- end;
|
|
|
|
- { If higher, element is in set }
|
|
|
|
- emitjmp(C_B,l);
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- emit_none(A_STC,S_NO);
|
|
|
|
- emitjmp(C_None,l);
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
- { Emit the jump over label }
|
|
|
|
- emitlab(l2);
|
|
|
|
|
|
+ begin
|
|
|
|
+ { otherwise, the value is already in a register }
|
|
|
|
+ { that can be modified }
|
|
|
|
+ if setparts[i].start-adjustment <> 1 then
|
|
|
|
+ emit_const_reg(A_SUB,opsize,
|
|
|
|
+ setparts[i].start-adjustment,pleftreg)
|
|
|
|
+ else emit_reg(A_DEC,opsize,pleftreg);
|
|
|
|
+ end;
|
|
|
|
+ { new total value substracted from x: }
|
|
|
|
+ { adjustment + (setparts[i].start - adjustment) }
|
|
|
|
+ adjustment := setparts[i].start;
|
|
|
|
+
|
|
|
|
+ { check if result < b-a+1 (not "result <= b-a", since }
|
|
|
|
+ { we need a carry in case the element is in the range }
|
|
|
|
+ { (this will never overflow since we check at the }
|
|
|
|
+ { beginning whether stop-start <> 255) }
|
|
|
|
+ emit_const_reg(A_CMP,opsize,
|
|
|
|
+ setparts[i].stop-setparts[i].start+1,pleftreg);
|
|
|
|
+ { use C_C instead of C_B: the meaning is the same, but }
|
|
|
|
+ { then the optimizer can easier trace the jump to its }
|
|
|
|
+ { final destination since the resultflag of this node }
|
|
|
|
+ { is set to the carryflag }
|
|
|
|
+ emitjmp(C_C,l);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ { if setparts[i].start = 0 and setparts[i].stop = 255, }
|
|
|
|
+ { it's always true since "in" is only allowed for bytes }
|
|
|
|
+ begin
|
|
|
|
+ emit_none(A_STC,S_NO);
|
|
|
|
+ emitjmp(C_NONE,l);
|
|
|
|
+ end;
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
{ Emit code to check if left is an element }
|
|
{ Emit code to check if left is an element }
|
|
- case left.location.loc of
|
|
|
|
- LOC_REGISTER,
|
|
|
|
- LOC_CREGISTER : emit_const_reg(A_CMP,opsize,
|
|
|
|
- setparts[i].stop,pleftreg);
|
|
|
|
- else
|
|
|
|
- emit_const_ref(A_CMP,S_B,
|
|
|
|
- setparts[i].stop,newreference(left.location.reference));
|
|
|
|
- end;
|
|
|
|
|
|
+ emit_const_reg(A_CMP,opsize,setparts[i].stop-adjustment,
|
|
|
|
+ pleftreg);
|
|
{ Result should be in carry flag when ranges are used }
|
|
{ Result should be in carry flag when ranges are used }
|
|
if ranges then
|
|
if ranges then
|
|
emit_none(A_STC,S_NO);
|
|
emit_none(A_STC,S_NO);
|
|
{ If found, jump to end }
|
|
{ If found, jump to end }
|
|
emitjmp(C_E,l);
|
|
emitjmp(C_E,l);
|
|
end;
|
|
end;
|
|
- if ranges then
|
|
|
|
|
|
+ if ranges and
|
|
|
|
+ { if the last one was a range, the carry flag is already }
|
|
|
|
+ { set appropriately }
|
|
|
|
+ not(setparts[numparts].range) then
|
|
emit_none(A_CLC,S_NO);
|
|
emit_none(A_CLC,S_NO);
|
|
{ To compensate for not doing a second pass }
|
|
{ To compensate for not doing a second pass }
|
|
right.location.reference.symbol:=nil;
|
|
right.location.reference.symbol:=nil;
|
|
@@ -340,8 +335,11 @@ implementation
|
|
LOC_REGISTER,
|
|
LOC_REGISTER,
|
|
LOC_CREGISTER : ungetregister(pleftreg);
|
|
LOC_CREGISTER : ungetregister(pleftreg);
|
|
else
|
|
else
|
|
- del_reference(left.location.reference);
|
|
|
|
- end;
|
|
|
|
|
|
+ begin
|
|
|
|
+ del_reference(left.location.reference);
|
|
|
|
+ ungetregister(R_EDI);
|
|
|
|
+ end
|
|
|
|
+ end
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
@@ -1069,7 +1067,10 @@ begin
|
|
end.
|
|
end.
|
|
{
|
|
{
|
|
$Log$
|
|
$Log$
|
|
- Revision 1.10 2000-12-25 00:07:33 peter
|
|
|
|
|
|
+ Revision 1.11 2001-02-11 12:14:56 jonas
|
|
|
|
+ * simplified and optimized code generated for in-statements
|
|
|
|
+
|
|
|
|
+ Revision 1.10 2000/12/25 00:07:33 peter
|
|
+ new tlinkedlist class (merge of old tstringqueue,tcontainer and
|
|
+ new tlinkedlist class (merge of old tstringqueue,tcontainer and
|
|
tlinkedlist objects)
|
|
tlinkedlist objects)
|
|
|
|
|