Browse Source

tcgvecnode, cleanup/refactoring:
* Separated two almost identical parts of code into procedure rangecheck_string;
- Removed range checking of regular_array[constant], which should, according to the comments, happen in typecheckpass. tvecnode.pass_typecheck indeed does the necessary tests, so removing this duplicate check also eliminates duplicate warning when range checking is off.

git-svn-id: trunk@17124 -

sergei 14 years ago
parent
commit
cf4c00e8d6
1 changed files with 74 additions and 127 deletions
  1. 74 127
      compiler/ncgmem.pas

+ 74 - 127
compiler/ncgmem.pas

@@ -59,6 +59,7 @@ interface
          function get_mul_size : aint;
        private
          procedure rangecheck_array;
+         procedure rangecheck_string;
        protected
          {# This routine is used to calculate the address of the reference.
             On entry reg contains the index in the array,
@@ -635,6 +636,10 @@ implementation
          hreg : tregister;
          paraloc1,paraloc2 : tcgpara;
        begin
+         { omit range checking when this is an array access to a pointer which has been
+           typecasted from an array }
+         if (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions) then
+           exit;
          paraloc1.init;
          paraloc2.init;
          if is_open_array(left.resultdef) or
@@ -690,6 +695,64 @@ implementation
          paraloc2.done;
        end;
 
+    procedure tcgvecnode.rangecheck_string;
+      var
+        paraloc1,
+        paraloc2: tcgpara;
+        href: treference;
+        offsetdec: aint;
+      begin
+        paraloc1.init;
+        paraloc2.init;
+        case tstringdef(left.resultdef).stringtype of
+          { it's the same for ansi- and wide strings }
+          st_unicodestring,
+          st_widestring,
+          st_ansistring:
+            begin
+              paramanager.getintparaloc(pocall_default,1,paraloc1);
+              paramanager.getintparaloc(pocall_default,2,paraloc2);
+              cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
+              href:=location.reference;
+              { Add back the offset which was subtracted to map string[1]->pchar(string)[0] }
+              { TODO: we'd better rangecheck on the original location, before offsetting it. }
+              if is_ansistring(left.resultdef) then
+                offsetdec:=1
+              else
+                offsetdec:=2;
+              if not(tf_winlikewidestring in target_info.flags) or
+                (tstringdef(left.resultdef).stringtype<>st_widestring) then
+                begin
+                  dec(href.offset,sizeof(pint)-offsetdec);
+                  cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
+                end
+              else
+                begin
+                  { winlike widestrings have a 4 byte length }
+                  dec(href.offset,4-offsetdec);
+                  cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
+                end;
+              paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+              paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
+              cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+              cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
+              cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+            end;
+
+          st_shortstring:
+            begin
+              {!!!!!!!!!!!!!!!!!}
+              { if this one is implemented making use of the high parameter for openshortstrings, update ncgutils.do_get_used_regvars() too (JM) }
+            end;
+
+          st_longstring:
+            begin
+              {!!!!!!!!!!!!!!!!!}
+            end;
+        end;
+        paraloc1.done;
+        paraloc2.done;
+      end;
 
     procedure tcgvecnode.pass_generate_code;
 
@@ -697,7 +760,6 @@ implementation
          offsetdec,
          extraoffset : aint;
          t        : tnode;
-         href     : treference;
          otl,ofl  : tasmlabel;
          newsize  : tcgsize;
          mulsize,
@@ -828,84 +890,16 @@ implementation
          if right.nodetype=ordconstn then
            begin
               { offset can only differ from 0 if arraydef }
-              case left.resultdef.typ of
-                arraydef :
-                  begin
-		     { do not do any range checking when this is an array access to a pointer which has been
-		       typecasted from an array }
-		     if (not (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions)) then
-		       begin
-                     	if not(is_open_array(left.resultdef)) and
-                           not(is_array_of_const(left.resultdef)) and
-                           not(is_dynamic_array(left.resultdef)) then
-                          begin
-                            if (tordconstnode(right).value.svalue>tarraydef(left.resultdef).highrange) or
-                               (tordconstnode(right).value.svalue<tarraydef(left.resultdef).lowrange) then
-                              begin
-                                { this should be caught in the typecheckpass! (JM) }
-                                if (cs_check_range in current_settings.localswitches) then
-                                  CGMessage(parser_e_range_check_error)
-                                else
-                                  CGMessage(parser_w_range_check_error);
-                              end;
-                           end
-                         else
-                           begin
-                              { range checking for open and dynamic arrays needs
-                                runtime code }
-                              secondpass(right);
-                              if (cs_check_range in current_settings.localswitches) then
-                                rangecheck_array;
-                           end;
-		       end;
+              if cs_check_range in current_settings.localswitches then
+                begin
+                  secondpass(right);
+                  case left.resultdef.typ of
+                    arraydef :
+                      rangecheck_array;
+                    stringdef :
+                      rangecheck_string;
                   end;
-                stringdef :
-                  begin
-                    if (cs_check_range in current_settings.localswitches) then
-                     begin
-                       case tstringdef(left.resultdef).stringtype of
-                         { it's the same for ansi- and wide strings }
-                         st_unicodestring,
-                         st_widestring,
-                         st_ansistring:
-                           begin
-                              paramanager.getintparaloc(pocall_default,1,paraloc1);
-                              paramanager.getintparaloc(pocall_default,2,paraloc2);
-                              cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_INT,tordconstnode(right).value.svalue,paraloc2);
-                              href:=location.reference;
-                              if not(tf_winlikewidestring in target_info.flags) or
-                                 (tstringdef(left.resultdef).stringtype<>st_widestring) then
-                                begin
-                                  dec(href.offset,sizeof(pint)-offsetdec);
-                                  cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
-                                end
-                              else
-                                begin
-                                  { winlike widestrings have a 4 byte length }
-                                  dec(href.offset,4-offsetdec);
-                                  cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
-                                end;
-                              paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
-                              paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
-                              cg.allocallcpuregisters(current_asmdata.CurrAsmList);
-                              cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
-                              cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
-                           end;
-
-                         st_shortstring:
-                           begin
-                              {!!!!!!!!!!!!!!!!!}
-                              { if this one is implemented making use of the high parameter for openshortstrings, update ncgutils.do_get_used_regvars() too (JM) }
-                           end;
-
-                         st_longstring:
-                           begin
-                              {!!!!!!!!!!!!!!!!!}
-                           end;
-                       end;
-                     end;
-                   end;
-              end;
+                end;
               if not(is_packed_array(left.resultdef)) or
                  ((mulsize mod 8 = 0) and
                   (ispowerof2(mulsize div 8,temp) or
@@ -1015,56 +1009,9 @@ implementation
               if cs_check_range in current_settings.localswitches then
                begin
                  if left.resultdef.typ=arraydef then
-                   begin
-		     { do not do any range checking when this is an array access to a pointer which has been
-		       typecasted from an array }
-		     if (not (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions)) then
-                       rangecheck_array
-                   end
+                   rangecheck_array
                  else if (left.resultdef.typ=stringdef) then
-                   begin
-                      case tstringdef(left.resultdef).stringtype of
-                         { it's the same for ansi- and wide strings }
-                         st_unicodestring,
-                         st_widestring,
-                         st_ansistring:
-                           begin
-                              paramanager.getintparaloc(pocall_default,1,paraloc1);
-                              paramanager.getintparaloc(pocall_default,2,paraloc2);
-                              cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_INT,right.location.register,paraloc2);
-                              href:=location.reference;
-                              dec(href.offset,sizeof(pint)-offsetdec);
-
-                              href:=location.reference;
-                              if not(tf_winlikewidestring in target_info.flags) or
-                                 (tstringdef(left.resultdef).stringtype<>st_widestring) then
-                                begin
-                                  dec(href.offset,sizeof(pint)-offsetdec);
-                                  cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
-                                end
-                              else
-                                begin
-                                  { winlike widestrings have a 4 byte length }
-                                  dec(href.offset,4-offsetdec);
-                                  cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
-                                end;
-
-                              paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
-                              paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
-                              cg.allocallcpuregisters(current_asmdata.CurrAsmList);
-                              cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
-                              cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
-                           end;
-                         st_shortstring:
-                           begin
-                              {!!!!!!!!!!!!!!!!!}
-                           end;
-                         st_longstring:
-                           begin
-                              {!!!!!!!!!!!!!!!!!}
-                           end;
-                      end;
-                   end;
+                   rangecheck_string;
                end;
 
               { insert the register and the multiplication factor in the