فهرست منبع

* counterpart of r12844 for storing elements to a bitpacked array:
do not access any data after the array in that case either
* adapted tparray7 so it checks this on unix platforms

git-svn-id: trunk@12851 -

Jonas Maebe 16 سال پیش
والد
کامیت
0af39c77d9
2فایلهای تغییر یافته به همراه121 افزوده شده و 40 حذف شده
  1. 17 40
      compiler/cgobj.pas
  2. 104 0
      tests/test/tparray7.pp

+ 17 - 40
compiler/cgobj.pas

@@ -1437,6 +1437,7 @@ implementation
 
     procedure tcg.a_load_regconst_subsetref_intern(list : TAsmList; fromsize, subsetsize: tcgsize; fromreg: tregister; const sref: tsubsetreference; slopt: tsubsetloadopt);
       var
+        hl: tasmlabel;
         tmpreg, tmpindexreg, valuereg, extra_value_reg, maskreg: tregister;
         tosreg, fromsreg: tsubsetregister;
         tmpref: treference;
@@ -1676,21 +1677,24 @@ implementation
                 valuereg := makeregsize(list,valuereg,loadsize);
                 a_load_reg_ref(list,loadsize,loadsize,valuereg,sref.ref);
 
+                { make sure we do not read/write past the end of the array }
+                current_asmdata.getjumplabel(hl);
+                a_cmp_const_reg_label(list,OS_INT,OC_BE,loadbitsize-sref.bitlen,sref.bitindexreg,hl);
 
                 a_load_ref_reg(list,loadsize,OS_INT,tmpref,extra_value_reg);
                 tmpindexreg := getintregister(list,OS_INT);
 
-               { load current array value }
-               if (slopt <> SL_SETZERO) then
-                 begin
-                   tmpreg := getintregister(list,OS_INT);
-                   if (slopt <> SL_SETMAX) then
-                     a_load_reg_reg(list,fromsize,OS_INT,fromreg,tmpreg)
-                   else if (sref.bitlen <> AIntBits) then
-                     a_load_const_reg(list,OS_INT,aint((aword(1) shl sref.bitlen) - 1), tmpreg)
-                   else
-                     a_load_const_reg(list,OS_INT,-1,tmpreg);
-                 end;
+                { load current array value }
+                if (slopt <> SL_SETZERO) then
+                  begin
+                    tmpreg := getintregister(list,OS_INT);
+                    if (slopt <> SL_SETMAX) then
+                       a_load_reg_reg(list,fromsize,OS_INT,fromreg,tmpreg)
+                    else if (sref.bitlen <> AIntBits) then
+                      a_load_const_reg(list,OS_INT,aint((aword(1) shl sref.bitlen) - 1), tmpreg)
+                    else
+                      a_load_const_reg(list,OS_INT,-1,tmpreg);
+                  end;
 
                 { generate mask to zero the bits we have to insert }
                 if (slopt <> SL_SETMAX) then
@@ -1702,20 +1706,6 @@ implementation
                         a_op_reg_reg(list,OP_NEG,OS_INT,tmpindexreg,tmpindexreg);
                         a_load_const_reg(list,OS_INT,aint((aword(1) shl sref.bitlen)-1),maskreg);
                         a_op_reg_reg(list,OP_SHL,OS_INT,tmpindexreg,maskreg);
-{$ifdef sparc}
-                        {  on sparc, "shr X" = "shr (X and (bitsize-1))" -> fix so shr (x>32) = 0 }
-                        if (loadbitsize = AIntBits) then
-                          begin
-                            { if (tmpindexreg >= cpu_bit_size) then tmpreg := 1 else tmpreg := 0 }
-                            a_op_const_reg_reg(list,OP_SHR,OS_INT,{$ifdef cpu64bitalu}6{$else}5{$endif},tmpindexreg,valuereg);
-                            { if (tmpindexreg = cpu_bit_size) then maskreg := 0 else maskreg := -1 }
-                            a_op_const_reg(list,OP_SUB,OS_INT,1,valuereg);
-                            { if (tmpindexreg = cpu_bit_size) then maskreg := 0 }
-                            if (slopt <> SL_SETZERO) then
-                              a_op_reg_reg(list,OP_AND,OS_INT,valuereg,tmpreg);
-                            a_op_reg_reg(list,OP_AND,OS_INT,valuereg,maskreg);
-                          end;
-{$endif sparc}
                       end
                     else
                       begin
@@ -1724,21 +1714,6 @@ implementation
                         a_op_reg_reg(list,OP_NEG,OS_INT,tmpindexreg,tmpindexreg);
                         a_load_const_reg(list,OS_INT,aint((aword(1) shl sref.bitlen)-1),maskreg);
                         a_op_reg_reg(list,OP_SHR,OS_INT,tmpindexreg,maskreg);
-{$ifdef x86}
-                        { on i386 "x shl 32 = x shl 0", on x86/64 "x shl 64 = x shl 0". Fix so it's 0. }
-                        if (loadbitsize = AIntBits) then
-                          begin
-                            valuereg := getintregister(list,OS_INT);
-                            { if (tmpindexreg >= cpu_bit_size) then valuereg := 1 else valuereg := 0 }
-                            a_op_const_reg_reg(list,OP_SHR,OS_INT,{$ifdef cpu64bitalu}6{$else}5{$endif},tmpindexreg,valuereg);
-                            { if (tmpindexreg = cpu_bit_size) then valuereg := 0 else valuereg := -1 }
-                            a_op_const_reg(list,OP_SUB,OS_INT,1,valuereg);
-                            { if (tmpindexreg = cpu_bit_size) then tmpreg := maskreg := 0 }
-                            if (slopt <> SL_SETZERO) then
-                              a_op_reg_reg(list,OP_AND,OS_INT,valuereg,tmpreg);
-                            a_op_reg_reg(list,OP_AND,OS_INT,valuereg,maskreg);
-                          end;
-{$endif x86}
                       end;
 
                     a_op_reg_reg(list,OP_NOT,OS_INT,maskreg,maskreg);
@@ -1759,6 +1734,8 @@ implementation
                   end;
                 extra_value_reg := makeregsize(list,extra_value_reg,loadsize);
                 a_load_reg_ref(list,loadsize,loadsize,extra_value_reg,tmpref);
+
+                a_label(list,hl);
               end;
           end;
       end;

+ 104 - 0
tests/test/tparray7.pp

@@ -2,6 +2,11 @@
 
 {$r-}
 
+{$ifdef unix}
+uses
+  baseunix, unix;
+{$endif}
+
 procedure error(l: longint);
 begin
   writeln('error near ',l);
@@ -200,6 +205,104 @@ begin
 end;
 
 
+procedure test32bit2;
+type
+  ta = 0..(1 shl 24) - 1;
+  tb = packed array[0..3*32-1] of ta;
+  paa = ^tb;
+const
+  results: array[0..3*32-1] of ta = (
+$17E546,$6D0CA6,$BC9CCD,$34E268,$F2C58F,$492C7D,$DBDC0F,$375B2C,$8DCC08,$96FE74,
+$EF0AAD,$8BBB1A,$DF4554,$B75B0C,$728566,$81059B,$8D51F1,$88EF21,$CFF51E,$29BAAC,
+$C52266,$53315E,$A558E9,$093C36,$1357E7,$95CD2E,$173011,$770CB1,$85F746,$7601FE,
+$F5CD6A,$4E77B1,$F99073,$7520DB,$3F86DF,$2E5B82,$3282B8,$3A9FCD,$831B0B,$2DC3E6,
+$38426E,$22CA1A,$E4FE56,$1B562F,$9A7757,$33BE8B,$013A7A,$7A0A4D,$7BC0B0,$48BFFB,
+$62FA6C,$B3D806,$BFD49E,$3B5AB0,$696A18,$CADC48,$458E79,$834F63,$97D7A5,$5C92CB,
+$E8E260,$D95895,$3D2DF0,$7257F7,$33D25C,$389DD8,$21107B,$002344,$655E49,$FBA7EF,
+$D91F7E,$F694A2,$60F469,$160183,$275CAD,$1B8D0B,$41512E,$4184DE,$4319A9,$C93977,
+$D8D40A,$6EBEA5,$C137B8,$82BED4,$67DAC6,$142013,$614C0E,$38867C,$BE1CDD,$6A40E5,
+$518787,$219852,$48BD56,$827F40,$3CC0A6,$E79AF6
+  );
+var
+  a: ta;
+  i,j: longint;
+{$ifdef unix}
+  p,p2: pbyte;
+  bp: paa;
+{$else}
+  b: tb;
+{$endif}
+begin
+{$ifdef unix}
+  { check for reading/writing past end of array }
+  repeat
+    p := fpmmap(nil,4096,PROT_READ or PROT_WRITE,MAP_PRIVATE or MAP_ANONYMOUS,-1,0);
+    p2 := fpmmap(nil,4096,PROT_READ or PROT_WRITE,MAP_PRIVATE or MAP_ANONYMOUS,-1,0);
+  until (ptruint(p2) = ptruint(p) + 4096);
+  fpmunmap(p2,4096);
+  fillchar(p^,4096,$ff);
+  bp := paa(ptruint(p)+4096-sizeof(tb));
+  for i := low(results) to high(results) do
+    begin
+      bp^[i] := results[i];
+      for j := succ(i) to high(results) do
+        if bp^[j] <> high(ta) then
+          error(241);
+      if bp^[i] <> results[i] then
+        error(242);
+    end;
+  for i := low(results) to high(results) do
+    if bp^[i] <> results[i] then
+      begin
+        writeln(i);
+        error(47);
+      end;
+  if (bp^[0] <> results[0]) then
+    error(41);
+  if (bp^[1] <> results[1]) then
+    error(42);
+  if (bp^[2] <> results[2]) then
+    error(43);
+  if (bp^[3] <> results[3]) then
+    error(44);
+  if (bp^[4] <> results[4]) then
+    error(45);
+  if (bp^[3*32-2] <> results[3*32-2]) then
+    error(46);
+  if (bp^[3*32-1] <> results[3*32-1]) then
+    error(47);
+  for i := low(results) to high(results) do
+    if bp^[i] <> results[i] then
+      error(48);
+  fpmunmap(p,4096);
+{$else}
+  fillchar(b,sizeof(b),$ff);
+  for i := low(results) to high(results) do
+    begin
+      b[i] := results[i];
+      for j := succ(i) to high(results) do
+        if b[j] <> high(ta) then
+          error(241);
+      if b[i] <> results[i] then
+        error(242);
+    end;
+  if (b[0] <> results[0]) then
+    error(41);
+  if (b[1] <> results[1]) then
+    error(42);
+  if (b[2] <> results[2]) then
+    error(43);
+  if (b[3] <> results[3]) then
+    error(44);
+  if (b[4] <> results[4]) then
+    error(45);
+  for i := low(results) to high(results) do
+    if b[i] <> results[i] then
+      error(47);
+{$endif}
+end;
+
+
 procedure test32to40bit;
 type
   ta = 0..$7fffffff;
@@ -243,5 +346,6 @@ begin
   test16bit;
   test16to24bit;
   test32bit;
+  test32bit2;
   test32to40bit;
 end.