Pārlūkot izejas kodu

* self fixes for static methods (merged)

peter 22 gadi atpakaļ
vecāks
revīzija
25d973ef16
6 mainītis faili ar 151 papildinājumiem un 77 dzēšanām
  1. 44 36
      compiler/i386/n386cal.pas
  2. 42 32
      compiler/ncgcal.pas
  3. 46 3
      compiler/ncginl.pas
  4. 6 2
      compiler/ncgmem.pas
  5. 6 2
      compiler/nmem.pas
  6. 7 2
      compiler/pexpr.pas

+ 44 - 36
compiler/i386/n386cal.pas

@@ -712,7 +712,7 @@ implementation
                                     { extended syntax of new }
                                     { ESI must be zero }
                                     r.enum:=self_pointer_reg;
-                                    rg.getexplicitregisterint(exprasmlist,R_ESI);
+                                    rg.getexplicitregisterint(exprasmlist,r.enum);
                                     cg.a_load_const_reg(exprasmlist,OS_ADDR,0,r);
                                     cg.a_param_reg(exprasmlist,OS_ADDR,r,paramanager.getintparaloc(2));
                                     { insert the vmt }
@@ -764,15 +764,22 @@ implementation
                                       But, not for a class method via self }
                                     if not(po_containsself in procdefinition.procoptions) then
                                       begin
-                                        if (po_classmethod in procdefinition.procoptions) and
-                                           not(methodpointer.resulttype.def.deftype=classrefdef) then
+                                        if (po_staticmethod in procdefinition.procoptions) or
+                                           ((po_classmethod in procdefinition.procoptions) and
+                                            not(methodpointer.resulttype.def.deftype=classrefdef)) then
                                           begin
-                                             { class method needs current VMT }
-                                             r.enum:=self_pointer_reg;
-                                             rg.getexplicitregisterint(exprasmlist,R_ESI);
-                                             reference_reset_base(href,r,tprocdef(procdefinition)._class.vmt_offset);
-                                             cg.g_maybe_testself(exprasmlist);
-                                             cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,r);
+                                            r.enum:=self_pointer_reg;
+                                            rg.getexplicitregisterint(exprasmlist,r.enum);
+                                            if not(oo_has_vmt in tprocdef(procdefinition)._class.objectoptions) then
+                                              cg.a_load_const_reg(exprasmlist,OS_ADDR,0,r)
+                                            else
+                                              begin
+                                                { class method and static methods needs current VMT }
+                                                cg.g_maybe_testself(exprasmlist,r);
+                                                reference_reset_base(href,r,tprocdef(procdefinition)._class.vmt_offset);
+                                                cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,r);
+                                                cg.g_maybe_testvmt(exprasmlist,r,tprocdef(procdefinition)._class);
+                                              end;
                                           end;
 
                                         { direct call to destructor: remove data }
@@ -823,18 +830,29 @@ implementation
                      end
                    else
                      begin
-                        if (po_classmethod in procdefinition.procoptions) and
-                          not(
-                            assigned(aktprocdef) and
-                            (po_classmethod in aktprocdef.procoptions)
-                          ) then
+                        if (
+                            (po_classmethod in procdefinition.procoptions) and
+                            not(assigned(aktprocdef) and
+                                (po_classmethod in aktprocdef.procoptions))
+                           ) or
+                           (
+                            (po_staticmethod in procdefinition.procoptions) and
+                             not(assigned(aktprocdef) and
+                                 (po_staticmethod in aktprocdef.procoptions))
+                           ) then
                           begin
-                             { class method needs current VMT }
-                             rg.getexplicitregisterint(exprasmlist,R_ESI);
-                             r.enum:=R_ESI;
-                             reference_reset_base(href,r,tprocdef(procdefinition)._class.vmt_offset);
-                             cg.g_maybe_testself(exprasmlist);
-                             cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,r);
+                            r.enum:=self_pointer_reg;
+                            rg.getexplicitregisterint(exprasmlist,r.enum);
+                            if not(oo_has_vmt in tprocdef(procdefinition)._class.objectoptions) then
+                             cg.a_load_const_reg(exprasmlist,OS_ADDR,0,r)
+                            else
+                             begin
+                               { class method and static methods needs current VMT }
+                               cg.g_maybe_testself(exprasmlist,r);
+                               reference_reset_base(href,r,tprocdef(procdefinition)._class.vmt_offset);
+                               cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,r);
+                               cg.g_maybe_testvmt(exprasmlist,r,tprocdef(procdefinition)._class);
+                             end;
                           end
                         else
                           begin
@@ -983,9 +1001,9 @@ implementation
                          end
                        else
                          begin
+                            cg.g_maybe_testself(exprasmlist,r);
                             { this is one point where we need vmt_offset (PM) }
                             reference_reset_base(href,r,tprocdef(procdefinition)._class.vmt_offset);
-                            cg.g_maybe_testself(exprasmlist);
                             tmpreg:=cg.get_scratch_reg_address(exprasmlist);
                             cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,tmpreg);
                             reference_reset_base(href,tmpreg,0);
@@ -1002,20 +1020,7 @@ implementation
                    href.offset:=tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber);
                    if not(is_interface(tprocdef(procdefinition)._class)) and
                       not(is_cppclass(tprocdef(procdefinition)._class)) then
-                     begin
-                        if (cs_check_object in aktlocalswitches) then
-                          begin
-                             reference_reset_symbol(hrefvmt,objectlibrary.newasmsymbol(tprocdef(procdefinition)._class.vmt_mangledname),0);
-                             cg.a_paramaddr_ref(exprasmlist,hrefvmt,paramanager.getintparaloc(2));
-                             cg.a_param_reg(exprasmlist,OS_ADDR,href.base,paramanager.getintparaloc(1));
-                             cg.a_call_name(exprasmlist,'FPC_CHECK_OBJECT_EXT');
-                          end
-                        else if (cs_check_range in aktlocalswitches) then
-                          begin
-                             cg.a_param_reg(exprasmlist,OS_ADDR,href.base,paramanager.getintparaloc(1));
-                             cg.a_call_name(exprasmlist,'FPC_CHECK_OBJECT');
-                          end;
-                     end;
+                     cg.g_maybe_testvmt(exprasmlist,href.base,tprocdef(procdefinition)._class);
                    cg.a_call_ref(exprasmlist,href);
                    if release_tmpreg then
                      cg.free_scratch_reg(exprasmlist,tmpreg);
@@ -1277,7 +1282,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.80  2003-01-13 18:37:44  daniel
+  Revision 1.81  2003-01-30 21:46:57  peter
+    * self fixes for static methods (merged)
+
+  Revision 1.80  2003/01/13 18:37:44  daniel
     * Work on register conversion
 
   Revision 1.79  2003/01/08 18:43:57  daniel

+ 42 - 32
compiler/ncgcal.pas

@@ -922,14 +922,22 @@ implementation
                                       But, not for a class method via self }
                                     if not(po_containsself in procdefinition.procoptions) then
                                       begin
-                                        if (po_classmethod in procdefinition.procoptions) and
-                                           not(methodpointer.resulttype.def.deftype=classrefdef) then
+                                        if (po_staticmethod in procdefinition.procoptions) or
+                                           ((po_classmethod in procdefinition.procoptions) and
+                                            not(methodpointer.resulttype.def.deftype=classrefdef)) then
                                           begin
-                                             { class method needs current VMT }
-                                             rg.getexplicitregisterint(exprasmlist,R_ESI);
-                                             reference_reset_base(href,R_ESI,tprocdef(procdefinition)._class.vmt_offset);
-                                             cg.a_maybe_testself(exprasmlist);
-                                             cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,self_pointer_reg);
+                                            r.enum:=self_pointer_reg;
+                                            rg.getexplicitregisterint(exprasmlist,r.enum);
+                                            if not(oo_has_vmt in tprocdef(procdefinition)._class.objectoptions) then
+                                              cg.a_load_const_reg(exprasmlist,OS_ADDR,0,r)
+                                            else
+                                              begin
+                                                { class method and static methods needs current VMT }
+                                                cg.g_maybe_testself(exprasmlist,r);
+                                                reference_reset_base(href,r,tprocdef(procdefinition)._class.vmt_offset);
+                                                cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,r);
+                                                cg.g_maybe_testvmt(exprasmlist,r,tprocdef(procdefinition)._class);
+                                              end;
                                           end;
 
                                         { direct call to destructor: remove data }
@@ -979,17 +987,29 @@ implementation
                      end
                    else
                      begin
-                        if (po_classmethod in procdefinition.procoptions) and
-                          not(
-                            assigned(aktprocdef) and
-                            (po_classmethod in aktprocdef.procoptions)
-                          ) then
+                        if (
+                            (po_classmethod in procdefinition.procoptions) and
+                            not(assigned(aktprocdef) and
+                                (po_classmethod in aktprocdef.procoptions))
+                           ) or
+                           (
+                            (po_staticmethod in procdefinition.procoptions) and
+                             not(assigned(aktprocdef) and
+                                 (po_staticmethod in aktprocdef.procoptions))
+                           ) then
                           begin
-                             { class method needs current VMT }
-                             rg.getexplicitregisterint(exprasmlist,R_ESI);
-                             reference_reset_base(href,R_ESI,tprocdef(procdefinition)._class.vmt_offset);
-                             cg.a_maybe_testself(exprasmlist);
-                             cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,R_ESI);
+                            r.enum:=self_pointer_reg;
+                            rg.getexplicitregisterint(exprasmlist,r.enum);
+                            if not(oo_has_vmt in tprocdef(procdefinition)._class.objectoptions) then
+                             cg.a_load_const_reg(exprasmlist,OS_ADDR,0,r)
+                            else
+                             begin
+                               { class method and static methods needs current VMT }
+                               cg.g_maybe_testself(exprasmlist,r);
+                               reference_reset_base(href,r,tprocdef(procdefinition)._class.vmt_offset);
+                               cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,r);
+                               cg.g_maybe_testvmt(exprasmlist,r,tprocdef(procdefinition)._class);
+                             end;
                           end
                         else
                           begin
@@ -1113,20 +1133,7 @@ implementation
                    href.offset:=tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber);
                    if not(is_interface(tprocdef(procdefinition)._class)) and
                       not(is_cppclass(tprocdef(procdefinition)._class)) then
-                     begin
-                        if (cs_check_object in aktlocalswitches) then
-                          begin
-                             reference_reset_symbol(hrefvmt,objectlibrary.newasmsymbol(tprocdef(procdefinition)._class.vmt_mangledname),0);
-                             cg.a_paramaddr_ref(exprasmlist,hrefvmt,2);
-                             cg.a_param_reg(exprasmlist,OS_ADDR,href.base,1);
-                             cg.a_call_name(exprasmlist,'FPC_CHECK_OBJECT_EXT');
-                          end
-                        else if (cs_check_range in aktlocalswitches) then
-                          begin
-                             cg.a_param_reg(exprasmlist,OS_ADDR,href.base,1);
-                             cg.a_call_name(exprasmlist,'FPC_CHECK_OBJECT');
-                          end;
-                     end;
+                     cg.g_maybe_testvmt(exprasmlist,href.base,tprocdef(procdefinition)._class);
                    cg.a_call_ref(exprasmlist,href);
                    if release_tmpreg then
                      cg.free_scratch_reg(exprasmlist,tmpreg);
@@ -1572,7 +1579,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.35  2003-01-22 20:45:15  mazen
+  Revision 1.36  2003-01-30 21:46:57  peter
+    * self fixes for static methods (merged)
+
+  Revision 1.35  2003/01/22 20:45:15  mazen
   * making math code in RTL compiling.
   *NB : This does NOT mean necessary that it will generate correct code!
 

+ 46 - 3
compiler/ncginl.pas

@@ -54,7 +54,7 @@ implementation
     uses
       globtype,systems,
       cutils,verbose,globals,fmodule,
-      symconst,symdef,defutil,
+      symconst,symdef,defutil,symsym,
       aasmbase,aasmtai,aasmcpu,
       cginfo,cgbase,pass_1,pass_2,
       cpubase,paramgr,
@@ -220,7 +220,8 @@ implementation
     { second_handle_ the sizeof and typeof routines }
     procedure tcginlinenode.second_SizeOfTypeOf;
       var
-         href : treference;
+         href,
+         hrefvmt   : treference;
          hregister : tregister;
       begin
         location_reset(location,LOC_REGISTER,OS_ADDR);
@@ -236,6 +237,45 @@ implementation
             secondpass(left);
             location_release(exprasmlist,left.location);
             hregister:=rg.getaddressregister(exprasmlist);
+
+            { handle self inside a method of a class }
+            case left.location.loc of
+              LOC_CREGISTER,
+              LOC_REGISTER :
+                begin
+                  if (left.resulttype.def.deftype=classrefdef) or
+                     (po_staticmethod in aktprocdef.procoptions) then
+                    cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,hregister)
+                  else
+                   begin
+                     { load VMT pointer }
+                     reference_reset_base(hrefvmt,left.location.register,tobjectdef(left.resulttype.def).vmt_offset);
+                     cg.a_load_ref_reg(exprasmlist,OS_ADDR,hrefvmt,hregister);
+                   end
+                end;
+              LOC_REFERENCE,
+              LOC_CREFERENCE :
+                begin
+                  if is_class(left.resulttype.def) then
+                   begin
+                     { deref class }
+                     cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister);
+                     { load VMT pointer }
+                     reference_reset_base(hrefvmt,hregister,tobjectdef(left.resulttype.def).vmt_offset);
+                     cg.a_load_ref_reg(exprasmlist,OS_ADDR,hrefvmt,hregister);
+                   end
+                  else
+                   begin
+                     { load VMT pointer, but not for classrefdefs }
+                     if (left.resulttype.def.deftype=objectdef) then
+                       inc(left.location.reference.offset,tobjectdef(left.resulttype.def).vmt_offset);
+                     cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister);
+                   end;
+                end;
+              else
+                internalerror(200301301);
+            end;
+
             { load VMT pointer }
             inc(left.location.reference.offset,tobjectdef(left.resulttype.def).vmt_offset);
             cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister);
@@ -612,7 +652,10 @@ end.
 
 {
   $Log$
-  Revision 1.18  2003-01-08 18:43:56  daniel
+  Revision 1.19  2003-01-30 21:46:57  peter
+    * self fixes for static methods (merged)
+
+  Revision 1.18  2003/01/08 18:43:56  daniel
    * Tregister changed into a record
 
   Revision 1.17  2002/11/25 17:43:18  peter

+ 6 - 2
compiler/ncgmem.pas

@@ -349,7 +349,8 @@ implementation
       begin
          rg.getexplicitregisterint(exprasmlist,SELF_POINTER_REG);
          if (resulttype.def.deftype=classrefdef) or
-            is_class(resulttype.def) then
+            (is_class(resulttype.def) or
+             (po_staticmethod in aktprocdef.procoptions)) then
           begin
             location_reset(location,LOC_CREGISTER,OS_ADDR);
             location.register.enum:=SELF_POINTER_REG;
@@ -924,7 +925,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.40  2003-01-08 18:43:56  daniel
+  Revision 1.41  2003-01-30 21:46:57  peter
+    * self fixes for static methods (merged)
+
+  Revision 1.40  2003/01/08 18:43:56  daniel
    * Tregister changed into a record
 
   Revision 1.39  2002/12/20 18:13:19  peter

+ 6 - 2
compiler/nmem.pas

@@ -911,7 +911,8 @@ implementation
       begin
          result:=nil;
          if (resulttype.def.deftype=classrefdef) or
-           is_class(resulttype.def) then
+            is_class(resulttype.def) or
+            (po_staticmethod in aktprocdef.procoptions) then
            location.loc:=LOC_CREGISTER
          else
            location.loc:=LOC_REFERENCE;
@@ -1054,7 +1055,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.45  2003-01-09 21:52:37  peter
+  Revision 1.46  2003-01-30 21:46:57  peter
+    * self fixes for static methods (merged)
+
+  Revision 1.45  2003/01/09 21:52:37  peter
     * merged some verbosity options.
     * V_LineInfo is a verbosity flag to include line info
 

+ 7 - 2
compiler/pexpr.pas

@@ -315,7 +315,9 @@ implementation
               consume(_RKLAMMER);
               if p1.nodetype=typen then
                 ttypenode(p1).allowed:=true;
-              if p1.resulttype.def.deftype=objectdef then
+              if (p1.resulttype.def.deftype = objectdef) or
+                 ((p1.resulttype.def.deftype = classrefdef) and
+                  (p1.nodetype in [selfn,loadvmtn])) then
                statement_syssym:=geninlinenode(in_typeof_x,false,p1)
               else
                begin
@@ -2324,7 +2326,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.101  2003-01-16 22:12:22  peter
+  Revision 1.102  2003-01-30 21:46:57  peter
+    * self fixes for static methods (merged)
+
+  Revision 1.101  2003/01/16 22:12:22  peter
     * Find the correct procvar to load when using @ in fpc mode
 
   Revision 1.100  2003/01/15 01:44:32  peter