Explorar o código

* Do not use the LOC_VOID location to indicate unused parameters.
* Added the tprocdef.parentfpsym property. Set parentfpsym.varstate to vs_read instead of using the pio_needs_parentfp flag.
* Replaced tcgcallparanode.push_zero_sized_value_para by tparamanager.has_strict_proc_signature.

git-svn-id: trunk@45454 -

yury %!s(int64=5) %!d(string=hai) anos
pai
achega
627fcb4354

+ 7 - 0
compiler/jvm/cpupara.pas

@@ -51,6 +51,7 @@ interface
         function param_use_paraloc(const cgpara: tcgpara): boolean; override;
         function param_use_paraloc(const cgpara: tcgpara): boolean; override;
         function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
         function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
         function is_stack_paraloc(paraloc: pcgparalocation): boolean;override;
         function is_stack_paraloc(paraloc: pcgparalocation): boolean;override;
+        function has_strict_proc_signature: boolean;override;
       private
       private
         procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
         procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
                                              var parasize:longint);
                                              var parasize:longint);
@@ -209,6 +210,12 @@ implementation
       end;
       end;
 
 
 
 
+    function tcpuparamanager.has_strict_proc_signature: boolean;
+      begin
+        result:=true;
+      end;
+
+
     function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
     function tcpuparamanager.create_varargs_paraloc_info(p : tabstractprocdef; side: tcallercallee; varargspara:tvarargsparalist):longint;
       var
       var
         parasize : longint;
         parasize : longint;

+ 0 - 9
compiler/jvm/njvmcal.pas

@@ -33,8 +33,6 @@ interface
     type
     type
        tjvmcallparanode = class(tcgcallparanode)
        tjvmcallparanode = class(tcgcallparanode)
         protected
         protected
-         function push_zero_sized_value_para: boolean; override;
-
          procedure push_formal_para; override;
          procedure push_formal_para; override;
          procedure push_copyout_para; override;
          procedure push_copyout_para; override;
 
 
@@ -74,13 +72,6 @@ implementation
                            TJVMCALLPARANODE
                            TJVMCALLPARANODE
 *****************************************************************************}
 *****************************************************************************}
 
 
-    function tjvmcallparanode.push_zero_sized_value_para: boolean;
-      begin
-        { part of the signature -> need to be pushed }
-        result:=true;
-      end;
-
-
     procedure tjvmcallparanode.push_formal_para;
     procedure tjvmcallparanode.push_formal_para;
       begin
       begin
         { primitive values are boxed, so in all cases this is a pointer to
         { primitive values are boxed, so in all cases this is a pointer to

+ 7 - 0
compiler/llvm/llvmpara.pas

@@ -51,6 +51,7 @@ unit llvmpara;
         function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
         function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
         function create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee; varargspara: tvarargsparalist): longint; override;
         function create_varargs_paraloc_info(p: tabstractprocdef; side: tcallercallee; varargspara: tvarargsparalist): longint; override;
         function get_funcretloc(p: tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara; override;
         function get_funcretloc(p: tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara; override;
+        function has_strict_proc_signature: boolean; override;
        private
        private
         procedure create_paraloc_info_internllvm(p: tabstractprocdef; side: tcallercallee);
         procedure create_paraloc_info_internllvm(p: tabstractprocdef; side: tcallercallee);
         procedure set_llvm_paraloc_name(p: tabstractprocdef; hp: tparavarsym; var para: tcgpara);
         procedure set_llvm_paraloc_name(p: tabstractprocdef; hp: tparavarsym; var para: tcgpara);
@@ -261,6 +262,12 @@ unit llvmpara;
     end;
     end;
 
 
 
 
+  function tllvmparamanager.has_strict_proc_signature: boolean;
+    begin
+      result:=true;
+    end;
+
+
   procedure tllvmparamanager.create_paraloc_info_internllvm(p: tabstractprocdef; side: tcallercallee);
   procedure tllvmparamanager.create_paraloc_info_internllvm(p: tabstractprocdef; side: tcallercallee);
     begin
     begin
       { on the calleeside, llvm declares the parameters similar to Pascal or C
       { on the calleeside, llvm declares the parameters similar to Pascal or C

+ 0 - 13
compiler/llvm/nllvmcal.pas

@@ -32,8 +32,6 @@ interface
 
 
     type
     type
       tllvmcallparanode = class(tcgcallparanode)
       tllvmcallparanode = class(tcgcallparanode)
-       protected
-        function push_zero_sized_value_para: boolean; override;
       end;
       end;
 
 
       tllvmcallnode = class(tcgcallnode)
       tllvmcallnode = class(tcgcallnode)
@@ -50,17 +48,6 @@ implementation
        verbose,
        verbose,
        symconst,symdef;
        symconst,symdef;
 
 
-{*****************************************************************************
-                          TLLVMCALLPARANODE
- *****************************************************************************}
-
-    function tllvmcallparanode.push_zero_sized_value_para: boolean;
-      begin
-        { part of the signature -> need to be pushed }
-        result:=true;
-      end;
-
-
 {*****************************************************************************
 {*****************************************************************************
                            TLLVMCALLNODE
                            TLLVMCALLNODE
  *****************************************************************************}
  *****************************************************************************}

+ 0 - 3
compiler/ncal.pas

@@ -3522,9 +3522,6 @@ implementation
                         hiddentree:=cloadparentfpnode.create(current_procinfo.procdef,lpf_forpara)
                         hiddentree:=cloadparentfpnode.create(current_procinfo.procdef,lpf_forpara)
                       else
                       else
                         internalerror(200309287);
                         internalerror(200309287);
-                      { Always use parentfp for forward-declared nested procedures }
-                      if (procdefinition.typ=procdef) and not tprocdef(procdefinition).is_implemented then
-                        include(tprocdef(procdefinition).implprocoptions,pio_needs_parentfp);
                     end
                     end
                   else if not(po_is_block in procdefinition.procoptions) then
                   else if not(po_is_block in procdefinition.procoptions) then
                     hiddentree:=gen_procvar_context_tree_parentfp
                     hiddentree:=gen_procvar_context_tree_parentfp

+ 45 - 42
compiler/ncgcal.pas

@@ -35,8 +35,6 @@ interface
     type
     type
        tcgcallparanode = class(tcallparanode)
        tcgcallparanode = class(tcallparanode)
        protected
        protected
-          function push_zero_sized_value_para: boolean; virtual;
-
           procedure push_addr_para;
           procedure push_addr_para;
           procedure push_value_para;virtual;
           procedure push_value_para;virtual;
           procedure push_formal_para;virtual;
           procedure push_formal_para;virtual;
@@ -140,6 +138,42 @@ implementation
       wpobase;
       wpobase;
 
 
 
 
+    function can_opt_unused_para(parasym: tparavarsym): boolean;
+      var
+        pd: tprocdef;
+      begin
+        { The parameter can be optimized as unused when:
+            this is a direct call to a routine, not a procvar
+            and the routine is not an exception filter
+            and the parameter is not used by the routine
+            and implementation of the routine is already processed.
+        }
+        result:=assigned(parasym.Owner) and
+          (parasym.Owner.defowner.typ=procdef);
+        if not result then
+          exit;
+        pd:=tprocdef(parasym.Owner.defowner);
+        result:=(pd.proctypeoption<>potype_exceptfilter) and
+          not parasym.is_used and
+          pd.is_implemented;
+      end;
+
+
+    function can_skip_para_push(parasym: tparavarsym): boolean;
+      begin
+        { We can skip passing the parameter when:
+            the parameter can be optimized as unused
+            and the target does not strictly require all parameters (has_strict_proc_signature = false)
+            and fixed stack is used
+              or the parameter is in a register
+              or the parameter is $parentfp. }
+        result:=can_opt_unused_para(parasym) and
+          not paramanager.has_strict_proc_signature and
+          (paramanager.use_fixed_stack or
+           (vo_is_parentfp in parasym.varoptions) or
+           (parasym.paraloc[callerside].Location^.Loc in [LOC_REGISTER,LOC_CREGISTER]));
+      end;
+
 {*****************************************************************************
 {*****************************************************************************
                              TCGCALLPARANODE
                              TCGCALLPARANODE
 *****************************************************************************}
 *****************************************************************************}
@@ -158,13 +192,6 @@ implementation
       end;
       end;
 
 
 
 
-    function tcgcallparanode.push_zero_sized_value_para: boolean;
-      begin
-        { nothing to push by default }
-        result:=false;
-      end;
-
-
     procedure tcgcallparanode.push_addr_para;
     procedure tcgcallparanode.push_addr_para;
       var
       var
         valuedef: tdef;
         valuedef: tdef;
@@ -263,7 +290,7 @@ implementation
           -- except on platforms where the parameters are part of the signature
           -- except on platforms where the parameters are part of the signature
              and checked by the runtime/backend compiler (e.g. JVM, LLVM) }
              and checked by the runtime/backend compiler (e.g. JVM, LLVM) }
         if (left.resultdef.size=0) and
         if (left.resultdef.size=0) and
-           not push_zero_sized_value_para then
+           not paramanager.has_strict_proc_signature then
           exit;
           exit;
 
 
         if maybe_push_unused_para then
         if maybe_push_unused_para then
@@ -292,29 +319,12 @@ implementation
 
 
     function tcgcallparanode.maybe_push_unused_para: boolean;
     function tcgcallparanode.maybe_push_unused_para: boolean;
       begin
       begin
-        { Check if the parameter is unused.
-          Only the $parentfp parameter is supported for now. }
-        result:=(vo_is_parentfp in parasym.varoptions) and (parasym.varstate<=vs_initialised);
+        { Check if the parameter is unused and can be optimized }
+        result:=can_opt_unused_para(parasym);
         if not result then
         if not result then
           exit;
           exit;
-        { The parameter is unused.
-          We can skip loading of the parameter when:
-            - the target does not strictly require all parameters (push_zero_sized_value_para = false)
-            and
-            - fixed stack is used
-              or the parameter is in a register
-              or the parameter is $parentfp. }
-        if not push_zero_sized_value_para and
-          (paramanager.use_fixed_stack or
-           (vo_is_parentfp in parasym.varoptions) or
-           (parasym.paraloc[callerside].Location^.Loc in [LOC_REGISTER,LOC_CREGISTER])) then
-          begin
-            { Skip loading }
-            parasym.paraloc[callerside].Location^.Loc:=LOC_VOID;
-            tempcgpara.Location^.Loc:=LOC_VOID;
-          end
-        else
-          { Load an undefined dummy value }
+        { If we can't skip loading of the parameter, load an undefined dummy value. }
+        if not can_skip_para_push(parasym) then
           hlcg.a_load_undefined_cgpara(current_asmdata.CurrAsmList,left.resultdef,tempcgpara);
           hlcg.a_load_undefined_cgpara(current_asmdata.CurrAsmList,left.resultdef,tempcgpara);
       end;
       end;
 
 
@@ -775,7 +785,8 @@ implementation
          ppn:=tcgcallparanode(left);
          ppn:=tcgcallparanode(left);
          while assigned(ppn) do
          while assigned(ppn) do
            begin
            begin
-             if (ppn.left.nodetype<>nothingn) then
+             if (ppn.left.nodetype<>nothingn) and
+               not can_skip_para_push(ppn.parasym) then
                begin
                begin
                  { better check for the real location of the parameter here, when stack passed parameters
                  { better check for the real location of the parameter here, when stack passed parameters
                    are saved temporary in registers, checking for the tmpparaloc.loc is wrong
                    are saved temporary in registers, checking for the tmpparaloc.loc is wrong
@@ -948,17 +959,9 @@ implementation
 
 
 
 
     function tcgcallnode.is_parentfp_pushed: boolean;
     function tcgcallnode.is_parentfp_pushed: boolean;
-      var
-        i : longint;
       begin
       begin
-        for i:=0 to procdefinition.paras.Count-1 do
-          with tparavarsym(procdefinition.paras[i]) do
-            if vo_is_parentfp in varoptions then
-              begin
-                result:=paraloc[callerside].Location^.Loc in [LOC_REFERENCE,LOC_CREFERENCE];
-                exit;
-              end;
-        result:=false;
+        result:=(procdefinition.typ<>procdef) or
+          not can_skip_para_push(tparavarsym(tprocdef(procdefinition).parentfpsym));
       end;
       end;
 
 
 
 

+ 2 - 5
compiler/ncgmem.pas

@@ -170,7 +170,7 @@ implementation
             location_reset(location,LOC_REGISTER,def_cgsize(parentfpvoidpointertype));
             location_reset(location,LOC_REGISTER,def_cgsize(parentfpvoidpointertype));
             currpi:=current_procinfo;
             currpi:=current_procinfo;
             { load framepointer of current proc }
             { load framepointer of current proc }
-            hsym:=parentfpsym;
+            hsym:=tparavarsym(currpi.procdef.parentfpsym);
             if (currpi.procdef.owner.symtablelevel=parentpd.parast.symtablelevel) and (hsym.localloc.loc in [LOC_REGISTER,LOC_CREGISTER]) then
             if (currpi.procdef.owner.symtablelevel=parentpd.parast.symtablelevel) and (hsym.localloc.loc in [LOC_REGISTER,LOC_CREGISTER]) then
               location.register:=hsym.localloc.register
               location.register:=hsym.localloc.register
             else
             else
@@ -183,10 +183,7 @@ implementation
                     currpi:=currpi.parent;
                     currpi:=currpi.parent;
                     if not assigned(currpi) then
                     if not assigned(currpi) then
                       internalerror(200311201);
                       internalerror(200311201);
-                    hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
-                    if not assigned(hsym) then
-                      internalerror(200309282);
-
+                    hsym:=tparavarsym(currpi.procdef.parentfpsym);
                     if hsym.localloc.loc<>LOC_REFERENCE then
                     if hsym.localloc.loc<>LOC_REFERENCE then
                       internalerror(200309283);
                       internalerror(200309283);
 
 

+ 2 - 2
compiler/ncgnstmm.pas

@@ -83,7 +83,7 @@ implementation
             while assigned(currpi) and
             while assigned(currpi) and
                   (currpi.procdef.parast.symtablelevel>parentpd.parast.symtablelevel) do
                   (currpi.procdef.parast.symtablelevel>parentpd.parast.symtablelevel) do
               begin
               begin
-                hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
+                hsym:=tparavarsym(currpi.procdef.parentfpsym);
                 maybe_add_sym_to_parentfpstruct(currpi.procdef,hsym,nextpi.procdef.parentfpstructptrtype,false);
                 maybe_add_sym_to_parentfpstruct(currpi.procdef,hsym,nextpi.procdef.parentfpstructptrtype,false);
                 currpi:=nextpi;
                 currpi:=nextpi;
                 nextpi:=nextpi.parent;
                 nextpi:=nextpi.parent;
@@ -125,7 +125,7 @@ implementation
           need }
           need }
         while (currpi.procdef.parast.symtablelevel>parentpd.parast.symtablelevel) do
         while (currpi.procdef.parast.symtablelevel>parentpd.parast.symtablelevel) do
           begin
           begin
-            hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
+            hsym:=tparavarsym(currpi.procdef.parentfpsym);
             fsym:=tfieldvarsym(find_sym_in_parentfpstruct(currpi.procdef,hsym));
             fsym:=tfieldvarsym(find_sym_in_parentfpstruct(currpi.procdef,hsym));
             if not assigned(fsym) then
             if not assigned(fsym) then
               internalerror(2011060405);
               internalerror(2011060405);

+ 3 - 4
compiler/ncgutil.pas

@@ -866,10 +866,9 @@ implementation
                       location_reset(vs.initialloc,LOC_REGISTER,OS_ADDR);
                       location_reset(vs.initialloc,LOC_REGISTER,OS_ADDR);
                       vs.initialloc.register:=NR_FRAME_POINTER_REG;
                       vs.initialloc.register:=NR_FRAME_POINTER_REG;
                     end
                     end
-                  { Unused parameters ($parentfp for now) need to be kept in the original location
+                  { Unused parameters need to be kept in the original location
                     to prevent allocation of registers/resources for them. }
                     to prevent allocation of registers/resources for them. }
-                  else if (vs.varstate <= vs_initialised) and
-                    (vo_is_parentfp in vs.varoptions) then
+                  else if not tparavarsym(vs).is_used then
                     begin
                     begin
                       tparavarsym(vs).paraloc[calleeside].get_location(vs.initialloc);
                       tparavarsym(vs).paraloc[calleeside].get_location(vs.initialloc);
                     end
                     end
@@ -1065,7 +1064,7 @@ implementation
               add_regvars(rv^,tabstractnormalvarsym(tloadnode(n).symtableentry).localloc);
               add_regvars(rv^,tabstractnormalvarsym(tloadnode(n).symtableentry).localloc);
           loadparentfpn:
           loadparentfpn:
             if current_procinfo.procdef.parast.symtablelevel>tloadparentfpnode(n).parentpd.parast.symtablelevel then
             if current_procinfo.procdef.parast.symtablelevel>tloadparentfpnode(n).parentpd.parast.symtablelevel then
-              add_regvars(rv^,tloadparentfpnode(n).parentfpsym.localloc);
+              add_regvars(rv^,tparavarsym(current_procinfo.procdef.parentfpsym).localloc);
           vecn:
           vecn:
             begin
             begin
               { range checks sometimes need the high parameter }
               { range checks sometimes need the high parameter }

+ 0 - 17
compiler/nmem.pas

@@ -53,10 +53,6 @@ interface
          lpf_forload
          lpf_forload
        );
        );
        tloadparentfpnode = class(tunarynode)
        tloadparentfpnode = class(tunarynode)
-       private
-          _parentfpsym: tparavarsym;
-          function getparentfpsym: tparavarsym;
-       public
           parentpd : tprocdef;
           parentpd : tprocdef;
           parentpdderef : tderef;
           parentpdderef : tderef;
           kind: tloadparentfpkind;
           kind: tloadparentfpkind;
@@ -69,7 +65,6 @@ interface
           function pass_typecheck:tnode;override;
           function pass_typecheck:tnode;override;
           function docompare(p: tnode): boolean; override;
           function docompare(p: tnode): boolean; override;
           function dogetcopy : tnode;override;
           function dogetcopy : tnode;override;
-          property parentfpsym: tparavarsym read getparentfpsym;
        end;
        end;
        tloadparentfpnodeclass = class of tloadparentfpnode;
        tloadparentfpnodeclass = class of tloadparentfpnode;
 
 
@@ -389,18 +384,6 @@ implementation
         expectloc:=LOC_REGISTER;
         expectloc:=LOC_REGISTER;
       end;
       end;
 
 
-
-    function tloadparentfpnode.getparentfpsym: tparavarsym;
-      begin
-        if not assigned(_parentfpsym) then
-          begin
-            _parentfpsym:=tparavarsym(current_procinfo.procdef.parast.Find('parentfp'));
-            if not assigned(_parentfpsym) then
-              internalerror(200309281);
-          end;
-        result:=_parentfpsym;
-      end;
-
 {*****************************************************************************
 {*****************************************************************************
                              TADDRNODE
                              TADDRNODE
 *****************************************************************************}
 *****************************************************************************}

+ 10 - 0
compiler/paramgr.pas

@@ -161,6 +161,10 @@ unit paramgr;
           function use_fixed_stack: boolean;
           function use_fixed_stack: boolean;
           { whether stack pointer can be changed in the middle of procedure }
           { whether stack pointer can be changed in the middle of procedure }
           function use_stackalloc: boolean;
           function use_stackalloc: boolean;
+          { Returns true for platforms where the parameters are part of the signature
+            and checked by the runtime/backend compiler (e.g. JVM, LLVM).
+            The default implementation returns false. }
+          function has_strict_proc_signature: boolean; virtual;
          strict protected
          strict protected
           { common part of get_funcretloc; returns true if retloc is completely
           { common part of get_funcretloc; returns true if retloc is completely
             initialized afterwards }
             initialized afterwards }
@@ -651,6 +655,12 @@ implementation
       end;
       end;
 
 
 
 
+    function tparamanager.has_strict_proc_signature: boolean;
+      begin
+        result:=false;
+      end;
+
+
     function tparamanager.set_common_funcretloc_info(p : tabstractprocdef; forcetempdef: tdef; out retcgsize: tcgsize; out retloc: tcgpara): boolean;
     function tparamanager.set_common_funcretloc_info(p : tabstractprocdef; forcetempdef: tdef; out retcgsize: tcgsize; out retloc: tcgpara): boolean;
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;

+ 0 - 2
compiler/pparautl.pas

@@ -164,8 +164,6 @@ implementation
                 vs:=cparavarsym.create('$parentfp',paranr,vs_value,
                 vs:=cparavarsym.create('$parentfp',paranr,vs_value,
                       tprocdef(pd.owner.defowner).parentfpstructptrtype,[vo_is_parentfp,vo_is_hidden_para]);
                       tprocdef(pd.owner.defowner).parentfpstructptrtype,[vo_is_parentfp,vo_is_hidden_para]);
               end;
               end;
-            { Mark $parentfp as used by default }
-            vs.varstate:=vs_read;
             pd.parast.insert(vs);
             pd.parast.insert(vs);
 
 
             current_tokenpos:=storepos;
             current_tokenpos:=storepos;

+ 15 - 6
compiler/procinfo.pas

@@ -202,8 +202,8 @@ unit procinfo;
           procedure start_eh(list : TAsmList); virtual;
           procedure start_eh(list : TAsmList); virtual;
           { called to insert needed eh info into the exit code }
           { called to insert needed eh info into the exit code }
           procedure end_eh(list : TAsmList); virtual;
           procedure end_eh(list : TAsmList); virtual;
-          { Sets the pio_needs_parentfp flag for the current nested procedure.
-            Sets both pio_needs_parentfp and pio_nested_access for all parent
+          { Mark the parentfp as used for the current nested procedure.
+            Mark the parentfp as used and set pio_nested_access for all parent
             procedures until parent_level }
             procedures until parent_level }
           procedure set_needs_parentfp(parent_level: byte);
           procedure set_needs_parentfp(parent_level: byte);
        end;
        end;
@@ -437,20 +437,29 @@ implementation
     procedure tprocinfo.set_needs_parentfp(parent_level: byte);
     procedure tprocinfo.set_needs_parentfp(parent_level: byte);
       var
       var
         pi : tprocinfo;
         pi : tprocinfo;
+        p : tparavarsym;
       begin
       begin
         if (procdef.parast.symtablelevel<=normal_function_level)
         if (procdef.parast.symtablelevel<=normal_function_level)
           or (procdef.parast.symtablelevel<=parent_level) then
           or (procdef.parast.symtablelevel<=parent_level) then
           Internalerror(2020050302);
           Internalerror(2020050302);
         if parent_level<normal_function_level then
         if parent_level<normal_function_level then
           parent_level:=normal_function_level;
           parent_level:=normal_function_level;
-        { Set pio_needs_parentfp for the current proc }
+        { Mark parentfp as used for the current proc }
         pi:=Self;
         pi:=Self;
-        include(pi.procdef.implprocoptions, pio_needs_parentfp);
-        { Set both pio_needs_parentfp and pio_nested_access for all parent procs until parent_level }
+        tparavarsym(pi.procdef.parentfpsym).varstate:=vs_read;
+        { Set both parentfp is used and pio_nested_access for all parent procs until parent_level }
         while pi.procdef.parast.symtablelevel>parent_level do
         while pi.procdef.parast.symtablelevel>parent_level do
           begin
           begin
             pi:=pi.parent;
             pi:=pi.parent;
-            pi.procdef.implprocoptions:=pi.procdef.implprocoptions+[pio_needs_parentfp,pio_nested_access];
+            if pi.procdef.parast.symtablelevel>normal_function_level then
+              begin
+                p:=tparavarsym(pi.procdef.parentfpsym);
+                p.varstate:=vs_read;
+                { parentfp is accessed from a nested routine.
+                  Must be in the memory. }
+                p.varregable:=vr_none;
+              end;
+            include(pi.procdef.implprocoptions,pio_nested_access);
           end;
           end;
       end;
       end;
 
 

+ 1 - 3
compiler/symconst.pas

@@ -455,9 +455,7 @@ type
     { compiled with fastmath enabled }
     { compiled with fastmath enabled }
     pio_fastmath,
     pio_fastmath,
     { inline is forbidden (calls get_frame) }
     { inline is forbidden (calls get_frame) }
-    pio_inline_forbidden,
-    { a nested routine uses the frame pointer of the parent routine }
-    pio_needs_parentfp
+    pio_inline_forbidden
   );
   );
   timplprocoptions = set of timplprocoption;
   timplprocoptions = set of timplprocoption;
 
 

+ 17 - 49
compiler/symdef.pas

@@ -702,8 +702,6 @@ interface
        private
        private
           procedure count_para(p:TObject;arg:pointer);
           procedure count_para(p:TObject;arg:pointer);
           procedure insert_para(p:TObject;arg:pointer);
           procedure insert_para(p:TObject;arg:pointer);
-       protected
-          procedure handle_unused_paras(side: tcallercallee); virtual;
        end;
        end;
 
 
        tprocvardef = class(tabstractprocdef)
        tprocvardef = class(tabstractprocdef)
@@ -782,6 +780,7 @@ interface
 {$else symansistr}
 {$else symansistr}
          _mangledname : pshortstring;
          _mangledname : pshortstring;
 {$endif}
 {$endif}
+         _parentfpsym : tsym;
          { information that is only required until the implementation of the
          { information that is only required until the implementation of the
            procdef has been handled }
            procdef has been handled }
          implprocdefinfo : pimplprocdefinfo;
          implprocdefinfo : pimplprocdefinfo;
@@ -814,7 +813,7 @@ interface
          procedure SetIsEmpty(AValue: boolean);
          procedure SetIsEmpty(AValue: boolean);
          function GetHasInliningInfo: boolean;
          function GetHasInliningInfo: boolean;
          procedure SetHasInliningInfo(AValue: boolean);
          procedure SetHasInliningInfo(AValue: boolean);
-         procedure handle_unused_paras(side: tcallercallee); override;
+         function getparentfpsym: tsym;
        public
        public
           messageinf : tmessageinf;
           messageinf : tmessageinf;
           dispid : longint;
           dispid : longint;
@@ -937,6 +936,8 @@ interface
           property isempty: boolean read GetIsEmpty write SetIsEmpty;
           property isempty: boolean read GetIsEmpty write SetIsEmpty;
           { true if all information required to inline this routine is available }
           { true if all information required to inline this routine is available }
           property has_inlininginfo: boolean read GetHasInliningInfo write SetHasInliningInfo;
           property has_inlininginfo: boolean read GetHasInliningInfo write SetHasInliningInfo;
+          { returns the $parentfp parameter for nested routines }
+          property parentfpsym: tsym read getparentfpsym;
        end;
        end;
        tprocdefclass = class of tprocdef;
        tprocdefclass = class of tprocdef;
 
 
@@ -5276,11 +5277,6 @@ implementation
       end;
       end;
 
 
 
 
-    procedure tabstractprocdef.handle_unused_paras(side: tcallercallee);
-    begin
-    end;
-
-
     procedure tabstractprocdef.calcparas;
     procedure tabstractprocdef.calcparas;
       var
       var
         paracount : longint;
         paracount : longint;
@@ -5714,7 +5710,6 @@ implementation
               has_paraloc_info:=callbothsides
               has_paraloc_info:=callbothsides
             else
             else
               has_paraloc_info:=callerside;
               has_paraloc_info:=callerside;
-            handle_unused_paras(callerside);
           end;
           end;
         if (side in [calleeside,callbothsides]) and
         if (side in [calleeside,callbothsides]) and
            not(has_paraloc_info in [calleeside,callbothsides]) then
            not(has_paraloc_info in [calleeside,callbothsides]) then
@@ -5727,7 +5722,6 @@ implementation
               has_paraloc_info:=callbothsides
               has_paraloc_info:=callbothsides
             else
             else
               has_paraloc_info:=calleeside;
               has_paraloc_info:=calleeside;
-            handle_unused_paras(calleeside);
           end;
           end;
       end;
       end;
 
 
@@ -5774,6 +5768,8 @@ implementation
           if tsym(parast.SymList[i]).typ=paravarsym then
           if tsym(parast.SymList[i]).typ=paravarsym then
             begin
             begin
               p:=tparavarsym(parast.SymList[i]);
               p:=tparavarsym(parast.SymList[i]);
+              if not p.is_used then
+                continue;
               { check if no parameter is located on the stack }
               { check if no parameter is located on the stack }
               if (is_open_array(p.vardef) or
               if (is_open_array(p.vardef) or
                  is_array_of_const(p.vardef)) and (p.varspez=vs_value) then
                  is_array_of_const(p.vardef)) and (p.varspez=vs_value) then
@@ -5840,6 +5836,17 @@ implementation
                                   TPROCDEF
                                   TPROCDEF
 ***************************************************************************}
 ***************************************************************************}
 
 
+    function tprocdef.getparentfpsym: tsym;
+      begin
+        if not assigned(_parentfpsym) then
+          begin
+            _parentfpsym:=tsym(parast.Find('parentfp'));
+            if not assigned(_parentfpsym) then
+              internalerror(200309281);
+          end;
+        result:=_parentfpsym;
+      end;
+
 
 
     function tprocdef.store_localst: boolean;
     function tprocdef.store_localst: boolean;
       begin
       begin
@@ -6021,45 +6028,6 @@ implementation
       end;
       end;
 
 
 
 
-    procedure tprocdef.handle_unused_paras(side: tcallercallee);
-      var
-        i : longint;
-      begin
-        { Optimize unused parameters by preventing loading them on the callee side
-          and, if possible, preventing passing them on the caller side.
-          The caller side optimization is handled by tcgcallparanode.maybe_push_unused_para().
-        }
-        if (proctypeoption = potype_exceptfilter) or
-          (po_assembler in procoptions) then
-          exit;
-        { Only $parentfp is optmized for now. }
-        if not is_nested_pd(self) then
-          exit;
-        { Handle unused parameters }
-        for i:=0 to paras.Count-1 do
-          with tparavarsym(paras[i]) do
-            if vo_is_parentfp in varoptions then
-              begin
-                if pio_needs_parentfp in implprocoptions then
-                  begin
-                    { If this routine is accessed from other nested routine,
-                      $parentfp must be in a memory location. }
-                    if pio_nested_access in implprocoptions then
-                      varregable:=vr_none;
-                  end
-                else
-                  begin
-                    { Mark $parentfp as unused, since it has vs_read by default }
-                    varstate:=vs_initialised;
-                    if side=calleeside then
-                      { Set LOC_VOID as the parameter's location on the callee side }
-                      paraloc[side].location^.Loc:=LOC_VOID;
-                    break;
-                  end;
-              end;
-      end;
-
-
     procedure tprocdef.Setinterfacedef(AValue: boolean);
     procedure tprocdef.Setinterfacedef(AValue: boolean);
       begin
       begin
         if not assigned(implprocdefinfo) then
         if not assigned(implprocdefinfo) then

+ 8 - 0
compiler/symsym.pas

@@ -283,6 +283,7 @@ interface
             override ppuwrite_platform instead }
             override ppuwrite_platform instead }
           procedure ppuwrite(ppufile:tcompilerppufile);override;final;
           procedure ppuwrite(ppufile:tcompilerppufile);override;final;
           function needs_finalization: boolean;
           function needs_finalization: boolean;
+          function is_used: boolean;
       end;
       end;
       tparavarsymclass = class of tparavarsym;
       tparavarsymclass = class of tparavarsym;
 
 
@@ -2298,6 +2299,13 @@ implementation
           );
           );
       end;
       end;
 
 
+
+    function tparavarsym.is_used: boolean;
+      begin
+        { Only the $parentfp parameter is supported for now }
+        result:=not (vo_is_parentfp in varoptions) or (varstate>vs_initialised);
+      end;
+
 {****************************************************************************
 {****************************************************************************
                                TABSOLUTEVARSYM
                                TABSOLUTEVARSYM
 ****************************************************************************}
 ****************************************************************************}

+ 1 - 2
compiler/utils/ppuutils/ppudump.pp

@@ -3232,8 +3232,7 @@ const
     (mask:pio_nested_access; str:'NestedAccess'),
     (mask:pio_nested_access; str:'NestedAccess'),
     (mask:pio_thunk; str:'Thunk'),
     (mask:pio_thunk; str:'Thunk'),
     (mask:pio_fastmath; str:'FastMath'),
     (mask:pio_fastmath; str:'FastMath'),
-    (mask:pio_inline_forbidden; str:'InlineForbidden'),
-    (mask:pio_needs_parentfp; str:'NeedsParentFP')
+    (mask:pio_inline_forbidden; str:'InlineForbidden')
   );
   );
 var
 var
   i: timplprocoption;
   i: timplprocoption;