Browse Source

* refactor function result handling
* rename methodpointerinit/done to callinitblock/callcleanupblock
* moved checks in callnode to separate functions
* funcretnode is now always a simple node instead of a block of
statements
* funcret and methodpointer are generated/optimized only in pass_1 so
a conversion from calln to loadn is much easier
* function result assignments are much more often optimized to use the
assignment destination location instead of using a temp

git-svn-id: trunk@8558 -

peter 18 years ago
parent
commit
e0cf015159
9 changed files with 1511 additions and 1923 deletions
  1. 5 5
      compiler/nbas.pas
  2. 1338 1661
      compiler/ncal.pas
  3. 151 182
      compiler/ncgcal.pas
  4. 1 1
      compiler/ncgutil.pas
  5. 1 1
      compiler/ncnv.pas
  6. 1 59
      compiler/nld.pas
  7. 5 5
      compiler/nutils.pas
  8. 8 8
      compiler/opttail.pas
  9. 1 1
      compiler/pexpr.pas

+ 5 - 5
compiler/nbas.pas

@@ -94,12 +94,12 @@ interface
 
 
        ttempcreatenode = class;
        ttempcreatenode = class;
 
 
-       ttempinfoflag = (ti_may_be_in_reg,ti_valid,ti_nextref_set_hookoncopy_nil,ti_is_inlined_result,
+       ttempinfoflag = (ti_may_be_in_reg,ti_valid,ti_nextref_set_hookoncopy_nil,ti_is_funcret,
         ti_addr_taken);
         ti_addr_taken);
        ttempinfoflags = set of ttempinfoflag;
        ttempinfoflags = set of ttempinfoflag;
 
 
 const
 const
-       tempinfostoreflags = [ti_may_be_in_reg,ti_is_inlined_result,ti_addr_taken];
+       tempinfostoreflags = [ti_may_be_in_reg,ti_is_funcret,ti_addr_taken];
 
 
 type
 type
        { to allow access to the location by temp references even after the temp has }
        { to allow access to the location by temp references even after the temp has }
@@ -133,7 +133,7 @@ type
           { to it and *not* generate a ttempdeletenode                          }
           { to it and *not* generate a ttempdeletenode                          }
           constructor create(_typedef: tdef; _size: aint; _temptype: ttemptype;allowreg:boolean); virtual;
           constructor create(_typedef: tdef; _size: aint; _temptype: ttemptype;allowreg:boolean); virtual;
           constructor create_withnode(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean; withnode: tnode); virtual;
           constructor create_withnode(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean; withnode: tnode); virtual;
-          constructor create_inlined_result(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean); virtual;
+          constructor create_funcret(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean); virtual;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure buildderefimpl;override;
           procedure buildderefimpl;override;
@@ -742,10 +742,10 @@ implementation
       end;
       end;
 
 
 
 
-    constructor ttempcreatenode.create_inlined_result(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean);
+    constructor ttempcreatenode.create_funcret(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean);
       begin
       begin
         self.create(_typedef,_size,_temptype,allowreg);
         self.create(_typedef,_size,_temptype,allowreg);
-        include(tempinfo^.flags,ti_is_inlined_result);
+        include(tempinfo^.flags,ti_is_funcret);
       end;
       end;
 
 
 
 

File diff suppressed because it is too large
+ 1338 - 1661
compiler/ncal.pas


+ 151 - 182
compiler/ncgcal.pas

@@ -1,4 +1,4 @@
-{
+ {
     Copyright (c) 1998-2002 by Florian Klaempfl
     Copyright (c) 1998-2002 by Florian Klaempfl
 
 
     Generate assembler for call nodes
     Generate assembler for call nodes
@@ -45,13 +45,13 @@ interface
 
 
        tcgcallnode = class(tcallnode)
        tcgcallnode = class(tcallnode)
        private
        private
+          procedure handle_return_value;
+          procedure release_unused_return_value;
           procedure release_para_temps;
           procedure release_para_temps;
           procedure pushparas;
           procedure pushparas;
           procedure freeparas;
           procedure freeparas;
        protected
        protected
           framepointer_paraloc : tcgpara;
           framepointer_paraloc : tcgpara;
-          refcountedtemp : treference;
-          procedure handle_return_value;
           {# This routine is used to push the current frame pointer
           {# This routine is used to push the current frame pointer
              on the stack. This is used in nested routines where the
              on the stack. This is used in nested routines where the
              value of the frame pointer is always pushed as an extra
              value of the frame pointer is always pushed as an extra
@@ -509,190 +509,159 @@ implementation
       var
       var
         cgsize    : tcgsize;
         cgsize    : tcgsize;
         retloc    : tlocation;
         retloc    : tlocation;
-        hregister : tregister;
-        tempnode  : tnode;
       begin
       begin
-        cgsize:=procdefinition.funcretloc[callerside].size;
-
-        { structured results are easy to handle....
-          needed also when result_no_used !! }
+        { Check that the return location is set when the result is passed in
+          a parameter }
         if (procdefinition.proctypeoption<>potype_constructor) and
         if (procdefinition.proctypeoption<>potype_constructor) and
            paramanager.ret_in_param(resultdef,procdefinition.proccalloption) then
            paramanager.ret_in_param(resultdef,procdefinition.proccalloption) then
           begin
           begin
-            { Location should be setup by the funcret para }
             if location.loc<>LOC_REFERENCE then
             if location.loc<>LOC_REFERENCE then
-             internalerror(200304241);
-          end
-        else
-          { ansi/widestrings must be registered, so we can dispose them }
-          if resultdef.needs_inittable then
-            begin
-              if procdefinition.funcretloc[callerside].loc<>LOC_REGISTER then
-                internalerror(200409261);
-
-              retloc:=procdefinition.funcretloc[callerside];
-{$ifndef cpu64bit}
-              if cgsize in [OS_64,OS_S64] then
-                begin
-                  { the function result registers are already allocated }
-                  if getsupreg(retloc.register64.reglo)<first_int_imreg then
-                    cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reglo);
-                  retloc.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
-                  cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,procdefinition.funcretloc[callerside].register64.reglo,retloc.register64.reglo);
-                  if getsupreg(retloc.register64.reghi)<first_int_imreg then
-                    cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reghi);
-                  retloc.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
-                  cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,procdefinition.funcretloc[callerside].register64.reghi,retloc.register64.reghi);
-                end
-              else
-{$endif cpu64bit}
-                begin
-                  { the FUNCTION_RESULT_REG is already allocated }
-                  if getsupreg(retloc.register)<first_int_imreg then
-                    cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register);
-
-                  { reg_ref could generate two instrcutions and allocate a register so we've to
-                    save the result first before releasing it }
-                  retloc.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
-                  cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,procdefinition.funcretloc[callerside].register,retloc.register);
-                end;
+              internalerror(200304241);
+            exit;
+          end;
 
 
-              if not assigned(funcretnode) then
-                begin
-                  location_reset(location,LOC_REFERENCE,cgsize);
-                  location.reference:=refcountedtemp;
-                end
-              else
-                begin
-                  { in case of a regular funcretnode with ret_in_param, the }
-                  { original funcretnode isn't touched -> make sure it's    }
-                  { the same here (not sure if it's necessary)              }
-                  tempnode := funcretnode.getcopy;
-                  tempnode.pass_generate_code;
-                  location := tempnode.location;
-                  tempnode.free;
-                  cg.g_decrrefcount(current_asmdata.CurrAsmList,resultdef,location.reference);
-               end;
-{$ifndef cpu64bit}
-              if cgsize in [OS_64,OS_S64] then
-                cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,retloc.register64,location.reference)
-              else
-{$endif}
-                cg.a_load_reg_ref(current_asmdata.CurrAsmList,cgsize,cgsize,retloc.register,location.reference);
-            end
-        else
-          { normal (ordinal,float,pointer) result value }
-          begin
-            { we have only to handle the result if it is used }
-            if (cnf_return_value_used in callnodeflags) then
-              begin
-                location.loc:=procdefinition.funcretloc[callerside].loc;
-                case procdefinition.funcretloc[callerside].loc of
-                   LOC_FPUREGISTER:
-                     begin
-                       location_reset(location,LOC_FPUREGISTER,cgsize);
-                       location.register:=procdefinition.funcretloc[callerside].register;
+        { Load normal (ordinal,float,pointer) result value from accumulator }
+        cgsize:=procdefinition.funcretloc[callerside].size;
+        case procdefinition.funcretloc[callerside].loc of
+           LOC_FPUREGISTER:
+             begin
+               location_reset(location,LOC_FPUREGISTER,cgsize);
+               location.register:=procdefinition.funcretloc[callerside].register;
 {$ifdef x86}
 {$ifdef x86}
-                       tcgx86(cg).inc_fpu_stack;
+               tcgx86(cg).inc_fpu_stack;
 {$else x86}
 {$else x86}
-                       if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
-                         cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
-                       hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
-                       cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,location.size,location.size,location.register,hregister);
-                       location.register:=hregister;
+               if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
+                 cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
+               hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+               cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,location.size,location.size,location.register,hregister);
+               location.register:=hregister;
 {$endif x86}
 {$endif x86}
-                     end;
+             end;
 
 
-                   LOC_REGISTER:
-                     begin
-                       if cgsize<>OS_NO then
-                        begin
-                          location_reset(location,LOC_REGISTER,cgsize);
+           LOC_REGISTER:
+             begin
+               if cgsize<>OS_NO then
+                begin
+                  location_reset(location,LOC_REGISTER,cgsize);
 {$ifndef cpu64bit}
 {$ifndef cpu64bit}
-                          if cgsize in [OS_64,OS_S64] then
-                            begin
-                              retloc:=procdefinition.funcretloc[callerside];
-                              if retloc.loc<>LOC_REGISTER then
-                                internalerror(200409141);
-                              { the function result registers are already allocated }
-                              if getsupreg(retloc.register64.reglo)<first_int_imreg then
-                                cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reglo);
-                              location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
-                              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reglo,location.register64.reglo);
-                              if getsupreg(retloc.register64.reghi)<first_int_imreg then
-                                cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reghi);
-                              location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
-                              cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reghi,location.register64.reghi);
-                            end
-                          else
+                  if cgsize in [OS_64,OS_S64] then
+                    begin
+                      retloc:=procdefinition.funcretloc[callerside];
+                      if retloc.loc<>LOC_REGISTER then
+                        internalerror(200409141);
+                      { the function result registers are already allocated }
+                      if getsupreg(retloc.register64.reglo)<first_int_imreg then
+                        cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reglo);
+                      location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+                      cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reglo,location.register64.reglo);
+                      if getsupreg(retloc.register64.reghi)<first_int_imreg then
+                        cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reghi);
+                      location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
+                      cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reghi,location.register64.reghi);
+                    end
+                  else
 {$endif cpu64bit}
 {$endif cpu64bit}
-                            begin
-                              { change register size after the unget because the
-                                getregister was done for the full register
-                                def_cgsize(resultdef) is used here because
-                                it could be a constructor call }
-                              if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
-                                cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
-                              location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
-                              cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,def_cgsize(resultdef),procdefinition.funcretloc[callerside].register,location.register);
-                            end;
+                    begin
+                      { change register size after the unget because the
+                        getregister was done for the full register
+                        def_cgsize(resultdef) is used here because
+                        it could be a constructor call }
+                      if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
+                        cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
+                      location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
+                      cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,def_cgsize(resultdef),procdefinition.funcretloc[callerside].register,location.register);
+                    end;
 {$ifdef arm}
 {$ifdef arm}
-                          if (resultdef.typ=floatdef) and (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
-                            begin
-                              location_force_mem(current_asmdata.CurrAsmList,location);
-                            end;
+                  if (resultdef.typ=floatdef) and (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
+                    begin
+                      location_force_mem(current_asmdata.CurrAsmList,location);
+                    end;
 {$endif arm}
 {$endif arm}
-                        end
-                       else
-                        begin
-                          if resultdef.size>0 then
-                            internalerror(200305131);
-                        end;
-                     end;
+                end
+               else
+                begin
+                  if resultdef.size>0 then
+                    internalerror(200305131);
+                end;
+             end;
+
+           LOC_MMREGISTER:
+             begin
+               location_reset(location,LOC_MMREGISTER,cgsize);
+               if getsupreg(procdefinition.funcretloc[callerside].register)<first_mm_imreg then
+                 cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
+               location.register:=cg.getmmregister(current_asmdata.CurrAsmList,cgsize);
+               cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,cgsize,cgsize,procdefinition.funcretloc[callerside].register,location.register,mms_movescalar);
+             end;
+
+           else
+             internalerror(200405023);
+        end;
+
+        { copy value to the final location if this was already provided to the
+          callnode. This must be done after the call node, because the location can
+          also be used as parameter and may not be finalized yet }
+        if assigned(funcretnode) then
+          begin
+            funcretnode.pass_generate_code;
+            { Decrease refcount for refcounted types, this can be skipped when
+              we have used a temp, because then it is already done from tempcreatenode.
+              Also no finalize is needed, because there is no risk of exceptions from the
+              function since this is code is only executed after the function call has returned }
+            if funcretnode.resultdef.needs_inittable and
+               (funcretnode.nodetype<>temprefn) then
+              cg.g_decrrefcount(current_asmdata.CurrAsmList,funcretnode.resultdef,funcretnode.location.reference);
+
+            case location.loc of
+              LOC_REGISTER :
+{$ifndef cpu64bit}
+                if cgsize in [OS_64,OS_S64] then
+                  cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,location.register64,funcretnode.location)
+                else
+{$endif}
+                  cg.a_load_reg_loc(current_asmdata.CurrAsmList,cgsize,location.register,funcretnode.location);
+              else
+                internalerror(200709085);
+            end;
+            location := funcretnode.location;
+          end;
+      end;
 
 
-                   LOC_MMREGISTER:
-                     begin
-                       location_reset(location,LOC_MMREGISTER,cgsize);
-                       if getsupreg(procdefinition.funcretloc[callerside].register)<first_mm_imreg then
-                         cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
-                       location.register:=cg.getmmregister(current_asmdata.CurrAsmList,cgsize);
-                       cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,cgsize,cgsize,procdefinition.funcretloc[callerside].register,location.register,mms_movescalar);
-                     end;
 
 
-                   else
-                     internalerror(200405023);
-                end;
-              end
-            else
-              begin
+    procedure tcgcallnode.release_unused_return_value;
+      begin
+        { When the result is not used we need to finalize the result and
+          can release the temp. This need to be after the callcleanupblock
+          tree is generated, because that converts the temp from persistent to normal }
+        if not(cnf_return_value_used in callnodeflags) then
+          begin
+           case location.loc of
+             LOC_REFERENCE :
+               begin
+                 if resultdef.needs_inittable then
+                    cg.g_finalize(current_asmdata.CurrAsmList,resultdef,location.reference);
+                  tg.ungetiftemp(current_asmdata.CurrAsmList,location.reference);
+               end;
 {$ifdef x86}
 {$ifdef x86}
-                { release FPU stack }
-                if procdefinition.funcretloc[callerside].loc=LOC_FPUREGISTER then
+             LOC_FPUREGISTER :
+                begin
+                  { release FPU stack }
                   emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
                   emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
+                  tcgx86(cg).dec_fpu_stack;
+                end;
 {$endif x86}
 {$endif x86}
-                if cgsize<>OS_NO then
-                  location_free(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside]);
-                location_reset(location,LOC_VOID,OS_NO);
-              end;
            end;
            end;
-
-        { When the result is not used we need to finalize the result and
-          can release the temp }
-        if not(cnf_return_value_used in callnodeflags) then
-          begin
-            if location.loc=LOC_REFERENCE then
-              begin
-                if resultdef.needs_inittable then
-                  cg.g_finalize(current_asmdata.CurrAsmList,resultdef,location.reference);
-                tg.ungetiftemp(current_asmdata.CurrAsmList,location.reference)
-              end;
+            if procdefinition.funcretloc[callerside].size<>OS_NO then
+              location_free(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside]);
+            location_reset(location,LOC_VOID,OS_NO);
           end;
           end;
       end;
       end;
 
 
 
 
     procedure tcgcallnode.release_para_temps;
     procedure tcgcallnode.release_para_temps;
       var
       var
-        hp  : tnode;
+        hp,
+        hp2 : tnode;
         ppn : tcallparanode;
         ppn : tcallparanode;
       begin
       begin
         { Release temps from parameters }
         { Release temps from parameters }
@@ -714,7 +683,13 @@ implementation
                    begin
                    begin
                      while assigned(hp) do
                      while assigned(hp) do
                        begin
                        begin
-                         location_freetemp(current_asmdata.CurrAsmList,tarrayconstructornode(hp).left.location);
+                         hp2:=tarrayconstructornode(hp).left;
+                         { ignore typeconvs and addrn inserted by arrayconstructn for
+                           passing a shortstring }
+                         if (hp2.nodetype=typeconvn) and
+                            (tunarynode(hp2).left.nodetype=addrn) then
+                           hp2:=tunarynode(tunarynode(hp2).left).left;
+                         location_freetemp(current_asmdata.CurrAsmList,hp2.location);
                          hp:=tarrayconstructornode(hp).right;
                          hp:=tarrayconstructornode(hp).right;
                        end;
                        end;
                    end;
                    end;
@@ -864,19 +839,8 @@ implementation
             not procdefinition.has_paraloc_info then
             not procdefinition.has_paraloc_info then
            internalerror(200305264);
            internalerror(200305264);
 
 
-         if assigned(methodpointerinit) then
-           secondpass(methodpointerinit);
-
-         if resultdef.needs_inittable and
-            not paramanager.ret_in_param(resultdef,procdefinition.proccalloption) and
-            not assigned(funcretnode) then
-           begin
-             tg.gettemptyped(current_asmdata.CurrAsmList,resultdef,tt_normal,refcountedtemp);
-             { finalize instead of only decrref,  because if the called }
-             { function throws an exception this temp will be decrref'd }
-             { again (tw7100)                                           }
-             cg.g_finalize(current_asmdata.CurrAsmList,resultdef,refcountedtemp);
-           end;
+         if assigned(callinitblock) then
+           secondpass(callinitblock);
 
 
          regs_to_save_int:=paramanager.get_volatile_registers_int(procdefinition.proccalloption);
          regs_to_save_int:=paramanager.get_volatile_registers_int(procdefinition.proccalloption);
          regs_to_save_fpu:=paramanager.get_volatile_registers_fpu(procdefinition.proccalloption);
          regs_to_save_fpu:=paramanager.get_volatile_registers_fpu(procdefinition.proccalloption);
@@ -1120,6 +1084,18 @@ implementation
          else
          else
            location_reset(location,LOC_VOID,OS_NO);
            location_reset(location,LOC_VOID,OS_NO);
 
 
+         { convert persistent temps for parameters and function result to normal temps }
+         if assigned(callcleanupblock) then
+           secondpass(callcleanupblock);
+
+         { release temps and finalize unused return values, must be
+           after the callcleanupblock because that converts temps
+           from persistent to normal }
+         release_unused_return_value;
+
+         { release temps of paras }
+         release_para_temps;
+
          { perhaps i/o check ? }
          { perhaps i/o check ? }
          if (cs_check_io in current_settings.localswitches) and
          if (cs_check_io in current_settings.localswitches) and
             (po_iocheck in procdefinition.procoptions) and
             (po_iocheck in procdefinition.procoptions) and
@@ -1132,13 +1108,6 @@ implementation
               cg.a_call_name(current_asmdata.CurrAsmList,'FPC_IOCHECK');
               cg.a_call_name(current_asmdata.CurrAsmList,'FPC_IOCHECK');
               cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
               cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
            end;
            end;
-
-         { release temps of paras }
-         release_para_temps;
-
-
-         if assigned(methodpointerdone) then
-           secondpass(methodpointerdone);
       end;
       end;
 
 
 
 

+ 1 - 1
compiler/ncgutil.pas

@@ -2542,7 +2542,7 @@ implementation
               if (ti_valid in ttemprefnode(n).tempinfo^.flags) and
               if (ti_valid in ttemprefnode(n).tempinfo^.flags) and
                  (ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
                  (ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
                  (ttemprefnode(n).tempinfo^.location.register = rr^.old) and
                  (ttemprefnode(n).tempinfo^.location.register = rr^.old) and
-                 (not(ti_is_inlined_result in ttemprefnode(n).tempinfo^.flags) or
+                 (not(ti_is_funcret in ttemprefnode(n).tempinfo^.flags) or
                   not(fc_exit in flowcontrol)) then
                   not(fc_exit in flowcontrol)) then
                 begin
                 begin
 {$ifndef cpu64bit}
 {$ifndef cpu64bit}

+ 1 - 1
compiler/ncnv.pas

@@ -1696,7 +1696,7 @@ implementation
                         if (tcallnode(left).symtableprocentry.owner.symtabletype=ObjectSymtable) then
                         if (tcallnode(left).symtableprocentry.owner.symtabletype=ObjectSymtable) then
                          begin
                          begin
                            if assigned(tcallnode(left).methodpointer) then
                            if assigned(tcallnode(left).methodpointer) then
-                             tloadnode(hp).set_mp(tcallnode(left).get_load_methodpointer)
+                             tloadnode(hp).set_mp(tcallnode(left).methodpointer.getcopy)
                            else
                            else
                              tloadnode(hp).set_mp(load_self_node);
                              tloadnode(hp).set_mp(load_self_node);
                          end;
                          end;

+ 1 - 59
compiler/nld.pas

@@ -679,10 +679,7 @@ implementation
            is pushed as a parameter. Using the final destination of left directly
            is pushed as a parameter. Using the final destination of left directly
            save a temp allocation and copy of data (PFV) }
            save a temp allocation and copy of data (PFV) }
          oldassignmentnode:=aktassignmentnode;
          oldassignmentnode:=aktassignmentnode;
-         if right.nodetype=addn then
-           aktassignmentnode:=self
-         else
-           aktassignmentnode:=nil;
+         aktassignmentnode:=self;
          firstpass(right);
          firstpass(right);
          aktassignmentnode:=oldassignmentnode;
          aktassignmentnode:=oldassignmentnode;
          if nf_assign_done_in_right in flags then
          if nf_assign_done_in_right in flags then
@@ -695,66 +692,11 @@ implementation
          if codegenerror then
          if codegenerror then
            exit;
            exit;
 
 
-         { if right is a function call for which the address of the result  }
-         { is allocated by the caller and passed to the function via an     }
-         { invisible function result, try to pass the x in "x:=f(...)" as   }
-         { that function result instead. Condition: x cannot be accessible  }
-         { from within f. This is the case if x is a temp, or x is a local  }
-         { variable or value parameter of the current block and its address }
-         { is not passed to f. One problem: what if someone takes the       }
-         { address of x, puts it in a pointer variable/field and then       }
-         { accesses it that way from within the function? This is solved    }
-         { (in a conservative way) using the ti_addr_taken/addr_taken flags }
-         if (cs_opt_level1 in current_settings.optimizerswitches) and
-            (right.nodetype = calln) and
-            (right.resultdef=left.resultdef) and
-            { left must be a temp, since otherwise as soon as you modify the }
-            { result, the current left node is modified and that one may     }
-            { still be an argument to the function or even accessed in the   }
-            { function                                                       }
-            (
-             (
-              (((left.nodetype = temprefn) and
-                not(ti_addr_taken in ttemprefnode(left).tempinfo^.flags) and
-                not(ti_may_be_in_reg in ttemprefnode(left).tempinfo^.flags)) or
-               ((left.nodetype = loadn) and
-                { nested procedures may access the current procedure's locals }
-                (tcallnode(right).procdefinition.parast.symtablelevel=normal_function_level) and
-                { must be a local variable or a value para }
-                ((tloadnode(left).symtableentry.typ = localvarsym) or
-                 ((tloadnode(left).symtableentry.typ = paravarsym) and
-                  (tparavarsym(tloadnode(left).symtableentry).varspez = vs_value)
-                 )
-                ) and
-                { the address may not have been taken of the variable/parameter, because }
-                { otherwise it's possible that the called function can access it via a   }
-                { global variable or other stored state                                  }
-                not(tabstractvarsym(tloadnode(left).symtableentry).addr_taken) and
-                (tabstractvarsym(tloadnode(left).symtableentry).varregable in [vr_none,vr_addr])
-               )
-              ) and
-              paramanager.ret_in_param(right.resultdef,tcallnode(right).procdefinition.proccalloption)
-             ) or
-             { there's special support for ansi/widestrings in the callnode }
-             is_ansistring(right.resultdef) or
-             is_widestring(right.resultdef)
-            )  then
-           begin
-             if assigned(tcallnode(right).funcretnode) then
-               internalerror(2007080201);
-             tcallnode(right).funcretnode := left;
-             result := right;
-             left := nil;
-             right := nil;
-             exit;
-           end;
-
          { assignment to refcounted variable -> inc/decref }
          { assignment to refcounted variable -> inc/decref }
          if (not is_class(left.resultdef) and
          if (not is_class(left.resultdef) and
             left.resultdef.needs_inittable) then
             left.resultdef.needs_inittable) then
            include(current_procinfo.flags,pi_do_call);
            include(current_procinfo.flags,pi_do_call);
 
 
-
         if (is_shortstring(left.resultdef)) then
         if (is_shortstring(left.resultdef)) then
           begin
           begin
            if right.resultdef.typ=stringdef then
            if right.resultdef.typ=stringdef then

+ 5 - 5
compiler/nutils.pas

@@ -121,9 +121,9 @@ implementation
         calln:
         calln:
           begin
           begin
             { not in one statement, won't work because of b- }
             { not in one statement, won't work because of b- }
-            result := foreachnode(tcallnode(n).methodpointerinit,f,arg) or result;
+            result := foreachnode(tcallnode(n).callinitblock,f,arg) or result;
             result := foreachnode(tcallnode(n).methodpointer,f,arg) or result;
             result := foreachnode(tcallnode(n).methodpointer,f,arg) or result;
-            result := foreachnode(tcallnode(n).methodpointerdone,f,arg) or result;
+            result := foreachnode(tcallnode(n).callcleanupblock,f,arg) or result;
           end;
           end;
         ifn, whilerepeatn, forn, tryexceptn, tryfinallyn:
         ifn, whilerepeatn, forn, tryexceptn, tryfinallyn:
           begin
           begin
@@ -169,9 +169,9 @@ implementation
             end;
             end;
           calln:
           calln:
             begin
             begin
-              result := foreachnodestatic(procmethod,tcallnode(n).methodpointerinit,f,arg) or result;
+              result := foreachnodestatic(procmethod,tcallnode(n).callinitblock,f,arg) or result;
               result := foreachnodestatic(procmethod,tcallnode(n).methodpointer,f,arg) or result;
               result := foreachnodestatic(procmethod,tcallnode(n).methodpointer,f,arg) or result;
-              result := foreachnodestatic(procmethod,tcallnode(n).methodpointerdone,f,arg) or result;
+              result := foreachnodestatic(procmethod,tcallnode(n).callcleanupblock,f,arg) or result;
             end;
             end;
           ifn, whilerepeatn, forn, tryexceptn, tryfinallyn:
           ifn, whilerepeatn, forn, tryexceptn, tryfinallyn:
             begin
             begin
@@ -267,7 +267,7 @@ implementation
               method without a self pointer }
               method without a self pointer }
             if assigned(tcallnode(p1).methodpointer) and
             if assigned(tcallnode(p1).methodpointer) and
                (tcallnode(p1).methodpointer.nodetype<>typen) then
                (tcallnode(p1).methodpointer.nodetype<>typen) then
-              tloadnode(p2).set_mp(tcallnode(p1).get_load_methodpointer);
+              tloadnode(p2).set_mp(tcallnode(p1).methodpointer.getcopy);
           end;
           end;
         typecheckpass(p2);
         typecheckpass(p2);
         p1.free;
         p1.free;

+ 8 - 8
compiler/opttail.pas

@@ -144,10 +144,10 @@ unit opttail;
                     oldnodetree:=n;
                     oldnodetree:=n;
                     n:=internalstatements(nodes);
                     n:=internalstatements(nodes);
 
 
-                    if assigned(usedcallnode.methodpointerinit) then
+                    if assigned(usedcallnode.callinitblock) then
                       begin
                       begin
-                        addstatement(nodes,usedcallnode.methodpointerinit);
-                        usedcallnode.methodpointerinit:=nil;
+                        addstatement(nodes,usedcallnode.callinitblock);
+                        usedcallnode.callinitblock:=nil;
                       end;
                       end;
 
 
                     addstatement(nodes,calcnodes);
                     addstatement(nodes,calcnodes);
@@ -156,13 +156,13 @@ unit opttail;
                     { create goto }
                     { create goto }
                     addstatement(nodes,cgotonode.create(labelnode));
                     addstatement(nodes,cgotonode.create(labelnode));
 
 
-                    if assigned(usedcallnode.methodpointerdone) then
+                    if assigned(usedcallnode.callcleanupblock) then
                       begin
                       begin
-                        { methodpointerdone should contain only temp. node clean up }
-                        checktreenodetypes(usedcallnode.methodpointerdone,
+                        { callcleanupblock should contain only temp. node clean up }
+                        checktreenodetypes(usedcallnode.callcleanupblock,
                           [tempdeleten,blockn,statementn,temprefn,nothingn]);
                           [tempdeleten,blockn,statementn,temprefn,nothingn]);
-                        addstatement(nodes,usedcallnode.methodpointerdone);
-                        usedcallnode.methodpointerdone:=nil;
+                        addstatement(nodes,usedcallnode.callcleanupblock);
+                        usedcallnode.callcleanupblock:=nil;
                       end;
                       end;
 
 
                     oldnodetree.free;
                     oldnodetree.free;

+ 1 - 1
compiler/pexpr.pas

@@ -1079,7 +1079,7 @@ implementation
                begin
                begin
                  hp2:=cloadnode.create_procvar(tprocsym(tcallnode(hp).symtableprocentry),currprocdef,tcallnode(hp).symtableproc);
                  hp2:=cloadnode.create_procvar(tprocsym(tcallnode(hp).symtableprocentry),currprocdef,tcallnode(hp).symtableproc);
                  if (po_methodpointer in pv.procoptions) then
                  if (po_methodpointer in pv.procoptions) then
-                   tloadnode(hp2).set_mp(tcallnode(hp).get_load_methodpointer);
+                   tloadnode(hp2).set_mp(tcallnode(hp).methodpointer.getcopy);
                  hp.destroy;
                  hp.destroy;
                  { replace the old callnode with the new loadnode }
                  { replace the old callnode with the new loadnode }
                  hpp^:=hp2;
                  hpp^:=hp2;

Some files were not shown because too many files changed in this diff