diff --git a/compiler/pdecvar.pas b/compiler/pdecvar.pas index 179d82eb82..4dabb7a98d 100644 --- a/compiler/pdecvar.pas +++ b/compiler/pdecvar.pas @@ -686,7 +686,8 @@ implementation { startvarrec contains the start of the variant part of a record } maxsize, startvarrecsize : longint; usedalign, - maxalignment,startvarrecalign : byte; + maxalignment,startvarrecalign, + maxpadalign, startpadalign: shortint; hp,pt : tnode; vs,vs2 : tvarsym; srsym : tsym; @@ -699,7 +700,14 @@ implementation uniontype : ttype; dummysymoptions : tsymoptions; semicolonatend: boolean; +{$ifdef powerpc} + tempdef: tdef; + is_first_field: boolean; +{$endif powerpc} begin +{$ifdef powerpc} + is_first_field := true; +{$endif powerpc} old_current_object_option:=current_object_option; { all variables are public if not in a object declaration } if not is_object then @@ -760,6 +768,36 @@ implementation tt.def.typesym:=nil; newtype.free; end; +{$ifdef powerpc} + { from gcc/gcc/config/rs6000/rs6000.h: + /* APPLE LOCAL begin Macintosh alignment 2002-1-22 ff */ + /* Return the alignment of a struct based on the Macintosh PowerPC + alignment rules. In general the alignment of a struct is + determined by the greatest alignment of its elements. However, the + PowerPC rules cause the alignment of a struct to peg at word + alignment except when the first field has greater than word + (32-bit) alignment, in which case the alignment is determined by + the alignment of the first field. */ + } + if (target_info.system in [system_powerpc_darwin, system_powerpc_macos]) and + is_record and + is_first_field and + (trecordsymtable(symtablestack).usefieldalignment = -1) then + begin + tempdef := tt.def; + while tempdef.deftype = arraydef do + tempdef := tarraydef(tempdef).elementtype.def; + if tempdef.deftype <> recorddef then + maxpadalign := tempdef.alignment + else + maxpadalign := trecorddef(tempdef).padalignment; + + if (maxpadalign > 4) and + (maxpadalign > trecordsymtable(symtablestack).padalignment) then + trecordsymtable(symtablestack).padalignment := maxpadalign; + is_first_field := false; + end; +{$endif powerpc} { types that use init/final are not allowed in variant parts, but classes are allowed } if (variantrecordlevel>0) and @@ -1125,6 +1163,7 @@ implementation begin maxsize:=0; maxalignment:=0; + maxpadalign:=0; consume(_CASE); sorg:=orgpattern; hs:=pattern; @@ -1169,6 +1208,7 @@ implementation registerdef:=true; startvarrecsize:=UnionSymtable.datasize; startvarrecalign:=UnionSymtable.fieldalignment; + startpadalign:=Unionsymtable.padalignment; symtablestack:=UnionSymtable; repeat repeat @@ -1192,9 +1232,11 @@ implementation { calculates maximal variant size } maxsize:=max(maxsize,unionsymtable.datasize); maxalignment:=max(maxalignment,unionsymtable.fieldalignment); + maxpadalign:=max(maxpadalign,unionsymtable.padalignment); { the items of the next variant are overlayed } unionsymtable.datasize:=startvarrecsize; unionsymtable.fieldalignment:=startvarrecalign; + unionsymtable.padalignment:=startpadalign; if (token<>_END) and (token<>_RKLAMMER) then consume(_SEMICOLON) else @@ -1207,6 +1249,15 @@ implementation uniontype.sym:=nil; UnionSym:=tvarsym.create('$case',vs_value,uniontype); symtablestack:=symtablestack.next; + unionsymtable.addalignmentpadding; +{$ifdef powerpc} + { parent inherits the alignment padding if the variant is the first "field" of the parent record/variant } + if (target_info.system in [system_powerpc_darwin, system_powerpc_macos]) and + is_first_field and + (trecordsymtable(symtablestack).usefieldalignment = -1) and + (maxpadalign > trecordsymtable(symtablestack).padalignment) then + trecordsymtable(symtablestack).padalignment:=maxpadalign; +{$endif powerpc} { Align the offset where the union symtable is added } if (trecordsymtable(symtablestack).usefieldalignment=-1) then usedalign:=used_align(unionsymtable.recordalignment,aktalignment.recordalignmin,aktalignment.maxCrecordalign) @@ -1229,12 +1280,21 @@ implementation current_object_option:=old_current_object_option; { free the list } sc.free; +{$ifdef powerpc} + is_first_field := false; +{$endif powerpc} end; end. { $Log$ - Revision 1.78 2004-08-15 13:30:18 florian + Revision 1.79 2004-08-17 16:29:21 jonas + + padalgingment field for recordsymtables (saved by recorddefs) + + support for Macintosh PowerPC alignment (if the first field of a record + or union has an alignment > 4, then the record or union size must be + padded to a multiple of this size) + + Revision 1.78 2004/08/15 13:30:18 florian * fixed alignment of variant records * more alignment problems fixed diff --git a/compiler/ppu.pas b/compiler/ppu.pas index 53f2e1e21d..e36af73473 100644 --- a/compiler/ppu.pas +++ b/compiler/ppu.pas @@ -45,9 +45,9 @@ type const {$ifdef ansistring_bits} - CurrentPPUVersion=42; + CurrentPPUVersion=43; {$else} - CurrentPPUVersion=42; + CurrentPPUVersion=43; {$endif} { buffer sizes } @@ -1053,7 +1053,13 @@ end; end. { $Log$ - Revision 1.53 2004-07-12 09:14:04 jonas + Revision 1.54 2004-08-17 16:29:21 jonas + + padalgingment field for recordsymtables (saved by recorddefs) + + support for Macintosh PowerPC alignment (if the first field of a record + or union has an alignment > 4, then the record or union size must be + padded to a multiple of this size) + + Revision 1.53 2004/07/12 09:14:04 jonas * inline procedures at the node tree level, but only under some very limited circumstances for now (only procedures, and only if they have no or only vs_out/vs_var parameters). diff --git a/compiler/symdef.pas b/compiler/symdef.pas index 140589a7fd..7901f350af 100644 --- a/compiler/symdef.pas +++ b/compiler/symdef.pas @@ -244,6 +244,7 @@ interface procedure deref;override; function size:longint;override; function alignment : longint;override; + function padalignment: longint; function gettypename:string;override; { debug } {$ifdef GDB} @@ -3112,8 +3113,9 @@ implementation deftype:=recorddef; symtable:=trecordsymtable.create(0); trecordsymtable(symtable).datasize:=ppufile.getlongint; - trecordsymtable(symtable).fieldalignment:=ppufile.getbyte; - trecordsymtable(symtable).recordalignment:=ppufile.getbyte; + trecordsymtable(symtable).fieldalignment:=shortint(ppufile.getbyte); + trecordsymtable(symtable).recordalignment:=shortint(ppufile.getbyte); + trecordsymtable(symtable).padalignment:=shortint(ppufile.getbyte); trecordsymtable(symtable).ppuload(ppufile); symtable.defowner:=self; isunion:=false; @@ -3171,8 +3173,9 @@ implementation begin inherited ppuwritedef(ppufile); ppufile.putlongint(trecordsymtable(symtable).datasize); - ppufile.putbyte(trecordsymtable(symtable).fieldalignment); - ppufile.putbyte(trecordsymtable(symtable).recordalignment); + ppufile.putbyte(byte(trecordsymtable(symtable).fieldalignment)); + ppufile.putbyte(byte(trecordsymtable(symtable).recordalignment)); + ppufile.putbyte(byte(trecordsymtable(symtable).padalignment)); ppufile.writeentry(ibrecorddef); trecordsymtable(symtable).ppuwrite(ppufile); end; @@ -3190,6 +3193,11 @@ implementation end; + function trecorddef.padalignment:longint; + begin + padalignment := trecordsymtable(symtable).padalignment; + end; + {$ifdef GDB} function trecorddef.stabstring : pchar; var @@ -6146,7 +6154,13 @@ implementation end. { $Log$ - Revision 1.251 2004-08-15 15:05:16 peter + Revision 1.252 2004-08-17 16:29:21 jonas + + padalgingment field for recordsymtables (saved by recorddefs) + + support for Macintosh PowerPC alignment (if the first field of a record + or union has an alignment > 4, then the record or union size must be + padded to a multiple of this size) + + Revision 1.251 2004/08/15 15:05:16 peter * fixed padding of records to alignment Revision 1.250 2004/08/14 14:50:42 florian diff --git a/compiler/symtable.pas b/compiler/symtable.pas index 317068de58..f75f05b5b9 100644 --- a/compiler/symtable.pas +++ b/compiler/symtable.pas @@ -90,7 +90,8 @@ interface datasize : longint; usefieldalignment, { alignment to use for fields (PACKRECORDS value), -1 is C style } recordalignment, { alignment required when inserting this record } - fieldalignment : shortint; { alignment current alignment used when fields are inserted } + fieldalignment, { alignment current alignment used when fields are inserted } + padalignment : shortint; { size to a multiple of which the symtable has to be rounded up } constructor create(const n:string;usealign:shortint); procedure ppuload(ppufile:tcompilerppufile);override; procedure ppuwrite(ppufile:tcompilerppufile);override; @@ -908,6 +909,7 @@ implementation datasize:=0; recordalignment:=1; usefieldalignment:=usealign; + padalignment:=1; { recordalign -1 means C record packing, that starts with an alignment of 1 } if usealign=-1 then @@ -1044,18 +1046,17 @@ implementation procedure tabstractrecordsymtable.addalignmentpadding; - var - padalign : shortint; begin { make the record size aligned correctly so it can be used as elements in an array. For C records we use the fieldalignment, because that is updated with the used alignment. } - if usefieldalignment=-1 then - padalign:=fieldalignment - else - padalign:=recordalignment; - datasize:=align(datasize,padalign); + if (padalignment = 1) then + if usefieldalignment=-1 then + padalignment:=fieldalignment + else + padalignment:=recordalignment; + datasize:=align(datasize,padalignment); end; @@ -2314,7 +2315,13 @@ implementation end. { $Log$ - Revision 1.154 2004-08-15 15:05:16 peter + Revision 1.155 2004-08-17 16:29:21 jonas + + padalgingment field for recordsymtables (saved by recorddefs) + + support for Macintosh PowerPC alignment (if the first field of a record + or union has an alignment > 4, then the record or union size must be + padded to a multiple of this size) + + Revision 1.154 2004/08/15 15:05:16 peter * fixed padding of records to alignment Revision 1.153 2004/08/15 13:30:18 florian