2
0
Эх сурвалжийг харах

* factored out tcginnode.in_smallset
* indention changed to common compiler style

git-svn-id: trunk@22063 -

florian 13 жил өмнө
parent
commit
c1bca748ee
1 өөрчлөгдсөн 220 нэмэгдсэн , 201 устгасан
  1. 220 201
      compiler/ncgset.pas

+ 220 - 201
compiler/ncgset.pas

@@ -41,12 +41,16 @@ interface
        end;
        end;
        Tsetparts=array[1..8] of Tsetpart;
        Tsetparts=array[1..8] of Tsetpart;
 
 
+       { tcginnode }
+
        tcginnode = class(tinnode)
        tcginnode = class(tinnode)
-          function pass_1: tnode;override;
-          procedure pass_generate_code;override;
+         procedure in_smallset(uopsize: tcgsize; opdef: tdef; setbase: aint); virtual;
+
+         function pass_1: tnode;override;
+         procedure pass_generate_code;override;
        protected
        protected
-          function checkgenjumps(out setparts: Tsetparts; out numparts: byte; out use_small: boolean): boolean; virtual;
-          function analizeset(const Aset:Tconstset;out setparts: Tsetparts; out numparts: byte;is_small:boolean):boolean;virtual;
+         function checkgenjumps(out setparts: Tsetparts; out numparts: byte; out use_small: boolean): boolean; virtual;
+         function analizeset(const Aset:Tconstset;out setparts: Tsetparts; out numparts: byte;is_small:boolean):boolean;virtual;
        end;
        end;
 
 
        tcgcasenode = class(tcasenode)
        tcgcasenode = class(tcasenode)
@@ -96,25 +100,25 @@ implementation
 *****************************************************************************}
 *****************************************************************************}
 
 
     procedure tcgsetelementnode.pass_generate_code;
     procedure tcgsetelementnode.pass_generate_code;
-       begin
-       { load first value in 32bit register }
-         secondpass(left);
-         if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
-           hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,u32inttype,false);
+      begin
+      { load first value in 32bit register }
+        secondpass(left);
+        if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+          hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,u32inttype,false);
 
 
-       { also a second value ? }
-         if assigned(right) then
-           begin
-             secondpass(right);
-             if codegenerror then
-               exit;
-             if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
-              hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,u32inttype,false);
-           end;
+      { also a second value ? }
+        if assigned(right) then
+          begin
+            secondpass(right);
+            if codegenerror then
+              exit;
+            if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
+             hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,u32inttype,false);
+          end;
 
 
-         { we doesn't modify the left side, we check only the type }
-         location_copy(location,left.location);
-       end;
+        { we doesn't modify the left side, we check only the type }
+        location_copy(location,left.location);
+      end;
 
 
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -178,6 +182,36 @@ implementation
     end;
     end;
 
 
 
 
+    procedure tcginnode.in_smallset(uopsize: tcgsize; opdef: tdef; setbase: aint);
+      begin
+        { location is always LOC_REGISTER }
+        location_reset(location, LOC_REGISTER, uopsize{def_cgsize(resultdef)});
+        { allocate a register for the result }
+        location.register := cg.getintregister(current_asmdata.CurrAsmList, uopsize);
+        {****************************  SMALL SET **********************}
+        if left.location.loc=LOC_CONSTANT then
+          begin
+            hlcg.a_bit_test_const_loc_reg(current_asmdata.CurrAsmList,
+             right.resultdef, resultdef,
+              left.location.value-setbase, right.location,
+              location.register);
+          end
+        else
+          begin
+            hlcg.location_force_reg(current_asmdata.CurrAsmList, left.location,
+             left.resultdef, opdef, true);
+            register_maybe_adjust_setbase(current_asmdata.CurrAsmList, left.location,
+             setbase);
+            hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList, left.resultdef,
+              right.resultdef, resultdef, left.location.register, right.location,
+               location.register);
+          end;
+        location.size := def_cgsize(resultdef);
+        location.register := cg.makeregsize(current_asmdata.CurrAsmList,
+        location.register, location.size);
+      end;
+
+
     function tcginnode.checkgenjumps(out setparts: Tsetparts; out numparts: byte;out use_small: boolean): boolean;
     function tcginnode.checkgenjumps(out setparts: Tsetparts; out numparts: byte;out use_small: boolean): boolean;
       begin
       begin
          { check if we can use smallset operation using btl which is limited
          { check if we can use smallset operation using btl which is limited
@@ -231,7 +265,6 @@ implementation
 
 
          genjumps := checkgenjumps(setparts,numparts,use_small);
          genjumps := checkgenjumps(setparts,numparts,use_small);
 
 
-
          orgopsize := def_cgsize(left.resultdef);
          orgopsize := def_cgsize(left.resultdef);
          orgopdef := left.resultdef;
          orgopdef := left.resultdef;
          uopsize := OS_32;
          uopsize := OS_32;
@@ -291,191 +324,177 @@ implementation
 
 
          setbase:=tsetdef(right.resultdef).setbase;
          setbase:=tsetdef(right.resultdef).setbase;
          if genjumps then
          if genjumps then
-          begin
-            { location is always LOC_JUMP }
-            location_reset(location,LOC_JUMP,OS_NO);
-
-            { If register is used, use only lower 8 bits }
-            hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,false);
-            pleftreg := left.location.register;
-
-            { how much have we already substracted from the x in the }
-            { "x in [y..z]" expression                               }
-            adjustment := 0;
-            hr:=NR_NO;
-
-            for i:=1 to numparts do
-             if setparts[i].range then
-              { use fact that a <= x <= b <=> aword(x-a) <= aword(b-a) }
-              begin
-                { is the range different from all legal values? }
-                if (setparts[i].stop-setparts[i].start <> 255) or not (orgopsize = OS_8) 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 (left.location.loc = LOC_CREGISTER) and
-                         (hr<>pleftreg) then
-                        begin
-                          { don't change this back to a_op_const_reg/a_load_reg_reg, since pleftreg must not be modified }
-                          hr:=hlcg.getintregister(current_asmdata.CurrAsmList,opdef);
-                          hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,opdef,setparts[i].start,pleftreg,hr);
-                          pleftreg:=hr;
-                        end
-                      else
-                        begin
-                          { otherwise, the value is already in a register   }
-                          { that can be modified                            }
-                          hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opdef,
-                             setparts[i].start-adjustment,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)                }
-                    hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, uopdef, OC_B,
-                      setparts[i].stop-setparts[i].start+1,pleftreg,current_procinfo.CurrTrueLabel);
-                  end
-                else
-                  { if setparts[i].start = 0 and setparts[i].stop = 255,  }
-                  { it's always true since "in" is only allowed for bytes }
-                  begin
-                    hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
-                  end;
-              end
-             else
-              begin
-                { Emit code to check if left is an element }
-                hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opdef, OC_EQ,
-                      setparts[i].stop-adjustment,pleftreg,current_procinfo.CurrTrueLabel);
-              end;
-             { To compensate for not doing a second pass }
-             right.location.reference.symbol:=nil;
-             hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
-          end
+           begin
+             { location is always LOC_JUMP }
+             location_reset(location,LOC_JUMP,OS_NO);
+
+             { If register is used, use only lower 8 bits }
+             hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,false);
+             pleftreg := left.location.register;
+
+             { how much have we already substracted from the x in the }
+             { "x in [y..z]" expression                               }
+             adjustment := 0;
+             hr:=NR_NO;
+
+             for i:=1 to numparts do
+              if setparts[i].range then
+               { use fact that a <= x <= b <=> aword(x-a) <= aword(b-a) }
+               begin
+                 { is the range different from all legal values? }
+                 if (setparts[i].stop-setparts[i].start <> 255) or not (orgopsize = OS_8) 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 (left.location.loc = LOC_CREGISTER) and
+                          (hr<>pleftreg) then
+                         begin
+                           { don't change this back to a_op_const_reg/a_load_reg_reg, since pleftreg must not be modified }
+                           hr:=hlcg.getintregister(current_asmdata.CurrAsmList,opdef);
+                           hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,opdef,setparts[i].start,pleftreg,hr);
+                           pleftreg:=hr;
+                         end
+                       else
+                         begin
+                           { otherwise, the value is already in a register   }
+                           { that can be modified                            }
+                           hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opdef,
+                              setparts[i].start-adjustment,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)                }
+                     hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, uopdef, OC_B,
+                       setparts[i].stop-setparts[i].start+1,pleftreg,current_procinfo.CurrTrueLabel);
+                   end
+                 else
+                   { if setparts[i].start = 0 and setparts[i].stop = 255,  }
+                   { it's always true since "in" is only allowed for bytes }
+                   begin
+                     hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
+                   end;
+               end
+              else
+               begin
+                 { Emit code to check if left is an element }
+                 hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opdef, OC_EQ,
+                       setparts[i].stop-adjustment,pleftreg,current_procinfo.CurrTrueLabel);
+               end;
+              { To compensate for not doing a second pass }
+              right.location.reference.symbol:=nil;
+              hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
+           end
          else
          else
          {*****************************************************************}
          {*****************************************************************}
          {                     NO JUMP TABLE GENERATION                    }
          {                     NO JUMP TABLE GENERATION                    }
          {*****************************************************************}
          {*****************************************************************}
-          begin
-            { location is always LOC_REGISTER }
-            location_reset(location, LOC_REGISTER, uopsize{def_cgsize(resultdef)});
-            { allocate a register for the result }
-            location.register := cg.getintregister(current_asmdata.CurrAsmList, uopsize);
-
-            { We will now generated code to check the set itself, no jmps,
-              handle smallsets separate, because it allows faster checks }
-            if use_small then
-             begin
-               {****************************  SMALL SET **********************}
-               if left.location.loc=LOC_CONSTANT then
-                begin
-                  hlcg.a_bit_test_const_loc_reg(current_asmdata.CurrAsmList,right.resultdef,resultdef,
-                    left.location.value-setbase,right.location,
-                    location.register);
-                end
-               else
-                begin
-                  hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true);
-                  register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
-                  hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,left.resultdef,
-                    right.resultdef,resultdef,left.location.register,right.location,location.register);
-                end;
-             end
-            else
-             {************************** NOT SMALL SET ********************}
-             begin
-               if right.location.loc=LOC_CONSTANT then
-                begin
-                  { can it actually occur currently? CEC }
-                  { yes: "if bytevar in [1,3,5,7,9,11,13,15]" (JM) }
-
-                  { note: this code assumes that left in [0..255], which is a valid }
-                  { assumption (other cases will be caught by range checking) (JM)  }
-
-                  { load left in register }
-                  hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true);
-                  register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
-                  { emit bit test operation -- warning: do not use
-                    location_force_reg() to force a set into a register, except
-                    to a register of the same size as the set. The reason is
-                    that on big endian systems, this would require moving the
-                    set to the most significant part of the new register,
-                    and location_force_register can't do that (it does not
-                    know the type).
-
-                   a_bit_test_reg_loc_reg() properly takes into account the
-                   size of the set to adjust the register index to test }
-                  hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,
-                    left.resultdef,right.resultdef,resultdef,
-                    left.location.register,right.location,location.register);
-
-                  { now zero the result if left > nr_of_bits_in_right_register }
-                  hr := cg.getintregister(current_asmdata.CurrAsmList,location.size);
-                  { if left > tcgsize2size[opsize]*8 then hr := 0 else hr := $ffffffff }
-                  { (left.location.size = location.size at this point) }
-                  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SUB, location.size, tcgsize2size[opsize]*8, left.location.register, hr);
-                  cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SAR, location.size, (tcgsize2size[opsize]*8)-1, hr);
-
-                  { if left > tcgsize2size[opsize]*8-1, then result := 0 else result := result of bit test }
-                  cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_AND, location.size, hr, location.register);
-                end { of right.location.loc=LOC_CONSTANT }
-               { do search in a normal set which could have >32 elements
-                 but also used if the left side contains higher values > 32 }
-               else if (left.location.loc=LOC_CONSTANT) then
-                begin
-                  if (left.location.value < setbase) or (((left.location.value-setbase) shr 3) >= right.resultdef.size) then
-                    {should be caught earlier }
-                    internalerror(2007020402);
+           begin
+             { We will now generated code to check the set itself, no jmps,
+               handle smallsets separate, because it allows faster checks }
+             if use_small then
+               begin
+                 in_smallset(uopsize, opdef, setbase);
+               end
+             else
+               {************************** NOT SMALL SET ********************}
+               begin
+                 { location is always LOC_REGISTER }
+                 location_reset(location, LOC_REGISTER, uopsize{def_cgsize(resultdef)});
+                 { allocate a register for the result }
+                 location.register := cg.getintregister(current_asmdata.CurrAsmList, uopsize);
+
+                 if right.location.loc=LOC_CONSTANT then
+                   begin
+                     { can it actually occur currently? CEC }
+                     { yes: "if bytevar in [1,3,5,7,9,11,13,15]" (JM) }
+
+                     { note: this code assumes that left in [0..255], which is a valid }
+                     { assumption (other cases will be caught by range checking) (JM)  }
+
+                     { load left in register }
+                     hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true);
+                     register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
+                     { emit bit test operation -- warning: do not use
+                       location_force_reg() to force a set into a register, except
+                       to a register of the same size as the set. The reason is
+                       that on big endian systems, this would require moving the
+                       set to the most significant part of the new register,
+                       and location_force_register can't do that (it does not
+                       know the type).
+
+                      a_bit_test_reg_loc_reg() properly takes into account the
+                      size of the set to adjust the register index to test }
+                     hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,
+                       left.resultdef,right.resultdef,resultdef,
+                       left.location.register,right.location,location.register);
+
+                     { now zero the result if left > nr_of_bits_in_right_register }
+                     hr := cg.getintregister(current_asmdata.CurrAsmList,location.size);
+                     { if left > tcgsize2size[opsize]*8 then hr := 0 else hr := $ffffffff }
+                     { (left.location.size = location.size at this point) }
+                     cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SUB, location.size, tcgsize2size[opsize]*8, left.location.register, hr);
+                     cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SAR, location.size, (tcgsize2size[opsize]*8)-1, hr);
+
+                     { if left > tcgsize2size[opsize]*8-1, then result := 0 else result := result of bit test }
+                     cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_AND, location.size, hr, location.register);
+                   end { of right.location.loc=LOC_CONSTANT }
+                 { do search in a normal set which could have >32 elements
+                   but also used if the left side contains higher values > 32 }
+                 else if (left.location.loc=LOC_CONSTANT) then
+                   begin
+                     if (left.location.value < setbase) or (((left.location.value-setbase) shr 3) >= right.resultdef.size) then
+                       {should be caught earlier }
+                       internalerror(2007020402);
+
+                     hlcg.a_bit_test_const_loc_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.value-setbase,
+                       right.location,location.register);
+                   end
+                 else
+                   begin
+                     hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true);
+                     register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
+                     pleftreg := left.location.register;
+
+                     if (opsize >= OS_S8) or { = if signed }
+                        ((left.resultdef.typ=orddef) and
+                         ((torddef(left.resultdef).low < int64(tsetdef(right.resultdef).setbase)) or
+                          (torddef(left.resultdef).high > int64(tsetdef(right.resultdef).setmax)))) or
+                        ((left.resultdef.typ=enumdef) and
+                         ((tenumdef(left.resultdef).min < aint(tsetdef(right.resultdef).setbase)) or
+                          (tenumdef(left.resultdef).max > aint(tsetdef(right.resultdef).setmax)))) then
+                       begin
+                         current_asmdata.getjumplabel(l);
+                         current_asmdata.getjumplabel(l2);
+                         needslabel := True;
 
 
-                  hlcg.a_bit_test_const_loc_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.value-setbase,
-                    right.location,location.register);
-                end
-               else
-                begin
-                  hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true);
-                  register_maybe_adjust_setbase(current_asmdata.CurrAsmList,left.location,setbase);
-                  pleftreg := left.location.register;
-
-                  if (opsize >= OS_S8) or { = if signed }
-                     ((left.resultdef.typ=orddef) and
-                      ((torddef(left.resultdef).low < int64(tsetdef(right.resultdef).setbase)) or
-                       (torddef(left.resultdef).high > int64(tsetdef(right.resultdef).setmax)))) or
-                     ((left.resultdef.typ=enumdef) and
-                      ((tenumdef(left.resultdef).min < aint(tsetdef(right.resultdef).setbase)) or
-                       (tenumdef(left.resultdef).max > aint(tsetdef(right.resultdef).setmax)))) then
-                    begin
-                      current_asmdata.getjumplabel(l);
-                      current_asmdata.getjumplabel(l2);
-                      needslabel := True;
-
-                      cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, left.location.size, OC_BE, tsetdef(right.resultdef).setmax-tsetdef(right.resultdef).setbase, pleftreg, l);
-
-                      cg.a_load_const_reg(current_asmdata.CurrAsmList, location.size, 0, location.register);
-                      cg.a_jmp_always(current_asmdata.CurrAsmList, l2);
-
-                      cg.a_label(current_asmdata.CurrAsmList, l);
-                    end;
-
-                  hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,left.resultdef,right.resultdef,resultdef,
-                    pleftreg,right.location,location.register);
-
-                  if needslabel then
-                    cg.a_label(current_asmdata.CurrAsmList, l2);
-                end;
-             end;
-          end;
-          location_freetemp(current_asmdata.CurrAsmList, right.location);
+                         cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, left.location.size, OC_BE, tsetdef(right.resultdef).setmax-tsetdef(right.resultdef).setbase, pleftreg, l);
+
+                         cg.a_load_const_reg(current_asmdata.CurrAsmList, location.size, 0, location.register);
+                         cg.a_jmp_always(current_asmdata.CurrAsmList, l2);
 
 
-          location.size := def_cgsize(resultdef);
-          location.register := cg.makeregsize(current_asmdata.CurrAsmList, location.register, location.size);
+                         cg.a_label(current_asmdata.CurrAsmList, l);
+                       end;
+
+                     hlcg.a_bit_test_reg_loc_reg(current_asmdata.CurrAsmList,left.resultdef,right.resultdef,resultdef,
+                       pleftreg,right.location,location.register);
+
+                     if needslabel then
+                       cg.a_label(current_asmdata.CurrAsmList, l2);
+                   end;
+                 location.size := def_cgsize(resultdef);
+                 location.register := cg.makeregsize(current_asmdata.CurrAsmList, location.register, location.size);
+               end;
+           end;
+         location_freetemp(current_asmdata.CurrAsmList, right.location);
        end;
        end;
 
 
 {*****************************************************************************
 {*****************************************************************************