mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 14:27:59 +02:00
* changed {$align mac68k} from an alias for {$packrecords 2} to a proper
implementation for mac68k alignment (mantis #15061) * changed {$align power} from an alias for {$packrecords 4} to an alias for {$packrecords c}, as Power alignment is the default C alignment for PowerPC under Mac OS X (it's close to {$packrecords 4}, but not identical) git-svn-id: trunk@14577 -
This commit is contained in:
parent
699c07ce7f
commit
9cc211e88e
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -10178,6 +10178,8 @@ tests/webtbs/tw14992b.pp svneol=native#text/pascal
|
||||
tests/webtbs/tw14992c.pp svneol=native#text/pascal
|
||||
tests/webtbs/tw1501.pp svneol=native#text/plain
|
||||
tests/webtbs/tw15015.pp svneol=native#text/plain
|
||||
tests/webtbs/tw15061.pp svneol=native#text/plain
|
||||
tests/webtbs/tw15061a.pp svneol=native#text/plain
|
||||
tests/webtbs/tw15088.pp svneol=native#text/plain
|
||||
tests/webtbs/tw15169.pp svneol=native#text/plain
|
||||
tests/webtbs/tw15203.pp svneol=native#text/pascal
|
||||
|
@ -1613,6 +1613,8 @@ implementation
|
||||
{ 1 byte alignment if we are bitpacked }
|
||||
bit_alignment:
|
||||
usedalign:=1;
|
||||
mac68k_alignment:
|
||||
usedalign:=2;
|
||||
{ otherwise alignment at the packrecords alignment of the }
|
||||
{ current record }
|
||||
else
|
||||
|
@ -144,9 +144,11 @@ unit scandir;
|
||||
begin
|
||||
{ Support switches used in Apples Universal Interfaces}
|
||||
if (hs='MAC68K') then
|
||||
current_settings.packrecords:=2
|
||||
current_settings.packrecords:=mac68k_alignment
|
||||
{ "power" alignment is the default C packrecords setting on
|
||||
Mac OS X }
|
||||
else if (hs='POWER') then
|
||||
current_settings.packrecords:=4
|
||||
current_settings.packrecords:=C_alignment
|
||||
else if (hs='RESET') then
|
||||
current_settings.packrecords:=0
|
||||
else
|
||||
|
@ -28,10 +28,11 @@ uses
|
||||
globtype;
|
||||
|
||||
const
|
||||
def_alignment = 4;
|
||||
def_alignment = 4;
|
||||
|
||||
C_alignment = -1;
|
||||
bit_alignment = -2;
|
||||
C_alignment = -1;
|
||||
bit_alignment = -2;
|
||||
mac68k_alignment = -3;
|
||||
|
||||
{ if you change one of the following contants, }
|
||||
{ you have also to change the typinfo unit}
|
||||
|
@ -757,7 +757,9 @@ implementation
|
||||
case usealign of
|
||||
C_alignment,
|
||||
bit_alignment:
|
||||
fieldalignment:=1
|
||||
fieldalignment:=1;
|
||||
mac68k_alignment:
|
||||
fieldalignment:=2;
|
||||
else
|
||||
fieldalignment:=usealign;
|
||||
end;
|
||||
@ -813,10 +815,14 @@ implementation
|
||||
var
|
||||
varalignrecord: shortint;
|
||||
begin
|
||||
if (usefieldalignment=C_alignment) then
|
||||
varalignrecord:=used_align(varalign,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign)
|
||||
else
|
||||
varalignrecord:=field2recordalignment(fieldoffset,varalign);
|
||||
case usefieldalignment of
|
||||
C_alignment:
|
||||
varalignrecord:=used_align(varalign,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign);
|
||||
mac68k_alignment:
|
||||
varalignrecord:=2;
|
||||
else
|
||||
varalignrecord:=field2recordalignment(fieldoffset,varalign);
|
||||
end;
|
||||
recordalignment:=max(recordalignment,varalignrecord);
|
||||
end;
|
||||
|
||||
@ -840,70 +846,85 @@ implementation
|
||||
vardef:=sym.vardef;
|
||||
varalign:=vardef.alignment;
|
||||
|
||||
if (usefieldalignment=bit_alignment) then
|
||||
begin
|
||||
{ bitpacking only happens for ordinals, the rest is aligned at }
|
||||
{ 1 byte (compatible with GPC/GCC) }
|
||||
if is_ordinal(vardef) then
|
||||
begin
|
||||
sym.fieldoffset:=databitsize;
|
||||
l:=sym.getpackedbitsize;
|
||||
end
|
||||
else
|
||||
begin
|
||||
databitsize:=_datasize*8;
|
||||
sym.fieldoffset:=databitsize;
|
||||
if (l>high(aint) div 8) then
|
||||
case usefieldalignment of
|
||||
bit_alignment:
|
||||
begin
|
||||
{ bitpacking only happens for ordinals, the rest is aligned at }
|
||||
{ 1 byte (compatible with GPC/GCC) }
|
||||
if is_ordinal(vardef) then
|
||||
begin
|
||||
sym.fieldoffset:=databitsize;
|
||||
l:=sym.getpackedbitsize;
|
||||
end
|
||||
else
|
||||
begin
|
||||
databitsize:=_datasize*8;
|
||||
sym.fieldoffset:=databitsize;
|
||||
if (l>high(aint) div 8) then
|
||||
Message(sym_e_segment_too_large);
|
||||
l:=l*8;
|
||||
end;
|
||||
if varalign=0 then
|
||||
varalign:=size_2_align(l);
|
||||
recordalignment:=max(recordalignment,field2recordalignment(databitsize mod 8,varalign));
|
||||
{ bit packed records are limited to high(aint) bits }
|
||||
{ instead of bytes to avoid double precision }
|
||||
{ arithmetic in offset calculations }
|
||||
if int64(l)>high(aint)-sym.fieldoffset then
|
||||
begin
|
||||
Message(sym_e_segment_too_large);
|
||||
l:=l*8;
|
||||
end;
|
||||
if varalign=0 then
|
||||
varalign:=size_2_align(l);
|
||||
recordalignment:=max(recordalignment,field2recordalignment(databitsize mod 8,varalign));
|
||||
{ bit packed records are limited to high(aint) bits }
|
||||
{ instead of bytes to avoid double precision }
|
||||
{ arithmetic in offset calculations }
|
||||
if int64(l)>high(aint)-sym.fieldoffset then
|
||||
begin
|
||||
Message(sym_e_segment_too_large);
|
||||
_datasize:=high(aint);
|
||||
databitsize:=high(aint);
|
||||
end
|
||||
else
|
||||
begin
|
||||
databitsize:=sym.fieldoffset+l;
|
||||
_datasize:=(databitsize+7) div 8;
|
||||
end;
|
||||
{ rest is not applicable }
|
||||
exit;
|
||||
end;
|
||||
{ Calc the alignment size for C style records }
|
||||
if (usefieldalignment=C_alignment) then
|
||||
begin
|
||||
if (varalign>4) and
|
||||
((varalign mod 4)<>0) and
|
||||
(vardef.typ=arraydef) then
|
||||
Message1(sym_w_wrong_C_pack,vardef.typename);
|
||||
if varalign=0 then
|
||||
varalign:=l;
|
||||
if (fieldalignment<current_settings.alignment.maxCrecordalign) then
|
||||
begin
|
||||
if (varalign>16) and (fieldalignment<32) then
|
||||
fieldalignment:=32
|
||||
else if (varalign>12) and (fieldalignment<16) then
|
||||
fieldalignment:=16
|
||||
{ 12 is needed for long double }
|
||||
else if (varalign>8) and (fieldalignment<12) then
|
||||
fieldalignment:=12
|
||||
else if (varalign>4) and (fieldalignment<8) then
|
||||
fieldalignment:=8
|
||||
else if (varalign>2) and (fieldalignment<4) then
|
||||
fieldalignment:=4
|
||||
else if (varalign>1) and (fieldalignment<2) then
|
||||
fieldalignment:=2;
|
||||
end;
|
||||
fieldalignment:=min(fieldalignment,current_settings.alignment.maxCrecordalign);
|
||||
end;
|
||||
_datasize:=high(aint);
|
||||
databitsize:=high(aint);
|
||||
end
|
||||
else
|
||||
begin
|
||||
databitsize:=sym.fieldoffset+l;
|
||||
_datasize:=(databitsize+7) div 8;
|
||||
end;
|
||||
{ rest is not applicable }
|
||||
exit;
|
||||
end;
|
||||
{ Calc the alignment size for C style records }
|
||||
C_alignment:
|
||||
begin
|
||||
if (varalign>4) and
|
||||
((varalign mod 4)<>0) and
|
||||
(vardef.typ=arraydef) then
|
||||
Message1(sym_w_wrong_C_pack,vardef.typename);
|
||||
if varalign=0 then
|
||||
varalign:=l;
|
||||
if (fieldalignment<current_settings.alignment.maxCrecordalign) then
|
||||
begin
|
||||
if (varalign>16) and (fieldalignment<32) then
|
||||
fieldalignment:=32
|
||||
else if (varalign>12) and (fieldalignment<16) then
|
||||
fieldalignment:=16
|
||||
{ 12 is needed for long double }
|
||||
else if (varalign>8) and (fieldalignment<12) then
|
||||
fieldalignment:=12
|
||||
else if (varalign>4) and (fieldalignment<8) then
|
||||
fieldalignment:=8
|
||||
else if (varalign>2) and (fieldalignment<4) then
|
||||
fieldalignment:=4
|
||||
else if (varalign>1) and (fieldalignment<2) then
|
||||
fieldalignment:=2;
|
||||
end;
|
||||
fieldalignment:=min(fieldalignment,current_settings.alignment.maxCrecordalign);
|
||||
end;
|
||||
mac68k_alignment:
|
||||
begin
|
||||
{ mac68k alignment (C description):
|
||||
* char is aligned to 1 byte
|
||||
* everything else (except vector) is aligned to 2 bytes
|
||||
* vector is aligned to 16 bytes
|
||||
}
|
||||
if l>1 then
|
||||
fieldalignment:=2
|
||||
else
|
||||
fieldalignment:=1;
|
||||
varalign:=2;
|
||||
end;
|
||||
end;
|
||||
if varalign=0 then
|
||||
varalign:=size_2_align(l);
|
||||
varalignfield:=used_align(varalign,current_settings.alignment.recordalignmin,fieldalignment);
|
||||
@ -934,6 +955,9 @@ implementation
|
||||
{ bitpacked }
|
||||
bit_alignment:
|
||||
padalignment:=1;
|
||||
{ mac68k: always round to multiple of 2 }
|
||||
mac68k_alignment:
|
||||
padalignment:=2;
|
||||
{ default/no packrecords specified }
|
||||
0:
|
||||
padalignment:=recordalignment
|
||||
@ -1062,11 +1086,13 @@ implementation
|
||||
varalignrecord:=field2recordalignment(tfieldvarsym(sym).fieldoffset,varalign);
|
||||
end;
|
||||
{ update alignment of this record }
|
||||
if (usefieldalignment<>C_alignment) then
|
||||
if (usefieldalignment<>C_alignment) and
|
||||
(usefieldalignment<>mac68k_alignment) then
|
||||
recordalignment:=max(recordalignment,varalignrecord);
|
||||
end;
|
||||
{ update alignment for C records }
|
||||
if (usefieldalignment=C_alignment) then
|
||||
if (usefieldalignment=C_alignment) and
|
||||
(usefieldalignment<>mac68k_alignment) then
|
||||
recordalignment:=max(recordalignment,unionst.recordalignment);
|
||||
{ Register defs in the new record symtable }
|
||||
for i:=0 to unionst.DefList.Count-1 do
|
||||
|
37
tests/webtbs/tw15061.pp
Normal file
37
tests/webtbs/tw15061.pp
Normal file
@ -0,0 +1,37 @@
|
||||
{$ifdef FPC}
|
||||
{$mode macpas}
|
||||
{$align mac68k}
|
||||
{$endif}
|
||||
|
||||
{$ifdef __GPC__}
|
||||
{ maximum-field-alignment=16}
|
||||
{$endif}
|
||||
|
||||
program patbug;
|
||||
type
|
||||
{$ifdef FPC}
|
||||
PtrWord = PtrUInt;
|
||||
{$endif}
|
||||
pattern = record pat: array[0..7] of byte end;
|
||||
patrec = record b: boolean; p: pattern end;
|
||||
doublerec = record b: boolean; d: double end;
|
||||
var
|
||||
gPatRec: patrec;
|
||||
gDoubleRec: doublerec;
|
||||
begin
|
||||
writeln( 'SizeOf( patrec) = ', SizeOf( patrec));
|
||||
if (sizeof(patrec)<>10) then
|
||||
halt(1);
|
||||
writeln( 'Offset of p: pattern = ', PtrWord( @gPatRec.p) - PtrWord( @gPatRec));
|
||||
if ((PtrWord( @gPatRec.p) - PtrWord( @gPatRec)) <> 2) then
|
||||
halt(2);
|
||||
writeln;
|
||||
writeln( 'SizeOf( doublerec) = ', SizeOf( doublerec));
|
||||
if (sizeof(doublerec)<>10) then
|
||||
halt(3);
|
||||
writeln( 'Offset of d: double = ', PtrWord( @gDoubleRec.d) - PtrWord( @gDoubleRec));
|
||||
if ((PtrWord( @gDoubleRec.d) - PtrWord( @gDoubleRec))<>2) then
|
||||
halt(4);
|
||||
writeln;
|
||||
end.
|
||||
|
37
tests/webtbs/tw15061a.pp
Normal file
37
tests/webtbs/tw15061a.pp
Normal file
@ -0,0 +1,37 @@
|
||||
{$ifdef FPC}
|
||||
{$mode macpas}
|
||||
{$align power}
|
||||
{$endif}
|
||||
|
||||
{$ifdef __GPC__}
|
||||
{ maximum-field-alignment=16}
|
||||
{$endif}
|
||||
|
||||
program patbug;
|
||||
type
|
||||
{$ifdef FPC}
|
||||
PtrWord = PtrUInt;
|
||||
{$endif}
|
||||
pattern = record pat: array[0..7] of byte end;
|
||||
patrec = record b: boolean; p: pattern end;
|
||||
doublerec = record b: boolean; d: double end;
|
||||
var
|
||||
gPatRec: patrec;
|
||||
gDoubleRec: doublerec;
|
||||
begin
|
||||
writeln( 'SizeOf( patrec) = ', SizeOf( patrec));
|
||||
if (sizeof(patrec)<>9) then
|
||||
halt(1);
|
||||
writeln( 'Offset of p: pattern = ', PtrWord( @gPatRec.p) - PtrWord( @gPatRec));
|
||||
if ((PtrWord( @gPatRec.p) - PtrWord( @gPatRec)) <> 1) then
|
||||
halt(2);
|
||||
writeln;
|
||||
writeln( 'SizeOf( doublerec) = ', SizeOf( doublerec));
|
||||
if (sizeof(doublerec)<>12) then
|
||||
halt(3);
|
||||
writeln( 'Offset of d: double = ', PtrWord( @gDoubleRec.d) - PtrWord( @gDoubleRec));
|
||||
if ((PtrWord( @gDoubleRec.d) - PtrWord( @gDoubleRec))<>4) then
|
||||
halt(4);
|
||||
writeln;
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user