From dcdcc6988d38f67ec0c219dbff7e5c0ab79cf427 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Fri, 14 Sep 2012 13:59:59 +0000 Subject: [PATCH] * if an agregate contains unaligned fields, it has to be passed via memory (mantis #22878) git-svn-id: trunk@22390 - --- .gitattributes | 1 + compiler/x86_64/cpupara.pas | 31 +++++++++++++++++++++++++++---- tests/webtbs/tw22878.pp | 31 +++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 tests/webtbs/tw22878.pp diff --git a/.gitattributes b/.gitattributes index 0fd52612d2..bb9cdaadab 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12827,6 +12827,7 @@ tests/webtbs/tw2280.pp svneol=native#text/plain tests/webtbs/tw22860.pp svneol=native#text/plain tests/webtbs/tw22864.pp svneol=native#text/pascal tests/webtbs/tw22869.pp svneol=native#text/plain +tests/webtbs/tw22878.pp svneol=native#text/plain tests/webtbs/tw2289.pp svneol=native#text/plain tests/webtbs/tw2291.pp svneol=native#text/plain tests/webtbs/tw2294.pp svneol=native#text/plain diff --git a/compiler/x86_64/cpupara.pas b/compiler/x86_64/cpupara.pas index a590b3ee2c..0d6669c7c3 100644 --- a/compiler/x86_64/cpupara.pas +++ b/compiler/x86_64/cpupara.pas @@ -342,6 +342,7 @@ unit cpupara; i, words, num: longint; + checkalignment: boolean; begin result:=init_aggregate_classification(def,varspez,words,classes); if (words=0) then @@ -354,6 +355,7 @@ unit cpupara; continue; vs:=tfieldvarsym(tabstractrecorddef(def).symtable.symlist[i]); num:=-1; + checkalignment:=true; if not tabstractrecordsymtable(tabstractrecorddef(def).symtable).is_packed then begin new_byte_offset:=byte_offset+vs.fieldoffset; @@ -363,11 +365,25 @@ unit cpupara; begin new_byte_offset:=byte_offset+vs.fieldoffset div 8; if (vs.vardef.typ in [orddef,enumdef]) then - { calculate the number of bytes spanned by - this bitpacked field } - size:=((vs.fieldoffset+vs.vardef.packedbitsize+7) div 8)-(vs.fieldoffset div 8) + begin + { calculate the number of bytes spanned by + this bitpacked field } + size:=((vs.fieldoffset+vs.vardef.packedbitsize+7) div 8)-(vs.fieldoffset div 8); + { our bitpacked fields are interpreted as always being + aligned, because unlike in C we don't have char:1, int:1 + etc (so everything is basically a char:x) } + checkalignment:=false; + end else - size:=vs.vardef.size + size:=vs.vardef.size; + end; + { If [..] an object [..] contains unaligned fields, it has class + MEMORY } + if checkalignment and + (align(new_byte_offset,vs.vardef.structalignment)<>new_byte_offset) then + begin + result:=0; + exit; end; num:=classify_aggregate_element(vs.vardef,varspez,size,classes,new_byte_offset); if (num=0) then @@ -413,6 +429,13 @@ unit cpupara; begin { size does not change } new_byte_offset:=byte_offset+i*elesize; + { If [..] an object [..] contains unaligned fields, it has class + MEMORY } + if align(new_byte_offset,def.alignment)<>new_byte_offset then + begin + result:=0; + exit; + end; end else begin diff --git a/tests/webtbs/tw22878.pp b/tests/webtbs/tw22878.pp new file mode 100644 index 0000000000..42b98e4b44 --- /dev/null +++ b/tests/webtbs/tw22878.pp @@ -0,0 +1,31 @@ +program gr; +{$mode objfpc} + type + t0= record + p: pointer; + end; + t1= packed record + u16: word; + data: t0; + end; + + td= class + function return: t1; + end; + function td.return: t1; + begin + return.u16:=1; + return.data.p:=pointer(2); + end; +var + c: td; + r: t1; +begin + c:=td.create; + r:=c.return; + if r.u16<>1 then + halt(1); + if r.data.p<>pointer(2) then + halt(2); +end. +