瀏覽代碼

* methodpointer is loaded into a temp when it was a calln

peter 21 年之前
父節點
當前提交
b86f2c6a25
共有 13 個文件被更改,包括 252 次插入224 次删除
  1. 6 3
      compiler/htypechk.pas
  2. 11 3
      compiler/nbas.pas
  3. 114 57
      compiler/ncal.pas
  4. 5 1
      compiler/ncgbas.pas
  5. 16 7
      compiler/ncgcal.pas
  6. 5 3
      compiler/ncnv.pas
  7. 5 2
      compiler/ninl.pas
  8. 4 12
      compiler/node.pas
  9. 5 2
      compiler/nutils.pas
  10. 38 97
      compiler/pexpr.pas
  11. 28 29
      compiler/pinline.pas
  12. 5 2
      compiler/pstatmnt.pas
  13. 10 6
      compiler/psub.pas

+ 6 - 3
compiler/htypechk.pas

@@ -466,7 +466,7 @@ implementation
 
         { the nil as symtable signs firstcalln that this is
           an overloaded operator }
-        t:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil);
+        t:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil,[]);
 
         { we already know the procdef to use, so it can
           skip the overload choosing in callnode.det_resulttype }
@@ -612,7 +612,7 @@ implementation
 
         { the nil as symtable signs firstcalln that this is
           an overloaded operator }
-        ht:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil);
+        ht:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil,[]);
 
         { we already know the procdef to use, so it can
           skip the overload choosing in callnode.det_resulttype }
@@ -1922,7 +1922,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.87  2004-05-23 15:03:40  peter
+  Revision 1.88  2004-05-23 18:28:40  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.87  2004/05/23 15:03:40  peter
     * some typeconvs don't allow assignment or passing to var para
 
   Revision 1.86  2004/05/16 13:29:46  peter

+ 11 - 3
compiler/nbas.pas

@@ -27,7 +27,7 @@ unit nbas;
 interface
 
     uses
-       cpubase,cgbase,
+       cpuinfo,cpubase,cgbase,
        aasmbase,aasmtai,aasmcpu,
        node,tgobj,
        symtype;
@@ -393,7 +393,7 @@ implementation
                       not(cs_extsyntax in aktmoduleswitches) and
                       (hp.left.nodetype=calln) and
                       not(is_void(hp.left.resulttype.def)) and
-                      not(nf_return_value_used in tcallnode(hp.left).flags) and
+                      not(cnf_return_value_used in tcallnode(hp.left).callnodeflags) and
                       not((tcallnode(hp.left).procdefinition.proctypeoption=potype_constructor) and
                           assigned(tprocdef(tcallnode(hp.left).procdefinition)._class) and
                           is_object(tprocdef(tcallnode(hp.left).procdefinition)._class)) then
@@ -667,6 +667,11 @@ implementation
       begin
         create(_restype,_size,_temptype);
         tempinfo^.may_be_in_reg:=
+          { temp must fit a single register }
+          (_size<=sizeof(aint)) and
+          { size of register operations must be known }
+          (def_cgsize(_restype.def)<>OS_NO) and
+          { no init/final needed }
           not (_restype.def.needs_inittable) and
           ((_restype.def.deftype <> pointerdef) or
            (not tpointerdef(_restype.def).pointertype.def.needs_inittable));
@@ -1012,7 +1017,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.82  2004-05-23 15:06:20  peter
+  Revision 1.83  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.82  2004/05/23 15:06:20  peter
     * implicit_finally flag must be set in pass1
     * add check whether the implicit frame is generated when expected
 

+ 114 - 57
compiler/ncal.pas

@@ -37,10 +37,16 @@ interface
        symbase,symtype,symsym,symdef,symtable;
 
     type
-       tcallnodeflags = (
-         cnf_restypeset
+       tcallnodeflag = (
+         cnf_restypeset,
+         cnf_return_value_used,
+         cnf_inherited,
+         cnf_anon_inherited,
+         cnf_new_call,
+         cnf_dispose_call,
+         cnf_member_call        { called with implicit methodpointer tree }
        );
-       tcallnodeflagset = set of tcallnodeflags;
+       tcallnodeflags = set of tcallnodeflag;
 
        tcallnode = class(tbinarynode)
        private
@@ -68,6 +74,8 @@ interface
           procdefinition : tabstractprocdef;
           procdefinitionderef : tderef;
           { tree that contains the pointer to the object for this method }
+          methodpointerinit,
+          methodpointerdone,
           methodpointer  : tnode;
           { inline function body }
           inlinecode : tnode;
@@ -82,12 +90,11 @@ interface
           { you can't have a function with an "array of char" resulttype }
           { the RTL) (JM)                                                }
           restype: ttype;
-          callnodeflags : tcallnodeflagset;
+          callnodeflags : tcallnodeflags;
 
           { only the processor specific nodes need to override this }
           { constructor                                             }
-          constructor create(l:tnode; v : tprocsym;st : tsymtable; mp : tnode);virtual;
-          constructor create_def(l:tnode;def:tprocdef;mp:tnode);virtual;
+          constructor create(l:tnode; v : tprocsym;st : tsymtable; mp: tnode; callflags:tcallnodeflags);virtual;
           constructor create_procvar(l,r:tnode);
           constructor createintern(const name: string; params: tnode);
           constructor createinternres(const name: string; params: tnode; const res: ttype);
@@ -120,14 +127,15 @@ interface
        end;
        tcallnodeclass = class of tcallnode;
 
-       tcallparaflags = (
-          { flags used by tcallparanode }
-          cpf_is_colon_para
+       tcallparaflag = (
+          cpf_is_colon_para,
+          cpf_varargs_para   { belongs this para to varargs }
        );
+       tcallparaflags = set of tcallparaflag;
 
        tcallparanode = class(tbinarynode)
        public
-          callparaflags : set of tcallparaflags;
+          callparaflags : tcallparaflags;
           paraitem : tparaitem;
           used_by_callnode : boolean;
           { only the processor specific nodes need to override this }
@@ -150,7 +158,6 @@ interface
 
     function reverseparameters(p: tcallparanode): tcallparanode;
 
-
     var
       ccallnode : tcallnodeclass;
       ccallparanode : tcallparanodeclass;
@@ -388,7 +395,7 @@ type
 
              { Handle varargs and hidden paras directly, no typeconvs or }
              { typechecking needed                                       }
-             if (nf_varargs_para in flags) then
+             if (cpf_varargs_para in callparaflags) then
                begin
                  { convert pascal to C types }
                  case left.resulttype.def.deftype of
@@ -608,31 +615,16 @@ type
                                  TCALLNODE
  ****************************************************************************}
 
-    constructor tcallnode.create(l:tnode;v : tprocsym;st : tsymtable; mp : tnode);
+    constructor tcallnode.create(l:tnode;v : tprocsym;st : tsymtable; mp: tnode; callflags:tcallnodeflags);
       begin
          inherited create(calln,l,nil);
          symtableprocentry:=v;
          symtableproc:=st;
-         include(flags,nf_return_value_used);
+         callnodeflags:=callflags+[cnf_return_value_used];
          methodpointer:=mp;
+         methodpointerinit:=nil;
+         methodpointerdone:=nil;
          procdefinition:=nil;
-         callnodeflags:=[];
-         _funcretnode:=nil;
-         inlinecode:=nil;
-         paralength:=-1;
-         varargsparas:=nil;
-      end;
-
-
-    constructor tcallnode.create_def(l:tnode;def:tprocdef;mp:tnode);
-      begin
-         inherited create(calln,l,nil);
-         symtableprocentry:=nil;
-         symtableproc:=nil;
-         include(flags,nf_return_value_used);
-         methodpointer:=mp;
-         procdefinition:=def;
-         callnodeflags:=[];
          _funcretnode:=nil;
          inlinecode:=nil;
          paralength:=-1;
@@ -645,10 +637,11 @@ type
          inherited create(calln,l,r);
          symtableprocentry:=nil;
          symtableproc:=nil;
-         include(flags,nf_return_value_used);
          methodpointer:=nil;
+         methodpointerinit:=nil;
+         methodpointerdone:=nil;
          procdefinition:=nil;
-         callnodeflags:=[];
+         callnodeflags:=[cnf_return_value_used];
          _funcretnode:=nil;
          inlinecode:=nil;
          paralength:=-1;
@@ -680,7 +673,7 @@ type
 {$endif EXTDEBUG}
              internalerror(200107271);
            end;
-         self.create(params,tprocsym(srsym),symowner,nil);
+         self.create(params,tprocsym(srsym),symowner,nil,[]);
        end;
 
 
@@ -743,6 +736,8 @@ type
     destructor tcallnode.destroy;
       begin
          methodpointer.free;
+         methodpointerinit.free;
+         methodpointerdone.free;
          _funcretnode.free;
          inlinecode.free;
          if assigned(varargsparas) then
@@ -762,6 +757,8 @@ type
         ppufile.getderef(procdefinitionderef);
         ppufile.getsmallset(callnodeflags);
         methodpointer:=ppuloadnode(ppufile);
+        methodpointerinit:=ppuloadnode(ppufile);
+        methodpointerdone:=ppuloadnode(ppufile);
         _funcretnode:=ppuloadnode(ppufile);
         inlinecode:=ppuloadnode(ppufile);
       end;
@@ -774,6 +771,8 @@ type
         ppufile.putderef(procdefinitionderef);
         ppufile.putsmallset(callnodeflags);
         ppuwritenode(ppufile,methodpointer);
+        ppuwritenode(ppufile,methodpointerinit);
+        ppuwritenode(ppufile,methodpointerdone);
         ppuwritenode(ppufile,_funcretnode);
         ppuwritenode(ppufile,inlinecode);
       end;
@@ -811,7 +810,7 @@ type
         { Connect paraitems }
         pt:=tcallparanode(left);
         while assigned(pt) and
-              (nf_varargs_para in pt.flags) do
+              (cpf_varargs_para in pt.callparaflags) do
           pt:=tcallparanode(pt.right);
         currpara:=tparaitem(procdefinition.Para.last);
         while assigned(currpara) do
@@ -842,6 +841,14 @@ type
          n.methodpointer:=methodpointer.getcopy
         else
          n.methodpointer:=nil;
+        if assigned(methodpointerinit) then
+         n.methodpointerinit:=methodpointerinit.getcopy
+        else
+         n.methodpointerinit:=nil;
+        if assigned(methodpointerdone) then
+         n.methodpointerdone:=methodpointerdone.getcopy
+        else
+         n.methodpointerdone:=nil;
         if assigned(_funcretnode) then
          n._funcretnode:=_funcretnode.getcopy
         else
@@ -896,7 +903,7 @@ type
                 left:=ccallparanode.create(hp.left,left);
                 { set callparanode resulttype and flags }
                 left.resulttype:=hp.left.resulttype;
-                include(left.flags,nf_varargs_para);
+                include(tcallparanode(left).callparaflags,cpf_varargs_para);
                 hp.left:=nil;
                 hp:=tarrayconstructornode(hp.right);
               end;
@@ -1033,7 +1040,7 @@ type
         selftree:=nil;
 
         { inherited }
-        if (nf_inherited in flags) then
+        if (cnf_inherited in callnodeflags) then
           selftree:=load_self_node
         else
           { constructors }
@@ -1041,7 +1048,7 @@ type
             begin
               { push 0 as self when allocation is needed }
               if (methodpointer.resulttype.def.deftype=classrefdef) or
-                 (nf_new_call in flags) then
+                 (cnf_new_call in callnodeflags) then
                 selftree:=cpointerconstnode.create(0,voidpointertype)
               else
                 begin
@@ -1090,12 +1097,12 @@ type
           internalerror(200305051);
 
         { inherited call, no create/destroy }
-        if (nf_inherited in flags) then
+        if (cnf_inherited in callnodeflags) then
           vmttree:=cpointerconstnode.create(0,voidpointertype)
         else
           { do not create/destroy when called from member function
             without specifying self explicit }
-          if (nf_member_call in flags) then
+          if (cnf_member_call in callnodeflags) then
             begin
               if (methodpointer.resulttype.def.deftype=classrefdef) and
                 (procdefinition.proctypeoption=potype_constructor) then
@@ -1105,11 +1112,11 @@ type
             end
         else
           { constructor with extended syntax called from new }
-          if (nf_new_call in flags) then
+          if (cnf_new_call in callnodeflags) then
             vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resulttype))
         else
           { destructor with extended syntax called from dispose }
-          if (nf_dispose_call in flags) then
+          if (cnf_dispose_call in callnodeflags) then
             vmttree:=cloadvmtaddrnode.create(methodpointer.getcopy)
         else
          if (methodpointer.resulttype.def.deftype=classrefdef) then
@@ -1174,7 +1181,7 @@ type
         i:=paralength;
         while (i>procdefinition.maxparacount) do
           begin
-            include(pt.flags,nf_varargs_para);
+            include(pt.callparaflags,cpf_varargs_para);
             oldppt:[email protected];
             pt:=tcallparanode(pt.right);
             dec(i);
@@ -1182,7 +1189,7 @@ type
 
         { skip varargs that are inserted by array of const }
         while assigned(pt) and
-              (nf_varargs_para in pt.flags) do
+              (cpf_varargs_para in pt.callparaflags) do
           pt:=tcallparanode(pt.right);
 
         { process normal parameters and insert hidden parameters }
@@ -1271,7 +1278,7 @@ type
         pt:=tcallparanode(left);
         while assigned(pt) do
           begin
-            if nf_varargs_para in pt.flags then
+            if cpf_varargs_para in pt.callparaflags then
               begin
                 if not assigned(varargsparas) then
                   varargsparas:=tvarargspara.create;
@@ -1300,6 +1307,9 @@ type
         i : longint;
         method_must_be_valid,
         is_const : boolean;
+        hp : tnode;
+        mptemp : ttempcreatenode;
+        newstatement : tstatementnode;
       label
         errorexit;
       begin
@@ -1326,6 +1336,40 @@ type
              goto errorexit;
           end;
 
+         if assigned(methodpointer) then
+           begin
+             resulttypepass(methodpointer);
+             hp:=methodpointer;
+             while assigned(hp) and
+                   (hp.nodetype=typeconvn) do
+               hp:=tunarynode(hp).left;
+             if assigned(hp) and
+                (
+                 { call result must always be loaded in temp to prevent
+                   double creation }
+                 (hp.nodetype=calln)
+                 { Also optimize also complex loads }
+{$warning Complex loads can also be optimized}
+//                 not(hp.nodetype in [typen,loadvmtaddrn,loadn])
+                )  then
+               begin
+                 { methodpointer loading }
+                 methodpointerinit:=internalstatements(newstatement);
+                 mptemp:=ctempcreatenode.create_reg(methodpointer.resulttype,methodpointer.resulttype.def.size,tt_persistent);
+                 addstatement(newstatement,mptemp);
+                 addstatement(newstatement,cassignmentnode.create(
+                     ctemprefnode.create(mptemp),
+                     methodpointer));
+                 resulttypepass(methodpointerinit);
+                 { new methodpointer is only a temp reference }
+                 methodpointer:=ctemprefnode.create(mptemp);
+                 resulttypepass(methodpointer);
+                 { methodpointer cleanup }
+                 methodpointerdone:=ctempdeletenode.create(mptemp);
+                 resulttypepass(methodpointerdone);
+               end;
+           end;
+
          { procedure variable ? }
          if assigned(right) then
            begin
@@ -1404,7 +1448,7 @@ type
                         do this ugly hack in Delphi mode as it looks more
                         like a bug. It's also not documented }
                       if (m_delphi in aktmodeswitches) and
-                         (nf_anon_inherited in flags) and
+                         (cnf_anon_inherited in callnodeflags) and
                          (symtableprocentry.owner.symtabletype=objectsymtable) and
                          (po_overload in symtableprocentry.first_procdef.procoptions) and
                          (symtableprocentry.procdef_count>=2) then
@@ -1416,7 +1460,7 @@ type
                             when there is only one proc definition, else the
                             loadnode will give a strange error }
                           if not(assigned(left)) and
-                             not(nf_inherited in flags) and
+                             not(cnf_inherited in callnodeflags) and
                              (m_tp_procvar in aktmodeswitches) and
                              (symtableprocentry.procdef_count=1) then
                             begin
@@ -1576,12 +1620,15 @@ type
 
          if assigned(methodpointer) then
           begin
-            resulttypepass(methodpointer);
+            { when methodpointer is a callnode we must load it first into a
+              temp to prevent the processing callnode twice }
+            if (methodpointer.nodetype=calln) then
+              internalerror(200405121);
 
             { direct call to inherited abstract method, then we
               can already give a error in the compiler instead
               of a runtime error }
-            if (nf_inherited in flags) and
+            if (cnf_inherited in callnodeflags) and
                (po_abstractmethod in procdefinition.procoptions) then
               CGMessage(cg_e_cant_call_abstract_method);
 
@@ -1589,7 +1636,7 @@ type
             { called in a con- or destructor then a warning }
             { will be made                                  }
             { con- and destructors need a pointer to the vmt }
-            if (nf_inherited in flags) and
+            if (cnf_inherited in callnodeflags) and
                (procdefinition.proctypeoption in [potype_constructor,potype_destructor]) and
                is_object(methodpointer.resulttype.def) and
                not(current_procinfo.procdef.proctypeoption in [potype_constructor,potype_destructor]) then
@@ -1597,9 +1644,10 @@ type
 
             if methodpointer.nodetype<>typen then
              begin
-               hpt:=methodpointer;
-               while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do
-                hpt:=tunarynode(hpt).left;
+                { Remove all postfix operators }
+                hpt:=methodpointer;
+                while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do
+                  hpt:=tunarynode(hpt).left;
 
                if (procdefinition.proctypeoption=potype_constructor) and
                   assigned(symtableproc) and
@@ -1634,8 +1682,8 @@ type
               methods. Ignore inherited and member calls, because the
               class is then already created }
             if (procdefinition.proctypeoption=potype_constructor) and
-               not(nf_inherited in flags) and
-               not(nf_member_call in flags) then
+               not(cnf_inherited in callnodeflags) and
+               not(cnf_member_call in callnodeflags) then
               verifyabstractcalls;
           end
          else
@@ -1788,6 +1836,12 @@ type
          { order parameters }
          order_parameters;
 
+         if assigned(methodpointerinit) then
+           firstpass(methodpointerinit);
+
+         if assigned(methodpointerdone) then
+           firstpass(methodpointerdone);
+
          { function result node }
          if assigned(_funcretnode) then
            firstpass(_funcretnode);
@@ -1868,7 +1922,7 @@ type
                end
              else
              { we have only to handle the result if it is used }
-              if (nf_return_value_used in flags) then
+              if (cnf_return_value_used in callnodeflags) then
                begin
                  case resulttype.def.deftype of
                    enumdef,
@@ -2056,7 +2110,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.234  2004-05-23 15:06:20  peter
+  Revision 1.235  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.234  2004/05/23 15:06:20  peter
     * implicit_finally flag must be set in pass1
     * add check whether the implicit frame is generated when expected
 

+ 5 - 1
compiler/ncgbas.pas

@@ -339,6 +339,7 @@ interface
          end;
       end;
 
+
 {*****************************************************************************
                           TTEMPCREATENODE
 *****************************************************************************}
@@ -476,7 +477,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.61  2004-05-23 15:06:20  peter
+  Revision 1.62  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.61  2004/05/23 15:06:20  peter
     * implicit_finally flag must be set in pass1
     * add check whether the implicit frame is generated when expected
 

+ 16 - 7
compiler/ncgcal.pas

@@ -287,7 +287,7 @@ implementation
          begin
            { copy the value on the stack or use normal parameter push?
              Check for varargs first because that has no paraitem }
-           if not(nf_varargs_para in flags) and
+           if not(cpf_varargs_para in callparaflags) and
               paramanager.copy_value_on_stack(paraitem.paratyp,left.resulttype.def,
                   aktcallnode.procdefinition.proccalloption) then
             begin
@@ -361,7 +361,7 @@ implementation
          if not(assigned(paraitem)) or
             not(assigned(paraitem.paratype.def)) or
             not(assigned(paraitem.parasym) or
-                (nf_varargs_para in flags)) then
+                (cpf_varargs_para in callparaflags)) then
            internalerror(200304242);
 
          { Skip nothingn nodes which are used after disabling
@@ -377,7 +377,7 @@ implementation
              allocate_tempparaloc;
 
              { handle varargs first, because paraitem.parasym is not valid }
-             if (nf_varargs_para in flags) then
+             if (cpf_varargs_para in callparaflags) then
                begin
                  if paramanager.push_addr_param(vs_value,left.resulttype.def,
                         aktcallnode.procdefinition.proccalloption) then
@@ -537,7 +537,7 @@ implementation
           end
         else
         { we have only to handle the result if it is used }
-         if (nf_return_value_used in flags) then
+         if (cnf_return_value_used in callnodeflags) then
           begin
             if (resulttype.def.deftype=floatdef) then
               begin
@@ -1044,7 +1044,7 @@ implementation
          release_para_temps;
 
          { if return value is not used }
-         if (not(nf_return_value_used in flags)) and (not is_void(resulttype.def)) then
+         if (not(cnf_return_value_used in callnodeflags)) and (not is_void(resulttype.def)) then
            begin
               if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
                 begin
@@ -1209,7 +1209,7 @@ implementation
 
          { if return value is not used }
          if (not is_void(resulttype.def)) and
-            (not(nf_return_value_used in flags)) then
+            (not(cnf_return_value_used in callnodeflags)) then
            begin
               if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
                 begin
@@ -1259,10 +1259,16 @@ implementation
 
     procedure tcgcallnode.pass_2;
       begin
+        if assigned(methodpointerinit) then
+          secondpass(methodpointerinit);
+
         if assigned(inlinecode) then
           inlined_pass_2
         else
           normal_pass_2;
+
+        if assigned(methodpointerdone) then
+          secondpass(methodpointerdone);
       end;
 
 
@@ -1272,7 +1278,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.166  2004-05-22 23:34:27  peter
+  Revision 1.167  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.166  2004/05/22 23:34:27  peter
   tai_regalloc.allocation changed to ratype to notify rgobj of register size changes
 
   Revision 1.165  2004/04/28 15:19:03  florian

+ 5 - 3
compiler/ncnv.pas

@@ -1226,8 +1226,7 @@ implementation
             begin
               include(current_procinfo.flags,pi_do_call);
               inc(aprocdef.procsym.refs);
-              hp:=ccallnode.create(ccallparanode.create(left,nil),
-                                   Tprocsym(aprocdef.procsym),nil,nil);
+              hp:=ccallnode.create(ccallparanode.create(left,nil),Tprocsym(aprocdef.procsym),nil,nil,[]);
               { tell explicitly which def we must use !! (PM) }
               tcallnode(hp).procdefinition:=aprocdef;
               left:=nil;
@@ -2447,7 +2446,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.146  2004-05-23 15:03:40  peter
+  Revision 1.147  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.146  2004/05/23 15:03:40  peter
     * some typeconvs don't allow assignment or passing to var para
 
   Revision 1.145  2004/05/23 14:14:18  florian

+ 5 - 2
compiler/ninl.pas

@@ -1741,7 +1741,7 @@ implementation
                   srsym:=searchsymonlyin(systemunit,'SETTEXTBUF');
                   hp:=ccallparanode.create(cordconstnode.create(
                      tcallparanode(left).left.resulttype.def.size,s32inttype,true),left);
-                  hp:=ccallnode.create(hp,tprocsym(srsym),systemunit,nil);
+                  hp:=ccallnode.create(hp,tprocsym(srsym),systemunit,nil,[]);
                   left:=nil;
                   result:=hp;
                 end;
@@ -2374,7 +2374,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.133  2004-03-18 16:19:03  peter
+  Revision 1.134  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.133  2004/03/18 16:19:03  peter
     * fixed operator overload allowing for pointer-string
     * replaced some type_e_mismatch with more informational messages
 

+ 4 - 12
compiler/node.pas

@@ -204,17 +204,6 @@ interface
          nf_write,       { Node is written to            }
          nf_isproperty,
 
-         { flags used by tcallnode }
-         nf_return_value_used,
-         nf_inherited,
-         nf_anon_inherited,
-         nf_new_call,
-         nf_dispose_call,
-         nf_member_call, { called with implicit methodpointer tree }
-
-         { flags used by tcallparanode }
-         nf_varargs_para,  { belongs this para to varargs }
-
          { taddrnode }
          nf_procvarload,
          nf_typedaddr,
@@ -1093,7 +1082,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.83  2004-05-23 15:06:21  peter
+  Revision 1.84  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.83  2004/05/23 15:06:21  peter
     * implicit_finally flag must be set in pass1
     * add check whether the implicit frame is generated when expected
 

+ 5 - 2
compiler/nutils.pas

@@ -354,7 +354,7 @@ implementation
                                 load_vmt_pointer_node,
                                 voidpointertype),
                             cpointerconstnode.create(1,voidpointertype))),
-                    ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node),
+                    ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
                     nil));
               end
             else
@@ -438,7 +438,10 @@ end.
 
 {
   $Log$
-  Revision 1.11  2004-05-23 15:04:49  peter
+  Revision 1.12  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.11  2004/05/23 15:04:49  peter
     * generate better code for ansistring initialization
 
   Revision 1.10  2004/02/20 21:55:59  peter

+ 38 - 97
compiler/pexpr.pas

@@ -28,7 +28,7 @@ interface
 
     uses
       symtype,symdef,symbase,
-      node,
+      node,ncal,
       globals,
       cpuinfo;
 
@@ -50,7 +50,7 @@ interface
     function parse_paras(__colon,in_prop_paras : boolean) : tnode;
 
     { the ID token has to be consumed before calling this function }
-    procedure do_member_read(classh:tobjectdef;getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callnflags:tnodeflags);
+    procedure do_member_read(classh:tobjectdef;getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callflags:tcallnodeflags);
 
 {$ifdef int64funcresok}
     function get_intconst:TConstExprInt;
@@ -75,7 +75,7 @@ implementation
        symconst,symtable,symsym,defutil,defcmp,
        { pass 1 }
        pass_1,htypechk,
-       nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,nutils,
+       nmat,nadd,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,nutils,
        { parser }
        scanner,
        pbase,pinline,
@@ -711,7 +711,7 @@ implementation
 
 
     { reads the parameter for a subroutine call }
-    procedure do_proc_call(sym:tsym;st:tsymtable;obj:tobjectdef;getaddr:boolean;var again : boolean;var p1:tnode);
+    procedure do_proc_call(sym:tsym;st:tsymtable;obj:tobjectdef;getaddr:boolean;var again : boolean;var p1:tnode;callflags:tcallnodeflags);
       var
          membercall,
          prevafterassn : boolean;
@@ -798,19 +798,19 @@ implementation
                    consume(_RKLAMMER);
                  end;
               end;
+             { indicate if this call was generated by a member and
+               no explicit self is used, this is needed to determine
+               how to handle a destructor call (PFV) }
+             if membercall then
+               include(callflags,cnf_member_call);
              if assigned(obj) then
                begin
                  if (st.symtabletype<>objectsymtable) then
                    internalerror(200310031);
-                 p1:=ccallnode.create(para,tprocsym(sym),obj.symtable,p1);
+                 p1:=ccallnode.create(para,tprocsym(sym),obj.symtable,p1,callflags);
                end
              else
-               p1:=ccallnode.create(para,tprocsym(sym),st,p1);
-             { indicate if this call was generated by a member and
-               no explicit self is used, this is needed to determine
-               how to handle a destructor call (PFV) }
-             if membercall then
-               include(p1.flags,nf_member_call);
+               p1:=ccallnode.create(para,tprocsym(sym),st,p1,callflags);
            end;
          afterassignment:=prevafterassn;
       end;
@@ -860,6 +860,7 @@ implementation
          paras : tnode;
          p2    : tnode;
          membercall : boolean;
+         callflags  : tcallnodeflags;
       begin
          paras:=nil;
          { property parameters? read them only if the property really }
@@ -888,12 +889,12 @@ implementation
                    case tpropertysym(sym).writeaccess.firstsym^.sym.typ of
                      procsym :
                        begin
+                         callflags:=[];
                          { generate the method call }
                          membercall:=maybe_load_methodpointer(st,p1);
-                         p1:=ccallnode.create(paras,
-                                              tprocsym(tpropertysym(sym).writeaccess.firstsym^.sym),st,p1);
                          if membercall then
-                           include(tcallnode(p1).flags,nf_member_call);
+                           include(callflags,cnf_member_call);
+                         p1:=ccallnode.create(paras,tprocsym(tpropertysym(sym).writeaccess.firstsym^.sym),st,p1,callflags);
                          paras:=nil;
                          consume(_ASSIGNMENT);
                          { read the expression }
@@ -903,7 +904,8 @@ implementation
                          if assigned(getprocvardef) then
                            handle_procvar(getprocvardef,p2);
                          tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left);
-                         include(tcallnode(p1).flags,nf_isproperty);
+                         { mark as property, both the tcallnode and the real call block }
+                         include(p1.flags,nf_isproperty);
                          getprocvardef:=nil;
                        end;
                      varsym :
@@ -943,11 +945,12 @@ implementation
                        end;
                      procsym :
                        begin
+                          callflags:=[];
                           { generate the method call }
                           membercall:=maybe_load_methodpointer(st,p1);
-                          p1:=ccallnode.create(paras,tprocsym(tpropertysym(sym).readaccess.firstsym^.sym),st,p1);
                           if membercall then
-                            include(tcallnode(p1).flags,nf_member_call);
+                            include(callflags,cnf_member_call);
+                          p1:=ccallnode.create(paras,tprocsym(tpropertysym(sym).readaccess.firstsym^.sym),st,p1,callflags);
                           paras:=nil;
                           include(p1.flags,nf_isproperty);
                        end
@@ -972,16 +975,12 @@ implementation
 
 
     { the ID token has to be consumed before calling this function }
-    procedure do_member_read(classh:tobjectdef;getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callnflags:tnodeflags);
+    procedure do_member_read(classh:tobjectdef;getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callflags:tcallnodeflags);
 
       var
          static_name : string;
-         isclassref : boolean;
-         srsymtable : tsymtable;
-{$ifdef CHECKINHERITEDRESULT}
-         newstatement : tstatementnode;
-         newblock     : tblocknode;
-{$endif CHECKINHERITEDRESULT}
+         isclassref  : boolean;
+         srsymtable  : tsymtable;
       begin
          if sym=nil then
            begin
@@ -1011,77 +1010,16 @@ implementation
                    begin
                       do_proc_call(sym,sym.owner,classh,
                                    (getaddr and not(token in [_CARET,_POINT])),
-                                   again,p1);
-                      { add provided flags }
-                      if (p1.nodetype=calln) then
-                        p1.flags:=p1.flags+callnflags;
+                                   again,p1,callflags);
                       { we need to know which procedure is called }
                       do_resulttypepass(p1);
-                      { now we know the method that is called }
-                      if (p1.nodetype=calln) and
-                         assigned(tcallnode(p1).procdefinition) then
-                        begin
-                          { calling using classref? }
-                          if isclassref and
-                             not(po_classmethod in tcallnode(p1).procdefinition.procoptions) and
-                             not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
-                            Message(parser_e_only_class_methods_via_class_ref);
-{$ifdef CHECKINHERITEDRESULT}
-                           { when calling inherited constructor we need to check the return value }
-                           if (nf_inherited in callnflags) and
-                              (tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
-                             begin
-                               {
-                                 For Classes:
-
-                                 self:=inherited constructor
-                                 if self=nil then
-                                   exit
-
-                                 For objects:
-                                 if inherited constructor=false then
-                                   begin
-                                     self:=nil;
-                                     exit;
-                                   end;
-                               }
-                               if is_class(tprocdef(tcallnode(p1).procdefinition)._class) then
-                                 begin
-                                   newblock:=internalstatements(newstatement,true);
-                                   addstatement(newstatement,cassignmentnode.create(
-                                       ctypeconvnode.create(
-                                           load_self_pointer_node,
-                                           voidpointertype),
-                                       ctypeconvnode.create(
-                                           p1,
-                                           voidpointertype)));
-                                   addstatement(newstatement,cifnode.create(
-                                       caddnode.create(equaln,
-                                           load_self_pointer_node,
-                                           cnilnode.create),
-                                       cexitnode.create(nil),
-                                       nil));
-                                   p1:=newblock;
-                                 end
-                               else
-                                 if is_object(tprocdef(tcallnode(p1).procdefinition)._class) then
-                                   begin
-                                     newblock:=internalstatements(newstatement,true);
-                                     addstatement(newstatement,call_fail_node);
-                                     addstatement(newstatement,cexitnode.create(nil));
-                                     p1:=cifnode.create(
-                                         caddnode.create(equaln,
-                                             cordconstnode.create(0,booltype,false),
-                                             p1),
-                                         newblock,
-                                         nil);
-                                   end
-                                 else
-                                   internalerror(200305133);
-                             end;
-{$endif CHECKINHERITEDRESULT}
-                           do_resulttypepass(p1);
-                        end;
+                      { calling using classref? }
+                      if isclassref and
+                         (p1.nodetype=calln) and
+                         assigned(tcallnode(p1).procdefinition) and
+                         not(po_classmethod in tcallnode(p1).procdefinition.procoptions) and
+                         not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then
+                        Message(parser_e_only_class_methods_via_class_ref);
                    end;
                  varsym:
                    begin
@@ -1386,7 +1324,7 @@ implementation
                                     (po_classmethod in current_procinfo.procdef.procoptions);
                     do_proc_call(srsym,srsymtable,nil,
                                  (getaddr and not(token in [_CARET,_POINT])),
-                                 again,p1);
+                                 again,p1,[]);
                     { we need to know which procedure is called }
                     if possible_error then
                      begin
@@ -1867,7 +1805,7 @@ implementation
                           htype.setdef(tclassrefdef.create(htype));
                         p1:=ctypenode.create(htype);
                       end;
-                     do_member_read(classh,false,sym,p1,again,[nf_inherited,nf_anon_inherited]);
+                     do_member_read(classh,false,sym,p1,again,[cnf_inherited,cnf_anon_inherited]);
                    end
                   else
                    begin
@@ -1882,7 +1820,7 @@ implementation
                                (sym.typ<>procsym) then
                               internalerror(200303171);
                             p1:=nil;
-                            do_proc_call(sym,sym.owner,classh,false,again,p1);
+                            do_proc_call(sym,sym.owner,classh,false,again,p1,[]);
                           end
                         else
                           begin
@@ -2427,7 +2365,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.155  2004-05-16 15:03:48  florian
+  Revision 1.156  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.155  2004/05/16 15:03:48  florian
     + support for assigned(<dyn. array>) added
 
   Revision 1.154  2004/04/29 19:56:37  daniel

+ 28 - 29
compiler/pinline.pas

@@ -75,7 +75,7 @@ implementation
         destructorname : stringid;
         sym      : tsym;
         classh   : tobjectdef;
-        callflag : tnodeflag;
+        callflag : tcallnodeflag;
         destructorpos,
         storepos : tfileposinfo;
       begin
@@ -153,9 +153,9 @@ implementation
                   p2:=cderefnode.create(p);
                 do_resulttypepass(p2);
                 if is_new then
-                  callflag:=nf_new_call
+                  callflag:=cnf_new_call
                 else
-                  callflag:=nf_dispose_call;
+                  callflag:=cnf_dispose_call;
                 if is_new then
                   do_member_read(classh,false,sym,p2,again,[callflag])
                 else
@@ -164,11 +164,7 @@ implementation
                       do_member_read(classh,false,sym,p2,again,[callflag])
                     else
                       begin
-                        p2:=ccallnode.create(nil,tprocsym(sym),sym.owner,p2);
-                        if is_new then
-                          include(p2.flags,nf_new_call)
-                        else
-                          include(p2.flags,nf_dispose_call);
+                        p2:=ccallnode.create(nil,tprocsym(sym),sym.owner,p2,[callflag]);
                         { support dispose(p,done()); }
                         if try_to_consume(_LKLAMMER) then
                           begin
@@ -185,7 +181,22 @@ implementation
                 { we need the real called method }
                 do_resulttypepass(p2);
 
-                if p2.nodetype<>calln then
+                if (p2.nodetype=calln) then
+                  begin
+                    if is_new then
+                     begin
+                       if (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor) then
+                         Message(parser_e_expr_have_to_be_constructor_call);
+                       p2.resulttype:=p.resulttype;
+                       p2:=cassignmentnode.create(p,p2);
+                     end
+                    else
+                     begin
+                       if (tcallnode(p2).procdefinition.proctypeoption<>potype_destructor) then
+                         Message(parser_e_expr_have_to_be_destructor_call);
+                     end;
+                  end
+                else
                   begin
                     if is_new then
                       CGMessage(parser_e_expr_have_to_be_constructor_call)
@@ -193,22 +204,7 @@ implementation
                       CGMessage(parser_e_expr_have_to_be_destructor_call);
                   end;
 
-                if not codegenerror then
-                 begin
-                   if is_new then
-                    begin
-                      if (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor) then
-                        Message(parser_e_expr_have_to_be_constructor_call);
-                      p2.resulttype:=p.resulttype;
-                      p2:=cassignmentnode.create(p,p2);
-                    end
-                   else
-                    begin
-                      if (tcallnode(p2).procdefinition.proctypeoption<>potype_destructor) then
-                        Message(parser_e_expr_have_to_be_destructor_call);
-                    end;
-                 end;
-                new_dispose_statement:=p2;
+                result:=p2;
               end;
           end
         else
@@ -373,7 +369,7 @@ implementation
             afterassignment:=false;
             sym:=searchsym_in_class(classh,pattern);
             consume(_ID);
-            do_member_read(classh,false,sym,p1,again,[nf_new_call]);
+            do_member_read(classh,false,sym,p1,again,[cnf_new_call]);
             { we need to know which procedure is called }
             do_resulttypepass(p1);
             if not(
@@ -531,8 +527,6 @@ implementation
       var
         newblock,
         paras   : tnode;
-        npara,
-        destppn,
         ppn     : tcallparanode;
       begin
         { for easy exiting if something goes wrong }
@@ -633,7 +627,9 @@ implementation
         paradef : tdef;
         counter : integer;
         newstatement : tstatementnode;
+{$ifdef ansistring_bits}
         mode    : byte;
+{$endif ansistring_bits}
       begin
         { for easy exiting if something goes wrong }
         result := cerrornode.create;
@@ -763,7 +759,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.30  2004-04-29 19:56:37  daniel
+  Revision 1.31  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.30  2004/04/29 19:56:37  daniel
     * Prepare compiler infrastructure for multiple ansistring types
 
   Revision 1.29  2004/02/04 18:45:29  jonas

+ 5 - 2
compiler/pstatmnt.pas

@@ -977,7 +977,7 @@ implementation
                 - dispose of temp stack space
                 - dispose on FPU stack }
              if (p.nodetype=calln) then
-               exclude(p.flags,nf_return_value_used);
+               exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
 
              code:=p;
            end;
@@ -1105,7 +1105,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.133  2004-05-23 11:39:38  peter
+  Revision 1.134  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.133  2004/05/23 11:39:38  peter
     * give error when goto jumps to label outside current proc scope
 
   Revision 1.132  2004/03/04 17:22:10  peter

+ 10 - 6
compiler/psub.pas

@@ -302,7 +302,7 @@ implementation
                                 ctypeconvnode.create_explicit(
                                     load_self_pointer_node,
                                     voidpointertype),
-                                ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_vmt_pointer_node)),
+                                ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_vmt_pointer_node,[])),
                             nil));
                       end
                     else
@@ -361,7 +361,7 @@ implementation
                         caddnode.create(unequaln,
                             load_vmt_pointer_node,
                             cnilnode.create),
-                        ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node),
+                        ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
                         nil));
                   end
                 else
@@ -399,7 +399,7 @@ implementation
                             caddnode.create(unequaln,
                                 load_vmt_pointer_node,
                                 cnilnode.create)),
-                        ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node),
+                        ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
                         nil));
                   end
                 else
@@ -426,7 +426,7 @@ implementation
                                         load_vmt_pointer_node,
                                         voidpointertype),
                                     cpointerconstnode.create(1,voidpointertype))),
-                            ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node),
+                            ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
                             nil));
                       end
                     else
@@ -466,6 +466,7 @@ implementation
       var
         pd : tprocdef;
         newstatement : tstatementnode;
+        dummycall    : tcallnode;
       begin
         generate_except_block:=internalstatements(newstatement);
 
@@ -482,7 +483,7 @@ implementation
                     caddnode.create(unequaln,
                         load_vmt_pointer_node,
                         cnilnode.create),
-                    ccallnode.create(nil,tprocsym(pd.procsym),pd.procsym.owner,load_self_node),
+                    ccallnode.create(nil,tprocsym(pd.procsym),pd.procsym.owner,load_self_node,[]),
                     nil));
               end;
           end
@@ -1379,7 +1380,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.191  2004-05-23 15:06:21  peter
+  Revision 1.192  2004-05-23 18:28:41  peter
+    * methodpointer is loaded into a temp when it was a calln
+
+  Revision 1.191  2004/05/23 15:06:21  peter
     * implicit_finally flag must be set in pass1
     * add check whether the implicit frame is generated when expected