Browse Source

+ 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)

Jonas Maebe 21 years ago
parent
commit
c7544e69de
4 changed files with 106 additions and 19 deletions
  1. 62 2
      compiler/pdecvar.pas
  2. 9 3
      compiler/ppu.pas
  3. 19 5
      compiler/symdef.pas
  4. 16 9
      compiler/symtable.pas

+ 62 - 2
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
 

+ 9 - 3
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).

+ 19 - 5
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

+ 16 - 9
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