* 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 -
This commit is contained in:
Jonas Maebe 2016-03-06 13:20:25 +00:00
parent 7a966345e5
commit 096e1c45d6
3 changed files with 97 additions and 5 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -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
tests/webtbs/tw29669a.pp Normal file
View File

@ -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.