浏览代码

+ 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 年之前
父节点
当前提交
c7544e69de
共有 4 个文件被更改,包括 106 次插入19 次删除
  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 }
          { startvarrec contains the start of the variant part of a record }
          maxsize, startvarrecsize : longint;
          maxsize, startvarrecsize : longint;
          usedalign,
          usedalign,
-         maxalignment,startvarrecalign : byte;
+         maxalignment,startvarrecalign,
+         maxpadalign, startpadalign: shortint;
          hp,pt : tnode;
          hp,pt : tnode;
          vs,vs2    : tvarsym;
          vs,vs2    : tvarsym;
          srsym : tsym;
          srsym : tsym;
@@ -699,7 +700,14 @@ implementation
          uniontype : ttype;
          uniontype : ttype;
          dummysymoptions : tsymoptions;
          dummysymoptions : tsymoptions;
          semicolonatend: boolean;
          semicolonatend: boolean;
+{$ifdef powerpc}
+         tempdef: tdef;
+         is_first_field: boolean;
+{$endif powerpc}
       begin
       begin
+{$ifdef powerpc}
+        is_first_field := true;
+{$endif powerpc}
          old_current_object_option:=current_object_option;
          old_current_object_option:=current_object_option;
          { all variables are public if not in a object declaration }
          { all variables are public if not in a object declaration }
          if not is_object then
          if not is_object then
@@ -760,6 +768,36 @@ implementation
                   tt.def.typesym:=nil;
                   tt.def.typesym:=nil;
                   newtype.free;
                   newtype.free;
                end;
                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
              { types that use init/final are not allowed in variant parts, but
                classes are allowed }
                classes are allowed }
              if (variantrecordlevel>0) and
              if (variantrecordlevel>0) and
@@ -1125,6 +1163,7 @@ implementation
            begin
            begin
               maxsize:=0;
               maxsize:=0;
               maxalignment:=0;
               maxalignment:=0;
+              maxpadalign:=0;
               consume(_CASE);
               consume(_CASE);
               sorg:=orgpattern;
               sorg:=orgpattern;
               hs:=pattern;
               hs:=pattern;
@@ -1169,6 +1208,7 @@ implementation
               registerdef:=true;
               registerdef:=true;
               startvarrecsize:=UnionSymtable.datasize;
               startvarrecsize:=UnionSymtable.datasize;
               startvarrecalign:=UnionSymtable.fieldalignment;
               startvarrecalign:=UnionSymtable.fieldalignment;
+              startpadalign:=Unionsymtable.padalignment;
               symtablestack:=UnionSymtable;
               symtablestack:=UnionSymtable;
               repeat
               repeat
                 repeat
                 repeat
@@ -1192,9 +1232,11 @@ implementation
                 { calculates maximal variant size }
                 { calculates maximal variant size }
                 maxsize:=max(maxsize,unionsymtable.datasize);
                 maxsize:=max(maxsize,unionsymtable.datasize);
                 maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
                 maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
+                maxpadalign:=max(maxpadalign,unionsymtable.padalignment);
                 { the items of the next variant are overlayed }
                 { the items of the next variant are overlayed }
                 unionsymtable.datasize:=startvarrecsize;
                 unionsymtable.datasize:=startvarrecsize;
                 unionsymtable.fieldalignment:=startvarrecalign;
                 unionsymtable.fieldalignment:=startvarrecalign;
+                unionsymtable.padalignment:=startpadalign;
                 if (token<>_END) and (token<>_RKLAMMER) then
                 if (token<>_END) and (token<>_RKLAMMER) then
                   consume(_SEMICOLON)
                   consume(_SEMICOLON)
                 else
                 else
@@ -1207,6 +1249,15 @@ implementation
               uniontype.sym:=nil;
               uniontype.sym:=nil;
               UnionSym:=tvarsym.create('$case',vs_value,uniontype);
               UnionSym:=tvarsym.create('$case',vs_value,uniontype);
               symtablestack:=symtablestack.next;
               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 }
               { Align the offset where the union symtable is added }
               if (trecordsymtable(symtablestack).usefieldalignment=-1) then
               if (trecordsymtable(symtablestack).usefieldalignment=-1) then
                 usedalign:=used_align(unionsymtable.recordalignment,aktalignment.recordalignmin,aktalignment.maxCrecordalign)
                 usedalign:=used_align(unionsymtable.recordalignment,aktalignment.recordalignmin,aktalignment.maxCrecordalign)
@@ -1229,12 +1280,21 @@ implementation
          current_object_option:=old_current_object_option;
          current_object_option:=old_current_object_option;
          { free the list }
          { free the list }
          sc.free;
          sc.free;
+{$ifdef powerpc}
+         is_first_field := false;
+{$endif powerpc}
       end;
       end;
 
 
 end.
 end.
 {
 {
   $Log$
   $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
     * fixed alignment of variant records
     * more alignment problems fixed
     * more alignment problems fixed
 
 

+ 9 - 3
compiler/ppu.pas

@@ -45,9 +45,9 @@ type
 
 
 const
 const
 {$ifdef ansistring_bits}
 {$ifdef ansistring_bits}
-  CurrentPPUVersion=42;
+  CurrentPPUVersion=43;
 {$else}
 {$else}
-  CurrentPPUVersion=42;
+  CurrentPPUVersion=43;
 {$endif}
 {$endif}
 
 
 { buffer sizes }
 { buffer sizes }
@@ -1053,7 +1053,13 @@ end;
 end.
 end.
 {
 {
   $Log$
   $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
     * inline procedures at the node tree level, but only under some very
       limited circumstances for now (only procedures, and only if they have
       limited circumstances for now (only procedures, and only if they have
       no or only vs_out/vs_var parameters).
       no or only vs_out/vs_var parameters).

+ 19 - 5
compiler/symdef.pas

@@ -244,6 +244,7 @@ interface
           procedure deref;override;
           procedure deref;override;
           function  size:longint;override;
           function  size:longint;override;
           function  alignment : longint;override;
           function  alignment : longint;override;
+          function  padalignment: longint;
           function  gettypename:string;override;
           function  gettypename:string;override;
           { debug }
           { debug }
 {$ifdef GDB}
 {$ifdef GDB}
@@ -3112,8 +3113,9 @@ implementation
          deftype:=recorddef;
          deftype:=recorddef;
          symtable:=trecordsymtable.create(0);
          symtable:=trecordsymtable.create(0);
          trecordsymtable(symtable).datasize:=ppufile.getlongint;
          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);
          trecordsymtable(symtable).ppuload(ppufile);
          symtable.defowner:=self;
          symtable.defowner:=self;
          isunion:=false;
          isunion:=false;
@@ -3171,8 +3173,9 @@ implementation
       begin
       begin
          inherited ppuwritedef(ppufile);
          inherited ppuwritedef(ppufile);
          ppufile.putlongint(trecordsymtable(symtable).datasize);
          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);
          ppufile.writeentry(ibrecorddef);
          trecordsymtable(symtable).ppuwrite(ppufile);
          trecordsymtable(symtable).ppuwrite(ppufile);
       end;
       end;
@@ -3190,6 +3193,11 @@ implementation
       end;
       end;
 
 
 
 
+    function trecorddef.padalignment:longint;
+      begin
+        padalignment := trecordsymtable(symtable).padalignment;
+      end;
+
 {$ifdef GDB}
 {$ifdef GDB}
     function trecorddef.stabstring : pchar;
     function trecorddef.stabstring : pchar;
       var
       var
@@ -6146,7 +6154,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $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
     * fixed padding of records to alignment
 
 
   Revision 1.250  2004/08/14 14:50:42  florian
   Revision 1.250  2004/08/14 14:50:42  florian

+ 16 - 9
compiler/symtable.pas

@@ -90,7 +90,8 @@ interface
           datasize       : longint;
           datasize       : longint;
           usefieldalignment,     { alignment to use for fields (PACKRECORDS value), -1 is C style }
           usefieldalignment,     { alignment to use for fields (PACKRECORDS value), -1 is C style }
           recordalignment,       { alignment required when inserting this record }
           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);
           constructor create(const n:string;usealign:shortint);
           procedure ppuload(ppufile:tcompilerppufile);override;
           procedure ppuload(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
@@ -908,6 +909,7 @@ implementation
         datasize:=0;
         datasize:=0;
         recordalignment:=1;
         recordalignment:=1;
         usefieldalignment:=usealign;
         usefieldalignment:=usealign;
+        padalignment:=1;
         { recordalign -1 means C record packing, that starts
         { recordalign -1 means C record packing, that starts
           with an alignment of 1 }
           with an alignment of 1 }
         if usealign=-1 then
         if usealign=-1 then
@@ -1044,18 +1046,17 @@ implementation
 
 
 
 
     procedure tabstractrecordsymtable.addalignmentpadding;
     procedure tabstractrecordsymtable.addalignmentpadding;
-      var
-        padalign : shortint;
       begin
       begin
         { make the record size aligned correctly so it can be
         { make the record size aligned correctly so it can be
           used as elements in an array. For C records we
           used as elements in an array. For C records we
           use the fieldalignment, because that is updated with the
           use the fieldalignment, because that is updated with the
           used alignment. }
           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;
       end;
 
 
 
 
@@ -2314,7 +2315,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $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
     * fixed padding of records to alignment
 
 
   Revision 1.153  2004/08/15 13:30:18  florian
   Revision 1.153  2004/08/15 13:30:18  florian