Browse Source

* handle constructor function results that have been migrated to the
parentfpstruct the same as regular function results (see r32687)

git-svn-id: trunk@40641 -

Jonas Maebe 6 years ago
parent
commit
f754978540
5 changed files with 60 additions and 40 deletions
  1. 6 17
      compiler/hlcgobj.pas
  2. 10 0
      compiler/jvm/symcpu.pas
  3. 8 10
      compiler/nflw.pas
  4. 13 13
      compiler/ngenutil.pas
  5. 23 0
      compiler/symdef.pas

+ 6 - 17
compiler/hlcgobj.pas

@@ -5182,7 +5182,7 @@ implementation
 
 
   procedure thlcgobj.gen_load_return_value(list: TAsmList);
   procedure thlcgobj.gen_load_return_value(list: TAsmList);
     var
     var
-      ressym : tabstractnormalvarsym;
+      ressym : tsym;
       retdef : tdef;
       retdef : tdef;
     begin
     begin
       { Is the loading needed? }
       { Is the loading needed? }
@@ -5196,30 +5196,19 @@ implementation
         exit;
         exit;
 
 
       { constructors return self }
       { constructors return self }
-      if (current_procinfo.procdef.proctypeoption=potype_constructor) then
-        begin
-          ressym:=tabstractnormalvarsym(current_procinfo.procdef.parast.Find('self'));
-          retdef:=ressym.vardef;
-          { and TP-style constructors return a pointer to self }
-          if is_object(ressym.vardef) then
-            retdef:=cpointerdef.getreusable(retdef);
-        end
-      else
-        begin
-          ressym:=tabstractnormalvarsym(current_procinfo.procdef.funcretsym);
-          retdef:=ressym.vardef;
-        end;
+      if not current_procinfo.procdef.getfuncretsyminfo(ressym,retdef) then
+        internalerror(2018122501);
       if (ressym.refs>0) or
       if (ressym.refs>0) or
          is_managed_type(retdef) then
          is_managed_type(retdef) then
         begin
         begin
           { was: don't do anything if funcretloc.loc in [LOC_INVALID,LOC_REFERENCE] }
           { was: don't do anything if funcretloc.loc in [LOC_INVALID,LOC_REFERENCE] }
           if not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef) then
           if not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef) then
-            gen_load_loc_function_result(list,retdef,ressym.localloc);
+            gen_load_loc_function_result(list,retdef,tabstractnormalvarsym(ressym).localloc);
         end
         end
       else
       else
         gen_load_uninitialized_function_result(list,current_procinfo.procdef,retdef,current_procinfo.procdef.funcretloc[calleeside]);
         gen_load_uninitialized_function_result(list,current_procinfo.procdef,retdef,current_procinfo.procdef.funcretloc[calleeside]);
-      if ressym.localloc.loc=LOC_REFERENCE then
-        tg.UnGetLocal(list,ressym.localloc.reference);
+      if tabstractnormalvarsym(ressym).localloc.loc=LOC_REFERENCE then
+        tg.UnGetLocal(list,tabstractnormalvarsym(ressym).localloc.reference);
     end;
     end;
 
 
   procedure thlcgobj.gen_stack_check_size_para(list: TAsmList);
   procedure thlcgobj.gen_stack_check_size_para(list: TAsmList);

+ 10 - 0
compiler/jvm/symcpu.pas

@@ -109,6 +109,7 @@ type
     exprasmlist      : TAsmList;
     exprasmlist      : TAsmList;
     function  jvmmangledbasename(signature: boolean): TSymStr;
     function  jvmmangledbasename(signature: boolean): TSymStr;
     function mangledname: TSymStr; override;
     function mangledname: TSymStr; override;
+    function getfuncretsyminfo(out ressym: tsym; out resdef: tdef): boolean; override;
     destructor destroy; override;
     destructor destroy; override;
   end;
   end;
   tcpuprocdefclass = class of tcpuprocdef;
   tcpuprocdefclass = class of tcpuprocdef;
@@ -751,6 +752,15 @@ implementation
         result:=_mangledname;
         result:=_mangledname;
     end;
     end;
 
 
+  function tcpuprocdef.getfuncretsyminfo(out ressym: tsym; out resdef: tdef): boolean;
+    begin
+      { constructors don't have a result on the JVM platform }
+      if proctypeoption<>potype_constructor then
+        result:=inherited
+      else
+        result:=false;
+    end;
+
 
 
   destructor tcpuprocdef.destroy;
   destructor tcpuprocdef.destroy;
     begin
     begin

+ 8 - 10
compiler/nflw.pas

@@ -1773,8 +1773,9 @@ implementation
 
 
     function texitnode.pass_typecheck:tnode;
     function texitnode.pass_typecheck:tnode;
       var
       var
-        pd: tprocdef;
         newstatement : tstatementnode;
         newstatement : tstatementnode;
+        ressym: tsym;
+        resdef: tdef;
       begin
       begin
         result:=nil;
         result:=nil;
         newstatement:=nil;
         newstatement:=nil;
@@ -1790,16 +1791,13 @@ implementation
           because the code to this that we add in tnodeutils.wrap_proc_body()
           because the code to this that we add in tnodeutils.wrap_proc_body()
           gets inserted before the exit label to which this node will jump }
           gets inserted before the exit label to which this node will jump }
         if (target_info.system in systems_fpnestedstruct) and
         if (target_info.system in systems_fpnestedstruct) and
-           not(nf_internal in flags) then
+           not(nf_internal in flags) and
+           current_procinfo.procdef.getfuncretsyminfo(ressym,resdef) and
+           (tabstractnormalvarsym(ressym).inparentfpstruct) then
           begin
           begin
-            pd:=current_procinfo.procdef;
-            if assigned(pd.funcretsym) and
-               tabstractnormalvarsym(pd.funcretsym).inparentfpstruct then
-              begin
-                if not assigned(result) then
-                  result:=internalstatements(newstatement);
-                cnodeutils.load_parentfpstruct_nested_funcret(current_procinfo.procdef,newstatement);
-              end;
+            if not assigned(result) then
+              result:=internalstatements(newstatement);
+            cnodeutils.load_parentfpstruct_nested_funcret(ressym,newstatement);
           end;
           end;
         if assigned(result) then
         if assigned(result) then
           begin
           begin

+ 13 - 13
compiler/ngenutil.pas

@@ -74,7 +74,7 @@ interface
         the value to be returned; replacing it with an absolutevarsym that
         the value to be returned; replacing it with an absolutevarsym that
         redirects to the field in the parentfpstruct doesn't work, as the code
         redirects to the field in the parentfpstruct doesn't work, as the code
         generator cannot deal with such symbols }
         generator cannot deal with such symbols }
-       class procedure load_parentfpstruct_nested_funcret(pd: tprocdef; var stat: tstatementnode);
+       class procedure load_parentfpstruct_nested_funcret(ressym: tsym; var stat: tstatementnode);
       { called after parsing a routine with the code of the entire routine
       { called after parsing a routine with the code of the entire routine
         as argument; can be used to modify the node tree. By default handles
         as argument; can be used to modify the node tree. By default handles
         insertion of code for systems that perform the typed constant
         insertion of code for systems that perform the typed constant
@@ -579,17 +579,17 @@ implementation
     end;
     end;
 
 
 
 
-  class procedure tnodeutils.load_parentfpstruct_nested_funcret(pd: tprocdef; var stat: tstatementnode);
+  class procedure tnodeutils.load_parentfpstruct_nested_funcret(ressym: tsym; var stat: tstatementnode);
     var
     var
       target: tnode;
       target: tnode;
     begin
     begin
-      target:=cloadnode.create(pd.funcretsym, pd.funcretsym.owner);
+      target:=cloadnode.create(ressym, ressym.owner);
       { ensure the target of this assignment doesn't translate the
       { ensure the target of this assignment doesn't translate the
         funcretsym also to its alias in the parentfpstruct }
         funcretsym also to its alias in the parentfpstruct }
       include(target.flags, nf_internal);
       include(target.flags, nf_internal);
       addstatement(stat,
       addstatement(stat,
         cassignmentnode.create(
         cassignmentnode.create(
-          target, cloadnode.create(pd.funcretsym, pd.funcretsym.owner)
+          target, cloadnode.create(ressym, ressym.owner)
         )
         )
       );
       );
     end;
     end;
@@ -599,7 +599,9 @@ implementation
     var
     var
       stat: tstatementnode;
       stat: tstatementnode;
       block: tnode;
       block: tnode;
+      ressym,
       psym: tsym;
       psym: tsym;
+      resdef: tdef;
     begin
     begin
       result:=maybe_insert_trashing(pd,n);
       result:=maybe_insert_trashing(pd,n);
 
 
@@ -669,16 +671,14 @@ implementation
             end;
             end;
           end;
           end;
         end;
         end;
-      if target_info.system in systems_fpnestedstruct then
+      if (target_info.system in systems_fpnestedstruct) and
+         pd.getfuncretsyminfo(ressym,resdef) and
+         (tabstractnormalvarsym(ressym).inparentfpstruct) then
         begin
         begin
-          if assigned(pd.funcretsym) and
-             tabstractnormalvarsym(pd.funcretsym).inparentfpstruct then
-            begin
-              block:=internalstatements(stat);
-              addstatement(stat,result);
-              load_parentfpstruct_nested_funcret(pd,stat);
-              result:=block;
-            end;
+          block:=internalstatements(stat);
+          addstatement(stat,result);
+          load_parentfpstruct_nested_funcret(ressym,stat);
+          result:=block;
         end;
         end;
     end;
     end;
 
 

+ 23 - 0
compiler/symdef.pas

@@ -828,6 +828,8 @@ interface
           procedure make_external;
           procedure make_external;
           procedure init_genericdecl;
           procedure init_genericdecl;
 
 
+          function getfuncretsyminfo(out ressym: tsym; out resdef: tdef): boolean; virtual;
+
           { returns whether the mangled name or any of its aliases is equal to
           { returns whether the mangled name or any of its aliases is equal to
             s }
             s }
           function  has_alias_name(const s: TSymStr):boolean;
           function  has_alias_name(const s: TSymStr):boolean;
@@ -6046,6 +6048,27 @@ implementation
       end;
       end;
 
 
 
 
+    function tprocdef.getfuncretsyminfo(out ressym: tsym; out resdef: tdef): boolean;
+      begin
+        result:=false;
+        if proctypeoption=potype_constructor then
+          begin
+            result:=true;
+            ressym:=tsym(parast.Find('self'));
+            resdef:=tabstractnormalvarsym(ressym).vardef;
+            { and TP-style constructors return a pointer to self }
+            if is_object(resdef) then
+              resdef:=cpointerdef.getreusable(resdef);
+          end
+        else if not is_void(returndef) then
+          begin
+            result:=true;
+            ressym:=funcretsym;
+            resdef:=tabstractnormalvarsym(ressym).vardef;
+          end;
+      end;
+
+
     function tprocdef.has_alias_name(const s: TSymStr): boolean;
     function tprocdef.has_alias_name(const s: TSymStr): boolean;
       var
       var
         item : TCmdStrListItem;
         item : TCmdStrListItem;