瀏覽代碼

--- Merging r18098 into '.':
U compiler/htypechk.pas
--- Merging r18114 into '.':
U compiler/symdef.pas
U compiler/pdecobj.pas
U compiler/symtable.pas
U compiler/ppu.pas
--- Merging r18117 into '.':
U compiler/utils/ppudump.pp
--- Merging r18118 into '.':
G compiler/symdef.pas
G compiler/ppu.pas
--- Merging r18119 into '.':
G compiler/symdef.pas
G compiler/symtable.pas
G compiler/ppu.pas
G compiler/utils/ppudump.pp
--- Merging r18124 into '.':
U compiler/nmem.pas
U compiler/ncal.pas
--- Merging r18171 into '.':
U compiler/ncnv.pas
--- Merging r18792 into '.':
U compiler/ncgadd.pas

# revisions: 18098,18114,18117,18118,18119,18124,18171,18792
------------------------------------------------------------------------
r18098 | jonas | 2011-08-05 00:44:00 +0200 (Fri, 05 Aug 2011) | 3 lines
Changed paths:
M /trunk/compiler/htypechk.pas

* fixed two places where after r1913 valid_for_assign() didn't immediately
exit anymore if an error was detected

------------------------------------------------------------------------
------------------------------------------------------------------------
r18114 | jonas | 2011-08-06 15:11:23 +0200 (Sat, 06 Aug 2011) | 7 lines
Changed paths:
M /trunk/compiler/pdecobj.pas
M /trunk/compiler/ppu.pas
M /trunk/compiler/symdef.pas
M /trunk/compiler/symtable.pas

* store the current field alignment of tobjectdefs that use C_alignment,
because it influences the offset at which the next field in child classes
should be placed in case it also uses C_alignment
* also pad objectdefs based on the packrecords setting (Delphi-compatible)
-> field offset calculation in objcclasses is now correct if they are
compiled with {$packrecords c}

------------------------------------------------------------------------
------------------------------------------------------------------------
r18117 | jonas | 2011-08-06 19:14:22 +0200 (Sat, 06 Aug 2011) | 2 lines
Changed paths:
M /trunk/compiler/utils/ppudump.pp

* update of ppudump for r18114

------------------------------------------------------------------------
------------------------------------------------------------------------
r18118 | jonas | 2011-08-06 19:18:21 +0200 (Sat, 06 Aug 2011) | 7 lines
Changed paths:
M /trunk/compiler/ppu.pas
M /trunk/compiler/symdef.pas

+ tppufile.putasizeint()
* save/restore tabstractrecordsymtable.datasize as asizeint instead of
aint (not ppu version change because they are the same on all
production targets)
* add shortint() typecasts when reading/writing fieldalignment/
recordalignment fields

------------------------------------------------------------------------
------------------------------------------------------------------------
r18119 | jonas | 2011-08-06 20:01:39 +0200 (Sat, 06 Aug 2011) | 6 lines
Changed paths:
M /trunk/compiler/ppu.pas
M /trunk/compiler/symdef.pas
M /trunk/compiler/symtable.pas
M /trunk/compiler/utils/ppudump.pp

* also save/restore the size of the padding of record/objectsymtables
* when creating a child class, ignore the padding added to the parent
in case of objcclasses (gcc/clang also do that; maybe the same
has to be done for cppclass as well)
-> objcclass layouts seem to finally completely match the gcc ones

------------------------------------------------------------------------
------------------------------------------------------------------------
r18124 | jonas | 2011-08-06 21:49:59 +0200 (Sat, 06 Aug 2011) | 6 lines
Changed paths:
M /trunk/compiler/ncal.pas
M /trunk/compiler/nmem.pas

* when an constant Objective-C class reference is used for anything but
the methodpointer of a call, transform it into a call to the classclass
method because otherwise it can be used before the first call to any
method of the class (such as in the packages/cocoaint/src/IvarSize test)
and this can result in crashes

------------------------------------------------------------------------
------------------------------------------------------------------------
r18171 | jonas | 2011-08-11 18:05:11 +0200 (Thu, 11 Aug 2011) | 4 lines
Changed paths:
M /trunk/compiler/ncnv.pas

* when removing unnecessary 64 bit widenings, modify both the resultdef
and the totypedef of typeconvnodes because the totypedef is used for
equality comparisons in the node cse

------------------------------------------------------------------------
------------------------------------------------------------------------
r18792 | jonas | 2011-08-20 22:36:13 +0200 (Sat, 20 Aug 2011) | 4 lines
Changed paths:
M /trunk/compiler/ncgadd.pas

* fixed generic code for subtracting one set from another if both are
in registers, because the left set could be overwritten before its
last use

------------------------------------------------------------------------

git-svn-id: branches/fixes_2_6@18887 -

marco 14 年之前
父節點
當前提交
17941f0c2e
共有 10 個文件被更改,包括 152 次插入28 次删除
  1. 7 7
      compiler/htypechk.pas
  2. 16 1
      compiler/ncal.pas
  3. 7 0
      compiler/ncgadd.pas
  4. 4 1
      compiler/ncnv.pas
  5. 36 0
      compiler/nmem.pas
  6. 1 0
      compiler/pdecobj.pas
  7. 9 1
      compiler/ppu.pas
  8. 21 8
      compiler/symdef.pas
  9. 23 2
      compiler/symtable.pas
  10. 28 8
      compiler/utils/ppudump.pp

+ 7 - 7
compiler/htypechk.pas

@@ -1322,9 +1322,8 @@ implementation
                     (vo_is_loop_counter in tsubscriptnode(hp).vs.varoptions) then
                    begin
                      if report_errors then
-                       CGMessage1(parser_e_illegal_assignment_to_count_var,tsubscriptnode(hp).vs.realname)
-                     else
-                       exit;
+                       CGMessage1(parser_e_illegal_assignment_to_count_var,tsubscriptnode(hp).vs.realname);
+                     exit;
                    end;
                  { implicit pointer object types result in dereferencing }
                  hp:=tsubscriptnode(hp).left;
@@ -1475,10 +1474,11 @@ implementation
                        if not(Valid_Const in opts) and
                           not gotderef and
                           (vo_is_loop_counter in tabstractvarsym(tloadnode(hp).symtableentry).varoptions) then
-                         if report_errors then
-                          CGMessage1(parser_e_illegal_assignment_to_count_var,tloadnode(hp).symtableentry.realname)
-                         else
-                          exit;
+                         begin
+                           if report_errors then
+                             CGMessage1(parser_e_illegal_assignment_to_count_var,tloadnode(hp).symtableentry.realname);
+                           exit;
+                         end;
                        { read-only variable? }
                        if (tabstractvarsym(tloadnode(hp).symtableentry).varspez in [vs_const,vs_constref]) then
                         begin

+ 16 - 1
compiler/ncal.pas

@@ -1877,6 +1877,11 @@ implementation
           firstpass would be called multiple times }
         include(callnodeflags,cnf_objc_processed);
 
+        { make sure the methodpointer doesn't get translated into a call
+          as well (endless loop) }
+        if methodpointer.nodetype=loadvmtaddrn then
+          tloadvmtaddrnode(methodpointer).forcall:=true;
+
         { A) set the appropriate objc_msgSend* variant to call }
 
         { record returned via implicit pointer }
@@ -1938,6 +1943,10 @@ implementation
                 (selftree.resultdef.typ<>classrefdef) then
                begin
                  selftree:=cloadvmtaddrnode.create(selftree);
+                 { since we're in a class method of the current class, its
+                   information has already been initialized (and that of all of
+                   its parent classes too) }
+                 tloadvmtaddrnode(selftree).forcall:=true;
                  typecheckpass(selftree);
                end;
              selfrestype:=selftree.resultdef;
@@ -1981,6 +1990,9 @@ implementation
                 (methodpointer.resultdef.typ<>classrefdef)) then
               begin
                 methodpointer:=cloadvmtaddrnode.create(methodpointer);
+                { no need to obtain the class ref by calling class(), sending
+                  this message will initialize it if necessary }
+                tloadvmtaddrnode(methodpointer).forcall:=true;
                 firstpass(methodpointer);
               end;
           end;
@@ -2013,7 +2025,10 @@ implementation
                 vmttree:=methodpointer.getcopy;
                 { Only a typenode can be passed when it is called with <class of xx>.create }
                 if vmttree.nodetype=typen then
-                  vmttree:=cloadvmtaddrnode.create(vmttree);
+                  begin
+                    vmttree:=cloadvmtaddrnode.create(vmttree);
+                    tloadvmtaddrnode(vmttree).forcall:=true;
+                  end;
               end
             else
               begin

+ 7 - 0
compiler/ncgadd.pas

@@ -303,6 +303,13 @@ interface
                   if (right.location.size<>left.location.size) or
                      (location.size<>left.location.size) then
                     internalerror(2010123001);
+                  { make sure that location.register is different from
+                    left.location.register, since right will overwrite it
+                    and we'll use left afterwards }
+                  if (right.location.loc=LOC_REGISTER) then
+                    location.register:=right.location.register
+                  else
+                    location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
                   { make sure we don't modify left/right.location, because we told
                     force_reg_left_right above that they can be constant }
                   cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,location.size,right.location.register,location.register);

+ 4 - 1
compiler/ncnv.pas

@@ -2137,7 +2137,10 @@ implementation
           ordconstn:
             inserttypeconv_internal(n,todef);
           typeconvn:
-            n.resultdef:=todef;
+            begin
+              n.resultdef:=todef;
+              ttypeconvnode(n).totypedef:=todef;
+            end;
         end;
       end;
 {$endif not cpu64bitalu}

+ 36 - 0
compiler/nmem.pas

@@ -31,9 +31,17 @@ interface
 
     type
        tloadvmtaddrnode = class(tunarynode)
+          { unless this is for a call, we have to send the "class" message to
+            the objctype because the type information only gets initialized
+            after the first message has been sent -> crash if you pass an
+            uninitialized type to e.g. class_getInstanceSize() or so. No need
+            to save to/restore from ppu. }
+          forcall: boolean;
           constructor create(l : tnode);virtual;
           function pass_1 : tnode;override;
           function pass_typecheck:tnode;override;
+          function docompare(p: tnode): boolean; override;
+          function dogetcopy: tnode; override;
        end;
        tloadvmtaddrnodeclass = class of tloadvmtaddrnode;
 
@@ -190,6 +198,21 @@ implementation
       end;
 
 
+    function tloadvmtaddrnode.docompare(p: tnode): boolean;
+      begin
+        result:=inherited docompare(p);
+        if result then
+          result:=forcall=tloadvmtaddrnode(p).forcall;
+      end;
+
+
+    function tloadvmtaddrnode.dogetcopy: tnode;
+      begin
+        result:=inherited dogetcopy;
+        tloadvmtaddrnode(result).forcall:=forcall;
+      end;
+
+
     function tloadvmtaddrnode.pass_1 : tnode;
       var
         vs: tsym;
@@ -229,6 +252,19 @@ implementation
                else if (left.resultdef.typ=objectdef) then
                  tobjectdef(left.resultdef).register_maybe_created_object_type
              end
+           end
+         else if is_objcclass(left.resultdef) and
+              not(forcall) then
+           begin
+             { call "class" method (= "classclass" in FPC), because otherwise
+               we may use the class information before it has been
+               initialized }
+             vs:=search_struct_member(tobjectdef(left.resultdef),'CLASSCLASS');
+             if not assigned(vs) or
+                (vs.typ<>procsym) then
+               internalerror(2011080601);
+             { can't reuse "self", because it will be freed when we return }
+             result:=ccallnode.create(nil,tprocsym(vs),vs.owner,self.getcopy,[]);
            end;
       end;
 

+ 1 - 0
compiler/pdecobj.pas

@@ -1251,6 +1251,7 @@ implementation
                 list.add(current_structdef);
               end;
           end;
+        tabstractrecordsymtable(current_objectdef.symtable).addalignmentpadding;
 
         { return defined objectdef }
         result:=current_objectdef;

+ 9 - 1
compiler/ppu.pas

@@ -43,7 +43,7 @@ type
 {$endif Test_Double_checksum}
 
 const
-  CurrentPPUVersion = 131;
+  CurrentPPUVersion = 133;
 
 { buffer sizes }
   maxentrysize = 1024;
@@ -132,6 +132,7 @@ const
 
   ibmainname       = 90;
   ibsymtableoptions = 91;
+  ibrecsymtableoptions = 91;
   { target-specific things }
   iblinkotherframeworks = 100;
 
@@ -286,6 +287,7 @@ type
     procedure putint64(i:int64);
     procedure putqword(q:qword);
     procedure putaint(i:aint);
+    procedure putasizeint(i:asizeint);
     procedure putaword(i:aword);
     procedure putreal(d:ppureal);
     procedure putstring(const s:string);
@@ -1271,6 +1273,12 @@ begin
 end;
 
 
+procedure tppufile.putasizeint(i: asizeint);
+begin
+  putdata(i,sizeof(asizeint));
+end;
+
+
 procedure tppufile.putaword(i:aword);
 begin
   putdata(i,sizeof(aword));

+ 21 - 8
compiler/symdef.pas

@@ -3001,7 +3001,8 @@ implementation
              trecordsymtable(symtable).recordalignment:=shortint(ppufile.getbyte);
              trecordsymtable(symtable).padalignment:=shortint(ppufile.getbyte);
              trecordsymtable(symtable).usefieldalignment:=shortint(ppufile.getbyte);
-             trecordsymtable(symtable).datasize:=ppufile.getaint;
+             trecordsymtable(symtable).datasize:=ppufile.getasizeint;
+             trecordsymtable(symtable).paddingsize:=ppufile.getword;
              trecordsymtable(symtable).ppuload(ppufile);
              { requires usefieldalignment to be set }
              symtable.defowner:=self;
@@ -3086,7 +3087,8 @@ implementation
              ppufile.putbyte(byte(trecordsymtable(symtable).recordalignment));
              ppufile.putbyte(byte(trecordsymtable(symtable).padalignment));
              ppufile.putbyte(byte(trecordsymtable(symtable).usefieldalignment));
-             ppufile.putaint(trecordsymtable(symtable).datasize);
+             ppufile.putasizeint(trecordsymtable(symtable).datasize);
+             ppufile.putword(trecordsymtable(symtable).paddingsize);
            end;
 
          ppufile.writeentry(ibrecorddef);
@@ -4384,9 +4386,10 @@ implementation
          if (import_lib^='') then
            stringdispose(import_lib);
          symtable:=tObjectSymtable.create(self,objrealname^,0);
-         tObjectSymtable(symtable).datasize:=ppufile.getaint;
-         tObjectSymtable(symtable).fieldalignment:=ppufile.getbyte;
-         tObjectSymtable(symtable).recordalignment:=ppufile.getbyte;
+         tObjectSymtable(symtable).datasize:=ppufile.getasizeint;
+         tObjectSymtable(symtable).paddingsize:=ppufile.getword;
+         tObjectSymtable(symtable).fieldalignment:=shortint(ppufile.getbyte);
+         tObjectSymtable(symtable).recordalignment:=shortint(ppufile.getbyte);
          vmt_offset:=ppufile.getlongint;
          ppufile.getderef(childofderef);
 
@@ -4554,9 +4557,10 @@ implementation
            ppufile.putstring(import_lib^)
          else
            ppufile.putstring('');
-         ppufile.putaint(tObjectSymtable(symtable).datasize);
-         ppufile.putbyte(tObjectSymtable(symtable).fieldalignment);
-         ppufile.putbyte(tObjectSymtable(symtable).recordalignment);
+         ppufile.putasizeint(tObjectSymtable(symtable).datasize);
+         ppufile.putword(tObjectSymtable(symtable).paddingsize);
+         ppufile.putbyte(byte(tObjectSymtable(symtable).fieldalignment));
+         ppufile.putbyte(byte(tObjectSymtable(symtable).recordalignment));
          ppufile.putlongint(vmt_offset);
          ppufile.putderef(childofderef);
          if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface] then
@@ -4799,6 +4803,15 @@ implementation
             tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize+tObjectSymtable(c.symtable).datasize;
             { inherit recordalignment }
             tObjectSymtable(symtable).recordalignment:=tObjectSymtable(c.symtable).recordalignment;
+            { if both the parent and this record use C-alignment, also inherit
+              the current field alignment }
+            if (tObjectSymtable(c.symtable).usefieldalignment=C_alignment) and
+               (tObjectSymtable(symtable).usefieldalignment=C_alignment) then
+              tObjectSymtable(symtable).fieldalignment:=tObjectSymtable(c.symtable).fieldalignment;
+            { the padding is not inherited for Objective-C classes (maybe not
+              for cppclass either?) }
+            if objecttype=odt_objcclass then
+              tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize-tObjectSymtable(c.symtable).paddingsize;
             if (oo_has_vmt in objectoptions) and
                (oo_has_vmt in c.objectoptions) then
               tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize-sizeof(pint);

+ 23 - 2
compiler/symtable.pas

@@ -92,14 +92,18 @@ interface
           function has_single_field(out sym:tfieldvarsym): boolean;
           function get_unit_symtable: tsymtable;
         protected
-          _datasize       : asizeint;
+          { size in bytes including padding }
+          _datasize      : asizeint;
           { size in bits of the data in case of bitpacked record. Only important during construction, }
           { no need to save in/restore from ppu file. datasize is always (databitsize+7) div 8.       }
           databitsize    : asizeint;
+          { size in bytes of padding }
+          _paddingsize   : word;
           procedure setdatasize(val: asizeint);
         public
           function iscurrentunit: boolean; override;
           property datasize : asizeint read _datasize write setdatasize;
+          property paddingsize: word read _paddingsize write _paddingsize;
        end;
 
        trecordsymtable = class(tabstractrecordsymtable)
@@ -833,6 +837,12 @@ implementation
 
     procedure tabstractrecordsymtable.ppuload(ppufile:tcompilerppufile);
       begin
+        if ppufile.readentry<>ibrecsymtableoptions then
+          Message(unit_f_ppu_read_error);
+        recordalignment:=shortint(ppufile.getbyte);
+        usefieldalignment:=shortint(ppufile.getbyte);
+        if (usefieldalignment=C_alignment) then
+          fieldalignment:=shortint(ppufile.getbyte);
         inherited ppuload(ppufile);
       end;
 
@@ -843,6 +853,13 @@ implementation
       begin
          oldtyp:=ppufile.entrytyp;
          ppufile.entrytyp:=subentryid;
+         { in case of classes using C alignment, the alignment of the parent
+           affects the alignment of fields of the childs }
+         ppufile.putbyte(byte(recordalignment));
+         ppufile.putbyte(byte(usefieldalignment));
+         if (usefieldalignment=C_alignment) then
+           ppufile.putbyte(byte(fieldalignment));
+         ppufile.writeentry(ibrecsymtableoptions);
 
          inherited ppuwrite(ppufile);
 
@@ -1008,6 +1025,8 @@ implementation
 
 
     procedure tabstractrecordsymtable.addalignmentpadding;
+      var
+        padded_datasize: asizeint;
       begin
         { make the record size aligned correctly so it can be
           used as elements in an array. For C records we
@@ -1030,7 +1049,9 @@ implementation
             else
               padalignment:=min(recordalignment,usefieldalignment);
           end;
-        _datasize:=align(_datasize,padalignment);
+        padded_datasize:=align(_datasize,padalignment);
+        _paddingsize:=padded_datasize-_datasize;
+        _datasize:=padded_datasize;
       end;
 
 

+ 28 - 8
compiler/utils/ppudump.pp

@@ -366,6 +366,22 @@ end;
                              Read Routines
 ****************************************************************************}
 
+procedure readrecsymtableoptions;
+var
+  usefieldalignment : shortint;
+begin
+  if ppufile.readentry<>ibrecsymtableoptions then
+    begin
+      has_errors:=true;
+      exit;
+    end;
+  writeln(space,' recordalignment: ',shortint(ppufile.getbyte));
+  usefieldalignment:=shortint(ppufile.getbyte);
+  writeln(space,' usefieldalignment: ',usefieldalignment);
+  if (usefieldalignment=C_alignment) then
+    writeln(space,' fieldalignment: ',shortint(ppufile.getbyte));
+end;
+
 procedure readsymtableoptions(const s: string);
 type
   tsymtblopt=record
@@ -1959,15 +1975,17 @@ begin
              writeln(space,'   Name of Record : ',getstring);
              write  (space,'          Options : ');
              readobjectdefoptions;
-             writeln(space,'       FieldAlign : ',getbyte);
-             writeln(space,'      RecordAlign : ',getbyte);
-             writeln(space,'         PadAlign : ',getbyte);
-             writeln(space,'UseFieldAlignment : ',getbyte);
-             writeln(space,'         DataSize : ',getaint);
+             writeln(space,'       FieldAlign : ',shortint(getbyte));
+             writeln(space,'      RecordAlign : ',shortint(getbyte));
+             writeln(space,'         PadAlign : ',shortint(getbyte));
+             writeln(space,'UseFieldAlignment : ',shortint(getbyte));
+             writeln(space,'         DataSize : ',getasizeint);
+             writeln(space,'      PaddingSize : ',getword);
              if not EndOfEntry then
                HasMoreInfos;
              {read the record definitions and symbols}
              space:='    '+space;
+             readrecsymtableoptions;
              readsymtableoptions('fields');
              readdefinitions('fields');
              readsymbols('fields');
@@ -1996,9 +2014,10 @@ begin
              end;
              writeln(space,'    External name : ',getstring);
              writeln(space,'       Import lib : ',getstring);
-             writeln(space,'         DataSize : ',getaint);
-             writeln(space,'       FieldAlign : ',getbyte);
-             writeln(space,'      RecordAlign : ',getbyte);
+             writeln(space,'         DataSize : ',getasizeint);
+             writeln(space,'      PaddingSize : ',getword);
+             writeln(space,'       FieldAlign : ',shortint(getbyte));
+             writeln(space,'      RecordAlign : ',shortint(getbyte));
              writeln(space,'       Vmt offset : ',getlongint);
              write  (space,  '   Ancestor Class : ');
              readderef('');
@@ -2051,6 +2070,7 @@ begin
                begin
                  {read the record definitions and symbols}
                  space:='    '+space;
+                 readrecsymtableoptions;
                  readsymtableoptions('fields');
                  readdefinitions('fields');
                  readsymbols('fields');