Browse Source

* don't keep records in registers if they contain a field that spans the
boundary between two awords, as our subscript code does not handle
them correctly (second part of mantis #29669)

git-svn-id: trunk@33180 -

Jonas Maebe 9 years ago
parent
commit
096e1c45d6
3 changed files with 97 additions and 5 deletions
  1. 1 0
      .gitattributes
  2. 44 5
      compiler/symdef.pas
  3. 52 0
      tests/webtbs/tw29669a.pp

+ 1 - 0
.gitattributes

@@ -14969,6 +14969,7 @@ tests/webtbs/tw29585.pp svneol=native#text/plain
 tests/webtbs/tw29609.pp svneol=native#text/pascal
 tests/webtbs/tw2966.pp svneol=native#text/plain
 tests/webtbs/tw29669.pp svneol=native#text/plain
+tests/webtbs/tw29669a.pp svneol=native#text/plain
 tests/webtbs/tw2975.pp svneol=native#text/plain
 tests/webtbs/tw2976.pp svneol=native#text/plain
 tests/webtbs/tw2983.pp svneol=native#text/plain

+ 44 - 5
compiler/symdef.pas

@@ -300,6 +300,8 @@ interface
           function jvm_full_typename(with_package_name: boolean): string;
           { check if the symtable contains a float field }
           function contains_float_field : boolean;
+          { check if the symtable contains a field that spans an aword boundary }
+          function contains_cross_aword_field: boolean;
        end;
 
        pvariantrecdesc = ^tvariantrecdesc;
@@ -2114,12 +2116,14 @@ implementation
               recsize:=size;
               is_intregable:=
                 ispowerof2(recsize,temp) and
-                (((recsize <= sizeof(aint)*2) and
+                not trecorddef(self).contains_cross_aword_field and
+                ((recsize<=sizeof(aint)*2) and
                  { records cannot go into registers on 16 bit targets for now }
-                  (sizeof(aint)>2) and
-                  not trecorddef(self).contains_float_field) or
-                  (recsize <= sizeof(aint))) and
-                not needs_inittable;
+                 (sizeof(aint)>2) and
+                 (not trecorddef(self).contains_float_field) or
+                  (recsize <= sizeof(aint))
+                 ) and
+                 not needs_inittable;
 {$endif llvm}
             end;
         end;
@@ -4253,6 +4257,41 @@ implementation
       end;
 
 
+    function tabstractrecorddef.contains_cross_aword_field: boolean;
+      var
+        i : longint;
+        foffset, fsize: aword;
+      begin
+        result:=true;
+        for i:=0 to symtable.symlist.count-1 do
+          begin
+            if (tsym(symtable.symlist[i]).typ<>fieldvarsym) or
+               (sp_static in tsym(symtable.symlist[i]).symoptions) then
+              continue;
+            if assigned(tfieldvarsym(symtable.symlist[i]).vardef) then
+              begin
+                if is_packed then
+                  begin
+                    foffset:=tfieldvarsym(symtable.symlist[i]).fieldoffset;
+                    fsize:=tfieldvarsym(symtable.symlist[i]).vardef.packedbitsize;
+                  end
+                else
+                  begin
+                    foffset:=tfieldvarsym(symtable.symlist[i]).fieldoffset*8;
+                    fsize:=tfieldvarsym(symtable.symlist[i]).vardef.size*8;
+                  end;
+                if (foffset div (sizeof(aword)*8)) <> ((foffset+fsize-1) div (sizeof(aword)*8)) then
+                  exit;
+                { search recursively }
+                if (tstoreddef(tfieldvarsym(symtable.symlist[i]).vardef).typ=recorddef) and
+                  (tabstractrecorddef(tfieldvarsym(symtable.symlist[i]).vardef).contains_cross_aword_field) then
+                  exit;
+              end;
+          end;
+        result:=false;
+      end;
+
+
 {***************************************************************************
                                   trecorddef
 ***************************************************************************}

+ 52 - 0
tests/webtbs/tw29669a.pp

@@ -0,0 +1,52 @@
+{$mode objfpc}
+
+program Project1;
+
+uses
+ SysUtils;
+
+type
+  TPackedIdLevel1 = 0..255;
+  TPackedIdLevel2 = 0..65535;
+  TPackedIdLevel3 = 0..65535;
+  TPackedIdLevel4 = 0..65535;
+  TPackedIdLevel5 = 0..255;
+
+  TPackedId = bitpacked record
+    clusterId : TPackedIdLevel5;
+    esmId : TPackedIdLevel1;
+    agentId : TPackedIdLevel4;
+    dataSourceId : TPackedIdLevel3;
+    deviceId : TPackedIdLevel2;
+  end;
+
+function PackedIdToStr(const ipsid : qword) : string;
+begin
+  result := IntToStr(TPackedId(ipsid).esmId) + '-' +
+            IntToStr(TPackedId(ipsid).deviceId) + '-' +
+            IntToStr(TPackedId(ipsid).dataSourceId) + '-' +
+            IntToStr(TPackedId(ipsid).agentId) + '-' +
+            IntToStr(TPackedId(ipsid).clusterId);
+  if TPackedId(ipsid).clusterid<>123 then
+    halt(1);
+  if TPackedId(ipsid).agentid<>45678 then
+    halt(2);
+  if TPackedId(ipsid).datasourceid<>9012 then
+    halt(3);
+  if TPackedId(ipsid).deviceid<>34567 then
+    halt(4);
+  if TPackedId(ipsid).esmid<>89 then
+    halt(5);
+
+end;
+
+var
+  pi: TPackedId;
+begin
+  pi.clusterid:=123;
+  pi.agentid:=45678;
+  pi.datasourceid:=9012;
+  pi.deviceid:=34567;
+  pi.esmid:=89;
+  writeln(PackedIdToStr(qword(pi)));
+end.