From 5f14029e74fdd316a8d5b8b1d54af4cb965956b9 Mon Sep 17 00:00:00 2001
From: Jonas Maebe <jonas@freepascal.org>
Date: Sun, 20 Dec 2015 20:56:08 +0000
Subject: [PATCH]   * if a function result has been migrated to the
 parentfpstruct because it is     accessed by a nested routine, assign it back
 to the original funcretsym     at the end because the code generator is
 hardcoded to use funcretsym.     We can't replace funcretsym with an
 absolutevarsym that redirects to     the parentfpstruct field, because the
 code generator can only handle     simple variables

git-svn-id: trunk@32687 -
---
 compiler/ngenutil.pas | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/compiler/ngenutil.pas b/compiler/ngenutil.pas
index 4f5793a7e1..3e8050ba9b 100644
--- a/compiler/ngenutil.pas
+++ b/compiler/ngenutil.pas
@@ -117,7 +117,7 @@ implementation
       verbose,version,globals,cutils,constexp,
       scanner,systems,procinfo,fmodule,
       aasmbase,aasmtai,aasmcnst,
-      symbase,symtable,defutil,
+      symbase,symtable,defutil,symcreat,
       nadd,ncal,ncnv,ncon,nflw,ninl,nld,nmem,nobj,nutils,
       ppu,
       pass_1;
@@ -313,7 +313,8 @@ implementation
   class function tnodeutils.wrap_proc_body(pd: tprocdef; n: tnode): tnode;
     var
       stat: tstatementnode;
-      block: tnode;
+      block,
+      target: tnode;
       psym: tsym;
     begin
       result:=maybe_insert_trashing(pd,n);
@@ -384,6 +385,31 @@ implementation
             end;
           end;
         end;
+      if target_info.system in systems_fpnestedstruct then
+        begin
+          { if the funcretsym was moved to the parentfpstruct, move its value
+            back into the funcretsym now, as the code generator is hardcoded
+            to use the funcretsym when loading the value to be returned;
+            replacing it with an absolutevarsym that redirects to the field in
+            the parentfpstruct doesn't work, as the code generator cannot deal
+            with such symbols }
+          if assigned(pd.funcretsym) and
+             tabstractnormalvarsym(pd.funcretsym).inparentfpstruct then
+            begin
+              block:=internalstatements(stat);
+              addstatement(stat,result);
+              target:=cloadnode.create(pd.funcretsym,pd.funcretsym.owner);
+              { ensure the target of this assignment doesn't translate the
+                funcretsym also to its alias in the parentfpstruct }
+              include(target.flags,nf_internal);
+              addstatement(stat,
+                cassignmentnode.create(
+                  target,cloadnode.create(pd.funcretsym,pd.funcretsym.owner)
+                )
+              );
+              result:=block;
+            end;
+        end;
     end;